# HG changeset patch # User prymula # Date 1697486014 -7200 # Node ID 84e66ea83026fc0fe7cf75b430d8653f6d80eefd # Parent cf2cb71d31dd1650c59382ec49ccf2660a1d1238 DPF-Prymula-audioplugins-0.231015-2 diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/LICENSE Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,27 @@ +License / Copyright Information + +The DPF-Plugins package consists of several plugins based on the DISTHRO Plugin +Framework (DPF). Different copyrights and licenses apply to different plugins. + +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. + +DPF-Plugins licenses + +Component Location License +------------------------------------------------------------------ +DPF src/dpf ISC + +ndc Plugs: + + CloneChannel src/plugins/CloneChannel MIT + + +------------------------------------------------------------------ + +The LICENSE file for each component can be retrieved at the specified Location. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/Makefile Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,94 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +include dpf/Makefile.base.mk + +all: dgl plugins gen + +# -------------------------------------------------------------- + +PREFIX ?= /usr/local +DESTDIR ?= + +# -------------------------------------------------------------- +# Check for system-wide projectM + +HAVE_PROJECTM = $(shell pkg-config --exists libprojectM && echo true) + +# -------------------------------------------------------------- + +ifneq ($(CROSS_COMPILING),true) +CAN_GENERATE_TTL = true +else ifneq ($(EXE_WRAPPER),) +CAN_GENERATE_TTL = true +endif + +dgl: +ifeq ($(HAVE_CAIRO_OR_OPENGL),true) + $(MAKE) FILE_BROWSER_DISABLED=true -C dpf/dgl +ifeq ($(HAVE_OPENGL),true) + $(MAKE) FILE_BROWSER_DISABLED=true -C dpf/dgl opengl3 +endif +endif + +plugins: dgl + + $(MAKE) all -C plugins/CloneChannel + +gen: plugins dpf/utils/lv2_ttl_generator +ifeq ($(CAN_GENERATE_TTL),true) + @$(CURDIR)/dpf/utils/generate-ttl.sh +endif + +dpf/utils/lv2_ttl_generator: + $(MAKE) -C dpf/utils/lv2-ttl-generator + +# -------------------------------------------------------------- + +clean: + rm -rf bin build + + $(MAKE) clean -C dpf/dgl + $(MAKE) clean -C dpf/utils/lv2-ttl-generator + + + $(MAKE) clean -C plugins/CloneChannel + +# -------------------------------------------------------------- + +install: + install -d $(DESTDIR)$(PREFIX)/lib/ladspa/ + install -d $(DESTDIR)$(PREFIX)/lib/dssi/ + install -d $(DESTDIR)$(PREFIX)/lib/lv2/ + install -d $(DESTDIR)$(PREFIX)/lib/vst/ + install -d $(DESTDIR)$(PREFIX)/lib/vst3/ + install -d $(DESTDIR)$(PREFIX)/lib/clap/ + install -d $(DESTDIR)$(PREFIX)/bin/ + + install -m 644 bin/*-ladspa.* $(DESTDIR)$(PREFIX)/lib/ladspa/ + install -m 644 bin/*-dssi.* $(DESTDIR)$(PREFIX)/lib/dssi/ +ifneq ($(MACOS),true) + install -m 644 bin/*-vst.* $(DESTDIR)$(PREFIX)/lib/vst/ +endif + +ifeq ($(HAVE_CAIRO_OR_OPENGL),true) +ifeq ($(HAVE_LIBLO),true) + cp -r bin/*-dssi $(DESTDIR)$(PREFIX)/lib/dssi/ +endif # HAVE_LIBLO +endif # HAVE_CAIRO_OR_OPENGL + cp -rL bin/*.lv2 $(DESTDIR)$(PREFIX)/lib/lv2/ +ifeq ($(HAVE_OPENGL),true) + cp -rL bin/*.vst $(DESTDIR)$(PREFIX)/lib/vst/ +endif # HAVE_OPENGL + cp -rL bin/*.vst3 $(DESTDIR)$(PREFIX)/lib/vst3/ + cp -rL bin/*.clap $(DESTDIR)$(PREFIX)/lib/clap/ + + install -m 755 bin/CLoneChannel$(APP_EXT) $(DESTDIR)$(PREFIX)/bin/ + + +# -------------------------------------------------------------- + +.PHONY: plugins diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/README.md Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,11 @@ +DPF-Plugins +=========== + +Collection of DPF-based plugins ready for packaging.
+They come in LADSPA, DSSI, LV2, VST2, VST3 and CLAP formats. + +This repository does not use submodules,
+everything you need to build is included in a simple clone. + +The list of plugins/packs are: + - CloneChannel diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/CMakeLists.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,61 @@ +# DISTRHO Plugin Framework (DPF) +# Copyright (C) 2021 Jean Pierre Cimalando +# +# SPDX-License-Identifier: ISC + +cmake_minimum_required(VERSION 3.7) + +project(DPF) + +# ensure c++11 at minimum, the parent project can override +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +endif() + +# check if we are building from this project, or are imported by another +if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(DPF_BUILD_FROM_HERE TRUE) +else() + set(DPF_BUILD_FROM_HERE FALSE) +endif() + +option(DPF_LIBRARIES "Build the libraries" "${DPF_BUILD_FROM_HERE}") +option(DPF_EXAMPLES "Build the examples" "${DPF_BUILD_FROM_HERE}") + +set(DPF_ROOT_DIR "${PROJECT_SOURCE_DIR}" CACHE INTERNAL + "Root directory of the DISTRHO Plugin Framework.") + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +include(DPF-plugin) + +if(DPF_LIBRARIES) + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(CAIRO "cairo") + if(CAIRO_FOUND AND (NOT HAIKU)) + dpf__add_dgl_cairo(FALSE) + endif() + endif() + dpf__add_dgl_opengl(FALSE) +endif() + +if(DPF_EXAMPLES) + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(CAIRO "cairo") + if(CAIRO_FOUND AND (NOT HAIKU)) + add_subdirectory("examples/CairoUI") + endif() + endif() + if((NOT WIN32) AND (NOT APPLE)) + add_subdirectory("examples/ExternalUI") + endif() + add_subdirectory("examples/EmbedExternalUI") + add_subdirectory("examples/FileHandling") + add_subdirectory("examples/Info") + add_subdirectory("examples/Latency") + add_subdirectory("examples/Meters") + add_subdirectory("examples/MidiThrough") + add_subdirectory("examples/Parameters") + add_subdirectory("examples/States") +endif() diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/FEATURES.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/FEATURES.md Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,98 @@ +# DPF - DISTRHO Plugin Framework + +This file describes the available features for each plugin format. +The limitations could be due to the plugin format itself or within DPF. +If the limitation is within DPF, a link is provided to a description below on the reason for it. + +| Feature | JACK/Standalone | LADSPA | DSSI | LV2 | VST2 | VST3 | CLAP | Feature | +|---------------------|---------------------------------------|--------------------|---------------------|-------------------------------|----------------------------|----------------------------|-------------------------------|---------------------| +| Audio port groups | [Yes*](#jack-audio-port-groups) | No | No | Yes | No | Yes | Yes | Audio port groups | +| Audio port as CV | Yes | No | No | Yes | No | [Yes*](#vst3-cv) | [No*](#work-in-progress) | Audio port as CV | +| Audio sidechan | Yes | No | No | Yes | [No*](#vst2-deprecated) | Yes | Yes | Audio sidechan | +| Bypass control | No | No | No | Yes | [No*](#vst2-deprecated) | Yes | Yes | Bypass control | +| MIDI input | Yes | No | Yes | Yes | Yes | Yes | Yes | MIDI input | +| MIDI output | Yes | No | No | Yes | Yes | Yes | Yes | MIDI output | +| Parameter changes | Yes | No | No | [No*](#lv2-parameter-changes) | Yes | Yes | Yes | Parameter changes | +| Parameter groups | No | No | No | Yes | Yes | [No*](#work-in-progress) | Yes | Parameter groups | +| Parameter outputs | No | No | No | Yes | No | Yes | Yes | Parameter outputs | +| Parameter triggers | Yes | No | No | Yes | [No*](#parameter-triggers) | [No*](#parameter-triggers) | [No*](#parameter-triggers) | Parameter triggers | +| Programs | [Yes*](#jack-parameters-and-programs) | [No*](#ladspa-rdf) | [Yes*](#dssi-state) | Yes | [No*](#vst2-programs) | Yes | No | Programs | +| States | Yes | No | [Yes*](#dssi-state) | Yes | Yes | Yes | Yes | States | +| Full/internal state | Yes | No | No | Yes | Yes | Yes | Yes | Full/internal state | +| Time position | Yes | No | No | Yes | Yes | Yes | Yes | Time position | +| UI | [Yes*](#jack-custom-ui-only) | No | External only | Yes | Embed only | Embed only | Yes | UI | +| UI bg/fg colors | No | No | No | Yes | No | No? | No | UI bg/fg colors | +| UI direct access | Yes | No | No | Yes | Yes | Yes | Yes | UI direct access | +| UI host-filebrowser | No | No | No | Yes | [No*](#vst2-deprecated) | [No*](#work-in-progress) | [No*](#work-in-progress) | UI host-filebrowser | +| UI host-resize | Yes | No | Yes | Yes | No | Yes | Yes | UI host-resize | +| UI remote control | No | No | Yes | Yes | No | Yes | No | UI remote control | +| UI send midi note | Yes | No | Yes | Yes | Yes | Yes | Yes | UI send midi note | + +For things that could be unclear: + +- "States" refers to DPF API support, supporting key-value string pairs for internal state saving +- "Full state" refers to plugins updating their state internally without outside intervention (like host or UI) +- "UI direct access" means `DISTRHO_PLUGIN_WANT_DIRECT_ACCESS` is possible, that is, running DSP and UI on the same process +- "UI remote control" means running the UI on a separate machine (for example over the network) +- An external UI on this table means that it cannot be embed into the host window, but the plugin can still provide one + +# Special notes + +## Parameter triggers + +Trigger-style parameters (parameters which value is reset to its default every run) are only supported in JACK and LV2. +For all other plugin formats DPF will simulate the behaviour through a parameter change request. + +## JACK audio port groups + +DPF will set JACK metadata information for grouping audio ports. +This is not supported by most JACK applications at the moment. + +## JACK parameters and programs + +Under JACK/Stanlone mode, MIDI input events will trigger program and parameter changes. +MIDI program change events work as expected (that is, MIDI program change 0 will load 1st plugin program). +MIDI CCs are used for parameter changes (matching the `midiCC` value you set on each parameter). + +## JACK custom UI only + +There is no generic plugin editor view. +If your plugin has no custom UI, the standalone executable will run but not show any window. + +## LADSPA RDF + +Programs for LADSPA could be done via LRDF but this is not supported in DPF. + +## DSSI State + +DSSI only supports state changes when called via UI, no "full state" possible. +This also makes it impossibe to use programs and state at the same time with DSSI, +because in DPF changing programs can lead to state changes but there is no way to fetch this information on DSSI plugins. + +To make it simpler to understand, think of DSSI programs and states as UI properties. +Because in DPF changing the state happens from UI to DSP side, regular DSSI can be supported. +But if we involve programs, they would need to pass through the UI in order to work. Which goes against DPF's design. + +## LV2 parameter changes + +Although this is already implemented in DPF (through a custom extension), this is not implemented on most hosts. +So for now you can pretty much treat it as if not supported. + +## VST2 deprecated + +Not supported in DPF at the moment. +It could eventually be, but likely not due to VST2 being phased out by Steinberg. +Contact DPF authors if you require such a feature. + +## VST2 programs + +VST2 program support requires saving state of all programs in memory, which is very expensive and thus not done in DPF. + +## VST3 CV + +Although VST3 officially supports CV (Control Voltage) tagged audio ports, +at the moment no host supports such feature and thus it is not possible to validate it. + +## Work in progress + +Feature is possible, just not implemented yet in DPF. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/LICENSE Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,12 @@ +Copyright (C) 2012-2022 Filipe Coelho + +Permission to use, copy, modify, and/or distribute this software for any purpose with +or without fee is hereby granted, provided that the above copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN +NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/LICENSING.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/LICENSING.md Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,44 @@ +# DPF - DISTRHO Plugin Framework + +Even though DPF is quite liberally licensed, not all plugin formats follow the same ideals. +This is usually due to plugin APIs/headers being tied to a specific license or having commercial restrictions. +This file describes the licensing that applies to each individual plugin format as a way to make it clear what is possible and compatible. + +Regardless of target format, DPF itself needs to be mentioned in attribution. +See the [LICENSE](LICENSE) file for copyright details. + +| Target | License(s) | License restrictions | Additional attribution | +|-----------------|----------------------|-----------------------|------------------------| +| JACK/Standalone | MIT (RtAudio) | Copyright attribution | **RtAudio**: 2001-2019 Gary P. Scavone | +| LADSPA | LGPLv2.1+ | ??? (*) | 2000-2002 Richard W. E. Furse, Paul Barton-Davis, Stefan Westerfeld | +| DSSI | LGPLv2.1+ | ??? (*) | **DSSI**: 2004, 2009 Chris Cannam, Steve Harris and Sean Bolton;
**ALSA**: 1998-2001 Jaroslav Kysela, Abramo Bagnara, Takashi Iwai | +| LV2 | ISC | Copyright attribution | 2006-2020 Steve Harris, David Robillard;
2000-2002 Richard W.E. Furse, Paul Barton-Davis, Stefan Westerfeld | +| VST2 | BSD-3 | Copyright attribution | 2020-2022 Michael Fabian 'Xaymar' Dirks | +| VST3 | ISC | Copyright attribution | (none, only DPF files used) | +| CLAP | MIT | Copyright attribution | 2014-2022 Alexandre Bique | + +### LADSPA and DSSI special note + +The header files on LADSPA and DSSI are LGPLv2.1+ licensed, which is unusual for pure APIs without libraries. +LADSPA authors mention this on ladspa.org homepage: + +> LADSPA has been released under LGPL (GNU Lesser General Public License). +> This is not intended to be the final license for LADSPA. +> In the long term it is hoped that LADSPA will have a public license that is even less restrictive, so that commercial applications can use it (in a protected way) without having to use a derived LGPL library. +> It may be that LGPL is already free enough for this, but we aren't sure. + +So the situation for LADSPA/DSSI plugins is unclear for commercial plugins. +These formats are very limited and not much used anymore anyway, feel free to skip them if this situation is a potential issue for you. + +### VST2 special note + +The DPF's VST2 implementation uses https://github.com/Xaymar/vst2sdk which is a liberally-licensed "clean room" untainted reverse engineered "SDK" for the VST2 interface. +Previously "vestige" was used, but was problematic due to it being GPLv2 licensed. +With the Xaymar's work, both open-source and proprietary plugins can be created from the same source, which helps in maintenance on DPF side. + +### VST3 special note + +Contrary to most plugins, DPF does not use the official VST3 SDK. +Instead, the API definitions are provided by the [travesty](distrho/src/travesty/) sub-project, licensed in the same way as DPF. +This allows us to freely build plugins without being encumbered by restrictive licensing deals. +It makes the internal implementation much harder for DPF, but this is not an issue for external developers. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/Makefile.base.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/Makefile.base.mk Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,819 @@ +#!/usr/bin/make -f +# Makefile for DPF # +# ---------------- # +# Created by falkTX +# + +AR ?= ar +CC ?= gcc +CXX ?= g++ + +# Before including this file, a few variables can be set in order to tweak build behaviour: +# DEBUG=true +# NOOPT=true +# SKIP_STRIPPING=true +# NVG_DISABLE_SKIPPING_WHITESPACE=true +# NVG_FONT_TEXTURE_FLAGS=0 +# FILE_BROWSER_DISABLED=true +# WINDOWS_ICON_ID=0 +# USE_GLES2=true +# USE_GLES3=true +# USE_OPENGL3=true +# USE_NANOVG_FBO=true +# USE_NANOVG_FREETYPE=true +# STATIC_BUILD=true +# FORCE_NATIVE_AUDIO_FALLBACK=true +# SKIP_NATIVE_AUDIO_FALLBACK=true + +# --------------------------------------------------------------------------------------------------------------------- +# Protect against multiple inclusion + +ifneq ($(DPF_MAKEFILE_BASE_INCLUDED),true) + +DPF_MAKEFILE_BASE_INCLUDED = true + +# --------------------------------------------------------------------------------------------------------------------- +# Auto-detect target compiler if not defined + +ifneq ($(shell echo -e escaped-by-default | grep -- '-e escaped-by-default'),-e escaped-by-default) +TARGET_COMPILER = $(shell echo -e '#ifdef __clang__\nclang\n#else\ngcc\n#endif' | $(CC) -E -P -x c - 2>/dev/null) +else ifeq ($(shell echo '\#escaped-by-default' | grep -- '\#escaped-by-default'),\#escaped-by-default) +TARGET_COMPILER = $(shell echo '\#ifdef __clang__\nclang\n\#else\ngcc\n\#endif' | $(CC) -E -P -x c - 2>/dev/null) +else +TARGET_COMPILER = $(shell echo '#ifdef __clang__\nclang\n#else\ngcc\n#endif' | $(CC) -E -P -x c - 2>/dev/null) +endif + +ifneq ($(CLANG),true) +ifneq ($(GCC),true) + +ifneq (,$(findstring clang,$(TARGET_COMPILER))) +CLANG = true +else +GCC = true +endif + +endif +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Auto-detect target OS if not defined + +TARGET_MACHINE := $(shell $(CC) -dumpmachine) + +ifneq ($(BSD),true) +ifneq ($(HAIKU),true) +ifneq ($(HURD),true) +ifneq ($(LINUX),true) +ifneq ($(MACOS),true) +ifneq ($(WASM),true) +ifneq ($(WINDOWS),true) + +ifneq (,$(findstring bsd,$(TARGET_MACHINE))) +BSD = true +else ifneq (,$(findstring haiku,$(TARGET_MACHINE))) +HAIKU = true +else ifneq (,$(findstring linux,$(TARGET_MACHINE))) +LINUX = true +else ifneq (,$(findstring gnu,$(TARGET_MACHINE))) +HURD = true +else ifneq (,$(findstring apple,$(TARGET_MACHINE))) +MACOS = true +else ifneq (,$(findstring mingw,$(TARGET_MACHINE))) +WINDOWS = true +else ifneq (,$(findstring msys,$(TARGET_MACHINE))) +WINDOWS = true +else ifneq (,$(findstring wasm,$(TARGET_MACHINE))) +WASM = true +else ifneq (,$(findstring windows,$(TARGET_MACHINE))) +WINDOWS = true +endif + +endif # WINDOWS +endif # WASM +endif # MACOS +endif # LINUX +endif # HURD +endif # HAIKU +endif # BSD + +# --------------------------------------------------------------------------------------------------------------------- +# Auto-detect target processor + +TARGET_PROCESSOR := $(firstword $(subst -, ,$(TARGET_MACHINE))) + +ifneq (,$(filter i%86,$(TARGET_PROCESSOR))) +CPU_I386 = true +CPU_I386_OR_X86_64 = true +endif +ifneq (,$(filter wasm32,$(TARGET_PROCESSOR))) +CPU_I386 = true +CPU_I386_OR_X86_64 = true +endif +ifneq (,$(filter x86_64,$(TARGET_PROCESSOR))) +CPU_X86_64 = true +CPU_I386_OR_X86_64 = true +endif +ifneq (,$(filter arm%,$(TARGET_PROCESSOR))) +CPU_ARM = true +CPU_ARM_OR_ARM64 = true +endif +ifneq (,$(filter arm64%,$(TARGET_PROCESSOR))) +CPU_ARM64 = true +CPU_ARM_OR_ARM64 = true +endif +ifneq (,$(filter aarch64%,$(TARGET_PROCESSOR))) +CPU_ARM64 = true +CPU_ARM_OR_ARM64 = true +endif +ifneq (,$(filter riscv64%,$(TARGET_PROCESSOR))) +CPU_RISCV64 = true +endif + +ifeq ($(CPU_ARM),true) +ifneq ($(CPU_ARM64),true) +CPU_ARM32 = true +endif +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set PKG_CONFIG (can be overridden by environment variable) + +ifeq ($(WASM),true) +# Skip on wasm by default +PKG_CONFIG ?= false +else ifeq ($(WINDOWS),true) +# Build statically on Windows by default +PKG_CONFIG ?= pkg-config --static +else +PKG_CONFIG ?= pkg-config +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set cross compiling flag + +ifeq ($(WASM),true) +CROSS_COMPILING = true +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set LINUX_OR_MACOS + +ifeq ($(LINUX),true) +LINUX_OR_MACOS = true +endif + +ifeq ($(MACOS),true) +LINUX_OR_MACOS = true +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set MACOS_OR_WINDOWS, MACOS_OR_WASM_OR_WINDOWS, HAIKU_OR_MACOS_OR_WINDOWS and HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS + +ifeq ($(HAIKU),true) +HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS = true +HAIKU_OR_MACOS_OR_WINDOWS = true +endif + +ifeq ($(MACOS),true) +HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS = true +HAIKU_OR_MACOS_OR_WINDOWS = true +MACOS_OR_WASM_OR_WINDOWS = true +MACOS_OR_WINDOWS = true +endif + +ifeq ($(WASM),true) +HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS = true +MACOS_OR_WASM_OR_WINDOWS = true +endif + +ifeq ($(WINDOWS),true) +HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS = true +HAIKU_OR_MACOS_OR_WINDOWS = true +MACOS_OR_WASM_OR_WINDOWS = true +MACOS_OR_WINDOWS = true +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set UNIX + +ifeq ($(BSD),true) +UNIX = true +endif + +ifeq ($(HURD),true) +UNIX = true +endif + +ifeq ($(LINUX),true) +UNIX = true +endif + +ifeq ($(MACOS),true) +UNIX = true +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set build and link flags + +BASE_FLAGS = -Wall -Wextra -pipe -MD -MP +BASE_OPTS = -O3 -ffast-math -fdata-sections -ffunction-sections +LINK_OPTS = -fdata-sections -ffunction-sections + +ifeq ($(GCC),true) +BASE_FLAGS += -fno-gnu-unique +endif + +ifeq ($(SKIP_STRIPPING),true) +BASE_FLAGS += -g +endif + +ifeq ($(STATIC_BUILD),true) +BASE_FLAGS += -DSTATIC_BUILD +endif + +ifeq ($(WINDOWS),true) +# Assume we want posix +BASE_FLAGS += -posix -D__STDC_FORMAT_MACROS=1 -D__USE_MINGW_ANSI_STDIO=1 +# Needed for windows, see https://github.com/falkTX/Carla/issues/855 +BASE_FLAGS += -mstackrealign +else +# Not needed for Windows +BASE_FLAGS += -fPIC -DPIC +endif + +ifeq ($(WASM),true) +BASE_OPTS += -msse -msse2 -msse3 -msimd128 +else ifeq ($(CPU_ARM32),true) +BASE_OPTS += -mfpu=neon-vfpv4 -mfloat-abi=hard +else ifeq ($(CPU_I386_OR_X86_64),true) +BASE_OPTS += -mtune=generic -msse -msse2 -mfpmath=sse +endif + +ifeq ($(MACOS),true) +LINK_OPTS += -Wl,-dead_strip,-dead_strip_dylibs +else ifeq ($(WASM),true) +LINK_OPTS += -O3 +LINK_OPTS += -Wl,--gc-sections +else +LINK_OPTS += -Wl,-O1,--as-needed,--gc-sections +endif + +ifneq ($(SKIP_STRIPPING),true) +ifeq ($(MACOS),true) +LINK_OPTS += -Wl,-x +else ifeq ($(WASM),true) +LINK_OPTS += -sAGGRESSIVE_VARIABLE_ELIMINATION=1 +else +LINK_OPTS += -Wl,--strip-all +endif +endif + +ifeq ($(NOOPT),true) +# Non-CPU-specific optimization flags +BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections +endif + +ifeq ($(DEBUG),true) +BASE_FLAGS += -DDEBUG -O0 -g +ifneq ($(HAIKU),true) +BASE_FLAGS += -fsanitize=address +endif +LINK_OPTS = +ifeq ($(WASM),true) +LINK_OPTS += -sASSERTIONS=1 +endif +else +BASE_FLAGS += -DNDEBUG $(BASE_OPTS) -fvisibility=hidden +CXXFLAGS += -fvisibility-inlines-hidden +endif + +ifeq ($(WITH_LTO),true) +BASE_FLAGS += -fno-strict-aliasing -flto +LINK_OPTS += -fno-strict-aliasing -flto -Werror=odr +ifeq ($(GCC),true) +LINK_OPTS += -Werror=lto-type-mismatch +endif +endif + +BUILD_C_FLAGS = $(BASE_FLAGS) -std=gnu99 $(CFLAGS) +BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++11 $(CXXFLAGS) +LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS) + +ifeq ($(WASM),true) +# Special flag for emscripten +LINK_FLAGS += -sENVIRONMENT=web -sLLD_REPORT_UNDEFINED +else ifneq ($(MACOS),true) +# Not available on MacOS +LINK_FLAGS += -Wl,--no-undefined +endif + +ifeq ($(MACOS_OLD),true) +BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0 +endif + +ifeq ($(WASM_CLIPBOARD),true) +BUILD_CXX_FLAGS += -DPUGL_WASM_ASYNC_CLIPBOARD +LINK_FLAGS += -sASYNCIFY -sASYNCIFY_IMPORTS=puglGetAsyncClipboardData +endif + +ifeq ($(WASM_EXCEPTIONS),true) +BUILD_CXX_FLAGS += -fexceptions +LINK_FLAGS += -fexceptions +endif + +ifeq ($(WINDOWS),true) +# Always build statically on windows +LINK_FLAGS += -static -static-libgcc -static-libstdc++ +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Strict test build + +ifeq ($(TESTBUILD),true) +BASE_FLAGS += -Werror -Wcast-qual -Wconversion -Wformat -Wformat-security -Wredundant-decls -Wshadow -Wstrict-overflow -fstrict-overflow -Wundef -Wwrite-strings +BASE_FLAGS += -Wpointer-arith -Wabi=98 -Winit-self -Wuninitialized -Wstrict-overflow=5 +# BASE_FLAGS += -Wfloat-equal +ifeq ($(CLANG),true) +BASE_FLAGS += -Wdocumentation -Wdocumentation-unknown-command +BASE_FLAGS += -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-exit-time-destructors -Wno-float-equal +else +BASE_FLAGS += -Wcast-align -Wunsafe-loop-optimizations +endif +ifneq ($(MACOS),true) +BASE_FLAGS += -Wmissing-declarations -Wsign-conversion +ifeq ($(GCC),true) +BASE_FLAGS += -Wlogical-op +endif +endif +CFLAGS += -Wold-style-definition -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes +CXXFLAGS += -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Check for required libraries + +ifneq ($(HAIKU)$(WASM),true) +HAVE_CAIRO = $(shell $(PKG_CONFIG) --exists cairo && echo true) +endif + +ifeq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) +HAVE_OPENGL = true +else +HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true) +HAVE_DBUS = $(shell $(PKG_CONFIG) --exists dbus-1 && echo true) +HAVE_X11 = $(shell $(PKG_CONFIG) --exists x11 && echo true) +HAVE_XCURSOR = $(shell $(PKG_CONFIG) --exists xcursor && echo true) +HAVE_XEXT = $(shell $(PKG_CONFIG) --exists xext && echo true) +HAVE_XRANDR = $(shell $(PKG_CONFIG) --exists xrandr && echo true) +endif + +# Vulkan is not supported yet +# HAVE_VULKAN = $(shell $(PKG_CONFIG) --exists vulkan && echo true) + +# --------------------------------------------------------------------------------------------------------------------- +# Check for optional libraries + +HAVE_LIBLO = $(shell $(PKG_CONFIG) --exists liblo && echo true) + +ifneq ($(SKIP_NATIVE_AUDIO_FALLBACK),true) +ifneq ($(SKIP_RTAUDIO_FALLBACK),true) + +ifeq ($(MACOS),true) +HAVE_RTAUDIO = true +else ifeq ($(WINDOWS),true) +HAVE_RTAUDIO = true +else +HAVE_ALSA = $(shell $(PKG_CONFIG) --exists alsa && echo true) +HAVE_PULSEAUDIO = $(shell $(PKG_CONFIG) --exists libpulse-simple && echo true) +HAVE_SDL2 = $(shell $(PKG_CONFIG) --exists sdl2 && echo true) +ifeq ($(HAVE_ALSA),true) +HAVE_RTAUDIO = true +else ifeq ($(HAVE_PULSEAUDIO),true) +HAVE_RTAUDIO = true +endif +endif + +endif +endif + +# backwards compat, always available/enabled +ifneq ($(FORCE_NATIVE_AUDIO_FALLBACK),true) +ifeq ($(STATIC_BUILD),true) +HAVE_JACK = $(shell $(PKG_CONFIG) --exists jack && echo true) +else +HAVE_JACK = true +endif +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set Generic DGL stuff + +ifeq ($(HAIKU),true) + +DGL_SYSTEM_LIBS += -lbe + +else ifeq ($(MACOS),true) + +DGL_SYSTEM_LIBS += -framework Cocoa +DGL_SYSTEM_LIBS += -framework CoreVideo + +else ifeq ($(WASM),true) + +# wasm builds cannot work using regular desktop OpenGL +ifeq (,$(USE_GLES2)$(USE_GLES3)) +USE_GLES2 = true +endif + +else ifeq ($(WINDOWS),true) + +DGL_SYSTEM_LIBS += -lcomdlg32 +DGL_SYSTEM_LIBS += -lgdi32 +# DGL_SYSTEM_LIBS += -lole32 + +else + +ifeq ($(HAVE_DBUS),true) +DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags dbus-1) -DHAVE_DBUS +DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs dbus-1) +endif + +ifeq ($(HAVE_X11),true) +DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11) -DHAVE_X11 +DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11) +ifeq ($(HAVE_XCURSOR),true) +DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xcursor) -DHAVE_XCURSOR +DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs xcursor) +endif +ifeq ($(HAVE_XEXT),true) +DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xext) -DHAVE_XEXT -DHAVE_XSYNC +DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs xext) +endif +ifeq ($(HAVE_XRANDR),true) +DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags xrandr) -DHAVE_XRANDR +DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs xrandr) +endif +endif # HAVE_X11 + +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set Cairo specific stuff + +ifeq ($(HAVE_CAIRO),true) + +DGL_FLAGS += -DHAVE_CAIRO + +CAIRO_FLAGS = $(shell $(PKG_CONFIG) --cflags cairo) +CAIRO_LIBS = $(shell $(PKG_CONFIG) --libs cairo) + +HAVE_CAIRO_OR_OPENGL = true + +endif # HAVE_CAIRO + +# --------------------------------------------------------------------------------------------------------------------- +# Set OpenGL specific stuff + +ifeq ($(HAVE_OPENGL),true) + +DGL_FLAGS += -DHAVE_OPENGL + +ifeq ($(HAIKU),true) +OPENGL_FLAGS = +OPENGL_LIBS = -lGL +else ifeq ($(MACOS),true) +OPENGL_FLAGS = -DGL_SILENCE_DEPRECATION=1 -Wno-deprecated-declarations +OPENGL_LIBS = -framework OpenGL +else ifeq ($(WASM),true) +ifeq ($(USE_GLES2),true) +OPENGL_LIBS = -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 +else +ifneq ($(USE_GLES3),true) +OPENGL_LIBS = -sLEGACY_GL_EMULATION -sGL_UNSAFE_OPTS=0 +endif +endif +else ifeq ($(WINDOWS),true) +OPENGL_LIBS = -lopengl32 +else +OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl x11) +OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl x11) +endif + +HAVE_CAIRO_OR_OPENGL = true + +endif # HAVE_OPENGL + +# --------------------------------------------------------------------------------------------------------------------- +# Set Stub specific stuff + +ifeq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) +HAVE_STUB = true +else +HAVE_STUB = $(HAVE_X11) +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set Vulkan specific stuff + +ifeq ($(HAVE_VULKAN),true) + +DGL_FLAGS += -DHAVE_VULKAN + +VULKAN_FLAGS = $(shell $(PKG_CONFIG) --cflags vulkan) +VULKAN_LIBS = $(shell $(PKG_CONFIG) --libs vulkan) + +ifneq ($(WINDOWS),true) +VULKAN_LIBS += -ldl +endif + +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set optional libraries specific stuff + +ifeq ($(HAVE_ALSA),true) +ALSA_FLAGS = $(shell $(PKG_CONFIG) --cflags alsa) +ALSA_LIBS = $(shell $(PKG_CONFIG) --libs alsa) +endif + +ifeq ($(HAVE_LIBLO),true) +LIBLO_FLAGS = $(shell $(PKG_CONFIG) --cflags liblo) +LIBLO_LIBS = $(shell $(PKG_CONFIG) --libs liblo) +endif + +ifeq ($(HAVE_PULSEAUDIO),true) +PULSEAUDIO_FLAGS = $(shell $(PKG_CONFIG) --cflags libpulse-simple) +PULSEAUDIO_LIBS = $(shell $(PKG_CONFIG) --libs libpulse-simple) +endif + +ifeq ($(HAVE_SDL2),true) +SDL2_FLAGS = $(shell $(PKG_CONFIG) --cflags sdl2) +SDL2_LIBS = $(shell $(PKG_CONFIG) --libs sdl2) +endif + +ifeq ($(HAVE_JACK),true) +ifeq ($(STATIC_BUILD),true) +JACK_FLAGS = $(shell $(PKG_CONFIG) --cflags jack) +JACK_LIBS = $(shell $(PKG_CONFIG) --libs jack) +endif +endif + +ifneq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) +SHARED_MEMORY_LIBS = -lrt +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Backwards-compatible HAVE_DGL + +ifeq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) +HAVE_DGL = true +else ifeq ($(HAVE_OPENGL),true) +HAVE_DGL = $(HAVE_X11) +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Namespace flags + +ifneq ($(DISTRHO_NAMESPACE),) +BUILD_CXX_FLAGS += -DDISTRHO_NAMESPACE=$(DISTRHO_NAMESPACE) +endif + +ifneq ($(DGL_NAMESPACE),) +BUILD_CXX_FLAGS += -DDGL_NAMESPACE=$(DGL_NAMESPACE) +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Optional flags + +ifeq ($(NVG_DISABLE_SKIPPING_WHITESPACE),true) +BUILD_CXX_FLAGS += -DNVG_DISABLE_SKIPPING_WHITESPACE +endif + +ifneq ($(NVG_FONT_TEXTURE_FLAGS),) +BUILD_CXX_FLAGS += -DNVG_FONT_TEXTURE_FLAGS=$(NVG_FONT_TEXTURE_FLAGS) +endif + +ifeq ($(FILE_BROWSER_DISABLED),true) +BUILD_CXX_FLAGS += -DDGL_FILE_BROWSER_DISABLED +endif + +ifneq ($(WINDOWS_ICON_ID),) +BUILD_CXX_FLAGS += -DDGL_WINDOWS_ICON_ID=$(WINDOWS_ICON_ID) +endif + +ifeq ($(USE_GLES2),true) +BUILD_CXX_FLAGS += -DDGL_USE_OPENGL3 -DDGL_USE_GLES -DDGL_USE_GLES2 +endif + +ifeq ($(USE_GLES3),true) +BUILD_CXX_FLAGS += -DDGL_USE_OPENGL3 -DDGL_USE_GLES -DDGL_USE_GLES3 +endif + +ifeq ($(USE_OPENGL3),true) +BUILD_CXX_FLAGS += -DDGL_USE_OPENGL3 +endif + +ifeq ($(USE_NANOVG_FBO),true) +BUILD_CXX_FLAGS += -DDGL_USE_NANOVG_FBO +endif + +ifeq ($(USE_NANOVG_FREETYPE),true) +BUILD_CXX_FLAGS += -DFONS_USE_FREETYPE $(shell $(PKG_CONFIG) --cflags freetype2) +endif + +ifeq ($(USE_RGBA),true) +BUILD_CXX_FLAGS += -DDGL_USE_RGBA +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set app extension + +ifeq ($(WASM),true) +APP_EXT = .html +else ifeq ($(WINDOWS),true) +APP_EXT = .exe +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set shared lib extension + +ifeq ($(MACOS),true) +LIB_EXT = .dylib +else ifeq ($(WASM),true) +LIB_EXT = .wasm +else ifeq ($(WINDOWS),true) +LIB_EXT = .dll +else +LIB_EXT = .so +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set shared library CLI arg + +ifeq ($(MACOS),true) +SHARED = -dynamiclib +else ifeq ($(WASM),true) +SHARED = -sSIDE_MODULE=2 +else +SHARED = -shared +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set CLAP binary directory + +ifeq ($(MACOS),true) +CLAP_BINARY_DIR = Contents/MacOS +else +CLAP_BINARY_DIR = +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set VST2 binary directory + +ifeq ($(MACOS),true) +VST2_BINARY_DIR = Contents/MacOS +else +VST2_BINARY_DIR = +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set VST3 binary directory, see https://vst3sdk-doc.diatonic.jp/doc/vstinterfaces/vst3loc.html + +ifeq ($(LINUX),true) +VST3_BINARY_DIR = Contents/$(TARGET_PROCESSOR)-linux +else ifeq ($(MACOS),true) +VST3_BINARY_DIR = Contents/MacOS +else ifeq ($(WASM),true) +VST3_BINARY_DIR = Contents/wasm +else ifeq ($(WINDOWS)$(CPU_I386),truetrue) +VST3_BINARY_DIR = Contents/x86-win +else ifeq ($(WINDOWS)$(CPU_X86_64),truetrue) +VST3_BINARY_DIR = Contents/x86_64-win +else +VST3_BINARY_DIR = +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Handle the verbosity switch + +SILENT = + +ifeq ($(VERBOSE),1) +else ifeq ($(VERBOSE),y) +else ifeq ($(VERBOSE),yes) +else ifeq ($(VERBOSE),true) +else +SILENT = @ +endif + +# --------------------------------------------------------------------------------------------------------------------- +# all needs to be first + +all: + +# --------------------------------------------------------------------------------------------------------------------- +# helper to print what is available/possible to build + +print_available = @echo $(1): $(shell echo $($(1)) | grep -q true && echo Yes || echo No) + +features: + @echo === Detected Compiler + $(call print_available,CLANG) + $(call print_available,GCC) + @echo === Detected CPU + $(call print_available,CPU_ARM) + $(call print_available,CPU_ARM32) + $(call print_available,CPU_ARM64) + $(call print_available,CPU_ARM_OR_ARM64) + $(call print_available,CPU_I386) + $(call print_available,CPU_I386_OR_X86_64) + $(call print_available,CPU_RISCV64) + $(call print_available,CPU_X86_64) + @echo === Detected OS + $(call print_available,BSD) + $(call print_available,HAIKU) + $(call print_available,HURD) + $(call print_available,LINUX) + $(call print_available,MACOS) + $(call print_available,WASM) + $(call print_available,WINDOWS) + $(call print_available,HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS) + $(call print_available,HAIKU_OR_MACOS_OR_WINDOWS) + $(call print_available,LINUX_OR_MACOS) + $(call print_available,MACOS_OR_WASM_OR_WINDOWS) + $(call print_available,MACOS_OR_WINDOWS) + $(call print_available,UNIX) + @echo === Detected features + $(call print_available,HAVE_ALSA) + $(call print_available,HAVE_DBUS) + $(call print_available,HAVE_CAIRO) + $(call print_available,HAVE_DGL) + $(call print_available,HAVE_JACK) + $(call print_available,HAVE_LIBLO) + $(call print_available,HAVE_OPENGL) + $(call print_available,HAVE_PULSEAUDIO) + $(call print_available,HAVE_RTAUDIO) + $(call print_available,HAVE_SDL2) + $(call print_available,HAVE_STUB) + $(call print_available,HAVE_VULKAN) + $(call print_available,HAVE_X11) + $(call print_available,HAVE_XCURSOR) + $(call print_available,HAVE_XEXT) + $(call print_available,HAVE_XRANDR) + +# --------------------------------------------------------------------------------------------------------------------- +# Extra rules for MOD Audio stuff + +# NOTE: path must be absolute +MOD_WORKDIR ?= $(HOME)/mod-workdir +MOD_ENVIRONMENT = \ + AR=${1}/host/usr/bin/${2}-gcc-ar \ + CC=${1}/host/usr/bin/${2}-gcc \ + CPP=${1}/host/usr/bin/${2}-cpp \ + CXX=${1}/host/usr/bin/${2}-g++ \ + LD=${1}/host/usr/bin/${2}-ld \ + PKG_CONFIG=${1}/host/usr/bin/pkg-config \ + PKG_CONFIG_PATH="${1}/staging/usr/lib/pkgconfig" \ + STRIP=${1}/host/usr/bin/${2}-strip \ + CFLAGS="-I${1}/staging/usr/include $(EXTRA_MOD_FLAGS)" \ + CPPFLAGS= \ + CXXFLAGS="-I${1}/staging/usr/include $(EXTRA_MOD_FLAGS)" \ + LDFLAGS="-L${1}/staging/usr/lib $(EXTRA_MOD_FLAGS)" \ + EXE_WRAPPER="qemu-${3}-static -L ${1}/target" \ + HAVE_CAIRO=false \ + HAVE_OPENGL=false \ + MOD_BUILD=true \ + NOOPT=true + +modduo: + $(MAKE) $(call MOD_ENVIRONMENT,$(MOD_WORKDIR)/modduo-static,arm-mod-linux-gnueabihf.static,arm) + +modduox: + $(MAKE) $(call MOD_ENVIRONMENT,$(MOD_WORKDIR)/modduox-static,aarch64-mod-linux-gnueabi.static,aarch64) + +moddwarf: + $(MAKE) $(call MOD_ENVIRONMENT,$(MOD_WORKDIR)/moddwarf,aarch64-mod-linux-gnu,aarch64) + +modpush: + tar -C bin -cz $(subst bin/,,$(wildcard bin/*.lv2)) | base64 | curl -F 'package=@-' http://192.168.51.1/sdk/install && echo + +ifneq (,$(findstring modduo-,$(MAKECMDGOALS))) +$(MAKECMDGOALS): + $(MAKE) $(call MOD_ENVIRONMENT,$(MOD_WORKDIR)/modduo-static,arm-mod-linux-gnueabihf.static,arm) $(subst modduo-,,$(MAKECMDGOALS)) +endif + +ifneq (,$(findstring modduox-,$(MAKECMDGOALS))) +$(MAKECMDGOALS): + $(MAKE) $(call MOD_ENVIRONMENT,$(MOD_WORKDIR)/modduox-static,aarch64-mod-linux-gnueabi.static,aarch64) $(subst modduox-,,$(MAKECMDGOALS)) +endif + +ifneq (,$(findstring moddwarf-,$(MAKECMDGOALS))) +$(MAKECMDGOALS): + $(MAKE) $(call MOD_ENVIRONMENT,$(MOD_WORKDIR)/moddwarf,aarch64-mod-linux-gnu,aarch64) $(subst moddwarf-,,$(MAKECMDGOALS)) +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Protect against multiple inclusion + +endif # DPF_MAKEFILE_BASE_INCLUDED + +# --------------------------------------------------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/Makefile.plugins.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/Makefile.plugins.mk Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,756 @@ +#!/usr/bin/make -f +# Makefile for DPF Example Plugins # +# -------------------------------- # +# Created by falkTX +# + +# NOTE: NAME, FILES_DSP and FILES_UI must have been defined before including this file! + +ifeq ($(DPF_PATH),) +ifneq (,$(wildcard dpf/Makefile.base.mk)) +BASE_PATH=. +DPF_PATH=dpf +else ifneq (,$(wildcard ../dpf/Makefile.base.mk)) +BASE_PATH=.. +DPF_PATH=../dpf +else ifneq (,$(wildcard ../../dpf/Makefile.base.mk)) +BASE_PATH=../.. +DPF_PATH=../../dpf +else +BASE_PATH=../.. +DPF_PATH=../.. +endif +endif + +include $(DPF_PATH)/Makefile.base.mk + +# --------------------------------------------------------------------------------------------------------------------- +# Basic setup + +ifeq ($(MODGUI_BUILD),true) +BUILD_DIR_SUFFIX = -modgui +endif + +ifneq ($(DPF_BUILD_DIR),) +BUILD_DIR = $(DPF_BUILD_DIR)$(BUILD_DIR_SUFFIX) +else +BUILD_DIR = $(BASE_PATH)/build$(BUILD_DIR_SUFFIX)/$(NAME) +endif + +ifneq ($(DPF_TARGET_DIR),) +TARGET_DIR = $(DPF_TARGET_DIR) +else +TARGET_DIR = $(BASE_PATH)/bin +endif + +DGL_BUILD_DIR = $(DPF_PATH)/build$(BUILD_DIR_SUFFIX) + +BUILD_C_FLAGS += -I. +BUILD_CXX_FLAGS += -I. -I$(DPF_PATH)/distrho -I$(DPF_PATH)/dgl + +ifeq ($(HAVE_ALSA),true) +BASE_FLAGS += -DHAVE_ALSA +endif + +ifeq ($(HAVE_JACK),true) +BASE_FLAGS += -DHAVE_JACK +endif + +ifeq ($(HAVE_LIBLO),true) +BASE_FLAGS += -DHAVE_LIBLO +endif + +ifeq ($(HAVE_PULSEAUDIO),true) +BASE_FLAGS += -DHAVE_PULSEAUDIO +endif + +ifeq ($(HAVE_RTAUDIO),true) +BASE_FLAGS += -DHAVE_RTAUDIO +endif + +ifeq ($(HAVE_SDL2),true) +BASE_FLAGS += -DHAVE_SDL2 +endif + +ifneq ($(MODGUI_CLASS_NAME),) +BASE_FLAGS += -DDISTRHO_PLUGIN_MODGUI_CLASS_NAME='"$(MODGUI_CLASS_NAME)"' +endif + +# always needed +ifneq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) +ifneq ($(STATIC_BUILD),true) +LINK_FLAGS += -ldl +endif +endif + +# --------------------------------------------------------------------------------------------------------------------- +# JACK/Standalone setup + +ifeq ($(WASM),true) + +JACK_FLAGS += -sUSE_SDL=2 +JACK_LIBS += -sUSE_SDL=2 +JACK_LIBS += -sMAIN_MODULE -ldl + +ifneq ($(FILE_BROWSER_DISABLED),true) +JACK_LIBS += -sEXPORTED_RUNTIME_METHODS=FS,cwrap +endif + +else ifneq ($(SKIP_RTAUDIO_FALLBACK),true) + +JACK_FLAGS += -DHAVE_GETTIMEOFDAY + +ifeq ($(MACOS),true) +JACK_LIBS += -framework CoreAudio -framework CoreFoundation -framework CoreMIDI +else ifeq ($(WINDOWS),true) +JACK_LIBS += -lole32 -lwinmm +# DirectSound +# JACK_LIBS += -ldsound +# WASAPI +JACK_LIBS += -lksuser -lmfplat -lmfuuid -lwmcodecdspuuid +else +ifeq ($(HAVE_PULSEAUDIO),true) +JACK_FLAGS += $(PULSEAUDIO_FLAGS) +JACK_LIBS += $(PULSEAUDIO_LIBS) +endif +ifeq ($(HAVE_ALSA),true) +JACK_FLAGS += $(ALSA_FLAGS) +JACK_LIBS += $(ALSA_LIBS) +endif +endif + +ifeq ($(HAVE_RTAUDIO),true) +ifneq ($(HAIKU),true) +JACK_LIBS += -lpthread +endif +endif + +ifeq ($(HAVE_SDL2),true) +JACK_FLAGS += $(SDL2_FLAGS) +JACK_LIBS += $(SDL2_LIBS) +endif + +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set files to build + +OBJS_DSP = $(FILES_DSP:%=$(BUILD_DIR)/%.o) +OBJS_UI = $(FILES_UI:%=$(BUILD_DIR)/%.o) + +ifeq ($(MACOS),true) +OBJS_UI += $(BUILD_DIR)/DistrhoUI_macOS_$(NAME).mm.o +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Handle UI stuff, disable UI support automatically + +ifeq ($(FILES_UI),) +HAVE_DGL = false +UI_TYPE = none +endif + +ifeq ($(UI_TYPE),) +UI_TYPE = opengl +endif + +ifeq ($(UI_TYPE),generic) +ifeq ($(HAVE_OPENGL),true) +UI_TYPE = opengl +else ifeq ($(HAVE_CAIRO),true) +UI_TYPE = cairo +endif +endif + +ifeq ($(UI_TYPE),cairo) +ifeq ($(HAVE_CAIRO),true) +DGL_FLAGS += -DDGL_CAIRO -DHAVE_DGL +DGL_FLAGS += $(CAIRO_FLAGS) +DGL_LIBS += $(CAIRO_LIBS) +DGL_LIB = $(DGL_BUILD_DIR)/libdgl-cairo.a +HAVE_DGL = true +else +HAVE_DGL = false +endif +endif + +ifeq ($(UI_TYPE),opengl) +ifeq ($(HAVE_OPENGL),true) +DGL_FLAGS += -DDGL_OPENGL -DHAVE_DGL +DGL_FLAGS += $(OPENGL_FLAGS) +DGL_LIBS += $(OPENGL_LIBS) +DGL_LIB = $(DGL_BUILD_DIR)/libdgl-opengl.a +HAVE_DGL = true +else +HAVE_DGL = false +endif +endif + +ifeq ($(UI_TYPE),opengl3) +ifeq ($(HAVE_OPENGL),true) +DGL_FLAGS += -DDGL_OPENGL -DDGL_USE_OPENGL3 -DHAVE_DGL +DGL_FLAGS += $(OPENGL_FLAGS) +DGL_LIBS += $(OPENGL_LIBS) +DGL_LIB = $(DGL_BUILD_DIR)/libdgl-opengl3.a +HAVE_DGL = true +else +HAVE_DGL = false +endif +endif + +ifeq ($(UI_TYPE),vulkan) +ifeq ($(HAVE_VULKAN),true) +DGL_FLAGS += -DDGL_VULKAN -DHAVE_DGL +DGL_FLAGS += $(VULKAN_FLAGS) +DGL_LIBS += $(VULKAN_LIBS) +DGL_LIB = $(DGL_BUILD_DIR)/libdgl-vulkan.a +HAVE_DGL = true +else +HAVE_DGL = false +endif +endif + +ifeq ($(UI_TYPE),external) +DGL_FLAGS += -DDGL_EXTERNAL +HAVE_DGL = true +endif + +ifeq ($(UI_TYPE),stub) +ifeq ($(HAVE_STUB),true) +DGL_LIB = $(DGL_BUILD_DIR)/libdgl-stub.a +HAVE_DGL = true +else +HAVE_DGL = false +endif +endif + +DGL_LIBS += $(DGL_SYSTEM_LIBS) -lm + +# TODO split dsp and ui object build flags +BASE_FLAGS += $(DGL_FLAGS) + +# --------------------------------------------------------------------------------------------------------------------- +# Set CLAP filename, either single binary or inside a bundle + +ifeq ($(MACOS),true) +CLAP_FILENAME = $(NAME).clap/$(CLAP_BINARY_DIR)/$(NAME) +else ifeq ($(USE_CLAP_BUNDLE),true) +CLAP_FILENAME = $(NAME).clap/$(NAME).clap +else +CLAP_FILENAME = $(NAME).clap +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set VST2 filename, either single binary or inside a bundle + +ifeq ($(MACOS),true) +VST2_FILENAME = $(NAME).vst/$(VST2_BINARY_DIR)/$(NAME) +else ifeq ($(USE_VST2_BUNDLE),true) +VST2_FILENAME = $(NAME).vst/$(NAME)$(LIB_EXT) +else +VST2_FILENAME = $(NAME)-vst$(LIB_EXT) +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set VST3 filename, see https://vst3sdk-doc.diatonic.jp/doc/vstinterfaces/vst3loc.html + +ifeq ($(LINUX),true) +VST3_FILENAME = $(NAME).vst3/$(VST3_BINARY_DIR)/$(NAME)$(LIB_EXT) +else ifeq ($(MACOS),true) +VST3_FILENAME = $(NAME).vst3/$(VST3_BINARY_DIR)/$(NAME) +else ifneq ($(VST3_BINARY_DIR),) +VST3_FILENAME = $(NAME).vst3/$(VST3_BINARY_DIR)/$(NAME).vst3 +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set plugin binary file targets + +ifeq ($(MACOS)$(HAVE_DGL),truetrue) +MACOS_APP_BUNDLE = true +endif + +ifeq ($(WINDOWS)$(HAVE_DGL),truetrue) +JACK_LIBS += -Wl,-subsystem,windows +endif + +ifeq ($(MACOS_APP_BUNDLE),true) +jack = $(TARGET_DIR)/$(NAME).app/Contents/MacOS/$(NAME) +jackfiles = $(TARGET_DIR)/$(NAME).app/Contents/Info.plist +else +jack = $(TARGET_DIR)/$(NAME)$(APP_EXT) +endif + +ladspa_dsp = $(TARGET_DIR)/$(NAME)-ladspa$(LIB_EXT) +dssi_dsp = $(TARGET_DIR)/$(NAME)-dssi$(LIB_EXT) +dssi_ui = $(TARGET_DIR)/$(NAME)-dssi/$(NAME)_ui$(APP_EXT) +lv2 = $(TARGET_DIR)/$(NAME).lv2/$(NAME)$(LIB_EXT) +lv2_dsp = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_dsp$(LIB_EXT) +lv2_ui = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_ui$(LIB_EXT) +vst2 = $(TARGET_DIR)/$(VST2_FILENAME) +ifneq ($(VST3_FILENAME),) +vst3 = $(TARGET_DIR)/$(VST3_FILENAME) +endif +clap = $(TARGET_DIR)/$(CLAP_FILENAME) +shared = $(TARGET_DIR)/$(NAME)$(LIB_EXT) +static = $(TARGET_DIR)/$(NAME).a + +ifeq ($(MACOS),true) +BUNDLE_RESOURCES = Info.plist PkgInfo Resources/empty.lproj +vst2files += $(BUNDLE_RESOURCES=%:$(TARGET_DIR)/$(NAME).vst/Contents/%) +vst3files += $(BUNDLE_RESOURCES=%:$(TARGET_DIR)/$(NAME).vst3/Contents/%) +clapfiles += $(BUNDLE_RESOURCES=%:$(TARGET_DIR)/$(NAME).clap/Contents/%) +endif + +ifneq ($(HAVE_DGL),true) +dssi_ui = +lv2_ui = +DGL_LIBS = +OBJS_UI = +endif + +ifneq ($(HAVE_LIBLO),true) +dssi_ui = +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Set plugin symbols to export + +ifeq ($(MACOS),true) +SYMBOLS_LADSPA = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/ladspa.exp +SYMBOLS_DSSI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/dssi.exp +SYMBOLS_LV2DSP = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2-dsp.exp +SYMBOLS_LV2UI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2-ui.exp +SYMBOLS_LV2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2.exp +SYMBOLS_VST2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst2.exp +SYMBOLS_VST3 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst3.exp +SYMBOLS_CLAP = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/clap.exp +SYMBOLS_SHARED = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/shared.exp +else ifeq ($(WASM),true) +SYMBOLS_LADSPA = -sEXPORTED_FUNCTIONS="['ladspa_descriptor']" +SYMBOLS_DSSI = -sEXPORTED_FUNCTIONS="['ladspa_descriptor','dssi_descriptor']" +SYMBOLS_LV2DSP = -sEXPORTED_FUNCTIONS="['lv2_descriptor','lv2_generate_ttl']" +SYMBOLS_LV2UI = -sEXPORTED_FUNCTIONS="['lv2ui_descriptor']" +SYMBOLS_LV2 = -sEXPORTED_FUNCTIONS="['lv2_descriptor','lv2_generate_ttl','lv2ui_descriptor']" +SYMBOLS_VST2 = -sEXPORTED_FUNCTIONS="['VSTPluginMain']" +SYMBOLS_VST3 = -sEXPORTED_FUNCTIONS="['GetPluginFactory','ModuleEntry','ModuleExit']" +SYMBOLS_CLAP = -sEXPORTED_FUNCTIONS="['clap_entry']" +SYMBOLS_SHARED = -sEXPORTED_FUNCTIONS="['createSharedPlugin']" +else ifeq ($(WINDOWS),true) +SYMBOLS_LADSPA = $(DPF_PATH)/utils/symbols/ladspa.def +SYMBOLS_DSSI = $(DPF_PATH)/utils/symbols/dssi.def +SYMBOLS_LV2DSP = $(DPF_PATH)/utils/symbols/lv2-dsp.def +SYMBOLS_LV2UI = $(DPF_PATH)/utils/symbols/lv2-ui.def +SYMBOLS_LV2 = $(DPF_PATH)/utils/symbols/lv2.def +SYMBOLS_VST2 = $(DPF_PATH)/utils/symbols/vst2.def +SYMBOLS_VST3 = $(DPF_PATH)/utils/symbols/vst3.def +SYMBOLS_CLAP = $(DPF_PATH)/utils/symbols/clap.def +SYMBOLS_SHARED = $(DPF_PATH)/utils/symbols/shared.def +else ifneq ($(DEBUG),true) +SYMBOLS_LADSPA = -Wl,--version-script=$(DPF_PATH)/utils/symbols/ladspa.version +SYMBOLS_DSSI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/dssi.version +SYMBOLS_LV2DSP = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2-dsp.version +SYMBOLS_LV2UI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2-ui.version +SYMBOLS_LV2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2.version +SYMBOLS_VST2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst2.version +SYMBOLS_VST3 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst3.version +SYMBOLS_CLAP = -Wl,--version-script=$(DPF_PATH)/utils/symbols/clap.version +SYMBOLS_SHARED = -Wl,--version-script=$(DPF_PATH)/utils/symbols/shared.version +endif + +# --------------------------------------------------------------------------------------------------------------------- +# Runtime test build + +ifeq ($(DPF_RUNTIME_TESTING),true) +BUILD_CXX_FLAGS += -DDPF_RUNTIME_TESTING -Wno-pmf-conversions +endif + +# --------------------------------------------------------------------------------------------------------------------- +# all needs to be first + +all: + +# --------------------------------------------------------------------------------------------------------------------- +# Common + +$(BUILD_DIR)/%.S.o: %.S + -@mkdir -p "$(shell dirname $@)" + @echo "Compiling $<" + @$(CC) $< $(BUILD_C_FLAGS) -c -o $@ + +$(BUILD_DIR)/%.c.o: %.c + -@mkdir -p "$(shell dirname $@)" + @echo "Compiling $<" + $(SILENT)$(CC) $< $(BUILD_C_FLAGS) -c -o $@ + +$(BUILD_DIR)/%.cc.o: %.cc + -@mkdir -p "$(shell dirname $@)" + @echo "Compiling $<" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ + +$(BUILD_DIR)/%.cpp.o: %.cpp + -@mkdir -p "$(shell dirname $@)" + @echo "Compiling $<" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ + +$(BUILD_DIR)/%.m.o: %.m + -@mkdir -p "$(shell dirname $@)" + @echo "Compiling $<" + $(SILENT)$(CC) $< $(BUILD_C_FLAGS) -ObjC -c -o $@ + +$(BUILD_DIR)/%.mm.o: %.mm + -@mkdir -p "$(shell dirname $@)" + @echo "Compiling $<" + $(SILENT)$(CC) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ + +clean: + rm -rf $(BUILD_DIR) +ifeq ($(DPF_BUILD_DIR),) + rm -rf $(BASE_PATH)/build-modgui/$(NAME) + rm -rf $(DPF_PATH)/build-modgui +endif + rm -rf $(TARGET_DIR)/$(NAME) + rm -rf $(TARGET_DIR)/$(NAME)-* + rm -rf $(TARGET_DIR)/$(NAME).lv2 + rm -rf $(TARGET_DIR)/$(NAME).vst + rm -rf $(TARGET_DIR)/$(NAME).vst3 + rm -rf $(TARGET_DIR)/$(NAME).clap + +# --------------------------------------------------------------------------------------------------------------------- +# DGL + +DGL_POSSIBLE_DEPS = \ + $(DPF_PATH)/dgl/*.* \ + $(DPF_PATH)/dgl/src/*.* \ + $(DPF_PATH)/dgl/src/nanovg/*.* \ + $(DPF_PATH)/dgl/src/pugl-extra/*.* \ + $(DPF_PATH)/dgl/src/pugl-upstream/include/pugl/*.* \ + $(DPF_PATH)/dgl/src/pugl-upstream/src/*.* + +$(DGL_BUILD_DIR)/libdgl-cairo.a: $(DGL_POSSIBLE_DEPS) + $(MAKE) -C $(DPF_PATH)/dgl cairo + +$(DGL_BUILD_DIR)/libdgl-opengl.a: $(DGL_POSSIBLE_DEPS) + $(MAKE) -C $(DPF_PATH)/dgl opengl + +$(DGL_BUILD_DIR)/libdgl-opengl3.a: $(DGL_POSSIBLE_DEPS) + $(MAKE) -C $(DPF_PATH)/dgl opengl3 + +$(DGL_BUILD_DIR)/libdgl-stub.a: $(DGL_POSSIBLE_DEPS) + $(MAKE) -C $(DPF_PATH)/dgl stub + +$(DGL_BUILD_DIR)/libdgl-vulkan.a: $(DGL_POSSIBLE_DEPS) + $(MAKE) -C $(DPF_PATH)/dgl vulkan + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/DistrhoPluginMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_DSP_DEPENDENCIES) + -@mkdir -p $(BUILD_DIR) + @echo "Compiling DistrhoPluginMain.cpp ($*)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_$* -c -o $@ + +$(BUILD_DIR)/DistrhoUIMain_%.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_UI_DEPENDENCIES) + -@mkdir -p $(BUILD_DIR) + @echo "Compiling DistrhoUIMain.cpp ($*)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_$* -c -o $@ + +$(BUILD_DIR)/DistrhoUI_macOS_%.mm.o: $(DPF_PATH)/distrho/DistrhoUI_macOS.mm $(EXTRA_DEPENDENCIES) $(EXTRA_UI_DEPENDENCIES) + -@mkdir -p $(BUILD_DIR) + @echo "Compiling DistrhoUI_macOS.mm ($*)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -ObjC++ -c -o $@ + +$(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_DSP_DEPENDENCIES) + -@mkdir -p $(BUILD_DIR) + @echo "Compiling DistrhoPluginMain.cpp (JACK)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_JACK $(JACK_FLAGS) -c -o $@ + +$(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_UI_DEPENDENCIES) + -@mkdir -p $(BUILD_DIR) + @echo "Compiling DistrhoUIMain.cpp (DSSI)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_DSSI $(LIBLO_FLAGS) -c -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# JACK + +jack: $(jack) $(jackfiles) + +ifeq ($(HAVE_DGL),true) +$(jack): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.o $(DGL_LIB) +else +$(jack): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o +endif + -@mkdir -p $(shell dirname $@) + @echo "Creating JACK standalone for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(JACK_LIBS) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# LADSPA + +ladspa: $(ladspa_dsp) + +$(ladspa_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_LADSPA.cpp.o + -@mkdir -p $(shell dirname $@) + @echo "Creating LADSPA plugin for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(SHARED) $(SYMBOLS_LADSPA) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# DSSI + +dssi: $(dssi_dsp) $(dssi_ui) +dssi_dsp: $(dssi_dsp) +dssi_ui: $(dssi_ui) + +$(dssi_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.o + -@mkdir -p $(shell dirname $@) + @echo "Creating DSSI plugin library for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(SHARED) $(SYMBOLS_DSSI) -o $@ + +$(dssi_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o $(DGL_LIB) + -@mkdir -p $(shell dirname $@) + @echo "Creating DSSI UI for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(LIBLO_LIBS) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# LV2 + +lv2: $(lv2) +lv2_dsp: $(lv2_dsp) +lv2_sep: $(lv2_dsp) $(lv2_ui) + +ifeq ($(HAVE_DGL),true) +$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) +else +$(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o +endif + -@mkdir -p $(shell dirname $@) + @echo "Creating LV2 plugin for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2) -o $@ + +$(lv2_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o + -@mkdir -p $(shell dirname $@) + @echo "Creating LV2 plugin library for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(SHARED) $(SYMBOLS_LV2DSP) -o $@ + +$(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) + -@mkdir -p $(shell dirname $@) + @echo "Creating LV2 plugin UI for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2UI) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# LV2 modgui + +ifeq ($(MODGUI_BUILD),true) +ifeq ($(MODGUI_CLASS_NAME),) +$(error MODGUI_CLASS_NAME undefined) +endif +endif + +# clear all possible flags coming from DPF, while keeping any extra flags specified for this build +MODGUI_IGNORED_FLAGS = -fdata-sections +MODGUI_IGNORED_FLAGS += -ffast-math +MODGUI_IGNORED_FLAGS += -ffunction-sections +MODGUI_IGNORED_FLAGS += -fno-gnu-unique +MODGUI_IGNORED_FLAGS += -fprefetch-loop-arrays +MODGUI_IGNORED_FLAGS += -fvisibility=hidden +MODGUI_IGNORED_FLAGS += -fvisibility-inlines-hidden +MODGUI_IGNORED_FLAGS += -fPIC +MODGUI_IGNORED_FLAGS += -ldl +MODGUI_IGNORED_FLAGS += -mfpmath=sse +MODGUI_IGNORED_FLAGS += -msse +MODGUI_IGNORED_FLAGS += -msse2 +MODGUI_IGNORED_FLAGS += -mtune=generic +MODGUI_IGNORED_FLAGS += -pipe +MODGUI_IGNORED_FLAGS += -std=gnu99 +MODGUI_IGNORED_FLAGS += -std=gnu++11 +MODGUI_IGNORED_FLAGS += -DDISTRHO_PLUGIN_MODGUI_CLASS_NAME='"$(MODGUI_CLASS_NAME)"' +MODGUI_IGNORED_FLAGS += -DDGL_OPENGL +MODGUI_IGNORED_FLAGS += -DGL_SILENCE_DEPRECATION=1 +MODGUI_IGNORED_FLAGS += -DHAVE_ALSA +MODGUI_IGNORED_FLAGS += -DHAVE_DGL +MODGUI_IGNORED_FLAGS += -DHAVE_JACK +MODGUI_IGNORED_FLAGS += -DHAVE_LIBLO +MODGUI_IGNORED_FLAGS += -DHAVE_OPENGL +MODGUI_IGNORED_FLAGS += -DHAVE_PULSEAUDIO +MODGUI_IGNORED_FLAGS += -DHAVE_RTAUDIO +MODGUI_IGNORED_FLAGS += -DHAVE_SDL2 +MODGUI_IGNORED_FLAGS += -DNDEBUG +MODGUI_IGNORED_FLAGS += -DPIC +MODGUI_IGNORED_FLAGS += -I. +MODGUI_IGNORED_FLAGS += -I$(DPF_PATH)/distrho +MODGUI_IGNORED_FLAGS += -I$(DPF_PATH)/dgl +MODGUI_IGNORED_FLAGS += -I$(MOD_WORKDIR)/modduo-static/staging/usr/include +MODGUI_IGNORED_FLAGS += -I$(MOD_WORKDIR)/modduox-static/staging/usr/include +MODGUI_IGNORED_FLAGS += -I$(MOD_WORKDIR)/moddwarf/staging/usr/include +MODGUI_IGNORED_FLAGS += -L$(MOD_WORKDIR)/modduo-static/staging/usr/lib +MODGUI_IGNORED_FLAGS += -L$(MOD_WORKDIR)/modduox-static/staging/usr/lib +MODGUI_IGNORED_FLAGS += -L$(MOD_WORKDIR)/moddwarf/staging/usr/lib +MODGUI_IGNORED_FLAGS += -MD +MODGUI_IGNORED_FLAGS += -MP +MODGUI_IGNORED_FLAGS += -O2 +MODGUI_IGNORED_FLAGS += -O3 +MODGUI_IGNORED_FLAGS += -Wall +MODGUI_IGNORED_FLAGS += -Wextra +MODGUI_IGNORED_FLAGS += -Wl,-O1,--as-needed,--gc-sections +MODGUI_IGNORED_FLAGS += -Wl,-dead_strip,-dead_strip_dylibs +MODGUI_IGNORED_FLAGS += -Wl,-x +MODGUI_IGNORED_FLAGS += -Wl,--gc-sections +MODGUI_IGNORED_FLAGS += -Wl,--no-undefined +MODGUI_IGNORED_FLAGS += -Wl,--strip-all +MODGUI_IGNORED_FLAGS += -Wno-deprecated-declarations +MODGUI_IGNORED_FLAGS += $(DGL_FLAGS) +MODGUI_CFLAGS = $(filter-out $(MODGUI_IGNORED_FLAGS),$(BUILD_C_FLAGS)) -D__MOD_DEVICES__ +MODGUI_CXXFLAGS = $(filter-out $(MODGUI_IGNORED_FLAGS),$(BUILD_CXX_FLAGS)) -D__MOD_DEVICES__ +MODGUI_LDFLAGS = $(filter-out $(MODGUI_IGNORED_FLAGS),$(LINK_FLAGS)) + +$(TARGET_DIR)/$(NAME).lv2/modgui/module.js: $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) + -@mkdir -p $(shell dirname $@) + @echo "Creating LV2 plugin modgui for $(NAME)" + $(SILENT)$(CXX) $^ $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) \ + -sALLOW_MEMORY_GROWTH -sALLOW_TABLE_GROWTH -sDISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0 -sLZ4=1 \ + -sMODULARIZE=1 -sMAIN_MODULE=2 \ + -sEXPORTED_FUNCTIONS="['_malloc','_free','_modgui_init','_modgui_param_set','_modgui_patch_set','_modgui_cleanup']" \ + -sEXPORTED_RUNTIME_METHODS=['addFunction','lengthBytesUTF8','stringToUTF8','UTF8ToString'] \ + -sEXPORT_NAME="Module_$(MODGUI_CLASS_NAME)" \ + -o $@ + +modgui: + $(MAKE) $(TARGET_DIR)/$(NAME).lv2/modgui/module.js \ + EXE_WRAPPER= \ + HAVE_OPENGL=true \ + MODGUI_BUILD=true \ + NOOPT=true \ + PKG_CONFIG=false \ + USE_GLES2=true \ + AR=emar \ + CC=emcc \ + CXX=em++ \ + CFLAGS="-O3 $(MODGUI_CFLAGS)" \ + CXXFLAGS="-O3 $(MODGUI_CXXFLAGS)" \ + LDFLAGS="-O3 $(MODGUI_LDFLAGS)" + +.PHONY: modgui + +# --------------------------------------------------------------------------------------------------------------------- +# VST2 + +vst2 vst: $(vst2) $(vst2files) + +ifeq ($(HAVE_DGL),true) +$(vst2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST2.cpp.o $(DGL_LIB) +else +$(vst2): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.o +endif + -@mkdir -p $(shell dirname $@) + @echo "Creating VST2 plugin for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST2) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# VST3 + +vst3: $(vst3) $(vst3files) + +ifeq ($(HAVE_DGL),true) +$(vst3): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST3.cpp.o $(DGL_LIB) +else +$(vst3): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.o +endif + -@mkdir -p $(shell dirname $@) + @echo "Creating VST3 plugin for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST3) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# CLAP + +ifeq ($(HAVE_DGL),true) +ifneq ($(HAIKU),true) +ifneq ($(WASM),true) +CLAP_LIBS = -lpthread +endif +endif +endif + +clap: $(clap) $(clapfiles) + +ifeq ($(HAVE_DGL),true) +$(clap): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_CLAP.cpp.o $(BUILD_DIR)/DistrhoUIMain_CLAP.cpp.o $(DGL_LIB) +else +$(clap): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_CLAP.cpp.o +endif + -@mkdir -p $(shell dirname $@) + @echo "Creating CLAP plugin for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(CLAP_LIBS) $(SHARED) $(SYMBOLS_CLAP) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# Shared + +shared: $(shared) + +ifeq ($(HAVE_DGL),true) +$(shared): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.o $(BUILD_DIR)/DistrhoUIMain_SHARED.cpp.o $(DGL_LIB) +else +$(shared): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.o +endif + -@mkdir -p $(shell dirname $@) + @echo "Creating shared library for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_SHARED) -o $@ + +# --------------------------------------------------------------------------------------------------------------------- +# Static + +static: $(static) + +ifeq ($(HAVE_DGL),true) +$(static): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_STATIC.cpp.o $(BUILD_DIR)/DistrhoUIMain_STATIC.cpp.o +else +$(static): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_STATIC.cpp.o +endif + -@mkdir -p $(shell dirname $@) + @echo "Creating static library for $(NAME)" + $(SILENT)rm -f $@ + $(SILENT)$(AR) crs $@ $^ + +# --------------------------------------------------------------------------------------------------------------------- +# macOS files + +$(TARGET_DIR)/%.app/Contents/Info.plist: $(DPF_PATH)/utils/plugin.app/Contents/Info.plist + -@mkdir -p $(shell dirname $@) + $(SILENT)sed -e "s/@INFO_PLIST_PROJECT_NAME@/$(NAME)/" $< > $@ + +$(TARGET_DIR)/%/Contents/Info.plist: $(DPF_PATH)/utils/plugin.bundle/Contents/Info.plist + -@mkdir -p $(shell dirname $@) + $(SILENT)sed -e "s/@INFO_PLIST_PROJECT_NAME@/$(NAME)/" $< > $@ + +$(TARGET_DIR)/%/Contents/PkgInfo: $(DPF_PATH)/utils/plugin.bundle/Contents/PkgInfo + -@mkdir -p $(shell dirname $@) + $(SILENT)cp $< $@ + +$(TARGET_DIR)/%/Resources/empty.lproj: $(DPF_PATH)/utils/plugin.bundle/Contents/Resources/empty.lproj + -@mkdir -p $(shell dirname $@) + $(SILENT)cp $< $@ + +# --------------------------------------------------------------------------------------------------------------------- + +-include $(OBJS_DSP:%.o=%.d) +ifneq ($(UI_TYPE),) +-include $(OBJS_UI:%.o=%.d) +endif + +-include $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_LADSPA.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_CLAP.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_STATIC.cpp.d + +-include $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_VST2.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_VST3.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_CLAP.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_SHARED.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_STATIC.cpp.d + +# --------------------------------------------------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/README.md Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,41 @@ +# DPF - DISTRHO Plugin Framework +[![makefile](https://github.com/DISTRHO/DPF/actions/workflows/makefile.yml/badge.svg)](https://github.com/DISTRHO/DPF/actions/workflows/makefile.yml) +[![cmake](https://github.com/DISTRHO/DPF/actions/workflows/cmake.yml/badge.svg)](https://github.com/DISTRHO/DPF/actions/workflows/cmake.yml) +[![example-plugins](https://github.com/DISTRHO/DPF/actions/workflows/example-plugins.yml/badge.svg)](https://github.com/DISTRHO/DPF/actions/workflows/example-plugins.yml) + +DPF is designed to make development of new plugins an easy and enjoyable task. +It allows developers to create plugins with custom UIs using a simple C++ API. +The framework facilitates exporting various different plugin formats from the same code-base. + +DPF can build for LADSPA, DSSI, LV2, VST2, VST3 and CLAP formats. +A JACK/Standalone mode is also available, allowing you to quickly test plugins. + +Plugin DSP and UI communication is done via key-value string pairs. +You send messages from the UI to the DSP side, which is automatically saved in the host when required. +(You can also store state internally if needed, but this breaks DSSI compatibility). + +Getting time information from the host is possible. +It uses the same format as the JACK Transport API, making porting some code easier. + +Provided features and implementation status for specific plugin formats can be seen in [FEATURES.md](FEATURES.md). + +## Licensing + +DPF is released under ISC, which basically means you can do whatever you want as long as you credit the original authors. +Some plugin formats may have additional restrictions, see [LICENSING.md](LICENSING.md) for details. + + +## Help and documentation + +Bug reports happen on the [DPF github project](https://github.com/DISTRHO/DPF/issues). + +Online documentation is available at [https://distrho.github.io/DPF/](https://distrho.github.io/DPF/). + +Online help and discussion about DPF happens in the [kx.studio chat, DPF room](https://chat.kx.studio/channel/dpf). + + +## List of plugins made with DPF: + +See [this wiki page](https://github.com/DISTRHO/DPF/wiki/Plugins-made-with-DPF) for a list of plugins made with DPF. + +Plugin examples are also available in the `example/` folder inside this repo. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/cmake/DPF-plugin.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/cmake/DPF-plugin.cmake Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,971 @@ +# DISTRHO Plugin Framework (DPF) +# Copyright (C) 2021 Jean Pierre Cimalando +# Copyright (C) 2022 Filipe Coelho +# +# SPDX-License-Identifier: ISC + +# ------------------------------------------------------------------------------ +# CMake support module for the DISTRHO Plugin Framework +# +# The purpose of this module is to help building music plugins easily, when the +# project uses CMake as its build system. +# +# In order to use the helpers provided by this module, a plugin author should +# add DPF as a subproject, making the function `dpf_add_plugin` available. +# The usage of this function is documented below in greater detail. +# +# Example project `CMakeLists.txt`: +# +# ``` +# cmake_minimum_required(VERSION 3.7) +# project(MyPlugin) +# +# add_subdirectory(DPF) +# +# dpf_add_plugin(MyPlugin +# TARGETS clap lv2 vst2 vst3 +# UI_TYPE opengl +# FILES_DSP +# src/MyPlugin.cpp +# FILES_UI +# src/MyUI.cpp) +# +# target_include_directories(MyPlugin +# PUBLIC src) +# ``` +# +# Important: note that properties, such as include directories, definitions, +# and linked libraries *must* be marked with `PUBLIC` so they take effect and +# propagate into all the plugin targets. + +include(CMakeParseArguments) + +# ------------------------------------------------------------------------------ +# DPF public functions +# ------------------------------------------------------------------------------ + +# dpf_add_plugin(name ) +# ------------------------------------------------------------------------------ +# +# Add a plugin built using the DISTRHO Plugin Framework. +# +# ------------------------------------------------------------------------------ +# Created targets: +# +# `` +# static library: the common part of the plugin +# The public properties set on this target apply to both DSP and UI. +# +# `-dsp` +# static library: the DSP part of the plugin +# The public properties set on this target apply to the DSP only. +# +# `-ui` +# static library: the UI part of the plugin +# The public properties set on this target apply to the UI only. +# +# `-` for each target specified with the `TARGETS` argument. +# This is target-dependent and not intended for public use. +# +# ------------------------------------------------------------------------------ +# Arguments: +# +# `TARGETS` ... +# a list of one of more of the following target types: +# `jack`, `ladspa`, `dssi`, `lv2`, `vst2`, `vst3`, `clap` +# +# `UI_TYPE` +# the user interface type: `opengl` (default), `cairo`, `external` +# +# `FILES_COMMON` ... +# list of sources which are part of both DSP and UI +# +# `FILES_DSP` ... +# list of sources which are part of the DSP +# +# `FILES_UI` ... +# list of sources which are part of the UI +# empty indicates the plugin does not have UI +# +# `MODGUI_CLASS_NAME` +# class name to use for modgui builds +# +# `MONOLITHIC` +# build LV2 as a single binary for UI and DSP +# +# `NO_SHARED_RESOURCES` +# do not build DPF shared resources (fonts, etc) +# +function(dpf_add_plugin NAME) + set(options MONOLITHIC NO_SHARED_RESOURCES) + set(oneValueArgs MODGUI_CLASS_NAME UI_TYPE) + set(multiValueArgs FILES_COMMON FILES_DSP FILES_UI TARGETS) + cmake_parse_arguments(_dpf_plugin "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if("${_dpf_plugin_UI_TYPE}" STREQUAL "") + set(_dpf_plugin_UI_TYPE "opengl") + endif() + + set(_dgl_library) + set(_dgl_external OFF) + if(_dpf_plugin_FILES_UI) + if(_dpf_plugin_UI_TYPE STREQUAL "cairo") + dpf__add_dgl_cairo("${_dpf_plugin_NO_SHARED_RESOURCES}") + set(_dgl_library dgl-cairo) + elseif(_dpf_plugin_UI_TYPE STREQUAL "opengl") + dpf__add_dgl_opengl("${_dpf_plugin_NO_SHARED_RESOURCES}") + set(_dgl_library dgl-opengl) + elseif(_dpf_plugin_UI_TYPE STREQUAL "external") + set(_dgl_external ON) + else() + message(FATAL_ERROR "Unrecognized UI type for plugin: ${_dpf_plugin_UI_TYPE}") + endif() + endif() + + set(_dgl_has_ui OFF) + if(_dgl_library OR _dgl_external) + set(_dgl_has_ui ON) + endif() + + ### + dpf__ensure_sources_non_empty(_dpf_plugin_FILES_COMMON) + dpf__ensure_sources_non_empty(_dpf_plugin_FILES_DSP) + dpf__ensure_sources_non_empty(_dpf_plugin_FILES_UI) + + ### + dpf__add_static_library("${NAME}" ${_dpf_plugin_FILES_COMMON}) + target_include_directories("${NAME}" PUBLIC + "${DPF_ROOT_DIR}/distrho") + + if(_dpf_plugin_MODGUI_CLASS_NAME) + target_compile_definitions("${NAME}" PUBLIC "DISTRHO_PLUGIN_MODGUI_CLASS_NAME=\"${_dpf_plugin_MODGUI_CLASS_NAME}\"") + endif() + + if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU)) + target_link_libraries("${NAME}" PRIVATE "dl") + endif() + + if(_dgl_library AND NOT _dgl_external) + # make sure that all code will see DGL_* definitions + target_link_libraries("${NAME}" PUBLIC + "${_dgl_library}-definitions" + dgl-system-libs-definitions + dgl-system-libs) + endif() + + dpf__add_static_library("${NAME}-dsp" ${_dpf_plugin_FILES_DSP}) + target_link_libraries("${NAME}-dsp" PUBLIC "${NAME}") + + if(_dgl_library AND NOT _dgl_external) + dpf__add_static_library("${NAME}-ui" ${_dpf_plugin_FILES_UI}) + target_link_libraries("${NAME}-ui" PUBLIC "${NAME}" ${_dgl_library}) + if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU)) + target_link_libraries("${NAME}-ui" PRIVATE "dl") + endif() + # add the files containing Objective-C classes + dpf__add_plugin_specific_ui_sources("${NAME}-ui") + elseif(_dgl_external) + dpf__add_static_library("${NAME}-ui" ${_dpf_plugin_FILES_UI}) + target_link_libraries("${NAME}-ui" PUBLIC "${NAME}") + if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU)) + target_link_libraries("${NAME}-ui" PRIVATE "dl") + endif() + # add the files containing Objective-C classes + dpf__add_plugin_specific_ui_sources("${NAME}-ui") + else() + add_library("${NAME}-ui" INTERFACE) + endif() + + ### + foreach(_target ${_dpf_plugin_TARGETS}) + if(_target STREQUAL "jack") + dpf__build_jack("${NAME}" "${_dgl_has_ui}") + elseif(_target STREQUAL "ladspa") + dpf__build_ladspa("${NAME}") + elseif(_target STREQUAL "dssi") + dpf__build_dssi("${NAME}" "${_dgl_has_ui}") + elseif(_target STREQUAL "lv2") + dpf__build_lv2("${NAME}" "${_dgl_has_ui}" "${_dpf_plugin_MONOLITHIC}") + elseif(_target STREQUAL "vst2") + dpf__build_vst2("${NAME}" "${_dgl_has_ui}") + elseif(_target STREQUAL "vst3") + dpf__build_vst3("${NAME}" "${_dgl_has_ui}") + elseif(_target STREQUAL "clap") + dpf__build_clap("${NAME}" "${_dgl_has_ui}") + elseif(_target STREQUAL "static") + dpf__build_static("${NAME}" "${_dgl_has_ui}") + else() + message(FATAL_ERROR "Unrecognized target type for plugin: ${_target}") + endif() + endforeach() +endfunction() + +# ------------------------------------------------------------------------------ +# DPF private functions (prefixed with `dpf__`) +# ------------------------------------------------------------------------------ + +# Note: The $<0:> trick is to prevent MSVC from appending the build type +# to the output directory. +# + +# dpf__build_jack +# ------------------------------------------------------------------------------ +# +# Add build rules for a JACK/Standalone program. +# +function(dpf__build_jack NAME HAS_UI) + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_executable("${NAME}-jack" ${_no_srcs}) + dpf__add_plugin_main("${NAME}-jack" "jack") + dpf__add_ui_main("${NAME}-jack" "jack" "${HAS_UI}") + target_link_libraries("${NAME}-jack" PRIVATE "${NAME}-dsp" "${NAME}-ui") + set_target_properties("${NAME}-jack" PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" + OUTPUT_NAME "${NAME}") + + target_compile_definitions("${NAME}" PUBLIC "HAVE_JACK") + target_compile_definitions("${NAME}-jack" PRIVATE "HAVE_GETTIMEOFDAY") + + find_package(PkgConfig) + pkg_check_modules(SDL2 "sdl2") + if(SDL2_FOUND) + target_compile_definitions("${NAME}" PUBLIC "HAVE_SDL2") + target_include_directories("${NAME}-jack" PRIVATE ${SDL2_STATIC_INCLUDE_DIRS}) + target_link_libraries("${NAME}-jack" PRIVATE ${SDL2_STATIC_LIBRARIES}) + dpf__target_link_directories("${NAME}-jack" "${SDL2_STATIC_LIBRARY_DIRS}") + endif() + + if(APPLE OR WIN32) + target_compile_definitions("${NAME}" PUBLIC "HAVE_RTAUDIO") + else() + find_package(Threads) + pkg_check_modules(ALSA "alsa") + pkg_check_modules(PULSEAUDIO "libpulse-simple") + if(ALSA_FOUND) + target_compile_definitions("${NAME}" PUBLIC "HAVE_ALSA") + target_include_directories("${NAME}-jack" PRIVATE ${ALSA_INCLUDE_DIRS}) + target_link_libraries("${NAME}-jack" PRIVATE ${ALSA_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + dpf__target_link_directories("${NAME}-jack" "${ALSA_LIBRARY_DIRS}") + endif() + if(PULSEAUDIO_FOUND) + target_compile_definitions("${NAME}" PUBLIC "HAVE_PULSEAUDIO") + target_include_directories("${NAME}-jack" PRIVATE ${PULSEAUDIO_INCLUDE_DIRS}) + target_link_libraries("${NAME}-jack" PRIVATE ${PULSEAUDIO_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + dpf__target_link_directories("${NAME}-jack" "${PULSEAUDIO_LIBRARY_DIRS}") + endif() + if(ALSA_FOUND OR PULSEAUDIO_FOUND) + target_compile_definitions("${NAME}" PUBLIC "HAVE_RTAUDIO") + endif() + endif() + + # for RtAudio native fallback + if(APPLE) + find_library(APPLE_COREAUDIO_FRAMEWORK "CoreAudio") + find_library(APPLE_COREFOUNDATION_FRAMEWORK "CoreFoundation") + find_library(APPLE_COREMIDI_FRAMEWORK "CoreMIDI") + target_link_libraries("${NAME}-jack" PRIVATE + "${APPLE_COREAUDIO_FRAMEWORK}" + "${APPLE_COREFOUNDATION_FRAMEWORK}" + "${APPLE_COREMIDI_FRAMEWORK}") + elseif(WIN32) + target_link_libraries("${NAME}-jack" PRIVATE "ksuser" "mfplat" "mfuuid" "ole32" "winmm" "wmcodecdspuuid") + if(HAS_UI AND MINGW) + set_target_properties("${NAME}-jack" PROPERTIES WIN32_EXECUTABLE TRUE) + endif() + endif() +endfunction() + +# dpf__build_ladspa +# ------------------------------------------------------------------------------ +# +# Add build rules for a LADSPA plugin. +# +function(dpf__build_ladspa NAME) + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_module("${NAME}-ladspa" ${_no_srcs}) + dpf__add_plugin_main("${NAME}-ladspa" "ladspa") + dpf__set_module_export_list("${NAME}-ladspa" "ladspa") + target_link_libraries("${NAME}-ladspa" PRIVATE "${NAME}-dsp") + set_target_properties("${NAME}-ladspa" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/ladspa/$<0:>" + OUTPUT_NAME "${NAME}-ladspa" + PREFIX "") +endfunction() + +# dpf__build_dssi +# ------------------------------------------------------------------------------ +# +# Add build rules for a DSSI plugin. +# +function(dpf__build_dssi NAME HAS_UI) + find_package(PkgConfig) + pkg_check_modules(LIBLO "liblo") + if(NOT LIBLO_FOUND) + dpf__warn_once_only(missing_liblo + "liblo is not found, skipping the `dssi` plugin targets") + return() + endif() + + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_module("${NAME}-dssi" ${_no_srcs}) + dpf__add_plugin_main("${NAME}-dssi" "dssi") + dpf__set_module_export_list("${NAME}-dssi" "dssi") + target_link_libraries("${NAME}-dssi" PRIVATE "${NAME}-dsp") + set_target_properties("${NAME}-dssi" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/dssi/$<0:>" + OUTPUT_NAME "${NAME}-dssi" + PREFIX "") + + if(HAS_UI) + dpf__add_executable("${NAME}-dssi-ui" ${_no_srcs}) + dpf__add_ui_main("${NAME}-dssi-ui" "dssi" "${HAS_UI}") + target_link_libraries("${NAME}-dssi-ui" PRIVATE "${NAME}-ui") + set_target_properties("${NAME}-dssi-ui" PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}-dssi/$<0:>" + OUTPUT_NAME "${NAME}_ui") + + target_compile_definitions("${NAME}" PUBLIC "HAVE_LIBLO") + target_include_directories("${NAME}-dssi-ui" PRIVATE ${LIBLO_INCLUDE_DIRS}) + target_link_libraries("${NAME}-dssi-ui" PRIVATE ${LIBLO_LIBRARIES}) + dpf__target_link_directories("${NAME}-dssi-ui" "${LIBLO_LIBRARY_DIRS}") + endif() +endfunction() + +# dpf__build_lv2 +# ------------------------------------------------------------------------------ +# +# Add build rules for an LV2 plugin. +# +function(dpf__build_lv2 NAME HAS_UI MONOLITHIC) + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_module("${NAME}-lv2" ${_no_srcs}) + dpf__add_plugin_main("${NAME}-lv2" "lv2") + if(HAS_UI AND MONOLITHIC) + dpf__set_module_export_list("${NAME}-lv2" "lv2") + else() + dpf__set_module_export_list("${NAME}-lv2" "lv2-dsp") + endif() + target_link_libraries("${NAME}-lv2" PRIVATE "${NAME}-dsp") + set_target_properties("${NAME}-lv2" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>" + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/lv2/$<0:>" + OUTPUT_NAME "${NAME}_dsp" + PREFIX "") + + if(HAS_UI) + if(MONOLITHIC) + dpf__add_ui_main("${NAME}-lv2" "lv2" "${HAS_UI}") + target_link_libraries("${NAME}-lv2" PRIVATE "${NAME}-ui") + set_target_properties("${NAME}-lv2" PROPERTIES + OUTPUT_NAME "${NAME}") + else() + dpf__add_module("${NAME}-lv2-ui" ${_no_srcs}) + dpf__add_ui_main("${NAME}-lv2-ui" "lv2" "${HAS_UI}") + dpf__set_module_export_list("${NAME}-lv2-ui" "lv2-ui") + target_link_libraries("${NAME}-lv2-ui" PRIVATE "${NAME}-ui") + set_target_properties("${NAME}-lv2-ui" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>" + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/lv2/$<0:>" + OUTPUT_NAME "${NAME}_ui" + PREFIX "") + endif() + endif() + + dpf__add_lv2_ttl_generator() + add_dependencies("${NAME}-lv2" lv2_ttl_generator) + + add_custom_command(TARGET "${NAME}-lv2" POST_BUILD + COMMAND + ${CMAKE_CROSSCOMPILING_EMULATOR} + "$" + "$" + WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2" + DEPENDS lv2_ttl_generator) +endfunction() + +# dpf__build_vst2 +# ------------------------------------------------------------------------------ +# +# Add build rules for a VST2 plugin. +# +function(dpf__build_vst2 NAME HAS_UI) + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_module("${NAME}-vst2" ${_no_srcs}) + dpf__add_plugin_main("${NAME}-vst2" "vst2") + dpf__add_ui_main("${NAME}-vst2" "vst2" "${HAS_UI}") + dpf__set_module_export_list("${NAME}-vst2" "vst2") + target_link_libraries("${NAME}-vst2" PRIVATE "${NAME}-dsp" "${NAME}-ui") + set_target_properties("${NAME}-vst2" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/vst2/$<0:>" + OUTPUT_NAME "${NAME}-vst2" + PREFIX "") + if(APPLE) + set_target_properties("${NAME}-vst2" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst/Contents/MacOS/$<0:>" + OUTPUT_NAME "${NAME}" + SUFFIX "") + set(INFO_PLIST_PROJECT_NAME "${NAME}") + configure_file("${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/Info.plist" + "${PROJECT_BINARY_DIR}/bin/${NAME}.vst/Contents/Info.plist" @ONLY) + file(COPY "${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/PkgInfo" + DESTINATION "${PROJECT_BINARY_DIR}/bin/${NAME}.vst/Contents") + endif() +endfunction() + +# dpf__determine_vst3_package_architecture +# ------------------------------------------------------------------------------ +# +# Determines the package architecture for a VST3 plugin target. +# +function(dpf__determine_vst3_package_architecture OUTPUT_VARIABLE) + # if set by variable, override the detection + if(DPF_VST3_ARCHITECTURE) + set("${OUTPUT_VARIABLE}" "${DPF_VST3_ARCHITECTURE}" PARENT_SCOPE) + return() + endif() + + # not used on Apple, which supports universal binary + if(APPLE) + set("${OUTPUT_VARIABLE}" "universal" PARENT_SCOPE) + return() + endif() + + # identify the target processor (special case of MSVC, problematic sometimes) + if(MSVC) + set(vst3_system_arch "${MSVC_CXX_ARCHITECTURE_ID}") + else() + set(vst3_system_arch "${CMAKE_SYSTEM_PROCESSOR}") + endif() + + # transform the processor name to a format that VST3 recognizes + if(vst3_system_arch MATCHES "^(x86_64|amd64|AMD64|x64|X64)$") + set(vst3_package_arch "x86_64") + elseif(vst3_system_arch MATCHES "^(i.86|x86|X86)$") + if(WIN32) + set(vst3_package_arch "x86") + else() + set(vst3_package_arch "i386") + endif() + elseif(vst3_system_arch MATCHES "^(armv[3-8][a-z]*)$") + set(vst3_package_arch "${vst3_system_arch}") + elseif(vst3_system_arch MATCHES "^(aarch64)$") + set(vst3_package_arch "aarch64") + else() + message(FATAL_ERROR "We don't know this architecture for VST3: ${vst3_system_arch}.") + endif() + + # TODO: the detections for Windows arm/arm64 when supported + + set("${OUTPUT_VARIABLE}" "${vst3_package_arch}" PARENT_SCOPE) +endfunction() + +# dpf__build_vst3 +# ------------------------------------------------------------------------------ +# +# Add build rules for a VST3 plugin. +# +function(dpf__build_vst3 NAME HAS_UI) + dpf__determine_vst3_package_architecture(vst3_arch) + + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_module("${NAME}-vst3" ${_no_srcs}) + dpf__add_plugin_main("${NAME}-vst3" "vst3") + dpf__add_ui_main("${NAME}-vst3" "vst3" "${HAS_UI}") + dpf__set_module_export_list("${NAME}-vst3" "vst3") + target_link_libraries("${NAME}-vst3" PRIVATE "${NAME}-dsp" "${NAME}-ui") + set_target_properties("${NAME}-vst3" PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/vst3/$<0:>" + OUTPUT_NAME "${NAME}" + PREFIX "") + + if(APPLE) + set_target_properties("${NAME}-vst3" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/MacOS/$<0:>" + SUFFIX "") + elseif(WIN32) + set_target_properties("${NAME}-vst3" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-win/$<0:>" SUFFIX ".vst3") + else() + set_target_properties("${NAME}-vst3" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-linux/$<0:>") + endif() + + if(APPLE) + # Uses the same macOS bundle template as VST2 + set(INFO_PLIST_PROJECT_NAME "${NAME}") + configure_file("${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/Info.plist" + "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/Info.plist" @ONLY) + file(COPY "${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/PkgInfo" + DESTINATION "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents") + endif() +endfunction() + +# dpf__build_clap +# ------------------------------------------------------------------------------ +# +# Add build rules for a CLAP plugin. +# +function(dpf__build_clap NAME HAS_UI) + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_module("${NAME}-clap" ${_no_srcs}) + dpf__add_plugin_main("${NAME}-clap" "clap") + dpf__add_ui_main("${NAME}-clap" "clap" "${HAS_UI}") + dpf__set_module_export_list("${NAME}-clap" "clap") + target_link_libraries("${NAME}-clap" PRIVATE "${NAME}-dsp" "${NAME}-ui") + set_target_properties("${NAME}-clap" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/clap/$<0:>" + OUTPUT_NAME "${NAME}" + PREFIX "" + SUFFIX ".clap") + + if(APPLE) + set_target_properties("${NAME}-clap" PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.clap/Contents/MacOS/$<0:>" + OUTPUT_NAME "${NAME}" + SUFFIX "") + set(INFO_PLIST_PROJECT_NAME "${NAME}") + configure_file("${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/Info.plist" + "${PROJECT_BINARY_DIR}/bin/${NAME}.clap/Contents/Info.plist" @ONLY) + file(COPY "${DPF_ROOT_DIR}/utils/plugin.bundle/Contents/PkgInfo" + DESTINATION "${PROJECT_BINARY_DIR}/bin/${NAME}.clap/Contents") + endif() +endfunction() + +# dpf__build_static +# ------------------------------------------------------------------------------ +# +# Add build rules for a static library. +# +function(dpf__build_static NAME HAS_UI) + dpf__create_dummy_source_list(_no_srcs) + + dpf__add_module("${NAME}-static" ${_no_srcs} STATIC) + dpf__add_plugin_main("${NAME}-static" "static") + dpf__add_ui_main("${NAME}-static" "static" "${HAS_UI}") + target_link_libraries("${NAME}-static" PRIVATE "${NAME}-dsp" "${NAME}-ui") + + get_target_property(dsp_srcs "${NAME}-dsp" SOURCES) + get_target_property(ui_srcs "${NAME}-ui" SOURCES) + foreach(src ${dsp_srcs}) + target_sources("${NAME}-static" PRIVATE ${src}) + endforeach() + foreach(src ${ui_srcs}) + target_sources("${NAME}-static" PRIVATE ${src}) + endforeach() + + set_target_properties("${NAME}-static" PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" + OUTPUT_NAME "${NAME}" + PREFIX "") +endfunction() + +# dpf__add_dgl_cairo +# ------------------------------------------------------------------------------ +# +# Add the Cairo variant of DGL, if not already available. +# +function(dpf__add_dgl_cairo NO_SHARED_RESOURCES) + if(TARGET dgl-cairo) + return() + endif() + + find_package(PkgConfig) + pkg_check_modules(CAIRO "cairo" REQUIRED) + + link_directories(${CAIRO_LIBRARY_DIRS}) + + dpf__add_static_library(dgl-cairo STATIC + "${DPF_ROOT_DIR}/dgl/src/Application.cpp" + "${DPF_ROOT_DIR}/dgl/src/ApplicationPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/Color.cpp" + "${DPF_ROOT_DIR}/dgl/src/EventHandlers.cpp" + "${DPF_ROOT_DIR}/dgl/src/Geometry.cpp" + "${DPF_ROOT_DIR}/dgl/src/ImageBase.cpp" + "${DPF_ROOT_DIR}/dgl/src/ImageBaseWidgets.cpp" + "${DPF_ROOT_DIR}/dgl/src/Layout.cpp" + "${DPF_ROOT_DIR}/dgl/src/SubWidget.cpp" + "${DPF_ROOT_DIR}/dgl/src/SubWidgetPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/TopLevelWidget.cpp" + "${DPF_ROOT_DIR}/dgl/src/TopLevelWidgetPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/Widget.cpp" + "${DPF_ROOT_DIR}/dgl/src/WidgetPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/Window.cpp" + "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/Cairo.cpp") + if(NO_SHARED_RESOURCES) + target_compile_definitions(dgl-cairo PUBLIC "DGL_NO_SHARED_RESOURCES") + else() + target_sources(dgl-cairo PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp") + endif() + if(NOT APPLE) + target_sources(dgl-cairo PRIVATE + "${DPF_ROOT_DIR}/dgl/src/pugl.cpp") + else() + target_sources(dgl-cairo PRIVATE + "${DPF_ROOT_DIR}/dgl/src/pugl.mm") + endif() + target_include_directories(dgl-cairo PUBLIC + "${DPF_ROOT_DIR}/dgl") + target_include_directories(dgl-cairo PUBLIC + "${DPF_ROOT_DIR}/dgl/src/pugl-upstream/include") + + dpf__add_dgl_system_libs() + target_link_libraries(dgl-cairo PRIVATE dgl-system-libs) + + add_library(dgl-cairo-definitions INTERFACE) + target_compile_definitions(dgl-cairo-definitions INTERFACE "DGL_CAIRO" "HAVE_CAIRO" "HAVE_DGL") + + target_include_directories(dgl-cairo PUBLIC ${CAIRO_INCLUDE_DIRS}) + if(MINGW) + target_link_libraries(dgl-cairo PRIVATE ${CAIRO_STATIC_LIBRARIES}) + else() + target_link_libraries(dgl-cairo PRIVATE ${CAIRO_LIBRARIES}) + endif() + target_link_libraries(dgl-cairo PRIVATE dgl-cairo-definitions) +endfunction() + +# dpf__add_dgl_opengl +# ------------------------------------------------------------------------------ +# +# Add the OpenGL variant of DGL, if not already available. +# +function(dpf__add_dgl_opengl NO_SHARED_RESOURCES) + if(TARGET dgl-opengl) + return() + endif() + + if(NOT OpenGL_GL_PREFERENCE) + set(OpenGL_GL_PREFERENCE "LEGACY") + endif() + + find_package(OpenGL REQUIRED) + + dpf__add_static_library(dgl-opengl STATIC + "${DPF_ROOT_DIR}/dgl/src/Application.cpp" + "${DPF_ROOT_DIR}/dgl/src/ApplicationPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/Color.cpp" + "${DPF_ROOT_DIR}/dgl/src/EventHandlers.cpp" + "${DPF_ROOT_DIR}/dgl/src/Geometry.cpp" + "${DPF_ROOT_DIR}/dgl/src/ImageBase.cpp" + "${DPF_ROOT_DIR}/dgl/src/ImageBaseWidgets.cpp" + "${DPF_ROOT_DIR}/dgl/src/Layout.cpp" + "${DPF_ROOT_DIR}/dgl/src/SubWidget.cpp" + "${DPF_ROOT_DIR}/dgl/src/SubWidgetPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/TopLevelWidget.cpp" + "${DPF_ROOT_DIR}/dgl/src/TopLevelWidgetPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/Widget.cpp" + "${DPF_ROOT_DIR}/dgl/src/WidgetPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/Window.cpp" + "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp" + "${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp" + "${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp") + if(NO_SHARED_RESOURCES) + target_compile_definitions(dgl-opengl PUBLIC "DGL_NO_SHARED_RESOURCES") + else() + target_sources(dgl-opengl PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp") + endif() + if(NOT APPLE) + target_sources(dgl-opengl PRIVATE + "${DPF_ROOT_DIR}/dgl/src/pugl.cpp") + else() + target_sources(dgl-opengl PRIVATE + "${DPF_ROOT_DIR}/dgl/src/pugl.mm") + endif() + target_include_directories(dgl-opengl PUBLIC + "${DPF_ROOT_DIR}/dgl") + target_include_directories(dgl-opengl PUBLIC + "${DPF_ROOT_DIR}/dgl/src/pugl-upstream/include") + + if(APPLE) + target_compile_definitions(dgl-opengl PUBLIC "GL_SILENCE_DEPRECATION") + endif() + + dpf__add_dgl_system_libs() + target_link_libraries(dgl-opengl PRIVATE dgl-system-libs) + + add_library(dgl-opengl-definitions INTERFACE) + target_compile_definitions(dgl-opengl-definitions INTERFACE "DGL_OPENGL" "HAVE_OPENGL" "HAVE_DGL") + + target_include_directories(dgl-opengl PUBLIC "${OPENGL_INCLUDE_DIR}") + target_link_libraries(dgl-opengl PRIVATE dgl-opengl-definitions "${OPENGL_gl_LIBRARY}") +endfunction() + +# dpf__add_plugin_specific_ui_sources +# ------------------------------------------------------------------------------ +# +# Compile system specific files, for now it is just Objective-C code +# +function(dpf__add_plugin_specific_ui_sources NAME) + if(APPLE) + target_sources("${NAME}" PRIVATE + "${DPF_ROOT_DIR}/distrho/DistrhoUI_macOS.mm") + endif() +endfunction() + +# dpf__add_dgl_system_libs +# ------------------------------------------------------------------------------ +# +# Find system libraries required by DGL and add them as an interface target. +# +function(dpf__add_dgl_system_libs) + if(TARGET dgl-system-libs) + return() + endif() + add_library(dgl-system-libs INTERFACE) + add_library(dgl-system-libs-definitions INTERFACE) + if(APPLE) + find_library(APPLE_COCOA_FRAMEWORK "Cocoa") + find_library(APPLE_COREVIDEO_FRAMEWORK "CoreVideo") + target_link_libraries(dgl-system-libs INTERFACE "${APPLE_COCOA_FRAMEWORK}" "${APPLE_COREVIDEO_FRAMEWORK}") + elseif(EMSCRIPTEN) + elseif(HAIKU) + target_link_libraries(dgl-system-libs INTERFACE "be") + elseif(WIN32) + target_link_libraries(dgl-system-libs INTERFACE "gdi32" "comdlg32") + else() + find_package(PkgConfig) + pkg_check_modules(DBUS "dbus-1") + if(DBUS_FOUND) + target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_DBUS") + target_include_directories(dgl-system-libs INTERFACE "${DBUS_INCLUDE_DIRS}") + target_link_libraries(dgl-system-libs INTERFACE "${DBUS_LIBRARIES}") + endif() + find_package(X11 REQUIRED) + target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_X11") + target_include_directories(dgl-system-libs INTERFACE "${X11_INCLUDE_DIR}") + target_link_libraries(dgl-system-libs INTERFACE "${X11_X11_LIB}") + if(X11_Xcursor_FOUND) + target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XCURSOR") + target_link_libraries(dgl-system-libs INTERFACE "${X11_Xcursor_LIB}") + endif() + if(X11_Xext_FOUND) + target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XEXT") + target_link_libraries(dgl-system-libs INTERFACE "${X11_Xext_LIB}") + endif() + if(X11_Xrandr_FOUND) + target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XRANDR") + target_link_libraries(dgl-system-libs INTERFACE "${X11_Xrandr_LIB}") + endif() + if(X11_XSync_FOUND) + target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XSYNC") + target_link_libraries(dgl-system-libs INTERFACE "${X11_XSync_LIB}") + endif() + endif() + + if(MSVC) + file(MAKE_DIRECTORY "${DPF_ROOT_DIR}/khronos/GL") + foreach(_gl_header "glext.h") + if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}") + file(DOWNLOAD "https://www.khronos.org/registry/OpenGL/api/GL/${_gl_header}" "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}" SHOW_PROGRESS) + endif() + endforeach() + foreach(_khr_header "khrplatform.h") + if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}") + file(DOWNLOAD "https://www.khronos.org/registry/EGL/api/KHR/${_khr_header}" "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}" SHOW_PROGRESS) + endif() + endforeach() + target_include_directories(dgl-system-libs-definitions INTERFACE "${DPF_ROOT_DIR}/khronos") + endif() + + target_link_libraries(dgl-system-libs INTERFACE dgl-system-libs-definitions) +endfunction() + +# dpf__add_executable +# ------------------------------------------------------------------------------ +# +# Adds an executable target, and set some default properties on the target. +# +function(dpf__add_executable NAME) + add_executable("${NAME}" ${ARGN}) + dpf__set_target_defaults("${NAME}") + if(MINGW) + target_link_libraries("${NAME}" PRIVATE "-static") + endif() +endfunction() + +# dpf__add_module +# ------------------------------------------------------------------------------ +# +# Adds a module target, and set some default properties on the target. +# +function(dpf__add_module NAME) + add_library("${NAME}" MODULE ${ARGN}) + dpf__set_target_defaults("${NAME}") + if(MINGW) + target_link_libraries("${NAME}" PRIVATE "-static") + endif() +endfunction() + +# dpf__add_static_library +# ------------------------------------------------------------------------------ +# +# Adds a static library target, and set some default properties on the target. +# +function(dpf__add_static_library NAME) + add_library("${NAME}" STATIC ${ARGN}) + dpf__set_target_defaults("${NAME}") +endfunction() + +# dpf__set_module_export_list +# ------------------------------------------------------------------------------ +# +# Applies a list of exported symbols to the module target. +# +function(dpf__set_module_export_list NAME EXPORTS) + if(WIN32) + target_sources("${NAME}" PRIVATE "${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.def") + elseif(APPLE) + set_property(TARGET "${NAME}" APPEND PROPERTY LINK_OPTIONS + "-Xlinker" "-exported_symbols_list" + "-Xlinker" "${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.exp") + else() + set_property(TARGET "${NAME}" APPEND PROPERTY LINK_OPTIONS + "-Xlinker" "--version-script=${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.version") + endif() +endfunction() + +# dpf__set_target_defaults +# ------------------------------------------------------------------------------ +# +# Set default properties which must apply to all DPF-defined targets. +# +function(dpf__set_target_defaults NAME) + set_target_properties("${NAME}" PROPERTIES + POSITION_INDEPENDENT_CODE TRUE + C_VISIBILITY_PRESET "hidden" + CXX_VISIBILITY_PRESET "hidden" + VISIBILITY_INLINES_HIDDEN TRUE) + if(WIN32) + target_compile_definitions("${NAME}" PUBLIC "NOMINMAX") + endif() + if (MINGW) + target_compile_options("${NAME}" PUBLIC "-mstackrealign") + endif() + if (MSVC) + target_compile_options("${NAME}" PUBLIC "/UTF-8") + target_compile_definitions("${NAME}" PUBLIC "_CRT_SECURE_NO_WARNINGS") + endif() + if (CMAKE_COMPILER_IS_GNUCXX) + target_compile_options("${NAME}" PUBLIC "-fno-gnu-unique") + endif() +endfunction() + +# dpf__add_plugin_main +# ------------------------------------------------------------------------------ +# +# Adds plugin code to the given target. +# +function(dpf__add_plugin_main NAME TARGET) + target_sources("${NAME}" PRIVATE + "${DPF_ROOT_DIR}/distrho/DistrhoPluginMain.cpp") + dpf__add_plugin_target_definition("${NAME}" "${TARGET}") +endfunction() + +# dpf__add_ui_main +# ------------------------------------------------------------------------------ +# +# Adds UI code to the given target (only if the target has UI). +# +function(dpf__add_ui_main NAME TARGET HAS_UI) + if(HAS_UI) + target_sources("${NAME}" PRIVATE + "${DPF_ROOT_DIR}/distrho/DistrhoUIMain.cpp") + dpf__add_plugin_target_definition("${NAME}" "${TARGET}") + endif() +endfunction() + +# dpf__add_plugin_target_definition +# ------------------------------------------------------------------------------ +# +# Adds the plugins target macro definition. +# This selects which entry file is compiled according to the target type. +# +function(dpf__add_plugin_target_definition NAME TARGET) + string(TOUPPER "${TARGET}" _upperTarget) + target_compile_definitions("${NAME}" PRIVATE "DISTRHO_PLUGIN_TARGET_${_upperTarget}") +endfunction() + +# dpf__add_lv2_ttl_generator +# ------------------------------------------------------------------------------ +# +# Build the LV2 TTL generator. +# +function(dpf__add_lv2_ttl_generator) + if(TARGET lv2_ttl_generator) + return() + endif() + add_executable(lv2_ttl_generator "${DPF_ROOT_DIR}/utils/lv2-ttl-generator/lv2_ttl_generator.c") + if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU)) + target_link_libraries(lv2_ttl_generator PRIVATE "dl") + endif() +endfunction() + +# dpf__ensure_sources_non_empty +# ------------------------------------------------------------------------------ +# +# Ensure the given source list contains at least one file. +# The function appends an empty source file to the list if necessary. +# This is useful when CMake does not permit to add targets without sources. +# +function(dpf__ensure_sources_non_empty VAR) + if(NOT "" STREQUAL "${${VAR}}") + return() + endif() + set(_file "${CMAKE_CURRENT_BINARY_DIR}/_dpf_empty.c") + if(NOT EXISTS "${_file}") + file(WRITE "${_file}" "") + endif() + set("${VAR}" "${_file}" PARENT_SCOPE) +endfunction() + +# dpf__create_dummy_source_list +# ------------------------------------------------------------------------------ +# +# Create a dummy source list which is equivalent to compiling nothing. +# This is only for compatibility with older CMake versions, which refuse to add +# targets without any sources. +# +macro(dpf__create_dummy_source_list VAR) + set("${VAR}") + if(CMAKE_VERSION VERSION_LESS "3.11") + dpf__ensure_sources_non_empty("${VAR}") + endif() +endmacro() + +# dpf__target_link_directories +# ------------------------------------------------------------------------------ +# +# Call `target_link_directories` if cmake >= 3.13, +# otherwise fallback to global `link_directories`. +# +macro(dpf__target_link_directories NAME DIRS) + if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.13") + target_link_directories("${NAME}" PUBLIC ${DIRS}) + else() + link_directories(${DIRS}) + endif() +endmacro() + +# dpf__warn_once +# ------------------------------------------------------------------------------ +# +# Prints a warning message once only. +# +function(dpf__warn_once_only TOKEN MESSAGE) + get_property(_warned GLOBAL PROPERTY "dpf__have_warned_${TOKEN}") + if(NOT _warned) + set_property(GLOBAL PROPERTY "dpf__have_warned_${TOKEN}" TRUE) + message(WARNING "${MESSAGE}") + endif() +endfunction() diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Application.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Application.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,143 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_APP_HPP_INCLUDED +#define DGL_APP_HPP_INCLUDED + +#include "Base.hpp" + +#ifdef DISTRHO_NAMESPACE +START_NAMESPACE_DISTRHO +class PluginApplication; +END_NAMESPACE_DISTRHO +#endif + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Base DGL Application class. + + One application instance is required for creating a window. + There's no single/global application instance in DGL, and multiple windows can share the same app instance. + + In standalone mode an application will automatically quit its event-loop when all its windows are closed. + + Unless stated otherwise, functions within this class are not thread-safe. + */ +class DISTRHO_API Application +{ +public: + /** + Constructor. + */ + // NOTE: the default value is not yet passed, so we catch where we use this + Application(bool isStandalone = true); + + /** + Destructor. + */ + virtual ~Application(); + + /** + Idle function. + This runs the application event-loop once. + */ + void idle(); + + /** + Run the application event-loop until all Windows are closed. + idle() is called at regular intervals. + @note This function is meant for standalones only, *never* call this from plugins. + */ + void exec(uint idleTimeInMs = 30); + + /** + Quit the application. + This stops the event-loop and closes all Windows. + This function is thread-safe. + */ + void quit(); + + /** + Check if the application is about to quit. + Returning true means there's no event-loop running at the moment (or it's just about to stop). + This function is thread-safe. + */ + bool isQuitting() const noexcept; + + /** + Check if the application is standalone, otherwise running as a module or plugin. + This function is thread-safe. + */ + bool isStandalone() const noexcept; + + /** + Return the time in seconds. + + This is a monotonically increasing clock with high resolution.@n + The returned time is only useful to compare against other times returned by this function, + its absolute value has no meaning. + */ + double getTime() const; + + /** + Add a callback function to be triggered on every idle cycle. + You can add more than one, and remove them at anytime with removeIdleCallback(). + Idle callbacks trigger right after OS event handling and Window idle events (within the same cycle). + There are no guarantees in terms of timing, use Window::addIdleCallback for time-relative callbacks. + */ + void addIdleCallback(IdleCallback* callback); + + /** + Remove an idle callback previously added via addIdleCallback(). + */ + void removeIdleCallback(IdleCallback* callback); + + /** + Get the class name of the application. + + This is a stable identifier for the application, used as the window class/instance name on X11 and Windows. + It is not displayed to the user, but can be used in scripts and by window managers, + so it should be the same for every instance of the application, but different from other applications. + + Plugins created with DPF have their class name automatically set based on DGL_NAMESPACE and plugin name. + */ + const char* getClassName() const noexcept; + + /** + Set the class name of the application. + @see getClassName + */ + void setClassName(const char* name); + +private: + struct PrivateData; + PrivateData* const pData; + friend class Window; + #ifdef DISTRHO_NAMESPACE + friend class DISTRHO_NAMESPACE::PluginApplication; + #endif + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Application) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_APP_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Base.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Base.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,235 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_BASE_HPP_INCLUDED +#define DGL_BASE_HPP_INCLUDED + +#include "../distrho/extra/LeakDetector.hpp" +#include "../distrho/extra/ScopedPointer.hpp" + +// -------------------------------------------------------------------------------------------------------------------- +// Define namespace + +#ifndef DGL_NAMESPACE +# define DGL_NAMESPACE DGL +#endif + +#define START_NAMESPACE_DGL namespace DGL_NAMESPACE { +#define END_NAMESPACE_DGL } +#define USE_NAMESPACE_DGL using namespace DGL_NAMESPACE; + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- +// Base DGL enums + +/** + Keyboard modifier flags. + */ +enum Modifier { + kModifierShift = 1u << 0u, ///< Shift key + kModifierControl = 1u << 1u, ///< Control key + kModifierAlt = 1u << 2u, ///< Alt/Option key + kModifierSuper = 1u << 3u ///< Mod4/Command/Windows key +}; + +/** + Keyboard key codepoints. + + All keys are identified by a Unicode code point in Widget::KeyboardEvent::key. + This enumeration defines constants for special keys that do not have a standard + code point, and some convenience constants for control characters. + Note that all keys are handled in the same way, this enumeration is just for + convenience when writing hard-coded key bindings. + + Keys that do not have a standard code point use values in the Private Use + Area in the Basic Multilingual Plane (`U+E000` to `U+F8FF`). + Applications must take care to not interpret these values beyond key detection, + the mapping used here is arbitrary and specific to DPF. + */ +enum Key { + // Convenience symbols for ASCII control characters + kKeyBackspace = 0x08, + kKeyEscape = 0x1B, + kKeyDelete = 0x7F, + + // Backwards compatibility with old DPF + kCharBackspace DISTRHO_DEPRECATED_BY("kKeyBackspace") = kKeyBackspace, + kCharEscape DISTRHO_DEPRECATED_BY("kKeyEscape") = kKeyEscape, + kCharDelete DISTRHO_DEPRECATED_BY("kKeyDelete") = kKeyDelete, + + // Unicode Private Use Area + kKeyF1 = 0xE000, + kKeyF2, + kKeyF3, + kKeyF4, + kKeyF5, + kKeyF6, + kKeyF7, + kKeyF8, + kKeyF9, + kKeyF10, + kKeyF11, + kKeyF12, + kKeyLeft, + kKeyUp, + kKeyRight, + kKeyDown, + kKeyPageUp, + kKeyPageDown, + kKeyHome, + kKeyEnd, + kKeyInsert, + kKeyShift, + kKeyShiftL = kKeyShift, + kKeyShiftR, + kKeyControl, + kKeyControlL = kKeyControl, + kKeyControlR, + kKeyAlt, + kKeyAltL = kKeyAlt, + kKeyAltR, + kKeySuper, + kKeySuperL = kKeySuper, + kKeySuperR, + kKeyMenu, + kKeyCapsLock, + kKeyScrollLock, + kKeyNumLock, + kKeyPrintScreen, + kKeyPause +}; + +/** + Common flags for all events. + */ +enum EventFlag { + kFlagSendEvent = 1, ///< Event is synthetic + kFlagIsHint = 2 ///< Event is a hint (not direct user input) +}; + +/** + Reason for a crossing event. + */ +enum CrossingMode { + kCrossingNormal, ///< Crossing due to pointer motion + kCrossingGrab, ///< Crossing due to a grab + kCrossingUngrab ///< Crossing due to a grab release +}; + +/** + A mouse button. + + Mouse button numbers start from 1, and are ordered: primary, secondary, middle. + So, on a typical right-handed mouse, the button numbers are: + + Left: 1 + Right: 2 + Middle (often a wheel): 3 + + Higher button numbers are reported in the same order they are represented on the system. + There is no universal standard here, but buttons 4 and 5 are typically a pair of buttons or a rocker, + which are usually bound to "back" and "forward" operations. + + Note that these numbers may differ from those used on the underlying + platform, since they are manipulated to provide a consistent portable API. +*/ +enum MouseButton { + kMouseButtonLeft = 1, + kMouseButtonRight, + kMouseButtonMiddle, +}; + +/** + A mouse cursor type. + + This is a portable subset of mouse cursors that exist on X11, MacOS, and Windows. +*/ +enum MouseCursor { + kMouseCursorArrow, ///< Default pointing arrow + kMouseCursorCaret, ///< Caret (I-Beam) for text entry + kMouseCursorCrosshair, ///< Cross-hair + kMouseCursorHand, ///< Hand with a pointing finger + kMouseCursorNotAllowed, ///< Operation not allowed + kMouseCursorLeftRight, ///< Left/right arrow for horizontal resize + kMouseCursorUpDown, ///< Up/down arrow for vertical resize + kMouseCursorDiagonal, ///< Top-left to bottom-right arrow for diagonal resize + kMouseCursorAntiDiagonal ///< Bottom-left to top-right arrow for diagonal resize +}; + +/** + Scroll direction. + + Describes the direction of a scroll event along with whether the scroll is a "smooth" scroll. + The discrete directions are for devices like mouse wheels with constrained axes, + while a smooth scroll is for those with arbitrary scroll direction freedom, like some touchpads. +*/ +enum ScrollDirection { + kScrollUp, ///< Scroll up + kScrollDown, ///< Scroll down + kScrollLeft, ///< Scroll left + kScrollRight, ///< Scroll right + kScrollSmooth ///< Smooth scroll in any direction +}; + +/** + A clipboard data offer. + @see Window::onClipboardDataOffer +*/ +struct ClipboardDataOffer { + /** + The id of this data offer. + @note The value 0 is reserved for null/invalid. + */ + uint32_t id; + + /** + The type of this data offer. + Usually a MIME type, but may also be another platform-specific type identifier. + */ + const char* type; +}; + +// -------------------------------------------------------------------------------------------------------------------- +// Base DGL classes + +/** + Graphics context, definition depends on build type. + */ +struct GraphicsContext {}; + +/** + Idle callback. + */ +struct IdleCallback +{ + virtual ~IdleCallback() {} + virtual void idleCallback() = 0; +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#ifndef DONT_SET_USING_DGL_NAMESPACE + // If your code uses a lot of DGL classes, then this will obviously save you + // a lot of typing, but can be disabled by setting DONT_SET_USING_DGL_NAMESPACE. + using namespace DGL_NAMESPACE; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +#endif // DGL_BASE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Cairo.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Cairo.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,193 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_CAIRO_HPP_INCLUDED +#define DGL_CAIRO_HPP_INCLUDED + +#include "ImageBase.hpp" +#include "ImageBaseWidgets.hpp" + +#include + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Cairo Graphics context. + */ +struct CairoGraphicsContext : GraphicsContext +{ + cairo_t* handle; +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Cairo Image class. + + TODO ... + */ +class CairoImage : public ImageBase +{ +public: + /** + Constructor for a null Image. + */ + CairoImage(); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + CairoImage(const char* rawData, uint width, uint height, ImageFormat format); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + CairoImage(const char* rawData, const Size& size, ImageFormat format); + + /** + Constructor using another image data. + */ + CairoImage(const CairoImage& image); + + /** + Destructor. + */ + ~CairoImage() override; + + /** + Load raw image data from memory. + @note @a rawData must remain valid for the lifetime of this Image. + */ + void loadFromMemory(const char* rawData, + const Size& size, + ImageFormat format = kImageFormatBGRA) noexcept override; + + /** + Load PNG image from memory. + Image size is read from PNG contents. + @note @a pngData must remain valid for the lifetime of this Image. + */ + void loadFromPNG(const char* pngData, uint dataSize) noexcept; + + /** + Draw this image at position @a pos using the graphics context @a context. + */ + void drawAt(const GraphicsContext& context, const Point& pos) override; + + /** + Get the cairo surface currently associated with this image. + FIXME might be removed + */ + inline cairo_surface_t* getSurface() const noexcept + { + return surface; + } + + /** + TODO document this. + */ + CairoImage& operator=(const CairoImage& image) noexcept; + + // FIXME this should not be needed + inline void loadFromMemory(const char* rdata, uint w, uint h, ImageFormat fmt = kImageFormatBGRA) + { loadFromMemory(rdata, Size(w, h), fmt); }; + inline void draw(const GraphicsContext& context) + { drawAt(context, Point(0, 0)); }; + inline void drawAt(const GraphicsContext& context, int x, int y) + { drawAt(context, Point(x, y)); }; + +private: + cairo_surface_t* surface; + uchar* surfacedata; + int* datarefcount; +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + CairoWidget, handy class that takes graphics context during onDisplay and passes it in a new function. + */ +template +class CairoBaseWidget : public BaseWidget +{ +public: + /** + Constructor for a CairoSubWidget. + */ + explicit CairoBaseWidget(Widget* const parentGroupWidget); + + /** + Constructor for a CairoTopLevelWidget. + */ + explicit CairoBaseWidget(Window& windowToMapTo); + + /** + Constructor for a CairoStandaloneWindow without parent window. + */ + explicit CairoBaseWidget(Application& app); + + /** + Constructor for a CairoStandaloneWindow with parent window. + */ + explicit CairoBaseWidget(Application& app, Window& parentWindow); + + /** + Destructor. + */ + ~CairoBaseWidget() override {} + +protected: + /** + New virtual onDisplay function. + @see onDisplay + */ + virtual void onCairoDisplay(const CairoGraphicsContext& context) = 0; + +private: + /** + Widget display function. + Implemented internally to pass context into the drawing function. + */ + void onDisplay() override + { + const CairoGraphicsContext& context((const CairoGraphicsContext&)BaseWidget::getGraphicsContext()); + onCairoDisplay(context); + } + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoBaseWidget); +}; + +typedef CairoBaseWidget CairoSubWidget; +typedef CairoBaseWidget CairoTopLevelWidget; +typedef CairoBaseWidget CairoStandaloneWindow; + +// -------------------------------------------------------------------------------------------------------------------- + +typedef ImageBaseAboutWindow CairoImageAboutWindow; +typedef ImageBaseButton CairoImageButton; +typedef ImageBaseKnob CairoImageKnob; +typedef ImageBaseSlider CairoImageSlider; +typedef ImageBaseSwitch CairoImageSwitch; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Color.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Color.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,149 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_COLOR_HPP_INCLUDED +#define DGL_COLOR_HPP_INCLUDED + +#include "Base.hpp" + +struct NVGcolor; + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +/** + A color made from red, green, blue and alpha floating-point values in [0..1] range. +*/ +struct Color { + /** + Direct access to the color values. + */ + union { + float rgba[4]; + struct { float red, green, blue, alpha; }; + }; + + /** + Create solid black color. + */ + Color() noexcept; + + /** + Create a color from red, green, blue and alpha numeric values. + All values except alpha must be in [0..255] range, with alpha in [0..1] range. + */ + Color(int red, int green, int blue, float alpha = 1.0f) noexcept; + + /** + Create a color from red, green, blue and alpha floating-point values. + All values must in [0..1] range. + */ + Color(float red, float green, float blue, float alpha = 1.0f) noexcept; + + /** + Create a color by copying another color. + */ + Color(const Color& color) noexcept; + Color& operator=(const Color& color) noexcept; + + /** + Create a color by linearly interpolating two other colors. + */ + Color(const Color& color1, const Color& color2, float u) noexcept; + + /** + Create a new color based on this one but with a different alpha value. + */ + Color withAlpha(float alpha) const noexcept; + + /** + Create a new color based on this one but with subtracted numeric value on all elements. + Value must be in [0..255] range. + */ + Color minus(int value) const noexcept; + + /** + Create a new color based on this one but with subtracted floating-point value on all elements. + Value must be in [0..1] range. + */ + Color minus(float value) const noexcept; + + /** + Create a new color based on this one but with added numeric value on all elements. + Value must be in [0..255] range. + */ + Color plus(int value) const noexcept; + + /** + Create a new color based on this one but with added floating-point value on all elements. + Value must be in [0..1] range. + */ + Color plus(float value) const noexcept; + + /** + Create a new color based on this one but colors inverted. + */ + Color invert() const noexcept; + + /** + Create a color specified by hue, saturation and lightness. + Values must in [0..1] range. + */ + static Color fromHSL(float hue, float saturation, float lightness, float alpha = 1.0f); + + /** + Create a color from a HTML string like "#333" or "#112233". + */ + static Color fromHTML(const char* rgb, float alpha = 1.0f) noexcept; + + /** + Linearly interpolate this color against another. + */ + void interpolate(const Color& other, float u) noexcept; + + /** + Check if this color matches another. + @note Comparison is done within 8-bit color space. + */ + bool isEqual(const Color& color, bool withAlpha = true) noexcept; + bool isNotEqual(const Color& color, bool withAlpha = true) noexcept; + bool operator==(const Color& color) noexcept; + bool operator!=(const Color& color) noexcept; + + /** + Fix color bounds if needed. + */ + void fixBounds() noexcept; + + /** + Set this color for use in the next drawing operation for the provided context. + */ + void setFor(const GraphicsContext& context, bool includeAlpha = false); + + /** + @internal + Needed for NanoVG compatibility. + */ + Color(const NVGcolor&) noexcept; + operator NVGcolor() const noexcept; +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_COLOR_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/EventHandlers.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/EventHandlers.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,197 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_EVENT_HANDLERS_HPP_INCLUDED +#define DGL_EVENT_HANDLERS_HPP_INCLUDED + +#include "Widget.hpp" + +START_NAMESPACE_DGL + +/* NOTE none of these classes get assigned to a widget automatically + Manual plugging into Widget events is needed, like so: + + ``` + bool onMouse(const MouseEvent& ev) override + { + return ButtonEventHandler::mouseEvent(ev); + } + ``` +*/ + +// -------------------------------------------------------------------------------------------------------------------- + +class ButtonEventHandler +{ +public: + enum State { + kButtonStateDefault = 0x0, + kButtonStateHover = 0x1, + kButtonStateActive = 0x2, + kButtonStateActiveHover = kButtonStateActive|kButtonStateHover + }; + + class Callback + { + public: + virtual ~Callback() {} + virtual void buttonClicked(SubWidget* widget, int button) = 0; + }; + + explicit ButtonEventHandler(SubWidget* self); + virtual ~ButtonEventHandler(); + + bool isActive() noexcept; + void setActive(bool active, bool sendCallback) noexcept; + + bool isChecked() const noexcept; + void setChecked(bool checked, bool sendCallback) noexcept; + + bool isCheckable() const noexcept; + void setCheckable(bool checkable) noexcept; + + Point getLastClickPosition() const noexcept; + Point getLastMotionPosition() const noexcept; + + void setCallback(Callback* callback) noexcept; + + bool mouseEvent(const Widget::MouseEvent& ev); + bool motionEvent(const Widget::MotionEvent& ev); + +protected: + State getState() const noexcept; + void clearState() noexcept; + + virtual void stateChanged(State state, State oldState); + + void setInternalCallback(Callback* callback) noexcept; + void triggerUserCallback(SubWidget* widget, int button); + +private: + struct PrivateData; + PrivateData* const pData; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ButtonEventHandler) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +class KnobEventHandler +{ +public: + enum Orientation { + Horizontal, + Vertical, + Both + }; + + // NOTE hover not implemented yet + enum State { + kKnobStateDefault = 0x0, + kKnobStateHover = 0x1, + kKnobStateDragging = 0x2, + kKnobStateDraggingHover = kKnobStateDragging|kKnobStateHover + }; + + class Callback + { + public: + virtual ~Callback() {} + virtual void knobDragStarted(SubWidget* widget) = 0; + virtual void knobDragFinished(SubWidget* widget) = 0; + virtual void knobValueChanged(SubWidget* widget, float value) = 0; + virtual void knobDoubleClicked(SubWidget*) {}; + }; + + explicit KnobEventHandler(SubWidget* self); + explicit KnobEventHandler(SubWidget* self, const KnobEventHandler& other); + KnobEventHandler& operator=(const KnobEventHandler& other); + virtual ~KnobEventHandler(); + + // if setStep(1) has been called before, this returns true + bool isInteger() const noexcept; + + // returns raw value, is assumed to be scaled if using log + float getValue() const noexcept; + + // NOTE: value is assumed to be scaled if using log + virtual bool setValue(float value, bool sendCallback = false) noexcept; + + // returns 0-1 ranged value, already with log scale as needed + float getNormalizedValue() const noexcept; + + // NOTE: value is assumed to be scaled if using log + void setDefault(float def) noexcept; + + // NOTE: value is assumed to be scaled if using log + void setRange(float min, float max) noexcept; + + void setStep(float step) noexcept; + + void setUsingLogScale(bool yesNo) noexcept; + + Orientation getOrientation() const noexcept; + void setOrientation(Orientation orientation) noexcept; + + void setCallback(Callback* callback) noexcept; + + // default 200, higher means slower + void setMouseDeceleration(float accel) noexcept; + + bool mouseEvent(const Widget::MouseEvent& ev, double scaleFactor = 1.0); + bool motionEvent(const Widget::MotionEvent& ev, double scaleFactor = 1.0); + bool scrollEvent(const Widget::ScrollEvent& ev); + +protected: + State getState() const noexcept; + +private: + struct PrivateData; + PrivateData* const pData; + + /* not for use */ +#ifdef DISTRHO_PROPER_CPP11_SUPPORT + KnobEventHandler(KnobEventHandler& other) = delete; + KnobEventHandler(const KnobEventHandler& other) = delete; +#else + KnobEventHandler(KnobEventHandler& other); + KnobEventHandler(const KnobEventHandler& other); +#endif + + DISTRHO_LEAK_DETECTOR(KnobEventHandler) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +class SliderEventHandler +{ +public: + explicit SliderEventHandler(SubWidget* self); + virtual ~SliderEventHandler(); + +private: + struct PrivateData; + PrivateData* const pData; + + DISTRHO_LEAK_DETECTOR(SliderEventHandler) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_EVENT_HANDLERS_HPP_INCLUDED + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/FileBrowserDialog.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/FileBrowserDialog.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,28 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED +#define DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED + +#include "Base.hpp" + +START_NAMESPACE_DGL + +#include "../distrho/extra/FileBrowserDialogImpl.hpp" + +END_NAMESPACE_DGL + +#endif // DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Geometry.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Geometry.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,839 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_GEOMETRY_HPP_INCLUDED +#define DGL_GEOMETRY_HPP_INCLUDED + +#include "Base.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- +// Forward class names + +template class Line; +template class Circle; +template class Triangle; +template class Rectangle; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + DGL Point class. + + This class describes a single point in space, defined by an X and Y value. + */ +template +class Point +{ +public: + /** + Constructor for (0, 0) point. + */ + Point() noexcept; + + /** + Constructor using custom X and Y values. + */ + Point(const T& x, const T& y) noexcept; + + /** + Constructor using another Point class values. + */ + Point(const Point& pos) noexcept; + + /** + Get X value. + */ + const T& getX() const noexcept; + + /** + Get Y value. + */ + const T& getY() const noexcept; + + /** + Set X value to @a x. + */ + void setX(const T& x) noexcept; + + /** + Set Y value to @a y. + */ + void setY(const T& y) noexcept; + + /** + Set X and Y values to @a x and @a y respectively. + */ + void setPos(const T& x, const T& y) noexcept; + + /** + Set X and Y values according to @a pos. + */ + void setPos(const Point& pos) noexcept; + + /** + Move this point by @a x and @a y values. + */ + void moveBy(const T& x, const T& y) noexcept; + + /** + Move this point by @a pos. + */ + void moveBy(const Point& pos) noexcept; + + /** + Return true if point is (0, 0). + */ + bool isZero() const noexcept; + + /** + Return true if point is not (0, 0). + */ + bool isNotZero() const noexcept; + + Point operator+(const Point& pos) noexcept; + Point operator-(const Point& pos) noexcept; + Point& operator=(const Point& pos) noexcept; + Point& operator+=(const Point& pos) noexcept; + Point& operator-=(const Point& pos) noexcept; + bool operator==(const Point& pos) const noexcept; + bool operator!=(const Point& pos) const noexcept; + +private: + T x, y; + template friend class Line; + template friend class Circle; + template friend class Triangle; + template friend class Rectangle; +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + DGL Size class. + + This class describes a size, defined by a width and height value. + */ +template +class Size +{ +public: + /** + Constructor for null size (0x0). + */ + Size() noexcept; + + /** + Constructor using custom width and height values. + */ + Size(const T& width, const T& height) noexcept; + + /** + Constructor using another Size class values. + */ + Size(const Size& size) noexcept; + + /** + Get width. + */ + const T& getWidth() const noexcept; + + /** + Get height. + */ + const T& getHeight() const noexcept; + + /** + Set width. + */ + void setWidth(const T& width) noexcept; + + /** + Set height. + */ + void setHeight(const T& height) noexcept; + + /** + Set size to @a width and @a height. + */ + void setSize(const T& width, const T& height) noexcept; + + /** + Set size. + */ + void setSize(const Size& size) noexcept; + + /** + Grow size by @a multiplier. + */ + void growBy(double multiplier) noexcept; + + /** + Shrink size by @a divider. + */ + void shrinkBy(double divider) noexcept; + + /** + Return true if size is null (0x0). + An null size is also invalid. + */ + bool isNull() const noexcept; + + /** + Return true if size is not null (0x0). + A non-null size is still invalid if its width or height are negative. + */ + bool isNotNull() const noexcept; + + /** + Return true if size is valid (width and height are higher than zero). + */ + bool isValid() const noexcept; + + /** + Return true if size is invalid (width or height are lower or equal to zero). + An invalid size might not be null under some circumstances. + */ + bool isInvalid() const noexcept; + + Size toInt() const noexcept; + + Size operator+(const Size& size) noexcept; + Size operator-(const Size& size) noexcept; + Size& operator=(const Size& size) noexcept; + Size& operator+=(const Size& size) noexcept; + Size& operator-=(const Size& size) noexcept; + Size& operator*=(double m) noexcept; + Size& operator/=(double d) noexcept; + Size operator*(double m) const noexcept; + Size operator/(double m) const noexcept; + bool operator==(const Size& size) const noexcept; + bool operator!=(const Size& size) const noexcept; + +private: + T fWidth, fHeight; + template friend class Rectangle; +}; + +// ----------------------------------------------------------------------- + +/** + DGL Line class. + + This class describes a line, defined by two points. + */ +template +class Line +{ +public: + /** + Constructor for a null line ([0,0] to [0,0]). + */ + Line() noexcept; + + /** + Constructor using custom start X, start Y, end X and end Y values. + */ + Line(const T& startX, const T& startY, const T& endX, const T& endY) noexcept; + + /** + Constructor using custom start X, start Y and end pos values. + */ + Line(const T& startX, const T& startY, const Point& endPos) noexcept; + + /** + Constructor using custom start pos, end X and end Y values. + */ + Line(const Point& startPos, const T& endX, const T& endY) noexcept; + + /** + Constructor using custom start and end pos values. + */ + Line(const Point& startPos, const Point& endPos) noexcept; + + /** + Constructor using another Line class values. + */ + Line(const Line& line) noexcept; + + /** + Get start X value. + */ + const T& getStartX() const noexcept; + + /** + Get start Y value. + */ + const T& getStartY() const noexcept; + + /** + Get end X value. + */ + const T& getEndX() const noexcept; + + /** + Get end Y value. + */ + const T& getEndY() const noexcept; + + /** + Get start position. + */ + const Point& getStartPos() const noexcept; + + /** + Get end position. + */ + const Point& getEndPos() const noexcept; + + /** + Set start X value to @a x. + */ + void setStartX(const T& x) noexcept; + + /** + Set start Y value to @a y. + */ + void setStartY(const T& y) noexcept; + + /** + Set start X and Y values to @a x and @a y respectively. + */ + void setStartPos(const T& x, const T& y) noexcept; + + /** + Set start X and Y values according to @a pos. + */ + void setStartPos(const Point& pos) noexcept; + + /** + Set end X value to @a x. + */ + void setEndX(const T& x) noexcept; + + /** + Set end Y value to @a y. + */ + void setEndY(const T& y) noexcept; + + /** + Set end X and Y values to @a x and @a y respectively. + */ + void setEndPos(const T& x, const T& y) noexcept; + + /** + Set end X and Y values according to @a pos. + */ + void setEndPos(const Point& pos) noexcept; + + /** + Move this line by @a x and @a y values. + */ + void moveBy(const T& x, const T& y) noexcept; + + /** + Move this line by @a pos. + */ + void moveBy(const Point& pos) noexcept; + + /** + Return true if line is null (start and end pos are equal). + */ + bool isNull() const noexcept; + + /** + Return true if line is not null (start and end pos are different). + */ + bool isNotNull() const noexcept; + +#ifndef DPF_TEST_POINT_CPP + /** + Draw this line using the provided graphics context, optionally specifying line width. + */ + void draw(const GraphicsContext& context, T width = 1); +#endif + + Line& operator=(const Line& line) noexcept; + bool operator==(const Line& line) const noexcept; + bool operator!=(const Line& line) const noexcept; + +#ifndef DPF_TEST_POINT_CPP + /** + Draw this line using the current OpenGL state.@n + DEPRECATED Please use draw(const GraphicsContext&) instead. + */ + DISTRHO_DEPRECATED_BY("draw(const GraphicsContext&)") + void draw(); +#endif + +private: + Point posStart, posEnd; +}; + +// ----------------------------------------------------------------------- + +/** + DGL Circle class. + + This class describes a circle, defined by position, size and a minimum of 3 segments. + + TODO: report if circle starts at top-left, bottom-right or center. + and size grows from which point? + */ +template +class Circle +{ +public: + /** + Constructor for a null circle. + */ + Circle() noexcept; + + /** + Constructor using custom X, Y and size values. + */ + Circle(const T& x, const T& y, const float size, const uint numSegments = 300); + + /** + Constructor using custom position and size values. + */ + Circle(const Point& pos, const float size, const uint numSegments = 300); + + /** + Constructor using another Circle class values. + */ + Circle(const Circle& cir) noexcept; + + /** + Get X value. + */ + const T& getX() const noexcept; + + /** + Get Y value. + */ + const T& getY() const noexcept; + + /** + Get position. + */ + const Point& getPos() const noexcept; + + /** + Set X value to @a x. + */ + void setX(const T& x) noexcept; + + /** + Set Y value to @a y. + */ + void setY(const T& y) noexcept; + + /** + Set X and Y values to @a x and @a y respectively. + */ + void setPos(const T& x, const T& y) noexcept; + + /** + Set X and Y values according to @a pos. + */ + void setPos(const Point& pos) noexcept; + + /** + Get size. + */ + float getSize() const noexcept; + + /** + Set size. + @note Must always be > 0 + */ + void setSize(const float size) noexcept; + + /** + Get the current number of line segments that make this circle. + */ + uint getNumSegments() const noexcept; + + /** + Set the number of line segments that will make this circle. + @note Must always be >= 3 + */ + void setNumSegments(const uint num); + + /** + Draw this circle using the provided graphics context. + */ + void draw(const GraphicsContext& context); + + /** + Draw lines (outline of this circle) using the provided graphics context, optionally specifying line width. + */ + void drawOutline(const GraphicsContext& context, T lineWidth = 1); + + Circle& operator=(const Circle& cir) noexcept; + bool operator==(const Circle& cir) const noexcept; + bool operator!=(const Circle& cir) const noexcept; + +#ifndef DPF_TEST_POINT_CPP + /** + Draw this circle using the current OpenGL state.@n + DEPRECATED Please use draw(const GraphicsContext&) instead. + */ + DISTRHO_DEPRECATED_BY("draw(const GraphicsContext&)") + void draw(); + + /** + Draw lines (outline of this circle) using the current OpenGL state.@n + DEPRECATED Please use drawOutline(const GraphicsContext&,T) instead. + */ + DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)") + void drawOutline(); +#endif + +private: + Point fPos; + float fSize; + uint fNumSegments; + + // cached values + float fTheta, fCos, fSin; +}; + +// ----------------------------------------------------------------------- + +/** + DGL Triangle class. + + This class describes a triangle, defined by 3 points. + */ +template +class Triangle +{ +public: + /** + Constructor for a null triangle. + */ + Triangle() noexcept; + + /** + Constructor using custom X and Y values. + */ + Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept; + + /** + Constructor using custom position values. + */ + Triangle(const Point& pos1, const Point& pos2, const Point& pos3) noexcept; + + /** + Constructor using another Triangle class values. + */ + Triangle(const Triangle& tri) noexcept; + + /** + Return true if triangle is null (all its points are equal). + An null triangle is also invalid. + */ + bool isNull() const noexcept; + + /** + Return true if triangle is not null (one its points is different from the others). + A non-null triangle is still invalid if two of its points are equal. + */ + bool isNotNull() const noexcept; + + /** + Return true if triangle is valid (all its points are different). + */ + bool isValid() const noexcept; + + /** + Return true if triangle is invalid (one or two of its points are equal). + An invalid triangle might not be null under some circumstances. + */ + bool isInvalid() const noexcept; + + /** + Draw this triangle using the provided graphics context. + */ + void draw(const GraphicsContext& context); + + /** + Draw lines (outline of this triangle) using the provided graphics context, optionally specifying line width. + */ + void drawOutline(const GraphicsContext& context, T lineWidth = 1); + + Triangle& operator=(const Triangle& tri) noexcept; + bool operator==(const Triangle& tri) const noexcept; + bool operator!=(const Triangle& tri) const noexcept; + +#ifndef DPF_TEST_POINT_CPP + /** + Draw this triangle using the current OpenGL state.@n + DEPRECATED Please use draw(const GraphicsContext&) instead. + */ + DISTRHO_DEPRECATED_BY("draw(const GraphicsContext&)") + void draw(); + + /** + Draw lines (outline of this triangle) using the current OpenGL state.@n + DEPRECATED Please use drawOutline(const GraphicsContext&,T) instead. + */ + DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)") + void drawOutline(); +#endif + +private: + Point pos1, pos2, pos3; +}; + +// ----------------------------------------------------------------------- + +/** + DGL Rectangle class. + + This class describes a rectangle, defined by a starting point and a size. + */ +template +class Rectangle +{ +public: + /** + Constructor for a null rectangle. + */ + Rectangle() noexcept; + + /** + Constructor using custom X, Y, width and height values. + */ + Rectangle(const T& x, const T& y, const T& width, const T& height) noexcept; + + /** + Constructor using custom X, Y and size values. + */ + Rectangle(const T& x, const T& y, const Size& size) noexcept; + + /** + Constructor using custom pos, width and height values. + */ + Rectangle(const Point& pos, const T& width, const T& height) noexcept; + + /** + Constructor using custom position and size. + */ + Rectangle(const Point& pos, const Size& size) noexcept; + + /** + Constructor using another Rectangle class values. + */ + Rectangle(const Rectangle& rect) noexcept; + + /** + Get X value. + */ + const T& getX() const noexcept; + + /** + Get Y value. + */ + const T& getY() const noexcept; + + /** + Get width. + */ + const T& getWidth() const noexcept; + + /** + Get height. + */ + const T& getHeight() const noexcept; + + /** + Get position. + */ + const Point& getPos() const noexcept; + + /** + Get size. + */ + const Size& getSize() const noexcept; + + /** + Set X value as @a x. + */ + void setX(const T& x) noexcept; + + /** + Set Y value as @a y. + */ + void setY(const T& y) noexcept; + + /** + Set X and Y values as @a x and @a y respectively. + */ + void setPos(const T& x, const T& y) noexcept; + + /** + Set X and Y values according to @a pos. + */ + void setPos(const Point& pos) noexcept; + + /** + Move this rectangle by @a x and @a y values. + */ + void moveBy(const T& x, const T& y) noexcept; + + /** + Move this rectangle by @a pos. + */ + void moveBy(const Point& pos) noexcept; + + /** + Set width. + */ + void setWidth(const T& width) noexcept; + + /** + Set height. + */ + void setHeight(const T& height) noexcept; + + /** + Set size using @a width and @a height. + */ + void setSize(const T& width, const T& height) noexcept; + + /** + Set size. + */ + void setSize(const Size& size) noexcept; + + /** + Grow size by @a multiplier. + */ + void growBy(double multiplier) noexcept; + + /** + Shrink size by @a divider. + */ + void shrinkBy(double divider) noexcept; + + /** + Set rectangle using @a pos and @a size. + */ + void setRectangle(const Point& pos, const Size& size) noexcept; + + /** + Set rectangle. + */ + void setRectangle(const Rectangle& rect) noexcept; + + /** + Check if this rectangle contains the point defined by @a X and @a Y. + */ + bool contains(const T& x, const T& y) const noexcept; + + /** + Check if this rectangle contains the point @a pos. + */ + bool contains(const Point& pos) const noexcept; + + /** + Check if this rectangle contains the point @a pos affected by a custom scale. + */ + bool containsAfterScaling(const Point& pos, double scaling) const noexcept; + + /** + Check if this rectangle contains the point @a pos of another type. + */ + template + bool contains(const Point& pos) const noexcept; + + /** + Check if this rectangle contains X. + */ + bool containsX(const T& x) const noexcept; + + /** + Check if this rectangle contains Y. + */ + bool containsY(const T& y) const noexcept; + + /** + Return true if size is null (0x0). + An null size is also invalid. + */ + bool isNull() const noexcept; + + /** + Return true if size is not null (0x0). + A non-null size is still invalid if its width or height are negative. + */ + bool isNotNull() const noexcept; + + /** + Return true if size is valid (width and height are higher than zero). + */ + bool isValid() const noexcept; + + /** + Return true if size is invalid (width or height are lower or equal to zero). + An invalid size might not be null under some circumstances. + */ + bool isInvalid() const noexcept; + + /** + Draw this rectangle using the provided graphics context. + */ + void draw(const GraphicsContext& context); + + /** + Draw lines (outline of this rectangle) using the provided graphics context, optionally specifying line width. + */ + void drawOutline(const GraphicsContext& context, T lineWidth = 1); + + Rectangle& operator=(const Rectangle& rect) noexcept; + Rectangle& operator*=(double m) noexcept; + Rectangle& operator/=(double d) noexcept; + bool operator==(const Rectangle& size) const noexcept; + bool operator!=(const Rectangle& size) const noexcept; + + /** + Draw this rectangle using the current OpenGL state.@n + DEPRECATED Please use draw(const GraphicsContext&) instead. + */ + DISTRHO_DEPRECATED_BY("draw(const GraphicsContext&)") + void draw(); + + /** + Draw lines (outline of this rectangle) using the current OpenGL state.@n + DEPRECATED Please use drawOutline(const GraphicsContext&,T) instead. + */ + DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)") + void drawOutline(); + +private: + Point pos; + Size size; +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_GEOMETRY_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Image.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Image.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,36 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_IMAGE_HPP_INCLUDED +#define DGL_IMAGE_HPP_INCLUDED + +#ifdef DGL_CAIRO +#include "Cairo.hpp" +#else +#include "OpenGL.hpp" +#endif + +START_NAMESPACE_DGL + +#ifdef DGL_CAIRO +typedef CairoImage Image; +#else +typedef OpenGLImage Image; +#endif + +END_NAMESPACE_DGL + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/ImageBase.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/ImageBase.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,156 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_IMAGE_BASE_HPP_INCLUDED +#define DGL_IMAGE_BASE_HPP_INCLUDED + +#include "Geometry.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +enum ImageFormat { + kImageFormatNull, + kImageFormatGrayscale, + kImageFormatBGR, + kImageFormatBGRA, + kImageFormatRGB, + kImageFormatRGBA, +}; + +/** + Base DGL Image class. + + This is an Image class that handles raw image data in pixels. + It is an abstract class that provides the common methods to build on top. + Cairo and OpenGL Image classes are based upon this one. + + @see CairoImage, OpenGLImage + */ +class ImageBase +{ +protected: + /** + Constructor for a null Image. + */ + ImageBase(); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + ImageBase(const char* rawData, uint width, uint height, ImageFormat format); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + ImageBase(const char* rawData, const Size& size, ImageFormat format); + + /** + Constructor using another image data. + */ + ImageBase(const ImageBase& image); + +public: + /** + Destructor. + */ + virtual ~ImageBase(); + + /** + Check if this image is valid. + */ + bool isValid() const noexcept; + + /** + Check if this image is not valid. + */ + bool isInvalid() const noexcept; + + /** + Get width. + */ + uint getWidth() const noexcept; + + /** + Get height. + */ + uint getHeight() const noexcept; + + /** + Get size. + */ + const Size& getSize() const noexcept; + + /** + Get the raw image data. + */ + const char* getRawData() const noexcept; + + /** + Get the image format. + */ + ImageFormat getFormat() const noexcept; + + /** + Load image data from memory. + @note @a rawData must remain valid for the lifetime of this Image. + */ + void loadFromMemory(const char* rawData, uint width, uint height, ImageFormat format = kImageFormatBGRA) noexcept; + + /** + Load image data from memory. + @note @a rawData must remain valid for the lifetime of this Image. + */ + virtual void loadFromMemory(const char* rawData, + const Size& size, + ImageFormat format = kImageFormatBGRA) noexcept; + + /** + Draw this image at (0, 0) point using the current OpenGL context. + */ + void draw(const GraphicsContext& context); + + /** + Draw this image at (x, y) point using the current OpenGL context. + */ + void drawAt(const GraphicsContext& context, int x, int y); + + /** + Draw this image at position @a pos using the current OpenGL context. + */ + virtual void drawAt(const GraphicsContext& context, const Point& pos) = 0; + + /** + TODO document this. + */ + ImageBase& operator=(const ImageBase& image) noexcept; + bool operator==(const ImageBase& image) const noexcept; + bool operator!=(const ImageBase& image) const noexcept; + +protected: + const char* rawData; + Size size; + ImageFormat format; +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_IMAGE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/ImageBaseWidgets.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/ImageBaseWidgets.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,258 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_IMAGE_BASE_WIDGETS_HPP_INCLUDED +#define DGL_IMAGE_BASE_WIDGETS_HPP_INCLUDED + +#include "EventHandlers.hpp" +#include "StandaloneWindow.hpp" +#include "SubWidget.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +/** + DGL Image About Window class. + + This is a Window attached (transient) to another Window that simply shows an Image as its content. + It is typically used for "about this project" style pop-up Windows. + + Pressing 'Esc' or clicking anywhere on the window will automatically close it. + + @see CairoImageAboutWindow, OpenGLImageAboutWindow, Window::runAsModal(bool) + */ +template +class ImageBaseAboutWindow : public StandaloneWindow +{ +public: + /** + Constructor taking an existing Window as the parent transient window and an optional image. + If @a image is valid, the about window size will match the image size. + */ + explicit ImageBaseAboutWindow(Window& transientParentWindow, const ImageType& image = ImageType()); + + /** + Constructor taking a top-level-widget's Window as the parent transient window and an optional image. + If @a image is valid, the about window size will match the image size. + */ + explicit ImageBaseAboutWindow(TopLevelWidget* topLevelWidget, const ImageType& image = ImageType()); + + /** + Set a new image to use as background for this window. + Window size will adjust to match the image size. + */ + void setImage(const ImageType& image); + +protected: + void onDisplay() override; + bool onKeyboard(const KeyboardEvent&) override; + bool onMouse(const MouseEvent&) override; + +private: + ImageType img; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageBaseAboutWindow) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + DGL Image Button class. + + This is a typical button, where the drawing comes from a pregenerated set of images. + The button can be under "normal", "hover" and "down" states, with one separate image possible for each. + + The event logic for this button comes from the ButtonEventHandler class. + + @see CairoImageButton, OpenGLImageButton + */ +template +class ImageBaseButton : public SubWidget, + public ButtonEventHandler +{ +public: + class Callback + { + public: + virtual ~Callback() {} + virtual void imageButtonClicked(ImageBaseButton* imageButton, int button) = 0; + }; + + explicit ImageBaseButton(Widget* parentWidget, const ImageType& image); + explicit ImageBaseButton(Widget* parentWidget, const ImageType& imageNormal, const ImageType& imageDown); + explicit ImageBaseButton(Widget* parentWidget, const ImageType& imageNormal, const ImageType& imageHover, const ImageType& imageDown); + + ~ImageBaseButton() override; + + void setCallback(Callback* callback) noexcept; + +protected: + void onDisplay() override; + bool onMouse(const MouseEvent&) override; + bool onMotion(const MotionEvent&) override; + +private: + struct PrivateData; + PrivateData* const pData; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageBaseButton) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + DGL Image Knob class. + + This is a typical knob/dial, where the drawing comes from a pregenerated image "filmstrip". + The knob's "filmstrip" image can be either horizontal or vertical, + with the number of steps automatically based on the largest value (ie, horizontal if width>height, vertical if height>width). + There are no different images for "hover" or "down" states. + + The event logic for this knob comes from the KnobEventHandler class. + + @see CairoImageKnob, OpenGLImageKnob + */ +template +class ImageBaseKnob : public SubWidget, + public KnobEventHandler +{ +public: + class Callback + { + public: + virtual ~Callback() {} + virtual void imageKnobDragStarted(ImageBaseKnob* imageKnob) = 0; + virtual void imageKnobDragFinished(ImageBaseKnob* imageKnob) = 0; + virtual void imageKnobValueChanged(ImageBaseKnob* imageKnob, float value) = 0; + }; + + explicit ImageBaseKnob(Widget* parentWidget, const ImageType& image, Orientation orientation = Vertical) noexcept; + explicit ImageBaseKnob(const ImageBaseKnob& imageKnob); + ImageBaseKnob& operator=(const ImageBaseKnob& imageKnob); + ~ImageBaseKnob() override; + + void setCallback(Callback* callback) noexcept; + void setImageLayerCount(uint count) noexcept; + void setRotationAngle(int angle); + bool setValue(float value, bool sendCallback = false) noexcept override; + +protected: + void onDisplay() override; + bool onMouse(const MouseEvent&) override; + bool onMotion(const MotionEvent&) override; + bool onScroll(const ScrollEvent&) override; + +private: + struct PrivateData; + PrivateData* const pData; + + DISTRHO_LEAK_DETECTOR(ImageBaseKnob) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +// note set range and step before setting the value + +template +class ImageBaseSlider : public SubWidget +{ +public: + class Callback + { + public: + virtual ~Callback() {} + virtual void imageSliderDragStarted(ImageBaseSlider* imageSlider) = 0; + virtual void imageSliderDragFinished(ImageBaseSlider* imageSlider) = 0; + virtual void imageSliderValueChanged(ImageBaseSlider* imageSlider, float value) = 0; + }; + + explicit ImageBaseSlider(Widget* parentWidget, const ImageType& image) noexcept; + ~ImageBaseSlider() override; + + float getValue() const noexcept; + void setValue(float value, bool sendCallback = false) noexcept; + void setDefault(float def) noexcept; + + void setStartPos(const Point& startPos) noexcept; + void setStartPos(int x, int y) noexcept; + void setEndPos(const Point& endPos) noexcept; + void setEndPos(int x, int y) noexcept; + + void setCheckable(bool checkable) noexcept; + void setInverted(bool inverted) noexcept; + void setRange(float min, float max) noexcept; + void setStep(float step) noexcept; + + void setCallback(Callback* callback) noexcept; + +protected: + void onDisplay() override; + bool onMouse(const MouseEvent&) override; + bool onMotion(const MotionEvent&) override; + +private: + struct PrivateData; + PrivateData* const pData; + + // these should not be used + void setAbsoluteX(int) const noexcept {} + void setAbsoluteY(int) const noexcept {} + void setAbsolutePos(int, int) const noexcept {} + void setAbsolutePos(const Point&) const noexcept {} + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageBaseSlider) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +template +class ImageBaseSwitch : public SubWidget +{ +public: + class Callback + { + public: + virtual ~Callback() {} + virtual void imageSwitchClicked(ImageBaseSwitch* imageSwitch, bool down) = 0; + }; + + explicit ImageBaseSwitch(Widget* parentWidget, const ImageType& imageNormal, const ImageType& imageDown) noexcept; + explicit ImageBaseSwitch(const ImageBaseSwitch& imageSwitch) noexcept; + ImageBaseSwitch& operator=(const ImageBaseSwitch& imageSwitch) noexcept; + ~ImageBaseSwitch() override; + + bool isDown() const noexcept; + void setDown(bool down) noexcept; + + void setCallback(Callback* callback) noexcept; + +protected: + void onDisplay() override; + bool onMouse(const MouseEvent&) override; + +private: + struct PrivateData; + PrivateData* const pData; + + DISTRHO_LEAK_DETECTOR(ImageBaseSwitch) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_IMAGE_BASE_WIDGETS_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/ImageWidgets.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/ImageWidgets.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,41 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_IMAGE_WIDGETS_HPP_INCLUDED +#define DGL_IMAGE_WIDGETS_HPP_INCLUDED + +#include "Image.hpp" +#include "ImageBaseWidgets.hpp" + +START_NAMESPACE_DGL + +#ifdef DGL_CAIRO +typedef CairoImageAboutWindow ImageAboutWindow; +typedef CairoImageButton ImageButton; +typedef CairoImageKnob ImageKnob; +typedef CairoImageSlider ImageSlider; +typedef CairoImageSwitch ImageSwitch; +#else +typedef OpenGLImageAboutWindow ImageAboutWindow; +typedef OpenGLImageButton ImageButton; +typedef OpenGLImageKnob ImageKnob; +typedef OpenGLImageSlider ImageSlider; +typedef OpenGLImageSwitch ImageSwitch; +#endif + +END_NAMESPACE_DGL + +#endif // DGL_IMAGE_WIDGETS_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Layout.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Layout.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,71 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_LAYOUT_HPP_INCLUDED +#define DGL_LAYOUT_HPP_INCLUDED + +#include "Geometry.hpp" + +#include + +START_NAMESPACE_DGL + +class SubWidget; + +// -------------------------------------------------------------------------------------------------------------------- + +// NOTE: under development, API to be finalized and documented soon + +enum SizeHint { + Expanding, + Fixed +}; + +struct SubWidgetWithSizeHint { + SubWidget* widget; + SizeHint sizeHint; +}; + +template +struct Layout +{ + std::list widgets; + uint setAbsolutePos(int x, int y, uint padding); + void setSize(uint size, uint padding); +}; + +typedef Layout HorizontalLayout; +typedef Layout VerticalLayout; + +struct HorizontallyStackedVerticalLayout +{ + std::list items; + Size adjustSize(uint padding); // TODO + void setAbsolutePos(int x, int y, uint padding); +}; + +struct VerticallyStackedHorizontalLayout +{ + std::list items; + Size adjustSize(uint padding); + void setAbsolutePos(int x, int y, uint padding); +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_LAYOUT_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Makefile Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,273 @@ +#!/usr/bin/make -f +# Makefile for DGL # +# ---------------- # +# Created by falkTX +# + +include ../Makefile.base.mk + +# --------------------------------------------------------------------------------------------------------------------- + +BUILD_C_FLAGS += $(DGL_FLAGS) -I. -Isrc +BUILD_CXX_FLAGS += $(DGL_FLAGS) -I. -Isrc -DDONT_SET_USING_DGL_NAMESPACE -Wno-unused-parameter +BUILD_CXX_FLAGS += -Isrc/pugl-upstream/include +LINK_FLAGS += $(DGL_LIBS) + +ifeq ($(MACOS),true) +BUILD_CXX_FLAGS += -Wno-deprecated-declarations +else +PUGL_EXTRA_FLAGS = -Wno-extra -Wmissing-field-initializers +endif + +# ifneq ($(MACOS_OLD),true) +# needed by sofd right now, fix later +# BUILD_CXX_FLAGS += -Wno-type-limits -fpermissive +# endif + +# --------------------------------------------------------------------------------------------------------------------- + +ifeq ($(MODGUI_BUILD),true) +BUILD_DIR_SUFFIX = -modgui +endif + +BUILD_DIR = ../build$(BUILD_DIR_SUFFIX) + +# --------------------------------------------------------------------------------------------------------------------- + +OBJS_common = \ + $(BUILD_DIR)/dgl/Application.cpp.o \ + $(BUILD_DIR)/dgl/ApplicationPrivateData.cpp.o \ + $(BUILD_DIR)/dgl/Color.cpp.o \ + $(BUILD_DIR)/dgl/EventHandlers.cpp.o \ + $(BUILD_DIR)/dgl/Geometry.cpp.o \ + $(BUILD_DIR)/dgl/ImageBase.cpp.o \ + $(BUILD_DIR)/dgl/ImageBaseWidgets.cpp.o \ + $(BUILD_DIR)/dgl/Layout.cpp.o \ + $(BUILD_DIR)/dgl/Resources.cpp.o \ + $(BUILD_DIR)/dgl/SubWidget.cpp.o \ + $(BUILD_DIR)/dgl/SubWidgetPrivateData.cpp.o \ + $(BUILD_DIR)/dgl/TopLevelWidget.cpp.o \ + $(BUILD_DIR)/dgl/TopLevelWidgetPrivateData.cpp.o \ + $(BUILD_DIR)/dgl/Widget.cpp.o \ + $(BUILD_DIR)/dgl/WidgetPrivateData.cpp.o \ + $(BUILD_DIR)/dgl/Window.cpp.o \ + $(BUILD_DIR)/dgl/WindowPrivateData.cpp.o + +# --------------------------------------------------------------------------------------------------------------------- + +OBJS_cairo = $(OBJS_common) \ + $(BUILD_DIR)/dgl/Cairo.cpp.cairo.o + +ifeq ($(MACOS),true) +OBJS_cairo += $(BUILD_DIR)/dgl/pugl.mm.cairo.o +else +OBJS_cairo += $(BUILD_DIR)/dgl/pugl.cpp.cairo.o +endif + +# --------------------------------------------------------------------------------------------------------------------- + +OBJS_opengl = $(OBJS_common) \ + $(BUILD_DIR)/dgl/OpenGL.cpp.opengl.o \ + $(BUILD_DIR)/dgl/NanoVG.cpp.opengl.o + +ifeq ($(MACOS),true) +OBJS_opengl += $(BUILD_DIR)/dgl/pugl.mm.opengl.o +else +OBJS_opengl += $(BUILD_DIR)/dgl/pugl.cpp.opengl.o +endif + +# --------------------------------------------------------------------------------------------------------------------- + +OBJS_opengl3 = $(OBJS_common) \ + $(BUILD_DIR)/dgl/OpenGL.cpp.opengl3.o \ + $(BUILD_DIR)/dgl/NanoVG.cpp.opengl3.o + +ifeq ($(MACOS),true) +OBJS_opengl3 += $(BUILD_DIR)/dgl/pugl.mm.opengl3.o +else +OBJS_opengl3 += $(BUILD_DIR)/dgl/pugl.cpp.opengl3.o +endif + +# --------------------------------------------------------------------------------------------------------------------- + +OBJS_stub = $(OBJS_common) + +ifeq ($(MACOS),true) +OBJS_stub += $(BUILD_DIR)/dgl/pugl.mm.o +else +OBJS_stub += $(BUILD_DIR)/dgl/pugl.cpp.o +endif + +# --------------------------------------------------------------------------------------------------------------------- + +OBJS_vulkan = $(OBJS_common) \ + $(BUILD_DIR)/dgl/Vulkan.cpp.vulkan.o + +ifeq ($(MACOS),true) +OBJS_vulkan += $(BUILD_DIR)/dgl/pugl.mm.vulkan.o +else +OBJS_vulkan += $(BUILD_DIR)/dgl/pugl.cpp.vulkan.o +endif + +# --------------------------------------------------------------------------------------------------------------------- + +ifeq ($(HAVE_CAIRO),true) +TARGETS += $(BUILD_DIR)/libdgl-cairo.a +endif + +ifeq ($(HAVE_OPENGL),true) +TARGETS += $(BUILD_DIR)/libdgl-opengl.a +# Compat name, to be removed soon +TARGETS += $(BUILD_DIR)/libdgl.a +endif + +ifeq ($(HAVE_STUB),true) +TARGETS += $(BUILD_DIR)/libdgl-stub.a +endif + +ifeq ($(HAVE_VULKAN),true) +TARGETS += $(BUILD_DIR)/libdgl-vulkan.a +endif + +# --------------------------------------------------------------------------------------------------------------------- + +all: $(TARGETS) + +cairo: $(BUILD_DIR)/libdgl-cairo.a +opengl: $(BUILD_DIR)/libdgl-opengl.a +opengl3: $(BUILD_DIR)/libdgl-opengl3.a +stub: $(BUILD_DIR)/libdgl-stub.a +vulkan: $(BUILD_DIR)/libdgl-vulkan.a + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/libdgl-cairo.a: $(OBJS_cairo) + -@mkdir -p $(BUILD_DIR) + @echo "Creating libdgl-cairo.a" + $(SILENT)rm -f $@ + $(SILENT)$(AR) crs $@ $^ + +$(BUILD_DIR)/libdgl-opengl.a: $(OBJS_opengl) + -@mkdir -p $(BUILD_DIR) + @echo "Creating libdgl-opengl.a" + $(SILENT)rm -f $@ + $(SILENT)$(AR) crs $@ $^ + +$(BUILD_DIR)/libdgl-opengl3.a: $(OBJS_opengl3) + -@mkdir -p $(BUILD_DIR) + @echo "Creating libdgl-opengl3.a" + $(SILENT)rm -f $@ + $(SILENT)$(AR) crs $@ $^ + +$(BUILD_DIR)/libdgl-stub.a: $(OBJS_stub) + -@mkdir -p $(BUILD_DIR) + @echo "Creating libdgl-stub.a" + $(SILENT)rm -f $@ + $(SILENT)$(AR) crs $@ $^ + +$(BUILD_DIR)/libdgl-vulkan.a: $(OBJS_vulkan) + -@mkdir -p $(BUILD_DIR) + @echo "Creating libdgl-vulkan.a" + $(SILENT)rm -f $@ + $(SILENT)$(AR) crs $@ $^ + +# Compat name, to be removed soon +$(BUILD_DIR)/libdgl.a: $(BUILD_DIR)/libdgl-opengl.a + @echo "Symlinking libdgl.a" + $(SILENT)ln -sf $< $@ + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/dgl/%.c.o: src/%.c + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $<" + $(SILENT)$(CC) $< $(BUILD_C_FLAGS) -c -o $@ + +$(BUILD_DIR)/dgl/%.cpp.o: src/%.cpp + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $<" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ + +$(BUILD_DIR)/dgl/%.mm.o: src/%.mm + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $<" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -ObjC++ -o $@ + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/dgl/pugl.cpp.o: src/pugl.cpp + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $<" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) -c -o $@ + +$(BUILD_DIR)/dgl/pugl.mm.o: src/pugl.mm + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $<" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) -c -ObjC++ -o $@ + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/dgl/%.cpp.cairo.o: src/%.cpp + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (Cairo variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(CAIRO_FLAGS) -DDGL_CAIRO -c -o $@ + +$(BUILD_DIR)/dgl/%.mm.cairo.o: src/%.mm + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (Cairo variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(CAIRO_FLAGS) -DDGL_CAIRO -c -ObjC++ -o $@ + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/dgl/%.cpp.opengl.o: src/%.cpp + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (OpenGL variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(OPENGL_FLAGS) -DDGL_OPENGL -c -o $@ + +$(BUILD_DIR)/dgl/%.mm.opengl.o: src/%.mm + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (OpenGL variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(OPENGL_FLAGS) -DDGL_OPENGL -c -ObjC++ -o $@ + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/dgl/%.cpp.opengl3.o: src/%.cpp + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (OpenGL3 variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(OPENGL_FLAGS) -DDGL_OPENGL -DDGL_USE_OPENGL3 -c -o $@ + +$(BUILD_DIR)/dgl/%.mm.opengl3.o: src/%.mm + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (OpenGL3 variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(OPENGL_FLAGS) -DDGL_OPENGL -DDGL_USE_OPENGL3 -c -ObjC++ -o $@ + +# --------------------------------------------------------------------------------------------------------------------- + +$(BUILD_DIR)/dgl/%.cpp.vulkan.o: src/%.cpp + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (Vulkan variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(VULKAN_FLAGS) -DDGL_VULKAN -c -o $@ + +$(BUILD_DIR)/dgl/%.mm.vulkan.o: src/%.mm + -@mkdir -p $(BUILD_DIR)/dgl + @echo "Compiling $< (Vulkan variant)" + $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(PUGL_EXTRA_FLAGS) $(VULKAN_FLAGS) -DDGL_VULKAN -c -ObjC++ -o $@ + +# --------------------------------------------------------------------------------------------------------------------- + +clean: + rm -rf $(BUILD_DIR)/dgl $(BUILD_DIR)/libdgl*.* + +debug: + $(MAKE) DEBUG=true + +# --------------------------------------------------------------------------------------------------------------------- + +-include $(OBJS_common:%.o=%.d) +-include $(OBJS_cairo:%.o=%.d) +-include $(OBJS_opengl:%.o=%.d) +-include $(OBJS_opengl3:%.o=%.d) +-include $(OBJS_stub:%.o=%.d) +-include $(OBJS_vulkan:%.o=%.d) + +# --------------------------------------------------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/NanoVG.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/NanoVG.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,999 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_NANO_WIDGET_HPP_INCLUDED +#define DGL_NANO_WIDGET_HPP_INCLUDED + +#include "Color.hpp" +#include "OpenGL.hpp" +#include "SubWidget.hpp" +#include "TopLevelWidget.hpp" +#include "StandaloneWindow.hpp" + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4661) /* instantiated template classes whose methods are defined elsewhere */ +#endif + +#ifndef DGL_NO_SHARED_RESOURCES +# define NANOVG_DEJAVU_SANS_TTF "__dpf_dejavusans_ttf__" +#endif + +struct NVGcontext; +struct NVGpaint; + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- +// Forward class names + +class NanoVG; + +// ----------------------------------------------------------------------- +// Helper methods + +/** + Create a NanoVG context using the DPF-provided NanoVG library. + On Windows this will load a few extra OpenGL functions required for NanoVG to work. + */ +NVGcontext* nvgCreateGL(int flags); + +// ----------------------------------------------------------------------- +// NanoImage + +/** + NanoVG Image class. + + This implements NanoVG images as a C++ class where deletion is handled automatically. + Images need to be created within a NanoVG or NanoWidget class. + */ +class NanoImage +{ +private: + struct Handle { + NVGcontext* context; + int imageId; + + Handle() noexcept + : context(nullptr), + imageId(0) {} + + Handle(NVGcontext* c, int id) noexcept + : context(c), + imageId(id) {} + }; + +public: + /** + Constructor for an invalid/null image. + */ + NanoImage(); + + /** + Constructor. + */ + NanoImage(const Handle& handle); + + /** + Destructor. + */ + ~NanoImage(); + + /** + Create a new image without recreating the C++ class. + */ + NanoImage& operator=(const Handle& handle); + + /** + Wherever this image is valid. + */ + bool isValid() const noexcept; + + /** + Get size. + */ + Size getSize() const noexcept; + + /** + Get the OpenGL texture handle. + */ + GLuint getTextureHandle() const; + +private: + Handle fHandle; + Size fSize; + friend class NanoVG; + + /** @internal */ + void _updateSize(); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoImage) +}; + +// ----------------------------------------------------------------------- +// NanoVG + +/** + NanoVG class. + + This class exposes the NanoVG drawing API. + All calls should be wrapped in beginFrame() and endFrame(). + + @section State Handling + NanoVG contains state which represents how paths will be rendered. + The state contains transform, fill and stroke styles, text and font styles, and scissor clipping. + + @section Render styles + Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern. + Solid color is simply defined as a color value, different kinds of paints can be created + using linearGradient(), boxGradient(), radialGradient() and imagePattern(). + + Current render style can be saved and restored using save() and restore(). + + @section Transforms + The paths, gradients, patterns and scissor region are transformed by an transformation + matrix at the time when they are passed to the API. + The current transformation matrix is a affine matrix: + [sx kx tx] + [ky sy ty] + [ 0 0 1] + Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation. + The last row is assumed to be 0,0,1 and is not stored. + + Apart from resetTransform(), each transformation function first creates + specific transformation matrix and pre-multiplies the current transformation by it. + + Current coordinate system (transformation) can be saved and restored using save() and restore(). + + @section Images + NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering. + In addition you can upload your own image. The image loading is provided by stb_image. + + @section Paints + NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern. + These can be used as paints for strokes and fills. + + @section Scissoring + Scissoring allows you to clip the rendering into a rectangle. This is useful for various + user interface cases like rendering a text edit or a timeline. + + @section Paths + Drawing a new shape starts with beginPath(), it clears all the currently defined paths. + Then you define one or more paths and sub-paths which describe the shape. The are functions + to draw common shapes like rectangles and circles, and lower level step-by-step functions, + which allow to define a path curve by curve. + + NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise + winding and holes should have counter clockwise order. To specify winding of a path you can + call pathWinding(). This is useful especially for the common shapes, which are drawn CCW. + + Finally you can fill the path using current fill style by calling fill(), and stroke it + with current stroke style by calling stroke(). + + The curve segments and sub-paths are transformed by the current transform. + + @section Text + NanoVG allows you to load .ttf files and use the font to render text. + + The appearance of the text can be defined by setting the current text style + and by specifying the fill color. Common text and font settings such as + font size, letter spacing and text align are supported. Font blur allows you + to create simple text effects such as drop shadows. + + At render time the font face can be set based on the font handles or name. + + Font measure functions return values in local space, the calculations are + carried in the same resolution as the final rendering. This is done because + the text glyph positions are snapped to the nearest pixels sharp rendering. + + The local space means that values are not rotated or scale as per the current + transformation. For example if you set font size to 12, which would mean that + line height is 16, then regardless of the current scaling and rotation, the + returned line height is always 16. Some measures may vary because of the scaling + since aforementioned pixel snapping. + + While this may sound a little odd, the setup allows you to always render the + same way regardless of scaling. i.e. following works regardless of scaling: + + @code + const char* txt = "Text me up."; + vg.textBounds(x,y, txt, NULL, bounds); + vg.beginPath(); + vg.roundedRect(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); + vg.fill(); + @endcode + + Note: currently only solid color fill is supported for text. + */ +class NanoVG +{ +public: + enum CreateFlags { + /** + Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA). + */ + CREATE_ANTIALIAS = 1 << 0, + + /** + Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little + slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once. + */ + CREATE_STENCIL_STROKES = 1 << 1, + + /** + Flag indicating that additional debug checks are done. + */ + CREATE_DEBUG = 1 << 2, + }; + + enum ImageFlags { + IMAGE_GENERATE_MIPMAPS = 1 << 0, // Generate mipmaps during creation of the image. + IMAGE_REPEAT_X = 1 << 1, // Repeat image in X direction. + IMAGE_REPEAT_Y = 1 << 2, // Repeat image in Y direction. + IMAGE_FLIP_Y = 1 << 3, // Flips (inverses) image in Y direction when rendered. + IMAGE_PREMULTIPLIED = 1 << 4 // Image data has premultiplied alpha. + }; + + enum Align { + // Horizontal align + ALIGN_LEFT = 1 << 0, // Align horizontally to left (default). + ALIGN_CENTER = 1 << 1, // Align horizontally to center. + ALIGN_RIGHT = 1 << 2, // Align horizontally to right. + // Vertical align + ALIGN_TOP = 1 << 3, // Align vertically to top. + ALIGN_MIDDLE = 1 << 4, // Align vertically to middle. + ALIGN_BOTTOM = 1 << 5, // Align vertically to bottom. + ALIGN_BASELINE = 1 << 6 // Align vertically to baseline (default). + }; + + enum LineCap { + BUTT, + ROUND, + SQUARE, + BEVEL, + MITER + }; + + enum Solidity { + SOLID = 1, // CCW + HOLE = 2 // CW + }; + + enum Winding { + CCW = 1, // Winding for solid shapes + CW = 2 // Winding for holes + }; + + struct Paint { + float xform[6]; + float extent[2]; + float radius; + float feather; + Color innerColor; + Color outerColor; + int imageId; + + Paint() noexcept; + + /** + @internal + */ + Paint(const NVGpaint&) noexcept; + operator NVGpaint() const noexcept; + }; + + struct GlyphPosition { + const char* str; // Position of the glyph in the input string. + float x; // The x-coordinate of the logical glyph position. + float minx, maxx; // The bounds of the glyph shape. + }; + + struct TextRow { + const char* start; // Pointer to the input text where the row starts. + const char* end; // Pointer to the input text where the row ends (one past the last character). + const char* next; // Pointer to the beginning of the next row. + float width; // Logical width of the row. + float minx, maxx; // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending. + }; + + typedef int FontId; + + /** + Constructor. + @see CreateFlags + */ + NanoVG(int flags = CREATE_ANTIALIAS); + + /** + Constructor reusing a NanoVG context, used for subwidgets. + Context will not be deleted on class destructor. + */ + explicit NanoVG(NVGcontext* context); + + /** + Destructor. + */ + virtual ~NanoVG(); + + /** + Get the NanoVG context. + You should not need this under normal circumstances. + */ + NVGcontext* getContext() const noexcept + { + return fContext; + } + + /** + Begin drawing a new frame. + */ + void beginFrame(const uint width, const uint height, const float scaleFactor = 1.0f); + + /** + Begin drawing a new frame inside a widget. + */ + void beginFrame(Widget* const widget); + + /** + Cancels drawing the current frame. + */ + void cancelFrame(); + + /** + Ends drawing flushing remaining render state. + */ + void endFrame(); + + /* -------------------------------------------------------------------- + * State Handling */ + + /** + Pushes and saves the current render state into a state stack. + A matching restore() must be used to restore the state. + */ + void save(); + + /** + Pops and restores current render state. + */ + void restore(); + + /** + Resets current render state to default values. Does not affect the render state stack. + */ + void reset(); + + /* -------------------------------------------------------------------- + * Render styles */ + + /** + Sets current stroke style to a solid color. + */ + void strokeColor(const Color& color); + + /** + Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values. + Values must be in [0..255] range. + */ + void strokeColor(const int red, const int green, const int blue, const int alpha = 255); + + /** + Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values. + Values must in [0..1] range. + */ + void strokeColor(const float red, const float green, const float blue, const float alpha = 1.0f); + + /** + Sets current stroke style to a paint, which can be a one of the gradients or a pattern. + */ + void strokePaint(const Paint& paint); + + /** + Sets current fill style to a solid color. + */ + void fillColor(const Color& color); + + /** + Sets current fill style to a solid color, made from red, green, blue and alpha numeric values. + Values must be in [0..255] range. + */ + void fillColor(const int red, const int green, const int blue, const int alpha = 255); + + /** + Sets current fill style to a solid color, made from red, green, blue and alpha numeric values. + Values must in [0..1] range. + */ + void fillColor(const float red, const float green, const float blue, const float alpha = 1.0f); + + /** + Sets current fill style to a paint, which can be a one of the gradients or a pattern. + */ + void fillPaint(const Paint& paint); + + /** + Sets the miter limit of the stroke style. + Miter limit controls when a sharp corner is beveled. + */ + void miterLimit(float limit); + + /** + Sets the stroke width of the stroke style. + */ + void strokeWidth(float size); + + /** + Sets how the end of the line (cap) is drawn, + Can be one of: BUTT, ROUND, SQUARE. + */ + void lineCap(LineCap cap = BUTT); + + /** + Sets how sharp path corners are drawn. + Can be one of MITER, ROUND, BEVEL. + */ + void lineJoin(LineCap join = MITER); + + /** + Sets the transparency applied to all rendered shapes. + Already transparent paths will get proportionally more transparent as well. + */ + void globalAlpha(float alpha); + + /** + Sets the color tint applied to all rendered shapes. + */ + void globalTint(Color tint); + + /* -------------------------------------------------------------------- + * Transforms */ + + /** + Resets current transform to a identity matrix. + */ + void resetTransform(); + + /** + Pre-multiplies current coordinate system by specified matrix. + The parameters are interpreted as matrix as follows: + [a c e] + [b d f] + [0 0 1] + */ + void transform(float a, float b, float c, float d, float e, float f); + + /** + Translates current coordinate system. + */ + void translate(float x, float y); + + /** + Rotates current coordinate system. Angle is specified in radians. + */ + void rotate(float angle); + + /** + Skews the current coordinate system along X axis. Angle is specified in radians. + */ + void skewX(float angle); + + /** + Skews the current coordinate system along Y axis. Angle is specified in radians. + */ + void skewY(float angle); + + /** + Scales the current coordinate system. + */ + void scale(float x, float y); + + /** + Stores the top part (a-f) of the current transformation matrix in to the specified buffer. + [a c e] + [b d f] + [0 0 1] + */ + void currentTransform(float xform[6]); + + /** + The following functions can be used to make calculations on 2x3 transformation matrices. + A 2x3 matrix is represented as float[6]. */ + + /** + Sets the transform to identity matrix. + */ + static void transformIdentity(float dst[6]); + + /** + Sets the transform to translation matrix + */ + static void transformTranslate(float dst[6], float tx, float ty); + + /** + Sets the transform to scale matrix. + */ + static void transformScale(float dst[6], float sx, float sy); + + /** + Sets the transform to rotate matrix. Angle is specified in radians. + */ + static void transformRotate(float dst[6], float a); + + /** + Sets the transform to skew-x matrix. Angle is specified in radians. + */ + static void transformSkewX(float dst[6], float a); + + /** + Sets the transform to skew-y matrix. Angle is specified in radians. + */ + static void transformSkewY(float dst[6], float a); + + /** + Sets the transform to the result of multiplication of two transforms, of A = A*B. + */ + static void transformMultiply(float dst[6], const float src[6]); + + /** + Sets the transform to the result of multiplication of two transforms, of A = B*A. + */ + static void transformPremultiply(float dst[6], const float src[6]); + + /** + Sets the destination to inverse of specified transform. + Returns 1 if the inverse could be calculated, else 0. + */ + static int transformInverse(float dst[6], const float src[6]); + + /** + Transform a point by given transform. + */ + static void transformPoint(float& dstx, float& dsty, const float xform[6], float srcx, float srcy); + + /** + Convert degrees to radians. + */ + static float degToRad(float deg); + + /** + Convert radians to degrees. + */ + static float radToDeg(float rad); + + /* -------------------------------------------------------------------- + * Images */ + + /** + Creates image by loading it from the disk from specified file name. + */ + NanoImage::Handle createImageFromFile(const char* filename, ImageFlags imageFlags); + + /** + Creates image by loading it from the disk from specified file name. + Overloaded function for convenience. + @see ImageFlags + */ + NanoImage::Handle createImageFromFile(const char* filename, int imageFlags); + + /** + Creates image by loading it from the specified chunk of memory. + */ + NanoImage::Handle createImageFromMemory(const uchar* data, uint dataSize, ImageFlags imageFlags); + + /** + Creates image by loading it from the specified chunk of memory. + Overloaded function for convenience. + @see ImageFlags + */ + NanoImage::Handle createImageFromMemory(const uchar* data, uint dataSize, int imageFlags); + + /** + Creates image from specified raw format image data. + */ + NanoImage::Handle createImageFromRawMemory(uint w, uint h, const uchar* data, + ImageFlags imageFlags, ImageFormat format); + + /** + Creates image from specified raw format image data. + Overloaded function for convenience. + @see ImageFlags + */ + NanoImage::Handle createImageFromRawMemory(uint w, uint h, const uchar* data, + int imageFlags, ImageFormat format); + + /** + Creates image from specified RGBA image data. + */ + NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags); + + /** + Creates image from specified RGBA image data. + Overloaded function for convenience. + @see ImageFlags + */ + NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, int imageFlags); + + /** + Creates image from an OpenGL texture handle. + */ + NanoImage::Handle createImageFromTextureHandle(GLuint textureId, uint w, uint h, ImageFlags imageFlags, bool deleteTexture = false); + + /** + Creates image from an OpenGL texture handle. + Overloaded function for convenience. + @see ImageFlags + */ + NanoImage::Handle createImageFromTextureHandle(GLuint textureId, uint w, uint h, int imageFlags, bool deleteTexture = false); + + /* -------------------------------------------------------------------- + * Paints */ + + /** + Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates + of the linear gradient, icol specifies the start color and ocol the end color. + The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint(). + */ + Paint linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol); + + /** + Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering + drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle, + (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry + the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient. + The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint(). + */ + Paint boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& ocol); + + /** + Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify + the inner and outer radius of the gradient, icol specifies the start color and ocol the end color. + The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint(). + */ + Paint radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol); + + /** + Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern, + (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render. + The gradient is transformed by the current transform when it is passed to fillPaint() or strokePaint(). + */ + Paint imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, float alpha); + + /* -------------------------------------------------------------------- + * Scissoring */ + + /** + Sets the current scissor rectangle. + The scissor rectangle is transformed by the current transform. + */ + void scissor(float x, float y, float w, float h); + + /** + Intersects current scissor rectangle with the specified rectangle. + The scissor rectangle is transformed by the current transform. + Note: in case the rotation of previous scissor rect differs from + the current one, the intersection will be done between the specified + rectangle and the previous scissor rectangle transformed in the current + transform space. The resulting shape is always rectangle. + */ + void intersectScissor(float x, float y, float w, float h); + + /** + Reset and disables scissoring. + */ + void resetScissor(); + + /* -------------------------------------------------------------------- + * Paths */ + + /** + Clears the current path and sub-paths. + */ + void beginPath(); + + /** + Starts new sub-path with specified point as first point. + */ + void moveTo(float x, float y); + + /** + Adds line segment from the last point in the path to the specified point. + */ + void lineTo(float x, float y); + + /** + Adds cubic bezier segment from last point in the path via two control points to the specified point. + */ + void bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y); + + /** + Adds quadratic bezier segment from last point in the path via a control point to the specified point. + */ + void quadTo(float cx, float cy, float x, float y); + + /** + Adds an arc segment at the corner defined by the last path point, and two specified points. + */ + void arcTo(float x1, float y1, float x2, float y2, float radius); + + /** + Closes current sub-path with a line segment. + */ + void closePath(); + + /** + Sets the current sub-path winding. + */ + void pathWinding(Winding dir); + + /** + Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r, + and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW or NVG_CW). + Angles are specified in radians. + */ + void arc(float cx, float cy, float r, float a0, float a1, Winding dir); + + /** + Creates new rectangle shaped sub-path. + */ + void rect(float x, float y, float w, float h); + + /** + Creates new rounded rectangle shaped sub-path. + */ + void roundedRect(float x, float y, float w, float h, float r); + + /** + Creates new ellipse shaped sub-path. + */ + void ellipse(float cx, float cy, float rx, float ry); + + /** + Creates new circle shaped sub-path. + */ + void circle(float cx, float cy, float r); + + /** + Fills the current path with current fill style. + */ + void fill(); + + /** + Fills the current path with current stroke style. + */ + void stroke(); + + /* -------------------------------------------------------------------- + * Text */ + + /** + Creates font by loading it from the disk from specified file name. + Returns handle to the font. + */ + FontId createFontFromFile(const char* name, const char* filename); + + /** + Creates font by loading it from the specified memory chunk. + Returns handle to the font. + */ + FontId createFontFromMemory(const char* name, const uchar* data, uint dataSize, bool freeData); + + /** + Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found. + */ + FontId findFont(const char* name); + + /** + Sets the font size of current text style. + */ + void fontSize(float size); + + /** + Sets the blur of current text style. + */ + void fontBlur(float blur); + + /** + Sets the letter spacing of current text style. + */ + void textLetterSpacing(float spacing); + + /** + Sets the proportional line height of current text style. The line height is specified as multiple of font size. + */ + void textLineHeight(float lineHeight); + + /** + Sets the text align of current text style. + */ + void textAlign(Align align); + + /** + Sets the text align of current text style. + Overloaded function for convenience. + @see Align + */ + void textAlign(int align); + + /** + Sets the font face based on specified id of current text style. + */ + void fontFaceId(FontId font); + + /** + Sets the font face based on specified name of current text style. + */ + void fontFace(const char* font); + + /** + Draws text string at specified location. If end is specified only the sub-string up to the end is drawn. + */ + float text(float x, float y, const char* string, const char* end); + + /** + Draws multi-line text string at specified location wrapped at the specified width. + If end is specified only the sub-string up to the end is drawn. + White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered. + Words longer than the max width are slit at nearest character (i.e. no hyphenation). + */ + void textBox(float x, float y, float breakRowWidth, const char* string, const char* end = nullptr); + + /** + Measures the specified text string. The bounds value are [xmin,ymin, xmax,ymax]. + Returns the horizontal advance of the measured text (i.e. where the next character should drawn). + Measured values are returned in local coordinate space. + */ + float textBounds(float x, float y, const char* string, const char* end, Rectangle& bounds); + + /** + Measures the specified multi-text string. Parameter bounds should be a pointer to float[4], + if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax] + Measured values are returned in local coordinate space. + */ + void textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float bounds[4]); + + /** + Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used. + Measured values are returned in local coordinate space. + */ + int textGlyphPositions(float x, float y, const char* string, const char* end, GlyphPosition& positions, int maxPositions); + + /** + Returns the vertical metrics based on the current text style. + Measured values are returned in local coordinate space. + */ + void textMetrics(float* ascender, float* descender, float* lineh); + + /** + Breaks the specified text into lines. If end is specified only the sub-string will be used. + White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered. + Words longer than the max width are slit at nearest character (i.e. no hyphenation). + */ + int textBreakLines(const char* string, const char* end, float breakRowWidth, TextRow& rows, int maxRows); + +#ifndef DGL_NO_SHARED_RESOURCES + /** + Load DPF's internal shared resources for this NanoVG class. + */ + virtual bool loadSharedResources(); +#endif + +private: + NVGcontext* const fContext; + bool fInFrame; + bool fIsSubWidget; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoVG) +}; + +// ----------------------------------------------------------------------- +// NanoWidget + +/** + NanoVG Widget class. + + This class implements the NanoVG drawing API inside a DGL Widget. + The drawing function onDisplay() is implemented internally but a + new onNanoDisplay() needs to be overridden instead. + */ +template +class NanoBaseWidget : public BaseWidget, + public NanoVG +{ +public: + /** + Constructor for a NanoSubWidget. + @see CreateFlags + */ + explicit NanoBaseWidget(Widget* parentWidget, int flags = CREATE_ANTIALIAS); + + /** + Constructor for a NanoSubWidget reusing a parent subwidget nanovg context. + */ + explicit NanoBaseWidget(NanoBaseWidget* parentWidget); + + /** + Constructor for a NanoSubWidget reusing a parent top-level-widget nanovg context. + */ + explicit NanoBaseWidget(NanoBaseWidget* parentWidget); + + /** + Constructor for a NanoTopLevelWidget. + @see CreateFlags + */ + explicit NanoBaseWidget(Window& windowToMapTo, int flags = CREATE_ANTIALIAS); + + /** + Constructor for a NanoStandaloneWindow without transient parent window. + @see CreateFlags + */ + explicit NanoBaseWidget(Application& app, int flags = CREATE_ANTIALIAS); + + /** + Constructor for a NanoStandaloneWindow with transient parent window. + @see CreateFlags + */ + explicit NanoBaseWidget(Application& app, Window& transientParentWindow, int flags = CREATE_ANTIALIAS); + + /** + Destructor. + */ + ~NanoBaseWidget() override {} + +protected: + /** + New virtual onDisplay function. + @see onDisplay + */ + virtual void onNanoDisplay() = 0; + +private: + /** + Widget display function. + Implemented internally to wrap begin/endFrame() automatically. + */ + void onDisplay() override; + + // these should not be used + void beginFrame(uint,uint) {} + void beginFrame(uint,uint,float) {} + void beginFrame(Widget*) {} + void cancelFrame() {} + void endFrame() {} + + /** @internal */ + const bool fUsingParentContext; + void displayChildren(); + friend class NanoBaseWidget; + friend class NanoBaseWidget; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoBaseWidget) +}; + +typedef NanoBaseWidget NanoSubWidget; +typedef NanoBaseWidget NanoTopLevelWidget; +typedef NanoBaseWidget NanoStandaloneWindow; + +DISTRHO_DEPRECATED_BY("NanoSubWidget") +typedef NanoSubWidget NanoWidget; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif // DGL_NANO_WIDGET_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/OpenGL-include.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/OpenGL-include.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,96 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_OPENGL_INCLUDE_HPP_INCLUDED +#define DGL_OPENGL_INCLUDE_HPP_INCLUDED + +#include "../distrho/src/DistrhoDefines.h" + +// -------------------------------------------------------------------------------------------------------------------- +// Fix OpenGL includes for Windows, based on glfw code (part 1) + +#undef DGL_WINGDIAPI_DEFINED + +#ifdef DISTRHO_OS_WINDOWS + +#ifndef WINAPI +# define WINAPI __stdcall +#endif + +#ifndef APIENTRY +# define APIENTRY WINAPI +#endif // APIENTRY + +/* We need WINGDIAPI defined */ +#ifndef WINGDIAPI +# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) +# define WINGDIAPI __declspec(dllimport) +# elif defined(__LCC__) +# define WINGDIAPI __stdcall +# else +# define WINGDIAPI extern +# endif +# define DGL_WINGDIAPI_DEFINED +#endif // WINGDIAPI + +#endif // DISTRHO_OS_WINDOWS + +// -------------------------------------------------------------------------------------------------------------------- +// OpenGL includes + +#ifdef DISTRHO_OS_MAC +# ifdef DGL_USE_OPENGL3 +# include +# include +# else +# include +# endif +#else +# ifndef DISTRHO_OS_WINDOWS +# define GL_GLEXT_PROTOTYPES +# endif +# ifndef __GLEW_H__ +# include +# include +# endif +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// Missing OpenGL defines + +#if defined(GL_BGR_EXT) && !defined(GL_BGR) +# define GL_BGR GL_BGR_EXT +#endif + +#if defined(GL_BGRA_EXT) && !defined(GL_BGRA) +# define GL_BGRA GL_BGRA_EXT +#endif + +#ifndef GL_CLAMP_TO_BORDER +# define GL_CLAMP_TO_BORDER 0x812D +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// Fix OpenGL includes for Windows, based on glfw code (part 2) + +#ifdef DGL_WINGDIAPI_DEFINED +# undef WINGDIAPI +# undef DGL_WINGDIAPI_DEFINED +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/OpenGL.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/OpenGL.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,222 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_OPENGL_HPP_INCLUDED +#define DGL_OPENGL_HPP_INCLUDED + +#include "ImageBase.hpp" +#include "ImageBaseWidgets.hpp" + +#include "OpenGL-include.hpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +/** + OpenGL Graphics context. + */ +struct OpenGLGraphicsContext : GraphicsContext +{ +#ifdef DGL_USE_OPENGL3 +#endif +}; + +// ----------------------------------------------------------------------- + +static inline +ImageFormat asDISTRHOImageFormat(const GLenum format) +{ + switch (format) + { +#ifdef DGL_USE_OPENGL3 + case GL_RED: +#else + case GL_LUMINANCE: +#endif + return kImageFormatGrayscale; + case GL_BGR: + return kImageFormatBGR; + case GL_BGRA: + return kImageFormatBGRA; + case GL_RGB: + return kImageFormatRGB; + case GL_RGBA: + return kImageFormatRGBA; + } + + return kImageFormatNull; +} + +static inline +GLenum asOpenGLImageFormat(const ImageFormat format) +{ + switch (format) + { + case kImageFormatNull: + break; + case kImageFormatGrayscale: +#ifdef DGL_USE_OPENGL3 + return GL_RED; +#else + return GL_LUMINANCE; +#endif + case kImageFormatBGR: + return GL_BGR; + case kImageFormatBGRA: + return GL_BGRA; + case kImageFormatRGB: + return GL_RGB; + case kImageFormatRGBA: + return GL_RGBA; + } + + return 0x0; +} + +// ----------------------------------------------------------------------- + +/** + OpenGL Image class. + + This is an Image class that handles raw image data in pixels. + You can init the image data on the contructor or later on by calling loadFromMemory(). + + To generate raw data useful for this class see the utils/png2rgba.py script. + Be careful when using a PNG without alpha channel, for those the format is 'GL_BGR' + instead of the default 'GL_BGRA'. + + Images are drawn on screen via 2D textures. + */ +class OpenGLImage : public ImageBase +{ +public: + /** + Constructor for a null Image. + */ + OpenGLImage(); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + OpenGLImage(const char* rawData, uint width, uint height, ImageFormat format = kImageFormatBGRA); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + OpenGLImage(const char* rawData, const Size& size, ImageFormat format = kImageFormatBGRA); + + /** + Constructor using another image data. + */ + OpenGLImage(const OpenGLImage& image); + + /** + Destructor. + */ + ~OpenGLImage() override; + + /** + Load image data from memory. + @note @a rawData must remain valid for the lifetime of this Image. + */ + void loadFromMemory(const char* rawData, + const Size& size, + ImageFormat format = kImageFormatBGRA) noexcept override; + + /** + Draw this image at position @a pos using the graphics context @a context. + */ + void drawAt(const GraphicsContext& context, const Point& pos) override; + + /** + TODO document this. + */ + OpenGLImage& operator=(const OpenGLImage& image) noexcept; + + // FIXME this should not be needed + inline void loadFromMemory(const char* rdata, uint w, uint h, ImageFormat fmt = kImageFormatBGRA) + { loadFromMemory(rdata, Size(w, h), fmt); } + inline void draw(const GraphicsContext& context) + { drawAt(context, Point(0, 0)); } + inline void drawAt(const GraphicsContext& context, int x, int y) + { drawAt(context, Point(x, y)); } + + /** + Constructor using raw image data, specifying an OpenGL image format. + @note @a rawData must remain valid for the lifetime of this Image. + DEPRECATED This constructor uses OpenGL image format instead of DISTRHO one. + */ + DISTRHO_DEPRECATED_BY("OpenGLImage(const char*, uint, uint, ImageFormat)") + explicit OpenGLImage(const char* rawData, uint width, uint height, GLenum glFormat); + + /** + Constructor using raw image data, specifying an OpenGL image format. + @note @a rawData must remain valid for the lifetime of this Image. + DEPRECATED This constructor uses OpenGL image format instead of DISTRHO one. + */ + DISTRHO_DEPRECATED_BY("OpenGLImage(const char*, const Size&, ImageFormat)") + explicit OpenGLImage(const char* rawData, const Size& size, GLenum glFormat); + + /** + Draw this image at (0, 0) point using the current OpenGL context. + DEPRECATED This function does not take into consideration the current graphics context and only works in OpenGL. + */ + DISTRHO_DEPRECATED_BY("draw(const GraphicsContext&)") + void draw(); + + /** + Draw this image at (x, y) point using the current OpenGL context. + DEPRECATED This function does not take into consideration the current graphics context and only works in OpenGL. + */ + DISTRHO_DEPRECATED_BY("drawAt(const GraphicsContext&, int, int)") + void drawAt(int x, int y); + + /** + Draw this image at position @a pos using the current OpenGL context. + DEPRECATED This function does not take into consideration the current graphics context and only works in OpenGL. + */ + DISTRHO_DEPRECATED_BY("drawAt(const GraphicsContext&, const Point&)") + void drawAt(const Point& pos); + + /** + Get the image type. + DEPRECATED Type is always assumed to be GL_UNSIGNED_BYTE. + */ + DISTRHO_DEPRECATED + GLenum getType() const noexcept { return GL_UNSIGNED_BYTE; } + +private: + bool setupCalled; + bool textureInit; + GLuint textureId; +}; + +// ----------------------------------------------------------------------- + +typedef ImageBaseAboutWindow OpenGLImageAboutWindow; +typedef ImageBaseButton OpenGLImageButton; +typedef ImageBaseKnob OpenGLImageKnob; +typedef ImageBaseSlider OpenGLImageSlider; +typedef ImageBaseSwitch OpenGLImageSwitch; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_OPENGL_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/StandaloneWindow.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/StandaloneWindow.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,100 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_STANDALONE_WINDOW_HPP_INCLUDED +#define DGL_STANDALONE_WINDOW_HPP_INCLUDED + +#include "TopLevelWidget.hpp" +#include "Window.hpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +class StandaloneWindow : public Window, + public TopLevelWidget +{ +public: + /** + Constructor without parent. + */ + StandaloneWindow(Application& app) + : Window(app), + TopLevelWidget((Window&)*this), + sgc((Window&)*this) {} + + /** + Constructor with a transient parent window, typically used to run as modal. + */ + StandaloneWindow(Application& app, Window& transientParentWindow) + : Window(app, transientParentWindow), + TopLevelWidget((Window&)*this), + sgc((Window&)*this, transientParentWindow) {} + + /** + Clear current graphics context. + Must be called at the end of your StandaloneWindow constructor. + */ + void done() + { + sgc.done(); + } + + /** + Get a graphics context back again. + Called when a valid graphics context is needed outside the constructor. + */ + void reinit() + { + sgc.reinit(); + } + + /** + Overloaded functions to ensure they apply to the Window class. + */ + bool isVisible() const noexcept { return Window::isVisible(); } + void setVisible(bool yesNo) { Window::setVisible(yesNo); } + void hide() { Window::hide(); } + void show() { Window::show(); } + uint getWidth() const noexcept { return Window::getWidth(); } + uint getHeight() const noexcept { return Window::getHeight(); } + const Size getSize() const noexcept { return Window::getSize(); } + void repaint() noexcept { Window::repaint(); } + void setWidth(uint width) { Window::setWidth(width); } + void setHeight(uint height) { Window::setHeight(height); } + void setSize(uint width, uint height) { Window::setSize(width, height); } + void setSize(const Size& size) { Window::setSize(size); } + bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs = 0) + { return Window::addIdleCallback(callback, timerFrequencyInMs); } + bool removeIdleCallback(IdleCallback* callback) { return Window::removeIdleCallback(callback); } + Application& getApp() const noexcept { return Window::getApp(); } + const GraphicsContext& getGraphicsContext() const noexcept { return Window::getGraphicsContext(); } + double getScaleFactor() const noexcept { return Window::getScaleFactor(); } + void setGeometryConstraints(uint minimumWidth, uint minimumHeight, + bool keepAspectRatio = false, bool automaticallyScale = false) + { Window::setGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio, automaticallyScale); } + +private: + ScopedGraphicsContext sgc; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_STANDALONE_WINDOW_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/SubWidget.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/SubWidget.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,185 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_SUBWIDGET_HPP_INCLUDED +#define DGL_SUBWIDGET_HPP_INCLUDED + +#include "Widget.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Sub-Widget class. + + This class is the main entry point for creating any reusable widgets from within DGL. + It can be freely positioned from within a parent widget, thus being named subwidget. + + Many subwidgets can share the same parent, and subwidgets themselves can also have its own subwidgets. + It is subwidgets all the way down. + + TODO check absolute vs relative position and see what makes more sense. + + @see CairoSubWidget + */ +class SubWidget : public Widget +{ +public: + /** + Constructor. + */ + explicit SubWidget(Widget* parentWidget); + + /** + Destructor. + */ + ~SubWidget() override; + + /** + Check if this widget contains the point defined by @a x and @a y. + */ + // TODO rename as containsRelativePos + template + bool contains(T x, T y) const noexcept; + + /** + Check if this widget contains the point @a pos. + */ + // TODO rename as containsRelativePos + template + bool contains(const Point& pos) const noexcept; + + /** + Get absolute X. + */ + int getAbsoluteX() const noexcept; + + /** + Get absolute Y. + */ + int getAbsoluteY() const noexcept; + + /** + Get absolute position. + */ + Point getAbsolutePos() const noexcept; + + /** + Get absolute area of this subwidget. + This is the same as `Rectangle(getAbsolutePos(), getSize());` + @see getConstrainedAbsoluteArea() + */ + Rectangle getAbsoluteArea() const noexcept; + + /** + Get absolute area of this subwidget, with special consideration for not allowing negative values. + @see getAbsoluteArea() + */ + Rectangle getConstrainedAbsoluteArea() const noexcept; + + /** + Set absolute X. + */ + void setAbsoluteX(int x) noexcept; + + /** + Set absolute Y. + */ + void setAbsoluteY(int y) noexcept; + + /** + Set absolute position using @a x and @a y values. + */ + void setAbsolutePos(int x, int y) noexcept; + + /** + Set absolute position. + */ + void setAbsolutePos(const Point& pos) noexcept; + + /** + Get the margin currently in use for widget coordinates. + By default this value is (0,0). + */ + Point getMargin() const noexcept; + + /** + Set a margin to be used for widget coordinates using @a x and @a y values. + */ + void setMargin(int x, int y) noexcept; + + /** + Set a margin to be used for widget coordinates. + */ + void setMargin(const Point& offset) noexcept; + + /** + Get parent Widget, as passed in the constructor. + */ + Widget* getParentWidget() const noexcept; + + /** + Request repaint of this subwidget's area to the window this widget belongs to. + */ + void repaint() noexcept override; + + /** + Pushes this widget to the "bottom" of the parent widget. + Makes the widget behave as if it was the first to be registered on the parent widget, thus being "on bottom". + */ + virtual void toBottom(); + + /** + Bring this widget to the "front" of the parent widget. + Makes the widget behave as if it was the last to be registered on the parent widget, thus being "in front". + */ + virtual void toFront(); + + /** + Indicate that this subwidget will draw out of bounds, and thus needs the entire viewport available for drawing. + */ + void setNeedsFullViewportDrawing(bool needsFullViewportForDrawing = true); + + /** + Indicate that this subwidget will always draw at its own internal size and needs scaling to fit target size. + */ + void setNeedsViewportScaling(bool needsViewportScaling = true, double autoScaleFactor = 0.0); + + /** + Indicate that this subwidget should not be drawn on screen, typically because it is managed by something else. + */ + void setSkipDrawing(bool skipDrawing = true); + +protected: + /** + A function called when the subwidget's absolute position is changed. + */ + virtual void onPositionChanged(const PositionChangedEvent&); + +private: + struct PrivateData; + PrivateData* const pData; + friend class Widget; + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SubWidget) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_SUBWIDGET_HPP_INCLUDED + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/TopLevelWidget.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/TopLevelWidget.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,146 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_TOP_LEVEL_WIDGET_HPP_INCLUDED +#define DGL_TOP_LEVEL_WIDGET_HPP_INCLUDED + +#include "Widget.hpp" + +#ifdef DISTRHO_DEFINES_H_INCLUDED +START_NAMESPACE_DISTRHO +class UI; +END_NAMESPACE_DISTRHO +#endif + +START_NAMESPACE_DGL + +class Window; + +// ----------------------------------------------------------------------- + +/** + Top-Level Widget class. + + This is the only Widget class that is allowed to be used directly on a Window. + + This widget takes the full size of the Window it is mapped to. + Sub-widgets can be added on top of this top-level widget, by creating them with this class as parent. + Doing so allows for custom position and sizes. + + This class is used as the type for DPF Plugin UIs. + So anything that a plugin UI might need that does not belong in a simple Widget will go here. + */ +class TopLevelWidget : public Widget +{ +public: + /** + Constructor. + */ + explicit TopLevelWidget(Window& windowToMapTo); + + /** + Destructor. + */ + ~TopLevelWidget() override; + + /** + Get the application associated with this top-level widget's window. + */ + Application& getApp() const noexcept; + + /** + Get the window associated with this top-level widget. + */ + Window& getWindow() const noexcept; + + /** + Set width of this widget's window. + @note This will not change the widget's size right away, but be pending on the OS resizing the window + */ + void setWidth(uint width); + + /** + Set height of this widget's window. + @note This will not change the widget's size right away, but be pending on the OS resizing the window + */ + void setHeight(uint height); + + /** + Set size of this widget's window, using @a width and @a height values. + @note This will not change the widget's size right away, but be pending on the OS resizing the window + */ + void setSize(uint width, uint height); + + /** + Set size of this widget's window. + @note This will not change the widget's size right away, but be pending on the OS resizing the window + */ + void setSize(const Size& size); + + /** + TODO document this. + */ + void repaint() noexcept override; + + /** + TODO document this. + */ + void repaint(const Rectangle& rect) noexcept; + + // TODO group stuff after here, convenience functions present in Window class + const void* getClipboard(size_t& dataSize); + bool setClipboard(const char* mimeType, const void* data, size_t dataSize); + bool setCursor(MouseCursor cursor); + bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs = 0); + bool removeIdleCallback(IdleCallback* callback); + double getScaleFactor() const noexcept; + void setGeometryConstraints(uint minimumWidth, + uint minimumHeight, + bool keepAspectRatio = false, + bool automaticallyScale = false, + bool resizeNowIfAutoScaling = true); + + DISTRHO_DEPRECATED_BY("getApp()") + Application& getParentApp() const noexcept { return getApp(); } + + DISTRHO_DEPRECATED_BY("getWindow()") + Window& getParentWindow() const noexcept { return getWindow(); } + +protected: + bool onKeyboard(const KeyboardEvent&) override; + bool onCharacterInput(const CharacterInputEvent&) override; + bool onMouse(const MouseEvent&) override; + bool onMotion(const MotionEvent&) override; + bool onScroll(const ScrollEvent&) override; + +private: + struct PrivateData; + PrivateData* const pData; + friend class Window; +#ifdef DISTRHO_DEFINES_H_INCLUDED + friend class DISTRHO_NAMESPACE::UI; +#endif + /** @internal */ + virtual void requestSizeChange(uint width, uint height); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TopLevelWidget) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_TOP_LEVEL_WIDGET_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Vulkan.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Vulkan.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,103 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_VULKAN_HPP_INCLUDED +#define DGL_VULKAN_HPP_INCLUDED + +#include "ImageBase.hpp" + +#include + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Vulkan Graphics context. + */ +struct VulkanGraphicsContext : GraphicsContext +{ +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Vulkan Image class. + + TODO ... + */ +class VulkanImage : public ImageBase +{ +public: + /** + Constructor for a null Image. + */ + VulkanImage(); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + VulkanImage(const char* rawData, uint width, uint height, ImageFormat format); + + /** + Constructor using raw image data. + @note @a rawData must remain valid for the lifetime of this Image. + */ + VulkanImage(const char* rawData, const Size& size, ImageFormat format); + + /** + Constructor using another image data. + */ + VulkanImage(const VulkanImage& image); + + /** + Destructor. + */ + ~VulkanImage() override; + + /** + Load image data from memory. + @note @a rawData must remain valid for the lifetime of this Image. + */ + void loadFromMemory(const char* rawData, + const Size& size, + ImageFormat format = kImageFormatBGRA) noexcept override; + + /** + Draw this image at position @a pos using the graphics context @a context. + */ + void drawAt(const GraphicsContext& context, const Point& pos) override; + + /** + TODO document this. + */ + VulkanImage& operator=(const VulkanImage& image) noexcept; + + // FIXME this should not be needed + inline void loadFromMemory(const char* rdata, uint w, uint h, ImageFormat fmt = kImageFormatBGRA) + { loadFromMemory(rdata, Size(w, h), fmt); }; + inline void draw(const GraphicsContext& context) + { drawAt(context, Point(0, 0)); }; + inline void drawAt(const GraphicsContext& context, int x, int y) + { drawAt(context, Point(x, y)); }; +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Widget.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Widget.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,483 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_WIDGET_HPP_INCLUDED +#define DGL_WIDGET_HPP_INCLUDED + +#include "Geometry.hpp" + +#include + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- +// Forward class names + +class Application; +class SubWidget; +class TopLevelWidget; +class Window; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Base DGL Widget class. + + This is the base Widget class, from which all widgets are built. + + All widgets have a parent widget where they'll be drawn, this can be the top-level widget or a group widget. + This parent is never changed during a widget's lifetime. + + Widgets receive events in relative coordinates. (0, 0) means its top-left position. + + The top-level widget will draw subwidgets in the order they are constructed. + Early subwidgets are drawn first, at the bottom, then newer ones on top. + Events are sent in the inverse order so that the top-most widgets get + a chance to catch the event and stop its propagation. + + All widget event callbacks do nothing by default and onDisplay MUST be reimplemented by subclasses. + + @note It is not possible to subclass this Widget class directly, you must use SubWidget or TopLevelWidget instead. + */ +class Widget +{ +public: + /** + Base event data. + These are the fields present on all Widget events. + */ + struct BaseEvent { + /** Currently active keyboard modifiers. @see Modifier */ + uint mod; + /** Event flags. @see EventFlag */ + uint flags; + /** Event timestamp in milliseconds (if any). */ + uint time; + + /** Constructor for default/null values */ + BaseEvent() noexcept : mod(0x0), flags(0x0), time(0) {} + /** Destuctor */ + virtual ~BaseEvent() noexcept {} + }; + + /** + Keyboard event. + + This event represents low-level key presses and releases. + This can be used for "direct" keyboard handing like key bindings, but must not be interpreted as text input. + + Keys are represented portably as Unicode code points, using the "natural" code point for the key. + The @a key field is the code for the pressed key, without any modifiers applied. + For example, a press or release of the 'A' key will have `key` 97 ('a') + regardless of whether shift or control are being held. + + Alternatively, the raw @a keycode can be used to work directly with physical keys, + but note that this value is not portable and differs between platforms and hardware. + + @see onKeyboard + */ + struct KeyboardEvent : BaseEvent { + /** True if the key was pressed, false if released. */ + bool press; + /** Unicode point of the key pressed. */ + uint key; + /** Raw keycode. */ + uint keycode; + + /** Constructor for default/null values */ + KeyboardEvent() noexcept + : BaseEvent(), + press(false), + key(0), + keycode(0) {} + }; + + /** + Special keyboard event. + + DEPRECATED This used to be part of DPF due to pugl, but now deprecated and simply non-functional. + All events go through KeyboardEvent or CharacterInputEvent, use those instead. + */ + struct DISTRHO_DEPRECATED_BY("KeyboardEvent") SpecialEvent : BaseEvent { + bool press; + Key key; + + /** Constructor for default/null values */ + SpecialEvent() noexcept + : BaseEvent(), + press(false), + key(Key(0)) {} + }; + + /** + Character input event. + + This event represents text input, usually as the result of a key press. + The text is given both as a Unicode character code and a UTF-8 string. + + Note that this event is generated by the platform's input system, + so there is not necessarily a direct correspondence between text events and physical key presses. + For example, with some input methods a sequence of several key presses will generate a single character. + + @see onCharacterInput + */ + struct CharacterInputEvent : BaseEvent { + /** Raw key code. */ + uint keycode; + /** Unicode character code. */ + uint character; + /** UTF-8 string. */ + char string[8]; + + /** Constructor for default/null values */ + CharacterInputEvent() noexcept + : BaseEvent(), + keycode(0), + character(0), +#ifdef DISTRHO_PROPER_CPP11_SUPPORT + string{'\0','\0','\0','\0','\0','\0','\0','\0'} {} +#else + string() { std::memset(string, 0, sizeof(string)); } +#endif + }; + + /** + Mouse press or release event. + @see onMouse + */ + struct MouseEvent : BaseEvent { + /** The button number starting from 1. @see MouseButton */ + uint button; + /** True if the button was pressed, false if released. */ + bool press; + /** The widget-relative coordinates of the pointer. */ + Point pos; + /** The absolute coordinates of the pointer. */ + Point absolutePos; + + /** Constructor for default/null values */ + MouseEvent() noexcept + : BaseEvent(), + button(0), + press(false), + pos(0.0, 0.0), + absolutePos(0.0, 0.0) {} + }; + + /** + Mouse motion event. + @see onMotion + */ + struct MotionEvent : BaseEvent { + /** The widget-relative coordinates of the pointer. */ + Point pos; + /** The absolute coordinates of the pointer. */ + Point absolutePos; + + /** Constructor for default/null values */ + MotionEvent() noexcept + : BaseEvent(), + pos(0.0, 0.0), + absolutePos(0.0, 0.0) {} + }; + + /** + Mouse scroll event. + + The scroll distance is expressed in "lines", + an arbitrary unit that corresponds to a single tick of a detented mouse wheel. + For example, `delta.y` = 1.0 scrolls 1 line up. + Some systems and devices support finer resolution and/or higher values for fast scrolls, + so programs should handle any value gracefully. + + @see onScroll + */ + struct ScrollEvent : BaseEvent { + /** The widget-relative coordinates of the pointer. */ + Point pos; + /** The absolute coordinates of the pointer. */ + Point absolutePos; + /** The scroll distance. */ + Point delta; + /** The direction of the scroll or "smooth". */ + ScrollDirection direction; + + /** Constructor for default/null values */ + ScrollEvent() noexcept + : BaseEvent(), + pos(0.0, 0.0), + absolutePos(0.0, 0.0), + delta(0.0, 0.0), + direction(kScrollSmooth) {} + }; + + /** + Resize event. + @see onResize + */ + struct ResizeEvent { + /** The new widget size. */ + Size size; + /** The previous size, can be null. */ + Size oldSize; + + /** Constructor for default/null values */ + ResizeEvent() noexcept + : size(0, 0), + oldSize(0, 0) {} + }; + + /** + Widget position changed event. + @see onPositionChanged + */ + struct PositionChangedEvent { + /** The new absolute position of the widget. */ + Point pos; + /** The previous absolute position of the widget. */ + Point oldPos; + + /** Constructor for default/null values */ + PositionChangedEvent() noexcept + : pos(0, 0), + oldPos(0, 0) {} + }; + +private: + /** + Private constructor, reserved for TopLevelWidget class. + */ + explicit Widget(TopLevelWidget* topLevelWidget); + + /** + Private constructor, reserved for SubWidget class. + */ + explicit Widget(Widget* widgetToGroupTo); + +public: + /** + Destructor. + */ + virtual ~Widget(); + + /** + Check if this widget is visible within its parent window. + Invisible widgets do not receive events except resize. + */ + bool isVisible() const noexcept; + + /** + Set widget visible (or not) according to @a visible. + */ + void setVisible(bool visible); + + /** + Show widget. + This is the same as calling setVisible(true). + */ + void show(); + + /** + Hide widget. + This is the same as calling setVisible(false). + */ + void hide(); + + /** + Get width. + */ + uint getWidth() const noexcept; + + /** + Get height. + */ + uint getHeight() const noexcept; + + /** + Get size. + */ + const Size getSize() const noexcept; + + /** + Set width. + */ + void setWidth(uint width) noexcept; + + /** + Set height. + */ + void setHeight(uint height) noexcept; + + /** + Set size using @a width and @a height values. + */ + void setSize(uint width, uint height) noexcept; + + /** + Set size. + */ + void setSize(const Size& size) noexcept; + + /** + Get the Id associated with this widget. + Returns 0 by default. + @see setId + */ + uint getId() const noexcept; + + /** + Get the name associated with this widget. + This is complately optional, mostly useful for debugging purposes. + Returns an empty string by default. + @see setName + */ + const char* getName() const noexcept; + + /** + Set an Id to be associated with this widget. + @see getId + */ + void setId(uint id) noexcept; + + /** + Set a name to be associated with this widget. + This is complately optional, only useful for debugging purposes. + @note name must not be null + @see getName + */ + void setName(const char* name) noexcept; + + /** + Get the application associated with this widget's window. + This is the same as calling `getTopLevelWidget()->getApp()`. + */ + Application& getApp() const noexcept; + + /** + Get the window associated with this widget. + This is the same as calling `getTopLevelWidget()->getWindow()`. + */ + Window& getWindow() const noexcept; + + /** + Get the graphics context associated with this widget's window. + GraphicsContext is an empty struct and needs to be casted into a different type in order to be usable, + for example GraphicsContext. + @see CairoSubWidget, CairoTopLevelWidget + */ + const GraphicsContext& getGraphicsContext() const noexcept; + + /** + Get top-level widget, as passed directly in the constructor + or going up the chain of group widgets until it finds the top-level one. + */ + TopLevelWidget* getTopLevelWidget() const noexcept; + + /** + Get list of children (a subwidgets) that belong to this widget. + */ + std::list getChildren() const noexcept; + + /** + Request repaint of this widget's area to the window this widget belongs to. + On the raw Widget class this function does nothing. + */ + virtual void repaint() noexcept; + + DISTRHO_DEPRECATED_BY("getApp()") + Application& getParentApp() const noexcept { return getApp(); } + + DISTRHO_DEPRECATED_BY("getWindow()") + Window& getParentWindow() const noexcept { return getWindow(); } + +protected: + /** + A function called to draw the widget contents. + */ + virtual void onDisplay() = 0; + + /** + A function called when a key is pressed or released. + @return True to stop event propagation, false otherwise. + */ + virtual bool onKeyboard(const KeyboardEvent&); + + /** + A function called when an UTF-8 character is received. + @return True to stop event propagation, false otherwise. + */ + virtual bool onCharacterInput(const CharacterInputEvent&); + + /** + A function called when a mouse button is pressed or released. + @return True to stop event propagation, false otherwise. + */ + virtual bool onMouse(const MouseEvent&); + + /** + A function called when the pointer moves. + @return True to stop event propagation, false otherwise. + */ + virtual bool onMotion(const MotionEvent&); + + /** + A function called on scrolling (e.g. mouse wheel or track pad). + @return True to stop event propagation, false otherwise. + */ + virtual bool onScroll(const ScrollEvent&); + + /** + A function called when the widget is resized. + */ + virtual void onResize(const ResizeEvent&); + + /** + A function called when a special key is pressed or released. + DEPRECATED use onKeyboard or onCharacterInput + */ + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable:4996) + #elif defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif + virtual bool onSpecial(const SpecialEvent&) { return false; } + #if defined(_MSC_VER) + #pragma warning(pop) + #elif defined(__clang__) + #pragma clang diagnostic pop + #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460 + #pragma GCC diagnostic pop + #endif + +private: + struct PrivateData; + PrivateData* const pData; + friend class SubWidget; + friend class TopLevelWidget; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_WIDGET_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/Window.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/Window.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,558 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_WINDOW_HPP_INCLUDED +#define DGL_WINDOW_HPP_INCLUDED + +#include "Geometry.hpp" + +#ifndef DGL_FILE_BROWSER_DISABLED +# include "FileBrowserDialog.hpp" +#endif + +#include + +#ifdef DISTRHO_NAMESPACE +START_NAMESPACE_DISTRHO +class PluginWindow; +END_NAMESPACE_DISTRHO +#endif + +START_NAMESPACE_DGL + +class Application; +class TopLevelWidget; + +// ----------------------------------------------------------------------- + +/** + DGL Window class. + + This is the where all OS-related events initially happen, before being propagated to any widgets. + + A Window MUST have an Application instance tied to it. + It is not possible to swap Application instances from within the lifetime of a Window. + But it is possible to completely change the Widgets that a Window contains during its lifetime. + + Typically the event handling functions as following: + Application -> Window -> Top-Level-Widget -> SubWidgets + + Please note that, unlike many other graphical toolkits out there, + DGL makes a clear distinction between a Window and a Widget. + You cannot directly draw in a Window, you need to create a Widget for that. + + Also, a Window MUST have a single top-level Widget. + The Window will take care of global screen positioning and resizing, everything else is sent for widgets to handle. + + ... + */ +class DISTRHO_API Window +{ + struct PrivateData; + +public: + /** + Window graphics context as a scoped struct. + This class gives graphics context drawing time to a window's widgets. + Typically used for allowing OpenGL drawing operations during a window + widget constructor. + + Unless you are subclassing the Window or StandaloneWindow classes, you do not need to care. + In such cases you will need to use this struct as a way to get a valid OpenGL context. + For example in a standalone application: + ``` + int main() + { + Application app; + Window win(app); + ScopedPointer widget; + { + const Window::ScopedGraphicsContext sgc(win); + widget = new MyCustomTopLevelWidget(win); + } + app.exec(); + return 0; + } + ``` + + This struct is necessary because we cannot automatically make the window leave the OpenGL context in custom code. + And we must always cleanly enter and leave the OpenGL context. + So in order to avoid messing up the global host context, this class is used around widget creation. + */ + struct ScopedGraphicsContext + { + /** Constructor that will make the @a window graphics context the current one */ + explicit ScopedGraphicsContext(Window& window); + + /** Overloaded constructor, gives back context to its transient parent when done */ + explicit ScopedGraphicsContext(Window& window, Window& transientParentWindow); + + /** Desstructor for clearing current context, if not done yet */ + ~ScopedGraphicsContext(); + + /** Early context clearing, useful for standalone windows not created by you. */ + void done(); + + /** Get a valid context back again. */ + void reinit(); + + DISTRHO_DECLARE_NON_COPYABLE(ScopedGraphicsContext) + DISTRHO_PREVENT_HEAP_ALLOCATION + + private: + Window& window; + Window::PrivateData* const ppData; + bool active; + bool reenter; + }; + + /** + Constructor for a regular, standalone window. + */ + explicit Window(Application& app); + + /** + Constructor for a modal window, by having another window as its transient parent. + The Application instance must be the same between the 2 windows. + */ + explicit Window(Application& app, Window& transientParentWindow); + + /** + Constructor for an embed Window without known size, + typically used in modules or plugins that run inside another host. + */ + explicit Window(Application& app, + uintptr_t parentWindowHandle, + double scaleFactor, + bool resizable); + + /** + Constructor for an embed Window with known size, + typically used in modules or plugins that run inside another host. + */ + explicit Window(Application& app, + uintptr_t parentWindowHandle, + uint width, + uint height, + double scaleFactor, + bool resizable); + + /** + Destructor. + */ + virtual ~Window(); + + /** + Whether this Window is embed into another (usually not DGL-controlled) Window. + */ + bool isEmbed() const noexcept; + + /** + Check if this window is visible / mapped. + Invisible windows do not receive events except resize. + @see setVisible(bool) + */ + bool isVisible() const noexcept; + + /** + Set window visible (or not) according to @a visible. + Only valid for standalones, embed windows are always visible. + @see isVisible(), hide(), show() + */ + void setVisible(bool visible); + + /** + Show window. + This is the same as calling setVisible(true). + @see isVisible(), setVisible(bool) + */ + void show(); + + /** + Hide window. + This is the same as calling setVisible(false). + @see isVisible(), setVisible(bool) + */ + void hide(); + + /** + Hide window and notify application of a window close event. + The application event-loop will stop when all windows have been closed. + For standalone windows only, has no effect if window is embed. + @see isEmbed() + + @note It is possible to hide the window while not stopping the event-loop. + A closed window is always hidden, but the reverse is not always true. + */ + void close(); + + /** + Check if this window is resizable (by the user or window manager). + @see setResizable + */ + bool isResizable() const noexcept; + + /** + Set window as resizable (by the user or window manager). + It is always possible to resize a window programmatically, which is not the same as the user being allowed to it. + @note This function does nothing for plugins, where the resizable state is set via macro. + @see DISTRHO_UI_USER_RESIZABLE + */ + void setResizable(bool resizable); + + /** + Get X offset, typically 0. + */ + int getOffsetX() const noexcept; + + /** + Get Y offset, typically 0. + */ + int getOffsetY() const noexcept; + + /** + Get offset. + */ + Point getOffset() const noexcept; + + /** + Set X offset. + */ + void setOffsetX(int x); + + /** + Set Y offset. + */ + void setOffsetY(int y); + + /** + Set offset using @a x and @a y values. + */ + void setOffset(int x, int y); + + /** + Set offset. + */ + void setOffset(const Point& offset); + + /** + Get width. + */ + uint getWidth() const noexcept; + + /** + Get height. + */ + uint getHeight() const noexcept; + + /** + Get size. + */ + Size getSize() const noexcept; + + /** + Set width. + */ + void setWidth(uint width); + + /** + Set height. + */ + void setHeight(uint height); + + /** + Set size using @a width and @a height values. + */ + void setSize(uint width, uint height); + + /** + Set size. + */ + void setSize(const Size& size); + + /** + Get the title of the window previously set with setTitle(). + */ + const char* getTitle() const noexcept; + + /** + Set the title of the window, typically displayed in the title bar or in window switchers. + + This only makes sense for non-embedded windows. + */ + void setTitle(const char* title); + + /** + Check if key repeat events are ignored. + */ + bool isIgnoringKeyRepeat() const noexcept; + + /** + Set to ignore (or not) key repeat events according to @a ignore. + */ + void setIgnoringKeyRepeat(bool ignore) noexcept; + + /** + Get the clipboard contents. + + This gets the system clipboard contents, + which may have been set with setClipboard() or copied from another application. + + Returns the clipboard contents, or null. + + @note By default only "text/plain" mimetype is supported and returned. + Override onClipboardDataOffer for supporting other types. + */ + const void* getClipboard(size_t& dataSize); + + /** + Set the clipboard contents. + + This sets the system clipboard contents, + which can be retrieved with getClipboard() or pasted into other applications. + + If using a string, the use of a null terminator is required (and must be part of dataSize).@n + The MIME type of the data "text/plain" is assumed if null is used. + */ + bool setClipboard(const char* mimeType, const void* data, size_t dataSize); + + /** + Set the mouse cursor. + + This changes the system cursor that is displayed when the pointer is inside the window. + May fail if setting the cursor is not supported on this system, + for example if compiled on X11 without Xcursor support. + */ + bool setCursor(MouseCursor cursor); + + /** + Add a callback function to be triggered on every idle cycle or on a specific timer frequency. + You can add more than one, and remove them at anytime with removeIdleCallback(). + This can be used to perform some action at a regular interval with relatively low frequency. + + If providing a timer frequency, there are a few things to note: + 1. There is a platform-specific limit to the number of supported timers, and overhead associated with each, + so you should create only a few timers and perform several tasks in one if necessary. + 2. This timer frequency is not guaranteed to have a resolution better than 10ms + (the maximum timer resolution on Windows) and may be rounded up if it is too short. + On X11 and MacOS, a resolution of about 1ms can usually be relied on. + */ + bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs = 0); + + /** + Remove an idle callback previously added via addIdleCallback(). + */ + bool removeIdleCallback(IdleCallback* callback); + + /** + Get the application associated with this window. + */ + Application& getApp() const noexcept; + + /** + Get the graphics context associated with this window. + GraphicsContext is an empty struct and needs to be casted into a different type in order to be usable, + for example GraphicsContext. + @see CairoSubWidget, CairoTopLevelWidget + */ + const GraphicsContext& getGraphicsContext() const noexcept; + + /** + Get the "native" window handle. + Returned value depends on the platform: + - HaikuOS: This is a pointer to a `BView`. + - MacOS: This is a pointer to an `NSView*`. + - Windows: This is a `HWND`. + - Everything else: This is an [X11] `Window`. + */ + uintptr_t getNativeWindowHandle() const noexcept; + + /** + Get the scale factor requested for this window. + This is purely informational, and up to developers to choose what to do with it. + + If you do not want to deal with this yourself, + consider using setGeometryConstraints() where you can specify to automatically scale the window contents. + @see setGeometryConstraints + */ + double getScaleFactor() const noexcept; + + /** + Grab the keyboard input focus. + */ + void focus(); + +#ifndef DGL_FILE_BROWSER_DISABLED + /** + Open a file browser dialog with this window as transient parent. + A few options can be specified to setup the dialog. + + If a path is selected, onFileSelected() will be called with the user chosen path. + If the user cancels or does not pick a file, onFileSelected() will be called with nullptr as filename. + + This function does not block the event loop. + */ + bool openFileBrowser(const DGL_NAMESPACE::FileBrowserOptions& options = FileBrowserOptions()); +#endif + + /** + Request repaint of this window, for the entire area. + */ + void repaint() noexcept; + + /** + Request partial repaint of this window, with bounds according to @a rect. + */ + void repaint(const Rectangle& rect) noexcept; + + /** + Render this window's content into a picture file, specified by @a filename. + Window must be visible and on screen. + Written picture format is PPM. + */ + void renderToPicture(const char* filename); + + /** + Run this window as a modal, blocking input events from the parent. + Only valid for windows that have been created with another window as parent (as passed in the constructor). + Can optionally block-wait, but such option is only available if the application is running as standalone. + */ + void runAsModal(bool blockWait = false); + + /** + Get the geometry constraints set for the Window. + @see setGeometryConstraints + */ + Size getGeometryConstraints(bool& keepAspectRatio); + + /** + Set geometry constraints for the Window when resized by the user, and optionally scale contents automatically. + */ + void setGeometryConstraints(uint minimumWidth, + uint minimumHeight, + bool keepAspectRatio = false, + bool automaticallyScale = false, + bool resizeNowIfAutoScaling = true); + + /** + Set the transient parent of the window. + + Set this for transient children like dialogs, to have them properly associated with their parent window. + This should be not be called for embed windows, or after making the window visible. + */ + void setTransientParent(uintptr_t transientParentWindowHandle); + + /** DEPRECATED Use isIgnoringKeyRepeat(). */ + DISTRHO_DEPRECATED_BY("isIgnoringKeyRepeat()") + inline bool getIgnoringKeyRepeat() const noexcept { return isIgnoringKeyRepeat(); } + + /** DEPRECATED Use getScaleFactor(). */ + DISTRHO_DEPRECATED_BY("getScaleFactor()") + inline double getScaling() const noexcept { return getScaleFactor(); } + + /** DEPRECATED Use runAsModal(bool). */ + DISTRHO_DEPRECATED_BY("runAsModal(bool)") + inline void exec(bool blockWait = false) { runAsModal(blockWait); } + +protected: + /** + Get the types available for the data in a clipboard. + Must only be called within the context of onClipboardDataOffer. + */ + std::vector getClipboardDataOfferTypes(); + + /** + A function called when clipboard has data present, possibly with several datatypes. + While handling this event, the data types can be investigated with getClipboardDataOfferTypes() to decide whether to accept the offer. + + Reimplement and return a non-zero id to accept the clipboard data offer for a particular type. + Applications must ignore any type they do not recognize. + + The default implementation accepts the "text/plain" mimetype. + */ + virtual uint32_t onClipboardDataOffer(); + + /** + A function called when the window is attempted to be closed. + Returning true closes the window, which is the default behaviour. + Override this method and return false to prevent the window from being closed by the user. + + This method is not used for embed windows, and not even made available in DISTRHO_NAMESPACE::UI. + For embed windows, closing is handled by the host/parent process and we have no control over it. + As such, a close action on embed windows will always succeed and cannot be cancelled. + + NOTE: This currently does not work under macOS. + */ + virtual bool onClose(); + + /** + A function called when the window gains or loses the keyboard focus. + The default implementation does nothing. + */ + virtual void onFocus(bool focus, CrossingMode mode); + + /** + A function called when the window is resized. + If there is a top-level widget associated with this window, its size will be set right after this function. + The default implementation sets up drawing context where necessary. + */ + virtual void onReshape(uint width, uint height); + + /** + A function called when scale factor requested for this window changes. + The default implementation does nothing. + WARNING function needs a proper name + */ + virtual void onScaleFactorChanged(double scaleFactor); + +#ifndef DGL_FILE_BROWSER_DISABLED + /** + A function called when a path is selected by the user, as triggered by openFileBrowser(). + This action happens after the user confirms the action, so the file browser dialog will be closed at this point. + The default implementation does nothing. + */ + virtual void onFileSelected(const char* filename); + + /** DEPRECATED Use onFileSelected(). */ + DISTRHO_DEPRECATED_BY("onFileSelected(const char*)") + inline virtual void fileBrowserSelected(const char* filename) { return onFileSelected(filename); } +#endif + +private: + PrivateData* const pData; + friend class Application; + friend class TopLevelWidget; + #ifdef DISTRHO_NAMESPACE + friend class DISTRHO_NAMESPACE::PluginWindow; + #endif + + /** @internal */ + explicit Window(Application& app, + uintptr_t parentWindowHandle, + uint width, + uint height, + double scaleFactor, + bool resizable, + bool usesSizeRequest, + bool doPostInit); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_WINDOW_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Application.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Application.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,112 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ApplicationPrivateData.hpp" + +#if defined(__EMSCRIPTEN__) +# include +#elif defined(DISTRHO_OS_MAC) +# include +#endif + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +#ifdef __EMSCRIPTEN__ +static void app_idle(void* const app) +{ + static_cast(app)->idle(); +} +#endif + +Application::Application(const bool isStandalone) + : pData(new PrivateData(isStandalone)) {} + +Application::~Application() +{ + delete pData; +} + +void Application::idle() +{ + pData->idle(0); +} + +void Application::exec(const uint idleTimeInMs) +{ + DISTRHO_SAFE_ASSERT_RETURN(pData->isStandalone,); + +#if defined(__EMSCRIPTEN__) + emscripten_set_main_loop_arg(app_idle, this, 0, true); +#elif defined(DISTRHO_OS_MAC) + const CFTimeInterval idleTimeInSecs = static_cast(idleTimeInMs) / 1000; + + while (! pData->isQuitting) + { + pData->idle(0); + + if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, idleTimeInSecs, true) == kCFRunLoopRunFinished) + break; + } +#else + while (! pData->isQuitting) + pData->idle(idleTimeInMs); +#endif +} + +void Application::quit() +{ + pData->quit(); +} + +bool Application::isQuitting() const noexcept +{ + return pData->isQuitting || pData->isQuittingInNextCycle; +} + +bool Application::isStandalone() const noexcept +{ + return pData->isStandalone; +} + +double Application::getTime() const +{ + return pData->getTime(); +} + +void Application::addIdleCallback(IdleCallback* const callback) +{ + DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,) + + pData->idleCallbacks.push_back(callback); +} + +void Application::removeIdleCallback(IdleCallback* const callback) +{ + DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,) + + pData->idleCallbacks.remove(callback); +} + +void Application::setClassName(const char* const name) +{ + pData->setClassName(name); +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/ApplicationPrivateData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/ApplicationPrivateData.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,178 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ApplicationPrivateData.hpp" +#include "../Window.hpp" + +#include "pugl.hpp" + +#include + +START_NAMESPACE_DGL + +typedef std::list::reverse_iterator WindowListReverseIterator; + +static d_ThreadHandle getCurrentThreadHandle() noexcept +{ +#ifdef DISTRHO_OS_WINDOWS + return GetCurrentThread(); +#else + return pthread_self(); +#endif +} + +static bool isThisTheMainThread(const d_ThreadHandle mainThreadHandle) noexcept +{ +#ifdef DISTRHO_OS_WINDOWS + return GetCurrentThread() == mainThreadHandle; // IsGUIThread ? +#else + return pthread_equal(getCurrentThreadHandle(), mainThreadHandle) != 0; +#endif +} + +// -------------------------------------------------------------------------------------------------------------------- + +const char* Application::getClassName() const noexcept +{ + return puglGetClassName(pData->world); +} + +// -------------------------------------------------------------------------------------------------------------------- + +Application::PrivateData::PrivateData(const bool standalone) + : world(puglNewWorld(standalone ? PUGL_PROGRAM : PUGL_MODULE, + standalone ? PUGL_WORLD_THREADS : 0x0)), + isStandalone(standalone), + isQuitting(false), + isQuittingInNextCycle(false), + isStarting(true), + visibleWindows(0), + mainThreadHandle(getCurrentThreadHandle()), + windows(), + idleCallbacks() +{ + DISTRHO_SAFE_ASSERT_RETURN(world != nullptr,); + + puglSetWorldHandle(world, this); + #ifdef __EMSCRIPTEN__ + puglSetClassName(world, "canvas"); + #else + puglSetClassName(world, DISTRHO_MACRO_AS_STRING(DGL_NAMESPACE)); + #endif +} + +Application::PrivateData::~PrivateData() +{ + DISTRHO_SAFE_ASSERT(isStarting || isQuitting); + DISTRHO_SAFE_ASSERT(visibleWindows == 0); + + windows.clear(); + idleCallbacks.clear(); + + if (world != nullptr) + puglFreeWorld(world); +} + +// -------------------------------------------------------------------------------------------------------------------- + +void Application::PrivateData::oneWindowShown() noexcept +{ + if (++visibleWindows == 1) + { + isQuitting = false; + isStarting = false; + } +} + +void Application::PrivateData::oneWindowClosed() noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(visibleWindows != 0,); + + if (--visibleWindows == 0) + isQuitting = true; +} + +// -------------------------------------------------------------------------------------------------------------------- + +void Application::PrivateData::idle(const uint timeoutInMs) +{ + if (isQuittingInNextCycle) + { + quit(); + isQuittingInNextCycle = false; + } + + if (world != nullptr) + { + const double timeoutInSeconds = timeoutInMs != 0 + ? static_cast(timeoutInMs) / 1000.0 + : 0.0; + + puglUpdate(world, timeoutInSeconds); + } + + triggerIdleCallbacks(); +} + +void Application::PrivateData::triggerIdleCallbacks() +{ + for (std::list::iterator it = idleCallbacks.begin(), ite = idleCallbacks.end(); it != ite; ++it) + { + IdleCallback* const idleCallback(*it); + idleCallback->idleCallback(); + } +} + +void Application::PrivateData::quit() +{ + if (! isThisTheMainThread(mainThreadHandle)) + { + if (! isQuittingInNextCycle) + { + isQuittingInNextCycle = true; + return; + } + } + + isQuitting = true; + +#ifndef DPF_TEST_APPLICATION_CPP + for (WindowListReverseIterator rit = windows.rbegin(), rite = windows.rend(); rit != rite; ++rit) + { + DGL_NAMESPACE::Window* const window(*rit); + window->close(); + } +#endif +} + +double Application::PrivateData::getTime() const +{ + DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, 0.0); + + return puglGetTime(world); +} + +void Application::PrivateData::setClassName(const char* const name) +{ + DISTRHO_SAFE_ASSERT_RETURN(world != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); + + puglSetClassName(world, name); +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/ApplicationPrivateData.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/ApplicationPrivateData.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,116 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_APP_PRIVATE_DATA_HPP_INCLUDED +#define DGL_APP_PRIVATE_DATA_HPP_INCLUDED + +#include "../Application.hpp" + +#include + +#ifdef DISTRHO_OS_WINDOWS +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include +typedef HANDLE d_ThreadHandle; +#else +# include +typedef pthread_t d_ThreadHandle; +#endif + +#ifdef DISTRHO_OS_MAC +typedef struct PuglWorldImpl PuglWorld; +#endif + +START_NAMESPACE_DGL + +class Window; + +#ifndef DISTRHO_OS_MAC +typedef struct PuglWorldImpl PuglWorld; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +struct Application::PrivateData { + /** Pugl world instance. */ + PuglWorld* const world; + + /** Whether the application is running as standalone, otherwise it is part of a plugin. */ + const bool isStandalone; + + /** Whether the applicating is about to quit, or already stopped. Defaults to false. */ + bool isQuitting; + + /** Helper for safely close everything from main thread. */ + bool isQuittingInNextCycle; + + /** Whether the applicating is starting up, that is, no windows have been made visible yet. Defaults to true. */ + bool isStarting; + + /** Counter of visible windows, only used in standalone mode. + If 0->1, application is starting. If 1->0, application is quitting/stopping. */ + uint visibleWindows; + + /** Handle that identifies the main thread. Used to check if calls belong to current thread or not. */ + d_ThreadHandle mainThreadHandle; + + /** List of windows for this application. Only used during `close`. */ + std::list windows; + + /** List of idle callbacks for this application. */ + std::list idleCallbacks; + + /** Constructor and destructor */ + explicit PrivateData(bool standalone); + ~PrivateData(); + + /** Flag one window as shown, which increments @a visibleWindows. + Sets @a isQuitting and @a isStarting as false if this is the first window. + For standalone mode only. */ + void oneWindowShown() noexcept; + + /** Flag one window as closed, which decrements @a visibleWindows. + Sets @a isQuitting as true if this is the last window. + For standalone mode only. */ + void oneWindowClosed() noexcept; + + /** Run Pugl world update for @a timeoutInMs, and then each idle callback in order of registration. */ + void idle(uint timeoutInMs); + + /** Run each idle callback without updating pugl world. */ + void triggerIdleCallbacks(); + + /** Set flag indicating application is quitting, and close all windows in reverse order of registration. + For standalone mode only. */ + void quit(); + + /** Get time via pugl */ + double getTime() const; + + /** Set pugl world class name. */ + void setClassName(const char* name); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_APP_PRIVATE_DATA_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Cairo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Cairo.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,827 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * Copyright (C) 2019-2021 Jean Pierre Cimalando + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef _MSC_VER +// instantiated template classes whose methods are defined elsewhere +# pragma warning(disable:4661) +#endif + +#include "../Cairo.hpp" +#include "../Color.hpp" +#include "../ImageBaseWidgets.hpp" + +#include "SubWidgetPrivateData.hpp" +#include "TopLevelWidgetPrivateData.hpp" +#include "WidgetPrivateData.hpp" +#include "WindowPrivateData.hpp" + +// templated classes +#include "ImageBaseWidgets.cpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +static void notImplemented(const char* const name) +{ + d_stderr2("cairo function not implemented: %s", name); +} + +// ----------------------------------------------------------------------- +// Color + +void Color::setFor(const GraphicsContext& context, const bool includeAlpha) +{ + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + if (includeAlpha) + cairo_set_source_rgba(handle, red, green, blue, alpha); + else + cairo_set_source_rgb(handle, red, green, blue); +} + +// ----------------------------------------------------------------------- +// Line + +template +void Line::draw(const GraphicsContext& context, const T width) +{ + DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,); + DISTRHO_SAFE_ASSERT_RETURN(width != 0,); + + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + cairo_set_line_width(handle, width); + cairo_move_to(handle, posStart.getX(), posStart.getY()); + cairo_line_to(handle, posEnd.getX(), posEnd.getY()); + cairo_stroke(handle); +} + +template +void Line::draw() +{ + notImplemented("Line::draw"); +} + +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; + +// ----------------------------------------------------------------------- +// Circle + +template +static void drawCircle(cairo_t* const handle, + const Point& pos, + const uint numSegments, + const float size, + const float sin, + const float cos, + const bool outline) +{ + DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,); + + const T origx = pos.getX(); + const T origy = pos.getY(); + double t, x = size, y = 0.0; + + // TODO use arc + /* + cairo_arc(handle, origx, origy, size, sin, cos); + */ + + cairo_move_to(handle, x + origx, y + origy); + + for (uint i=1; i +void Circle::draw(const GraphicsContext& context) +{ + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + drawCircle(handle, fPos, fNumSegments, fSize, fSin, fCos, false); +} + +template +void Circle::drawOutline(const GraphicsContext& context, const T lineWidth) +{ + DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,); + + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + cairo_set_line_width(handle, lineWidth); + drawCircle(handle, fPos, fNumSegments, fSize, fSin, fCos, true); +} + +template +void Circle::draw() +{ + notImplemented("Circle::draw"); +} + +template +void Circle::drawOutline() +{ + notImplemented("Circle::drawOutline"); +} + +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; + +// ----------------------------------------------------------------------- +// Triangle + +template +static void drawTriangle(cairo_t* const handle, + const Point& pos1, + const Point& pos2, + const Point& pos3, + const bool outline) +{ + DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,); + + cairo_move_to(handle, pos1.getX(), pos1.getY()); + cairo_line_to(handle, pos2.getX(), pos2.getY()); + cairo_line_to(handle, pos3.getX(), pos3.getY()); + cairo_line_to(handle, pos1.getX(), pos1.getY()); + + if (outline) + cairo_stroke(handle); + else + cairo_fill(handle); +} + +template +void Triangle::draw(const GraphicsContext& context) +{ + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + drawTriangle(handle, pos1, pos2, pos3, false); +} + +template +void Triangle::drawOutline(const GraphicsContext& context, const T lineWidth) +{ + DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,); + + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + cairo_set_line_width(handle, lineWidth); + drawTriangle(handle, pos1, pos2, pos3, true); +} + +template +void Triangle::draw() +{ + notImplemented("Triangle::draw"); +} + +template +void Triangle::drawOutline() +{ + notImplemented("Triangle::drawOutline"); +} + +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; + +// ----------------------------------------------------------------------- +// Rectangle + +template +static void drawRectangle(cairo_t* const handle, const Rectangle& rect, const bool outline) +{ + cairo_rectangle(handle, rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); + + if (outline) + cairo_stroke(handle); + else + cairo_fill(handle); +} + +template +void Rectangle::draw(const GraphicsContext& context) +{ + DISTRHO_SAFE_ASSERT_RETURN(isValid(),); + + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + drawRectangle(handle, *this, false); +} + +template +void Rectangle::drawOutline(const GraphicsContext& context, const T lineWidth) +{ + DISTRHO_SAFE_ASSERT_RETURN(isValid(),); + DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,); + + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + cairo_set_line_width(handle, lineWidth); + drawRectangle(handle, *this, true); +} + +template +void Rectangle::draw() +{ + notImplemented("Rectangle::draw"); +} + +template +void Rectangle::drawOutline() +{ + notImplemented("Rectangle::drawOutline"); +} + +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; + +// ----------------------------------------------------------------------- +// CairoImage + +static cairo_format_t asCairoImageFormat(const ImageFormat format) noexcept +{ + switch (format) + { + case kImageFormatNull: + break; + case kImageFormatGrayscale: + return CAIRO_FORMAT_A8; + case kImageFormatBGR: + case kImageFormatRGB: + return CAIRO_FORMAT_RGB24; + case kImageFormatBGRA: + case kImageFormatRGBA: + return CAIRO_FORMAT_ARGB32; + } + + return CAIRO_FORMAT_INVALID; +} + +/* +static ImageFormat asCairoImageFormat(const cairo_format_t format) noexcept +{ + switch (format) + { + case CAIRO_FORMAT_INVALID: + break; + case CAIRO_FORMAT_ARGB32: + break; + case CAIRO_FORMAT_RGB24: + break; + case CAIRO_FORMAT_A8: + break; + case CAIRO_FORMAT_A1: + break; + case CAIRO_FORMAT_RGB16_565: + break; + case CAIRO_FORMAT_RGB30: + break; + } + + return kImageFormatNull; +} +*/ + +CairoImage::CairoImage() + : ImageBase(), + surface(nullptr), + surfacedata(nullptr), + datarefcount(nullptr) {} + +CairoImage::CairoImage(const char* const rdata, const uint w, const uint h, const ImageFormat fmt) + : ImageBase(rdata, w, h, fmt), + surface(nullptr), + surfacedata(nullptr), + datarefcount(nullptr) +{ + loadFromMemory(rdata, w, h, fmt); +} + +CairoImage::CairoImage(const char* const rdata, const Size& s, const ImageFormat fmt) + : ImageBase(rdata, s, fmt), + surface(nullptr), + surfacedata(nullptr), + datarefcount(nullptr) +{ + loadFromMemory(rdata, s, fmt); +} + +CairoImage::CairoImage(const CairoImage& image) + : ImageBase(image.rawData, image.size, image.format), + surface(cairo_surface_reference(image.surface)), + surfacedata(image.surfacedata), + datarefcount(image.datarefcount) +{ + if (datarefcount != nullptr) + ++(*datarefcount); +} + +CairoImage::~CairoImage() +{ + cairo_surface_destroy(surface); + + if (datarefcount != nullptr && --(*datarefcount) == 0) + { + std::free(surfacedata); + std::free(datarefcount); + } +} + +void CairoImage::loadFromMemory(const char* const rdata, const Size& s, const ImageFormat fmt) noexcept +{ + const cairo_format_t cairoformat = asCairoImageFormat(fmt); + const int width = static_cast(s.getWidth()); + const int height = static_cast(s.getHeight()); + const int stride = cairo_format_stride_for_width(cairoformat, width); + + uchar* const newdata = (uchar*)std::malloc(static_cast(width * height * stride * 4)); + DISTRHO_SAFE_ASSERT_RETURN(newdata != nullptr,); + + cairo_surface_t* const newsurface = cairo_image_surface_create_for_data(newdata, cairoformat, width, height, stride); + DISTRHO_SAFE_ASSERT_RETURN(newsurface != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(static_cast(s.getWidth()) == cairo_image_surface_get_width(newsurface),); + DISTRHO_SAFE_ASSERT_RETURN(static_cast(s.getHeight()) == cairo_image_surface_get_height(newsurface),); + + cairo_surface_destroy(surface); + + if (datarefcount != nullptr && --(*datarefcount) == 0) + std::free(surfacedata); + else + datarefcount = (int*)malloc(sizeof(*datarefcount)); + + surface = newsurface; + surfacedata = newdata; + *datarefcount = 1; + + switch (fmt) + { + case kImageFormatNull: + break; + case kImageFormatGrayscale: + // Grayscale to A8 + // TODO + break; + case kImageFormatBGR: + // BGR8 to CAIRO_FORMAT_RGB24 + for (int h = 0; h < height; ++h) + { + for (int w = 0; w < width; ++w) + { + newdata[h*width*4+w*4+0] = static_cast(rdata[h*width*3+w*3+0]); + newdata[h*width*4+w*4+1] = static_cast(rdata[h*width*3+w*3+1]); + newdata[h*width*4+w*4+2] = static_cast(rdata[h*width*3+w*3+2]); + newdata[h*width*4+w*4+3] = 0; + } + } + break; + case kImageFormatBGRA: + // BGRA8 to CAIRO_FORMAT_ARGB32 + // FIXME something is wrong here... + for (int h = 0, t; h < height; ++h) + { + for (int w = 0; w < width; ++w) + { + if ((t = rdata[h*width*4+w*4+3]) != 0) + { + newdata[h*width*4+w*4+0] = static_cast(rdata[h*width*4+w*4+0]); + newdata[h*width*4+w*4+1] = static_cast(rdata[h*width*4+w*4+1]); + newdata[h*width*4+w*4+2] = static_cast(rdata[h*width*4+w*4+2]); + newdata[h*width*4+w*4+3] = static_cast(t); + } + else + { + // make all pixels zero, cairo does not render full transparency otherwise + memset(&newdata[h*width*4+w*4], 0, 4); + } + } + } + break; + case kImageFormatRGB: + // RGB8 to CAIRO_FORMAT_RGB24 + // TODO + break; + case kImageFormatRGBA: + // RGBA8 to CAIRO_FORMAT_ARGB32 + // TODO + break; + } + + ImageBase::loadFromMemory(rdata, s, fmt); +} + +// const GraphicsContext& context +void CairoImage::loadFromPNG(const char* const pngData, const uint pngSize) noexcept +{ + struct PngReaderData + { + const char* dataPtr; + uint sizeLeft; + + static cairo_status_t read(void* const closure, uchar* const data, const uint length) noexcept + { + PngReaderData& readerData = *reinterpret_cast(closure); + + if (readerData.sizeLeft < length) + return CAIRO_STATUS_READ_ERROR; + + std::memcpy(data, readerData.dataPtr, length); + readerData.dataPtr += length; + readerData.sizeLeft -= length; + return CAIRO_STATUS_SUCCESS; + } + }; + + PngReaderData readerData; + readerData.dataPtr = pngData; + readerData.sizeLeft = pngSize; + + cairo_surface_t* const newsurface = cairo_image_surface_create_from_png_stream(PngReaderData::read, &readerData); + DISTRHO_SAFE_ASSERT_RETURN(newsurface != nullptr,); + + const int newwidth = cairo_image_surface_get_width(newsurface); + const int newheight = cairo_image_surface_get_height(newsurface); + DISTRHO_SAFE_ASSERT_INT_RETURN(newwidth > 0, newwidth,); + DISTRHO_SAFE_ASSERT_INT_RETURN(newheight > 0, newheight,); + + cairo_surface_destroy(surface); + + if (datarefcount != nullptr && --(*datarefcount) == 0) + std::free(surfacedata); + else + datarefcount = (int*)malloc(sizeof(*datarefcount)); + + surface = newsurface; + surfacedata = nullptr; // cairo_image_surface_get_data(newsurface); + *datarefcount = 1; + + rawData = nullptr; + format = kImageFormatNull; // asCairoImageFormat(cairo_image_surface_get_format(newsurface)); + size = Size(static_cast(newwidth), static_cast(newheight)); +} + +void CairoImage::drawAt(const GraphicsContext& context, const Point& pos) +{ + if (surface == nullptr) + return; + + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + + cairo_set_source_surface(handle, surface, pos.getX(), pos.getY()); + cairo_paint(handle); +} + +CairoImage& CairoImage::operator=(const CairoImage& image) noexcept +{ + cairo_surface_t* newsurface = cairo_surface_reference(image.surface); + cairo_surface_destroy(surface); + + if (datarefcount != nullptr && --(*datarefcount) == 0) + { + std::free(surfacedata); + std::free(datarefcount); + } + + surface = newsurface; + rawData = image.rawData; + size = image.size; + format = image.format; + surfacedata = image.surfacedata; + datarefcount = image.datarefcount; + + if (datarefcount != nullptr) + ++(*datarefcount); + + return *this; +} + +// ----------------------------------------------------------------------- +// CairoSubWidget + +template <> +CairoBaseWidget::CairoBaseWidget(Widget* const parent) + : SubWidget(parent) {} + +template class CairoBaseWidget; + +// ----------------------------------------------------------------------- +// CairoTopLevelWidget + +template <> +CairoBaseWidget::CairoBaseWidget(Window& windowToMapTo) + : TopLevelWidget(windowToMapTo) {} + +template class CairoBaseWidget; + +// ----------------------------------------------------------------------- +// CairoStandaloneWindow + +template <> +CairoBaseWidget::CairoBaseWidget(Application& app) + : StandaloneWindow(app) {} + +template <> +CairoBaseWidget::CairoBaseWidget(Application& app, Window& parentWindow) + : StandaloneWindow(app, parentWindow) {} + +template class CairoBaseWidget; + +// ----------------------------------------------------------------------- +// ImageBaseAboutWindow + +#if 0 +template <> +void ImageBaseAboutWindow::onDisplay() +{ + img.draw(getGraphicsContext()); +} +#endif + +template class ImageBaseAboutWindow; + +// ----------------------------------------------------------------------- +// ImageBaseButton + +template class ImageBaseButton; + +// ----------------------------------------------------------------------- +// ImageBaseKnob + +template <> +void ImageBaseKnob::PrivateData::init() +{ + alwaysRepaint = true; + cairoSurface = nullptr; +} + +template <> +void ImageBaseKnob::PrivateData::cleanup() +{ + cairo_surface_destroy((cairo_surface_t*)cairoSurface); + cairoSurface = nullptr; +} + +/** + Get the pixel size in bytes. + @return pixel size, or 0 if the format is unknown, or pixels are not aligned to bytes. +*/ +static int getBytesPerPixel(const cairo_format_t format) noexcept +{ + switch (format) + { + case CAIRO_FORMAT_ARGB32: + case CAIRO_FORMAT_RGB24: + case CAIRO_FORMAT_RGB30: + return 4; + case CAIRO_FORMAT_RGB16_565: + return 2; + case CAIRO_FORMAT_A8: + return 1; + case CAIRO_FORMAT_A1: + return 0; + default: + DISTRHO_SAFE_ASSERT(false); + return 0; + } +} + +static cairo_surface_t* getRegion(cairo_surface_t* origsurface, int x, int y, int width, int height) noexcept +{ + const cairo_format_t format = cairo_image_surface_get_format(origsurface); + const int bpp = getBytesPerPixel(format); + + if (bpp == 0) + return nullptr; + + const int fullWidth = cairo_image_surface_get_width(origsurface); + const int fullHeight = cairo_image_surface_get_height(origsurface); + const int stride = cairo_image_surface_get_stride(origsurface); + uchar* const fullData = cairo_image_surface_get_data(origsurface); + + x = (x < fullWidth) ? x : fullWidth; + y = (y < fullHeight) ? y : fullHeight; + width = (x + width < fullWidth) ? width : (fullWidth - x); + height = (x + height < fullHeight) ? height : (fullHeight - x); + + uchar* const data = fullData + (x * bpp + y * stride); + return cairo_image_surface_create_for_data(data, format, width, height, stride); +} + +template <> +void ImageBaseKnob::onDisplay() +{ + const GraphicsContext& context(getGraphicsContext()); + cairo_t* const handle = ((const CairoGraphicsContext&)context).handle; + const double normValue = getNormalizedValue(); + + cairo_surface_t* surface = (cairo_surface_t*)pData->cairoSurface; + + if (! pData->isReady) + { + const int layerW = static_cast(pData->imgLayerWidth); + const int layerH = static_cast(pData->imgLayerHeight); + int layerNum = 0; + + if (pData->rotationAngle == 0) + layerNum = static_cast(normValue * static_cast(pData->imgLayerCount - 1) + 0.5); + + const int layerX = pData->isImgVertical ? 0 : layerNum * layerW; + const int layerY = !pData->isImgVertical ? 0 : layerNum * layerH; + + cairo_surface_t* newsurface; + + if (pData->rotationAngle == 0) + { + newsurface = getRegion(pData->image.getSurface(), layerX, layerY, layerW, layerH); + } + else + { + newsurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, layerW, layerH); + cairo_t* const cr = cairo_create(newsurface); + cairo_translate(cr, 0.5 * layerW, 0.5 * layerH); + cairo_rotate(cr, normValue * pData->rotationAngle * (M_PI / 180)); + cairo_set_source_surface(cr, pData->image.getSurface(), -0.5 * layerW, -0.5 * layerH); + cairo_paint(cr); + cairo_destroy(cr); + } + + DISTRHO_SAFE_ASSERT_RETURN(newsurface != nullptr,); + + cairo_surface_destroy(surface); + pData->cairoSurface = surface = newsurface; + pData->isReady = true; + } + + if (surface != nullptr) + { + cairo_set_source_surface(handle, surface, 0, 0); + cairo_paint(handle); + } +} + +template class ImageBaseKnob; + +// ----------------------------------------------------------------------- +// ImageBaseSlider + +template class ImageBaseSlider; + +// ----------------------------------------------------------------------- +// ImageBaseSwitch + +template class ImageBaseSwitch; + +// ----------------------------------------------------------------------- + +void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) +{ + cairo_t* const handle = static_cast(self->getGraphicsContext()).handle; + + bool needsResetClip = false; + + cairo_matrix_t matrix; + cairo_get_matrix(handle, &matrix); + + if (needsViewportScaling) + { + // limit viewport to widget bounds + // NOTE only used for nanovg for now, which is not relevant here + } + else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size(width, height))) + { + // full viewport size + cairo_translate(handle, 0, 0); + cairo_scale(handle, autoScaleFactor, autoScaleFactor); + } + else + { + // set viewport pos + cairo_translate(handle, absolutePos.getX() * autoScaleFactor, absolutePos.getY() * autoScaleFactor); + + // then cut the outer bounds + cairo_rectangle(handle, + 0, + 0, + std::round(self->getWidth() * autoScaleFactor), + std::round(self->getHeight() * autoScaleFactor)); + + cairo_clip(handle); + needsResetClip = true; + + // set viewport scaling + cairo_scale(handle, autoScaleFactor, autoScaleFactor); + } + + // display widget + self->onDisplay(); + + if (needsResetClip) + cairo_reset_clip(handle); + + cairo_set_matrix(handle, &matrix); + + selfw->pData->displaySubWidgets(width, height, autoScaleFactor); +} + +// ----------------------------------------------------------------------- + +void TopLevelWidget::PrivateData::display() +{ + if (! selfw->pData->visible) + return; + + cairo_t* const handle = static_cast(self->getGraphicsContext()).handle; + + const Size size(window.getSize()); + const uint width = size.getWidth(); + const uint height = size.getHeight(); + + const double autoScaleFactor = window.pData->autoScaleFactor; + + cairo_matrix_t matrix; + cairo_get_matrix(handle, &matrix); + + // full viewport size + if (window.pData->autoScaling) + { + cairo_translate(handle, 0, 0); + cairo_scale(handle, autoScaleFactor, autoScaleFactor); + } + else + { + cairo_translate(handle, 0, 0); + cairo_scale(handle, 1.0, 1.0); + } + + // main widget drawing + self->onDisplay(); + + cairo_set_matrix(handle, &matrix); + + // now draw subwidgets if there are any + selfw->pData->displaySubWidgets(width, height, autoScaleFactor); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::renderToPicture(const char*, const GraphicsContext&, uint, uint) +{ + notImplemented("Window::PrivateData::renderToPicture"); +} + +// ----------------------------------------------------------------------- + +const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept +{ + GraphicsContext& context((GraphicsContext&)graphicsContext); + ((CairoGraphicsContext&)context).handle = (cairo_t*)puglGetContext(view); + return context; +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Color.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Color.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,310 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../Color.hpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +static float computeHue(float h, float m1, float m2) +{ + if (h < 0) h += 1; + if (h > 1) h -= 1; + if (h < 1.0f/6.0f) + return m1 + (m2 - m1) * h * 6.0f; + if (h < 3.0f/6.0f) + return m2; + if (h < 4.0f/6.0f) + return m1 + (m2 - m1) * (2.0f/3.0f - h) * 6.0f; + return m1; +} + +static void fixRange(float& value) +{ + /**/ if (value < 0.0f) + value = 0.0f; + else if (value > 1.0f) + value = 1.0f; +} + +static float getFixedRange(const float& value) +{ + if (value <= 0.0f) + return 0.0f; + if (value >= 1.0f) + return 1.0f; + return value; +} + +static uchar getFixedRange2(const float& value) +{ + const float value2(getFixedRange(value)*255.0f); + if (value2 <= 0.0f) + return 0; + if (value2 >= 255.0f) + return 255; + return static_cast(value2 + 0.5f); +} + +// ----------------------------------------------------------------------- + +Color::Color() noexcept + : red(0.0f), + green(0.0f), + blue(0.0f), + alpha(1.0f) {} + +Color::Color(const int r, const int g, const int b, const float a) noexcept + : red(static_cast(r)/255.0f), + green(static_cast(g)/255.0f), + blue(static_cast(b)/255.0f), + alpha(a) +{ + fixBounds(); +} + +Color::Color(const float r, const float g, const float b, const float a) noexcept + : red(r), + green(g), + blue(b), + alpha(a) +{ + fixBounds(); +} + +Color::Color(const Color& color) noexcept + : red(color.red), + green(color.green), + blue(color.blue), + alpha(color.alpha) +{ + fixBounds(); +} + +Color& Color::operator=(const Color& color) noexcept +{ + red = color.red; + green = color.green; + blue = color.blue; + alpha = color.alpha; + fixBounds(); + return *this; +} + +Color::Color(const Color& color1, const Color& color2, const float u) noexcept + : red(color1.red), + green(color1.green), + blue(color1.blue), + alpha(color1.alpha) +{ + interpolate(color2, u); +} + +Color Color::withAlpha(const float alpha2) const noexcept +{ + Color color(*this); + color.alpha = alpha2; + return color; +} + +Color Color::minus(const int value) const noexcept +{ + const float fvalue = static_cast(value)/255.f; + Color color(*this); + color.red -= fvalue; + color.green -= fvalue; + color.blue -= fvalue; + color.fixBounds(); + return color; +} + +Color Color::minus(const float value) const noexcept +{ + Color color(*this); + color.red -= value; + color.green -= value; + color.blue -= value; + color.fixBounds(); + return color; +} + +Color Color::plus(const int value) const noexcept +{ + const float fvalue = static_cast(value)/255.f; + Color color(*this); + color.red += fvalue; + color.green += fvalue; + color.blue += fvalue; + color.fixBounds(); + return color; +} + +Color Color::plus(const float value) const noexcept +{ + Color color(*this); + color.red += value; + color.green += value; + color.blue += value; + color.fixBounds(); + return color; +} + +Color Color::invert() const noexcept +{ + Color color(*this); + color.red = 1.f - color.red; + color.green = 1.f - color.green; + color.blue = 1.f - color.blue; + return color; +} + +Color Color::fromHSL(float hue, float saturation, float lightness, float alpha) +{ + float m1, m2; + Color col; + hue = fmodf(hue, 1.0f); + if (hue < 0.0f) hue += 1.0f; + fixRange(saturation); + fixRange(lightness); + m2 = lightness <= 0.5f ? (lightness * (1 + saturation)) : (lightness + saturation - lightness * saturation); + m1 = 2 * lightness - m2; + col.red = computeHue(hue + 1.0f/3.0f, m1, m2); + col.green = computeHue(hue, m1, m2); + col.blue = computeHue(hue - 1.0f/3.0f, m1, m2); + col.alpha = alpha; + col.fixBounds(); + return col; +} + +Color Color::fromHTML(const char* rgb, const float alpha) noexcept +{ + Color fallback; + DISTRHO_SAFE_ASSERT_RETURN(rgb != nullptr && rgb[0] != '\0', fallback); + + if (rgb[0] == '#') + ++rgb; + DISTRHO_SAFE_ASSERT_RETURN(rgb[0] != '\0', fallback); + + std::size_t rgblen = std::strlen(rgb); + DISTRHO_SAFE_ASSERT_RETURN(rgblen == 3 || rgblen == 6, fallback); + + char rgbtmp[5] = { '0', 'x', '\0', '\0', '\0' }; + int r, g, b; + + if (rgblen == 3) + { + rgbtmp[2] = rgb[0]; + r = static_cast(std::strtol(rgbtmp, nullptr, 16)) * 17; + + rgbtmp[2] = rgb[1]; + g = static_cast(std::strtol(rgbtmp, nullptr, 16)) * 17; + + rgbtmp[2] = rgb[2]; + b = static_cast(std::strtol(rgbtmp, nullptr, 16)) * 17; + } + else + { + rgbtmp[2] = rgb[0]; + rgbtmp[3] = rgb[1]; + r = static_cast(std::strtol(rgbtmp, nullptr, 16)); + + rgbtmp[2] = rgb[2]; + rgbtmp[3] = rgb[3]; + g = static_cast(std::strtol(rgbtmp, nullptr, 16)); + + rgbtmp[2] = rgb[4]; + rgbtmp[3] = rgb[5]; + b = static_cast(std::strtol(rgbtmp, nullptr, 16)); + } + + return Color(r, g, b, alpha); +} + +void Color::interpolate(const Color& other, float u) noexcept +{ + fixRange(u); + const float oneMinusU = 1.0f - u; + + red = (red * oneMinusU) + (other.red * u); + green = (green * oneMinusU) + (other.green * u); + blue = (blue * oneMinusU) + (other.blue * u); + alpha = (alpha * oneMinusU) + (other.alpha * u); + + fixBounds(); +} + +// ----------------------------------------------------------------------- + +bool Color::isEqual(const Color& color, const bool withAlpha) noexcept +{ + const uchar r1 = getFixedRange2(rgba[0]); + const uchar g1 = getFixedRange2(rgba[1]); + const uchar b1 = getFixedRange2(rgba[2]); + const uchar a1 = getFixedRange2(rgba[3]); + + const uchar r2 = getFixedRange2(color.rgba[0]); + const uchar g2 = getFixedRange2(color.rgba[1]); + const uchar b2 = getFixedRange2(color.rgba[2]); + const uchar a2 = getFixedRange2(color.rgba[3]); + + if (withAlpha) + return (r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2); + else + return (r1 == r2 && g1 == g2 && b1 == b2); +} + +bool Color::isNotEqual(const Color& color, const bool withAlpha) noexcept +{ + const uchar r1 = getFixedRange2(rgba[0]); + const uchar g1 = getFixedRange2(rgba[1]); + const uchar b1 = getFixedRange2(rgba[2]); + const uchar a1 = getFixedRange2(rgba[3]); + + const uchar r2 = getFixedRange2(color.rgba[0]); + const uchar g2 = getFixedRange2(color.rgba[1]); + const uchar b2 = getFixedRange2(color.rgba[2]); + const uchar a2 = getFixedRange2(color.rgba[3]); + + if (withAlpha) + return (r1 != r2 || g1 != g2 || b1 != b2 || a1 != a2); + else + return (r1 != r2 || g1 != g2 || b1 != b2); +} + +bool Color::operator==(const Color& color) noexcept +{ + return isEqual(color, true); +} + +bool Color::operator!=(const Color& color) noexcept +{ + return isNotEqual(color, true); +} + +// ----------------------------------------------------------------------- + +void Color::fixBounds() noexcept +{ + fixRange(red); + fixRange(green); + fixRange(blue); + fixRange(alpha); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/EventHandlers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/EventHandlers.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,684 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../EventHandlers.hpp" +#include "../SubWidget.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +struct ButtonEventHandler::PrivateData { + ButtonEventHandler* const self; + SubWidget* const widget; + ButtonEventHandler::Callback* internalCallback; + ButtonEventHandler::Callback* userCallback; + + int button; + int state; + bool checkable; + bool checked; + + Point lastClickPos; + Point lastMotionPos; + + PrivateData(ButtonEventHandler* const s, SubWidget* const w) + : self(s), + widget(w), + internalCallback(nullptr), + userCallback(nullptr), + button(-1), + state(kButtonStateDefault), + checkable(false), + checked(false), + lastClickPos(0, 0), + lastMotionPos(0, 0) {} + + bool mouseEvent(const Widget::MouseEvent& ev) + { + lastClickPos = ev.pos; + + // button was released, handle it now + if (button != -1 && ! ev.press) + { + DISTRHO_SAFE_ASSERT(state & kButtonStateActive); + + // release button + const int button2 = button; + button = -1; + + const int state2 = state; + state &= ~kButtonStateActive; + + self->stateChanged(static_cast(state), static_cast(state2)); + widget->repaint(); + + // cursor was moved outside the button bounds, ignore click + if (! widget->contains(ev.pos)) + return true; + + // still on bounds, register click + if (checkable) + checked = !checked; + + if (internalCallback != nullptr) + internalCallback->buttonClicked(widget, button2); + else if (userCallback != nullptr) + userCallback->buttonClicked(widget, button2); + + return true; + } + + // button was pressed, wait for release + if (ev.press && widget->contains(ev.pos)) + { + const int state2 = state; + button = static_cast(ev.button); + state |= kButtonStateActive; + self->stateChanged(static_cast(state), static_cast(state2)); + widget->repaint(); + return true; + } + + return false; + } + + bool motionEvent(const Widget::MotionEvent& ev) + { + // keep pressed + if (button != -1) + { + lastMotionPos = ev.pos; + return true; + } + + bool ret = false; + + if (widget->contains(ev.pos)) + { + // check if entering hover + if ((state & kButtonStateHover) == 0x0) + { + const int state2 = state; + state |= kButtonStateHover; + ret = widget->contains(lastMotionPos); + self->stateChanged(static_cast(state), static_cast(state2)); + widget->repaint(); + } + } + else + { + // check if exiting hover + if (state & kButtonStateHover) + { + const int state2 = state; + state &= ~kButtonStateHover; + ret = widget->contains(lastMotionPos); + self->stateChanged(static_cast(state), static_cast(state2)); + widget->repaint(); + } + } + + lastMotionPos = ev.pos; + return ret; + } + + void setActive(const bool active2, const bool sendCallback) noexcept + { + const bool active = state & kButtonStateActive; + if (active == active2) + return; + + state |= kButtonStateActive; + widget->repaint(); + + if (sendCallback) + { + if (internalCallback != nullptr) + internalCallback->buttonClicked(widget, -1); + else if (userCallback != nullptr) + userCallback->buttonClicked(widget, -1); + } + } + + void setChecked(const bool checked2, const bool sendCallback) noexcept + { + if (checked == checked2) + return; + + checked = checked2; + widget->repaint(); + + if (sendCallback) + { + if (internalCallback != nullptr) + internalCallback->buttonClicked(widget, -1); + else if (userCallback != nullptr) + userCallback->buttonClicked(widget, -1); + } + } + + DISTRHO_DECLARE_NON_COPYABLE(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +ButtonEventHandler::ButtonEventHandler(SubWidget* const self) + : pData(new PrivateData(this, self)) {} + +ButtonEventHandler::~ButtonEventHandler() +{ + delete pData; +} + +bool ButtonEventHandler::isActive() noexcept +{ + return pData->state & kButtonStateActive; +} + +void ButtonEventHandler::setActive(const bool active, const bool sendCallback) noexcept +{ + pData->setActive(active, sendCallback); +} + +bool ButtonEventHandler::isChecked() const noexcept +{ + return pData->checked; +} + +void ButtonEventHandler::setChecked(const bool checked, const bool sendCallback) noexcept +{ + pData->setChecked(checked, sendCallback); +} + +bool ButtonEventHandler::isCheckable() const noexcept +{ + return pData->checkable; +} + +void ButtonEventHandler::setCheckable(const bool checkable) noexcept +{ + if (pData->checkable == checkable) + return; + + pData->checkable = checkable; +} + +Point ButtonEventHandler::getLastClickPosition() const noexcept +{ + return pData->lastClickPos; +} + +Point ButtonEventHandler::getLastMotionPosition() const noexcept +{ + return pData->lastMotionPos; +} + +void ButtonEventHandler::setCallback(Callback* const callback) noexcept +{ + pData->userCallback = callback; +} + +bool ButtonEventHandler::mouseEvent(const Widget::MouseEvent& ev) +{ + return pData->mouseEvent(ev); +} + +bool ButtonEventHandler::motionEvent(const Widget::MotionEvent& ev) +{ + return pData->motionEvent(ev); +} + +ButtonEventHandler::State ButtonEventHandler::getState() const noexcept +{ + return static_cast(pData->state); +} + +void ButtonEventHandler::clearState() noexcept +{ + pData->state = kButtonStateDefault; +} + +void ButtonEventHandler::stateChanged(State, State) +{ +} + +void ButtonEventHandler::setInternalCallback(Callback* const callback) noexcept +{ + pData->internalCallback = callback; +} + +void ButtonEventHandler::triggerUserCallback(SubWidget* const widget, const int button) +{ + if (pData->userCallback != nullptr) + pData->userCallback->buttonClicked(widget, button); +} + +// -------------------------------------------------------------------------------------------------------------------- + +struct KnobEventHandler::PrivateData { + KnobEventHandler* const self; + SubWidget* const widget; + KnobEventHandler::Callback* callback; + + float accel; + float minimum; + float maximum; + float step; + float value; + float valueDef; + float valueTmp; + bool usingDefault; + bool usingLog; + Orientation orientation; + int state; + + double lastX; + double lastY; + uint lastClickTime; + + PrivateData(KnobEventHandler* const s, SubWidget* const w) + : self(s), + widget(w), + callback(nullptr), + accel(200.f), + minimum(0.f), + maximum(1.f), + step(0.0f), + value(0.5f), + valueDef(value), + valueTmp(value), + usingDefault(false), + usingLog(false), + orientation(Vertical), + state(kKnobStateDefault), + lastX(0.0), + lastY(0.0), + lastClickTime(0) {} + + PrivateData(KnobEventHandler* const s, SubWidget* const w, PrivateData* const other) + : self(s), + widget(w), + callback(other->callback), + accel(other->accel), + minimum(other->minimum), + maximum(other->maximum), + step(other->step), + value(other->value), + valueDef(other->valueDef), + valueTmp(value), + usingDefault(other->usingDefault), + usingLog(other->usingLog), + orientation(other->orientation), + state(kKnobStateDefault), + lastX(0.0), + lastY(0.0), + lastClickTime(0) {} + + void assignFrom(PrivateData* const other) + { + callback = other->callback; + accel = other->accel; + minimum = other->minimum; + maximum = other->maximum; + step = other->step; + value = other->value; + valueDef = other->valueDef; + valueTmp = value; + usingDefault = other->usingDefault; + usingLog = other->usingLog; + orientation = other->orientation; + state = kKnobStateDefault; + lastX = 0.0; + lastY = 0.0; + lastClickTime = 0; + } + + inline float logscale(const float v) const + { + const float b = std::log(maximum/minimum)/(maximum-minimum); + const float a = maximum/std::exp(maximum*b); + return a * std::exp(b*v); + } + + inline float invlogscale(const float v) const + { + const float b = std::log(maximum/minimum)/(maximum-minimum); + const float a = maximum/std::exp(maximum*b); + return std::log(v/a)/b; + } + + bool mouseEvent(const Widget::MouseEvent& ev, const double scaleFactor) + { + if (ev.button != 1) + return false; + + if (ev.press) + { + if (! widget->contains(ev.pos)) + return false; + + if ((ev.mod & kModifierShift) != 0 && usingDefault) + { + setValue(valueDef, true); + valueTmp = value; + return true; + } + + lastX = ev.pos.getX() / scaleFactor; + lastY = ev.pos.getY() / scaleFactor; + + if (lastClickTime > 0 && ev.time > lastClickTime && ev.time - lastClickTime <= 300) + { + lastClickTime = 0; + + if (callback != nullptr) + callback->knobDoubleClicked(widget); + + return true; + } + + lastClickTime = ev.time; + state |= kKnobStateDragging; + widget->repaint(); + + if (callback != nullptr) + callback->knobDragStarted(widget); + + return true; + } + else if (state & kKnobStateDragging) + { + state &= ~kKnobStateDragging; + widget->repaint(); + + if (callback != nullptr) + callback->knobDragFinished(widget); + + return true; + } + + return false; + } + + bool motionEvent(const Widget::MotionEvent& ev, const double scaleFactor) + { + if ((state & kKnobStateDragging) == 0x0) + return false; + + float movDiff; + + switch (orientation) + { + case Horizontal: + movDiff = ev.pos.getX() / scaleFactor - lastX; + break; + case Vertical: + movDiff = lastY - ev.pos.getY() / scaleFactor; + break; + case Both: + { + const float movDiffX = ev.pos.getX() / scaleFactor - lastX; + const float movDiffY = lastY - ev.pos.getY() / scaleFactor; + movDiff = std::abs(movDiffX) > std::abs(movDiffY) ? movDiffX : movDiffY; + } + break; + default: + return false; + } + + if (d_isZero(movDiff)) + return true; + + const float divisor = (ev.mod & kModifierControl) ? accel * 10.f : accel; + valueTmp += (maximum - minimum) / divisor * movDiff; + + if (usingLog) + valueTmp = logscale(valueTmp); + + float value2; + bool valueChanged = false; + + if (valueTmp < minimum) + { + valueTmp = value2 = minimum; + valueChanged = true; + } + else if (valueTmp > maximum) + { + valueTmp = value2 = maximum; + valueChanged = true; + } + else + { + if (d_isNotZero(step)) + { + if (std::abs(valueTmp - value) >= step) + { + const float rest = std::fmod(valueTmp, step); + valueChanged = true; + value2 = valueTmp - rest; + + if (rest < 0 && rest < step * -0.5f) + value2 -= step; + else if (rest > 0 && rest > step * 0.5f) + value2 += step; + + if (value2 < minimum) + value2 = minimum; + else if (value2 > maximum) + value2 = maximum; + } + } + else + { + value2 = valueTmp; + valueChanged = true; + } + } + + if (valueChanged) + setValue(value2, true); + + lastX = ev.pos.getX() / scaleFactor; + lastY = ev.pos.getY() / scaleFactor; + + return true; + } + + bool scrollEvent(const Widget::ScrollEvent& ev) + { + if (! widget->contains(ev.pos)) + return false; + + const float dir = (ev.delta.getY() > 0.f) ? 1.f : -1.f; + const float d = (ev.mod & kModifierControl) ? accel * 10.f : accel; + float value2 = (usingLog ? invlogscale(valueTmp) : valueTmp) + + ((maximum - minimum) / d * 10.f * dir); + + if (usingLog) + value2 = logscale(value2); + + if (value2 < minimum) + { + valueTmp = value2 = minimum; + } + else if (value2 > maximum) + { + valueTmp = value2 = maximum; + } + else + { + valueTmp = value2; + + if (d_isNotZero(step)) + { + const float rest = std::fmod(value2, step); + value2 = value2 - rest + (rest > step/2.0f ? step : 0.0f); + } + } + + setValue(value2, true); + return true; + } + + float getNormalizedValue() const noexcept + { + const float diff = maximum - minimum; + return ((usingLog ? invlogscale(value) : value) - minimum) / diff; + } + + void setRange(const float min, const float max) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(max > min,); + + if (value < min) + { + valueTmp = value = min; + widget->repaint(); + } + else if (value > max) + { + valueTmp = value = max; + widget->repaint(); + } + + minimum = min; + maximum = max; + } + + bool setValue(const float value2, const bool sendCallback) + { + if (d_isEqual(value, value2)) + return false; + + valueTmp = value = value2; + widget->repaint(); + + if (sendCallback && callback != nullptr) + { + try { + callback->knobValueChanged(widget, value); + } DISTRHO_SAFE_EXCEPTION("KnobEventHandler::setValue"); + } + + return true; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +KnobEventHandler::KnobEventHandler(SubWidget* const self) + : pData(new PrivateData(this, self)) {} + +KnobEventHandler::KnobEventHandler(SubWidget* const self, const KnobEventHandler& other) + : pData(new PrivateData(this, self, other.pData)) {} + +KnobEventHandler& KnobEventHandler::operator=(const KnobEventHandler& other) +{ + pData->assignFrom(other.pData); + return *this; +} + +KnobEventHandler::~KnobEventHandler() +{ + delete pData; +} + +bool KnobEventHandler::isInteger() const noexcept +{ + return d_isEqual(pData->step, 1.f); +} + +float KnobEventHandler::getValue() const noexcept +{ + return pData->value; +} + +bool KnobEventHandler::setValue(const float value, const bool sendCallback) noexcept +{ + return pData->setValue(value, sendCallback); +} + +float KnobEventHandler::getNormalizedValue() const noexcept +{ + return pData->getNormalizedValue(); +} + +void KnobEventHandler::setDefault(const float def) noexcept +{ + pData->valueDef = def; + pData->usingDefault = true; +} + +void KnobEventHandler::setRange(const float min, const float max) noexcept +{ + pData->setRange(min, max); +} + +void KnobEventHandler::setStep(const float step) noexcept +{ + pData->step = step; +} + +void KnobEventHandler::setUsingLogScale(const bool yesNo) noexcept +{ + pData->usingLog = yesNo; +} + +KnobEventHandler::Orientation KnobEventHandler::getOrientation() const noexcept +{ + return pData->orientation; +} + +void KnobEventHandler::setOrientation(const Orientation orientation) noexcept +{ + pData->orientation = orientation; +} + +void KnobEventHandler::setCallback(Callback* const callback) noexcept +{ + pData->callback = callback; +} + +void KnobEventHandler::setMouseDeceleration(float accel) noexcept +{ + pData->accel = accel; +} + +bool KnobEventHandler::mouseEvent(const Widget::MouseEvent& ev, const double scaleFactor) +{ + return pData->mouseEvent(ev, scaleFactor); +} + +bool KnobEventHandler::motionEvent(const Widget::MotionEvent& ev, const double scaleFactor) +{ + return pData->motionEvent(ev, scaleFactor); +} + +bool KnobEventHandler::scrollEvent(const Widget::ScrollEvent& ev) +{ + return pData->scrollEvent(ev); +} + +KnobEventHandler::State KnobEventHandler::getState() const noexcept +{ + return static_cast(pData->state); +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Geometry.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Geometry.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1053 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef _MSC_VER +# pragma warning(disable:4661) /* instantiated template classes whose methods are defined elsewhere */ +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +#endif + +#include "../Geometry.hpp" + +#include + +START_NAMESPACE_DGL + +static const float M_2PIf = 3.14159265358979323846f*2.0f; + +// ----------------------------------------------------------------------- +// Point + +template +Point::Point() noexcept + : x(0), + y(0) {} + +template +Point::Point(const T& x2, const T& y2) noexcept + : x(x2), + y(y2) {} + +template +Point::Point(const Point& pos) noexcept + : x(pos.x), + y(pos.y) {} + +template +const T& Point::getX() const noexcept +{ + return x; +} + +template +const T& Point::getY() const noexcept +{ + return y; +} + +template +void Point::setX(const T& x2) noexcept +{ + x = x2; +} + +template +void Point::setY(const T& y2) noexcept +{ + y = y2; +} + +template +void Point::setPos(const T& x2, const T& y2) noexcept +{ + x = x2; + y = y2; +} + +template +void Point::setPos(const Point& pos) noexcept +{ + x = pos.x; + y = pos.y; +} + +template +void Point::moveBy(const T& x2, const T& y2) noexcept +{ + x = static_cast(x+x2); + y = static_cast(y+y2); +} + +template +void Point::moveBy(const Point& pos) noexcept +{ + x = static_cast(x+pos.x); + y = static_cast(y+pos.y); +} + +template +bool Point::isZero() const noexcept +{ + return x == 0 && y == 0; +} + +template +bool Point::isNotZero() const noexcept +{ + return x != 0 || y != 0; +} + +template +Point Point::operator+(const Point& pos) noexcept +{ + return Point(x+pos.x, y+pos.y); +} + +template +Point Point::operator-(const Point& pos) noexcept +{ + return Point(x-pos.x, y-pos.y); +} + +template +Point& Point::operator=(const Point& pos) noexcept +{ + x = pos.x; + y = pos.y; + return *this; +} + +template +Point& Point::operator+=(const Point& pos) noexcept +{ + x = static_cast(x+pos.x); + y = static_cast(y+pos.y); + return *this; +} + +template +Point& Point::operator-=(const Point& pos) noexcept +{ + x = static_cast(x-pos.x); + y = static_cast(y-pos.y); + return *this; +} + +template +bool Point::operator==(const Point& pos) const noexcept +{ + return (x == pos.x && y == pos.y); +} + +template +bool Point::operator!=(const Point& pos) const noexcept +{ + return (x != pos.x || y != pos.y); +} + +// ----------------------------------------------------------------------- +// Size + +template +Size::Size() noexcept + : fWidth(0), + fHeight(0) {} + +template +Size::Size(const T& width, const T& height) noexcept + : fWidth(width), + fHeight(height) {} + +template +Size::Size(const Size& size) noexcept + : fWidth(size.fWidth), + fHeight(size.fHeight) {} + +template +const T& Size::getWidth() const noexcept +{ + return fWidth; +} + +template +const T& Size::getHeight() const noexcept +{ + return fHeight; +} + +template +void Size::setWidth(const T& width) noexcept +{ + fWidth = width; +} + +template +void Size::setHeight(const T& height) noexcept +{ + fHeight = height; +} + +template +void Size::setSize(const T& width, const T& height) noexcept +{ + fWidth = width; + fHeight = height; +} + +template +void Size::setSize(const Size& size) noexcept +{ + fWidth = size.fWidth; + fHeight = size.fHeight; +} + +template +void Size::growBy(double multiplier) noexcept +{ + fWidth = static_cast(static_cast(fWidth)*multiplier); + fHeight = static_cast(static_cast(fHeight)*multiplier); +} + +template +void Size::shrinkBy(double divider) noexcept +{ + fWidth = static_cast(static_cast(fWidth)/divider); + fHeight = static_cast(static_cast(fHeight)/divider); +} + +template +bool Size::isNull() const noexcept +{ + return fWidth == 0 && fHeight == 0; +} + +template +bool Size::isNotNull() const noexcept +{ + return fWidth != 0 || fHeight != 0; +} + +template +bool Size::isValid() const noexcept +{ + return fWidth > 0 && fHeight > 0; +} + +template +bool Size::isInvalid() const noexcept +{ + return fWidth <= 0 || fHeight <= 0; +} + +template +Size Size::toInt() const noexcept +{ + return Size(static_cast(fWidth), + static_cast(fHeight)); +} + +template<> +Size Size::toInt() const noexcept +{ + return Size(static_cast(fWidth + 0.5), + static_cast(fHeight + 0.5)); +} + +template<> +Size Size::toInt() const noexcept +{ + return Size(static_cast(fWidth + 0.5f), + static_cast(fHeight + 0.5f)); +} + +template +Size Size::operator+(const Size& size) noexcept +{ + return Size(fWidth+size.fWidth, fHeight+size.fHeight); +} + +template +Size Size::operator-(const Size& size) noexcept +{ + return Size(fWidth-size.fWidth, fHeight-size.fHeight); +} + +template +Size& Size::operator=(const Size& size) noexcept +{ + fWidth = size.fWidth; + fHeight = size.fHeight; + return *this; +} + +template +Size& Size::operator+=(const Size& size) noexcept +{ + fWidth = static_cast(fWidth+size.fWidth); + fHeight = static_cast(fHeight+size.fHeight); + return *this; +} + +template +Size& Size::operator-=(const Size& size) noexcept +{ + fWidth = static_cast(fWidth-size.fWidth); + fHeight = static_cast(fHeight-size.fHeight); + return *this; +} + +template +Size& Size::operator*=(double m) noexcept +{ + fWidth = static_cast(static_cast(fWidth)*m); + fHeight = static_cast(static_cast(fHeight)*m); + return *this; +} + +template +Size& Size::operator/=(double d) noexcept +{ + fWidth = static_cast(static_cast(fWidth)/d); + fHeight = static_cast(static_cast(fHeight)/d); + return *this; +} + +template +Size Size::operator*(const double m) const noexcept +{ + Size size(fWidth, fHeight); + size *= m; + return size; +} + +template +Size Size::operator/(const double m) const noexcept +{ + Size size(fWidth, fHeight); + size /= m; + return size; +} + +template +bool Size::operator==(const Size& size) const noexcept +{ + return (fWidth == size.fWidth && fHeight == size.fHeight); +} + +template +bool Size::operator!=(const Size& size) const noexcept +{ + return (fWidth != size.fWidth || fHeight != size.fHeight); +} + +// ----------------------------------------------------------------------- +// Line + +template +Line::Line() noexcept + : posStart(0, 0), + posEnd(0, 0) {} + +template +Line::Line(const T& startX, const T& startY, const T& endX, const T& endY) noexcept + : posStart(startX, startY), + posEnd(endX, endY) {} + +template +Line::Line(const T& startX, const T& startY, const Point& endPos) noexcept + : posStart(startX, startY), + posEnd(endPos) {} + +template +Line::Line(const Point& startPos, const T& endX, const T& endY) noexcept + : posStart(startPos), + posEnd(endX, endY) {} + +template +Line::Line(const Point& startPos, const Point& endPos) noexcept + : posStart(startPos), + posEnd(endPos) {} + +template +Line::Line(const Line& line) noexcept + : posStart(line.posStart), + posEnd(line.posEnd) {} + +template +const T& Line::getStartX() const noexcept +{ + return posStart.x; +} + +template +const T& Line::getStartY() const noexcept +{ + return posStart.y; +} + +template +const T& Line::getEndX() const noexcept +{ + return posEnd.x; +} + +template +const T& Line::getEndY() const noexcept +{ + return posEnd.y; +} + +template +const Point& Line::getStartPos() const noexcept +{ + return posStart; +} + +template +const Point& Line::getEndPos() const noexcept +{ + return posEnd; +} + +template +void Line::setStartX(const T& x) noexcept +{ + posStart.x = x; +} + +template +void Line::setStartY(const T& y) noexcept +{ + posStart.y = y; +} + +template +void Line::setStartPos(const T& x, const T& y) noexcept +{ + posStart = Point(x, y); +} + +template +void Line::setStartPos(const Point& pos) noexcept +{ + posStart = pos; +} + +template +void Line::setEndX(const T& x) noexcept +{ + posEnd.x = x; +} + +template +void Line::setEndY(const T& y) noexcept +{ + posEnd.y = y; +} + +template +void Line::setEndPos(const T& x, const T& y) noexcept +{ + posEnd = Point(x, y); +} + +template +void Line::setEndPos(const Point& pos) noexcept +{ + posEnd = pos; +} + +template +void Line::moveBy(const T& x, const T& y) noexcept +{ + posStart.moveBy(x, y); + posEnd.moveBy(x, y); +} + +template +void Line::moveBy(const Point& pos) noexcept +{ + posStart.moveBy(pos); + posEnd.moveBy(pos); +} + +template +bool Line::isNull() const noexcept +{ + return posStart == posEnd; +} + +template +bool Line::isNotNull() const noexcept +{ + return posStart != posEnd; +} + +template +Line& Line::operator=(const Line& line) noexcept +{ + posStart = line.posStart; + posEnd = line.posEnd; + return *this; +} + +template +bool Line::operator==(const Line& line) const noexcept +{ + return (posStart == line.posStart && posEnd == line.posEnd); +} + +template +bool Line::operator!=(const Line& line) const noexcept +{ + return (posStart != line.posStart || posEnd != line.posEnd); +} + +// ----------------------------------------------------------------------- +// Circle + +template +Circle::Circle() noexcept + : fPos(0, 0), + fSize(0.0f), + fNumSegments(0), + fTheta(0.0f), + fCos(0.0f), + fSin(0.0f) {} + +template +Circle::Circle(const T& x, const T& y, const float size, const uint numSegments) + : fPos(x, y), + fSize(size), + fNumSegments(numSegments >= 3 ? numSegments : 3), + fTheta(M_2PIf / static_cast(fNumSegments)), + fCos(std::cos(fTheta)), + fSin(std::sin(fTheta)) +{ + DISTRHO_SAFE_ASSERT(fSize > 0.0f); +} + +template +Circle::Circle(const Point& pos, const float size, const uint numSegments) + : fPos(pos), + fSize(size), + fNumSegments(numSegments >= 3 ? numSegments : 3), + fTheta(M_2PIf / static_cast(fNumSegments)), + fCos(std::cos(fTheta)), + fSin(std::sin(fTheta)) +{ + DISTRHO_SAFE_ASSERT(fSize > 0.0f); +} + +template +Circle::Circle(const Circle& cir) noexcept + : fPos(cir.fPos), + fSize(cir.fSize), + fNumSegments(cir.fNumSegments), + fTheta(cir.fTheta), + fCos(cir.fCos), + fSin(cir.fSin) +{ + DISTRHO_SAFE_ASSERT(fSize > 0.0f); +} + +template +const T& Circle::getX() const noexcept +{ + return fPos.x; +} + +template +const T& Circle::getY() const noexcept +{ + return fPos.y; +} + +template +const Point& Circle::getPos() const noexcept +{ + return fPos; +} + +template +void Circle::setX(const T& x) noexcept +{ + fPos.x = x; +} + +template +void Circle::setY(const T& y) noexcept +{ + fPos.y = y; +} + +template +void Circle::setPos(const T& x, const T& y) noexcept +{ + fPos.x = x; + fPos.y = y; +} + +template +void Circle::setPos(const Point& pos) noexcept +{ + fPos = pos; +} + +template +float Circle::getSize() const noexcept +{ + return fSize; +} + +template +void Circle::setSize(const float size) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); + + fSize = size; +} + +template +uint Circle::getNumSegments() const noexcept +{ + return fNumSegments; +} + +template +void Circle::setNumSegments(const uint num) +{ + DISTRHO_SAFE_ASSERT_RETURN(num >= 3,); + + if (fNumSegments == num) + return; + + fNumSegments = num; + + fTheta = M_2PIf / static_cast(fNumSegments); + fCos = std::cos(fTheta); + fSin = std::sin(fTheta); +} + +template +Circle& Circle::operator=(const Circle& cir) noexcept +{ + fPos = cir.fPos; + fSize = cir.fSize; + fTheta = cir.fTheta; + fCos = cir.fCos; + fSin = cir.fSin; + fNumSegments = cir.fNumSegments; + return *this; +} + +template +bool Circle::operator==(const Circle& cir) const noexcept +{ + return (fPos == cir.fPos && d_isEqual(fSize, cir.fSize) && fNumSegments == cir.fNumSegments); +} + +template +bool Circle::operator!=(const Circle& cir) const noexcept +{ + return (fPos != cir.fPos || d_isNotEqual(fSize, cir.fSize) || fNumSegments != cir.fNumSegments); +} + +// ----------------------------------------------------------------------- +// Triangle + +template +Triangle::Triangle() noexcept + : pos1(0, 0), + pos2(0, 0), + pos3(0, 0) {} + +template +Triangle::Triangle(const T& x1, const T& y1, const T& x2, const T& y2, const T& x3, const T& y3) noexcept + : pos1(x1, y1), + pos2(x2, y2), + pos3(x3, y3) {} + +template +Triangle::Triangle(const Point& p1, const Point& p2, const Point& p3) noexcept + : pos1(p1), + pos2(p2), + pos3(p3) {} + +template +Triangle::Triangle(const Triangle& tri) noexcept + : pos1(tri.pos1), + pos2(tri.pos2), + pos3(tri.pos3) {} + +template +bool Triangle::isNull() const noexcept +{ + return pos1 == pos2 && pos1 == pos3; +} + +template +bool Triangle::isNotNull() const noexcept +{ + return pos1 != pos2 || pos1 != pos3; +} + +template +bool Triangle::isValid() const noexcept +{ + return pos1 != pos2 && pos1 != pos3; +} + +template +bool Triangle::isInvalid() const noexcept +{ + return pos1 == pos2 || pos1 == pos3; +} + +template +Triangle& Triangle::operator=(const Triangle& tri) noexcept +{ + pos1 = tri.pos1; + pos2 = tri.pos2; + pos3 = tri.pos3; + return *this; +} + +template +bool Triangle::operator==(const Triangle& tri) const noexcept +{ + return (pos1 == tri.pos1 && pos2 == tri.pos2 && pos3 == tri.pos3); +} + +template +bool Triangle::operator!=(const Triangle& tri) const noexcept +{ + return (pos1 != tri.pos1 || pos2 != tri.pos2 || pos3 != tri.pos3); +} + +// ----------------------------------------------------------------------- +// Rectangle + +template +Rectangle::Rectangle() noexcept + : pos(0, 0), + size(0, 0) {} + +template +Rectangle::Rectangle(const T& x, const T& y, const T& w, const T& h) noexcept + : pos(x, y), + size(w, h) {} + +template +Rectangle::Rectangle(const T& x, const T& y, const Size& s) noexcept + : pos(x, y), + size(s) {} + +template +Rectangle::Rectangle(const Point& p, const T& w, const T& h) noexcept + : pos(p), + size(w, h) {} + +template +Rectangle::Rectangle(const Point& p, const Size& s) noexcept + : pos(p), + size(s) {} + +template +Rectangle::Rectangle(const Rectangle& rect) noexcept + : pos(rect.pos), + size(rect.size) {} + +template +const T& Rectangle::getX() const noexcept +{ + return pos.x; +} + +template +const T& Rectangle::getY() const noexcept +{ + return pos.y; +} + +template +const T& Rectangle::getWidth() const noexcept +{ + return size.fWidth; +} + +template +const T& Rectangle::getHeight() const noexcept +{ + return size.fHeight; +} + +template +const Point& Rectangle::getPos() const noexcept +{ + return pos; +} + +template +const Size& Rectangle::getSize() const noexcept +{ + return size; +} + +template +void Rectangle::setX(const T& x) noexcept +{ + pos.x = x; +} + +template +void Rectangle::setY(const T& y) noexcept +{ + pos.y = y; +} + +template +void Rectangle::setPos(const T& x, const T& y) noexcept +{ + pos.x = x; + pos.y = y; +} + +template +void Rectangle::setPos(const Point& pos2) noexcept +{ + pos = pos2; +} + +template +void Rectangle::moveBy(const T& x, const T& y) noexcept +{ + pos.moveBy(x, y); +} + +template +void Rectangle::moveBy(const Point& pos2) noexcept +{ + pos.moveBy(pos2); +} + +template +void Rectangle::setWidth(const T& width) noexcept +{ + size.fWidth = width; +} + +template +void Rectangle::setHeight(const T& height) noexcept +{ + size.fHeight = height; +} + +template +void Rectangle::setSize(const T& width, const T& height) noexcept +{ + size.fWidth = width; + size.fHeight = height; +} + +template +void Rectangle::setSize(const Size& size2) noexcept +{ + size = size2; +} + +template +void Rectangle::growBy(double multiplier) noexcept +{ + size.growBy(multiplier); +} + +template +void Rectangle::shrinkBy(double divider) noexcept +{ + size.shrinkBy(divider); +} + +template +void Rectangle::setRectangle(const Point& pos2, const Size& size2) noexcept +{ + pos = pos2; + size = size2; +} + +template +void Rectangle::setRectangle(const Rectangle& rect) noexcept +{ + pos = rect.pos; + size = rect.size; +} + +template +bool Rectangle::contains(const T& x, const T& y) const noexcept +{ + return (x >= pos.x && y >= pos.y && x <= pos.x+size.fWidth && y <= pos.y+size.fHeight); +} + +template +bool Rectangle::contains(const Point& p) const noexcept +{ + return contains(p.x, p.y); +} + +template +template +bool Rectangle::contains(const Point& p) const noexcept +{ + return (p.x >= pos.x && p.y >= pos.y && p.x <= pos.x+size.fWidth && p.y <= pos.y+size.fHeight); +} + +template<> template<> +bool Rectangle::contains(const Point& p) const noexcept +{ + return (p.x >= pos.x && p.y >= pos.y && p.x <= pos.x+size.fWidth && p.y <= pos.y+size.fHeight); +} + +template<> template<> +bool Rectangle::contains(const Point& p) const noexcept +{ + return (p.x >= pos.x && p.y >= pos.y && p.x <= pos.x+size.fWidth && p.y <= pos.y+size.fHeight); +} + +template +bool Rectangle::containsAfterScaling(const Point& p, const double scaling) const noexcept +{ + return (p.x >= pos.x && p.y >= pos.y && p.x/scaling <= pos.x+size.fWidth && p.y/scaling <= pos.y+size.fHeight); +} + +template +bool Rectangle::containsX(const T& x) const noexcept +{ + return (x >= pos.x && x <= pos.x + size.fWidth); +} + +template +bool Rectangle::containsY(const T& y) const noexcept +{ + return (y >= pos.y && y <= pos.y + size.fHeight); +} + +template +bool Rectangle::isNull() const noexcept +{ + return size.isNull(); +} + +template +bool Rectangle::isNotNull() const noexcept +{ + return size.isNotNull(); +} + +template +bool Rectangle::isValid() const noexcept +{ + return size.isValid(); +} + +template +bool Rectangle::isInvalid() const noexcept +{ + return size.isInvalid(); +} + +template +Rectangle& Rectangle::operator=(const Rectangle& rect) noexcept +{ + pos = rect.pos; + size = rect.size; + return *this; +} + +template +Rectangle& Rectangle::operator*=(double m) noexcept +{ + size *= m; + return *this; +} + +template +Rectangle& Rectangle::operator/=(double d) noexcept +{ + size /= d; + return *this; +} + +template +bool Rectangle::operator==(const Rectangle& rect) const noexcept +{ + return (pos == rect.pos && size == rect.size); +} + +template +bool Rectangle::operator!=(const Rectangle& rect) const noexcept +{ + return (pos != rect.pos || size != rect.size); +} + +// ----------------------------------------------------------------------- +// Possible template data types + +template class Point; +template class Point; +template class Point; +template class Point; +template class Point; +template class Point; + +template class Size; +template class Size; +template class Size; +template class Size; +template class Size; +template class Size; + +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; + +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; + +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; + +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/ImageBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/ImageBase.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,132 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../ImageBase.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- +// protected constructors + +ImageBase::ImageBase() + : rawData(nullptr), + size(0, 0), + format(kImageFormatNull) {} + +ImageBase::ImageBase(const char* const rdata, const uint width, const uint height, const ImageFormat fmt) + : rawData(rdata), + size(width, height), + format(fmt) {} + +ImageBase::ImageBase(const char* const rdata, const Size& s, const ImageFormat fmt) + : rawData(rdata), + size(s), + format(fmt) {} + +ImageBase::ImageBase(const ImageBase& image) + : rawData(image.rawData), + size(image.size), + format(image.format) {} + +// -------------------------------------------------------------------------------------------------------------------- +// public methods + +ImageBase::~ImageBase() {} + +bool ImageBase::isValid() const noexcept +{ + return (rawData != nullptr && size.isValid()); +} + +bool ImageBase::isInvalid() const noexcept +{ + return (rawData == nullptr || size.isInvalid()); +} + +uint ImageBase::getWidth() const noexcept +{ + return size.getWidth(); +} + +uint ImageBase::getHeight() const noexcept +{ + return size.getHeight(); +} + +const Size& ImageBase::getSize() const noexcept +{ + return size; +} + +const char* ImageBase::getRawData() const noexcept +{ + return rawData; +} + +ImageFormat ImageBase::getFormat() const noexcept +{ + return format; +} + +void ImageBase::loadFromMemory(const char* const rdata, + const uint width, + const uint height, + const ImageFormat fmt) noexcept +{ + loadFromMemory(rdata, Size(width, height), fmt); +} + +void ImageBase::loadFromMemory(const char* const rdata, const Size& s, const ImageFormat fmt) noexcept +{ + rawData = rdata; + size = s; + format = fmt; +} + +void ImageBase::draw(const GraphicsContext& context) +{ + drawAt(context, Point(0, 0)); +} + +void ImageBase::drawAt(const GraphicsContext& context, const int x, const int y) +{ + drawAt(context, Point(x, y)); +} + +// -------------------------------------------------------------------------------------------------------------------- +// public operators + +ImageBase& ImageBase::operator=(const ImageBase& image) noexcept +{ + rawData = image.rawData; + size = image.size; + format = image.format; + return *this; +} + +bool ImageBase::operator==(const ImageBase& image) const noexcept +{ + return (rawData == image.rawData && size == image.size && format == image.format); +} + +bool ImageBase::operator!=(const ImageBase& image) const noexcept +{ + return !operator==(image); +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/ImageBaseWidgets.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/ImageBaseWidgets.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,967 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../ImageBaseWidgets.hpp" +#include "../Color.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +template +ImageBaseAboutWindow::ImageBaseAboutWindow(Window& transientParentWindow, const ImageType& image) + : StandaloneWindow(transientParentWindow.getApp(), transientParentWindow), + img(image) +{ + setResizable(false); + setTitle("About"); + + if (image.isValid()) + { + setSize(image.getSize()); + setGeometryConstraints(image.getWidth(), image.getHeight(), true, true); + } + + done(); +} + +template +ImageBaseAboutWindow::ImageBaseAboutWindow(TopLevelWidget* const topLevelWidget, const ImageType& image) + : StandaloneWindow(topLevelWidget->getApp(), topLevelWidget->getWindow()), + img(image) +{ + setResizable(false); + setTitle("About"); + + if (image.isValid()) + { + setSize(image.getSize()); + setGeometryConstraints(image.getWidth(), image.getHeight(), true, true); + } + + done(); +} + +template +void ImageBaseAboutWindow::setImage(const ImageType& image) +{ + if (img == image) + return; + + if (image.isInvalid()) + { + img = image; + return; + } + + reinit(); + + img = image; + + setSize(image.getSize()); + setGeometryConstraints(image.getWidth(), image.getHeight(), true, true); + + done(); +} + +template +void ImageBaseAboutWindow::onDisplay() +{ + img.draw(getGraphicsContext()); +} + +template +bool ImageBaseAboutWindow::onKeyboard(const KeyboardEvent& ev) +{ + if (ev.press && ev.key == kKeyEscape) + { + close(); + return true; + } + + return false; +} + +template +bool ImageBaseAboutWindow::onMouse(const MouseEvent& ev) +{ + if (ev.press) + { + close(); + return true; + } + + return false; +} + +// -------------------------------------------------------------------------------------------------------------------- + +template +struct ImageBaseButton::PrivateData : public ButtonEventHandler::Callback { + ImageBaseButton::Callback* callback; + ImageType imageNormal; + ImageType imageHover; + ImageType imageDown; + + PrivateData(const ImageType& normal, const ImageType& hover, const ImageType& down) + : callback(nullptr), + imageNormal(normal), + imageHover(hover), + imageDown(down) {} + + void buttonClicked(SubWidget* widget, int button) override + { + if (callback != nullptr) + if (ImageBaseButton* const imageButton = dynamic_cast(widget)) + callback->imageButtonClicked(imageButton, button); + } + + DISTRHO_DECLARE_NON_COPYABLE(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +template +ImageBaseButton::ImageBaseButton(Widget* const parentWidget, const ImageType& image) + : SubWidget(parentWidget), + ButtonEventHandler(this), + pData(new PrivateData(image, image, image)) +{ + ButtonEventHandler::setCallback(pData); + setSize(image.getSize()); +} + +template +ImageBaseButton::ImageBaseButton(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageDown) + : SubWidget(parentWidget), + ButtonEventHandler(this), + pData(new PrivateData(imageNormal, imageNormal, imageDown)) +{ + DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize()); + + ButtonEventHandler::setCallback(pData); + setSize(imageNormal.getSize()); +} + +template +ImageBaseButton::ImageBaseButton(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageHover, const ImageType& imageDown) + : SubWidget(parentWidget), + ButtonEventHandler(this), + pData(new PrivateData(imageNormal, imageHover, imageDown)) +{ + DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageHover.getSize() && imageHover.getSize() == imageDown.getSize()); + + ButtonEventHandler::setCallback(pData); + setSize(imageNormal.getSize()); +} + +template +ImageBaseButton::~ImageBaseButton() +{ + delete pData; +} + +template +void ImageBaseButton::setCallback(Callback* callback) noexcept +{ + pData->callback = callback; +} + +template +void ImageBaseButton::onDisplay() +{ + const GraphicsContext& context(getGraphicsContext()); + + const State state = ButtonEventHandler::getState(); + + if (ButtonEventHandler::isCheckable()) + { + if (ButtonEventHandler::isChecked()) + pData->imageDown.draw(context); + else if (state & kButtonStateHover) + pData->imageHover.draw(context); + else + pData->imageNormal.draw(context); + } + else + { + if (state & kButtonStateActive) + pData->imageDown.draw(context); + else if (state & kButtonStateHover) + pData->imageHover.draw(context); + else + pData->imageNormal.draw(context); + } +} + +template +bool ImageBaseButton::onMouse(const MouseEvent& ev) +{ + if (SubWidget::onMouse(ev)) + return true; + return ButtonEventHandler::mouseEvent(ev); +} + +template +bool ImageBaseButton::onMotion(const MotionEvent& ev) +{ + if (SubWidget::onMotion(ev)) + return true; + return ButtonEventHandler::motionEvent(ev); +} + +// -------------------------------------------------------------------------------------------------------------------- + +template +struct ImageBaseKnob::PrivateData : public KnobEventHandler::Callback { + ImageBaseKnob::Callback* callback; + ImageType image; + + int rotationAngle; + + bool alwaysRepaint; + bool isImgVertical; + uint imgLayerWidth; + uint imgLayerHeight; + uint imgLayerCount; + bool isReady; + + union { + uint glTextureId; + void* cairoSurface; + }; + + explicit PrivateData(const ImageType& img) + : callback(nullptr), + image(img), + rotationAngle(0), + alwaysRepaint(false), + isImgVertical(img.getHeight() > img.getWidth()), + imgLayerWidth(isImgVertical ? img.getWidth() : img.getHeight()), + imgLayerHeight(imgLayerWidth), + imgLayerCount(isImgVertical ? img.getHeight()/imgLayerHeight : img.getWidth()/imgLayerWidth), + isReady(false) + { + init(); + } + + explicit PrivateData(PrivateData* const other) + : callback(other->callback), + image(other->image), + rotationAngle(other->rotationAngle), + alwaysRepaint(other->alwaysRepaint), + isImgVertical(other->isImgVertical), + imgLayerWidth(other->imgLayerWidth), + imgLayerHeight(other->imgLayerHeight), + imgLayerCount(other->imgLayerCount), + isReady(false) + { + init(); + } + + void assignFrom(PrivateData* const other) + { + cleanup(); + image = other->image; + rotationAngle = other->rotationAngle; + callback = other->callback; + alwaysRepaint = other->alwaysRepaint; + isImgVertical = other->isImgVertical; + imgLayerWidth = other->imgLayerWidth; + imgLayerHeight = other->imgLayerHeight; + imgLayerCount = other->imgLayerCount; + isReady = false; + init(); + } + + ~PrivateData() + { + cleanup(); + } + + void knobDragStarted(SubWidget* const widget) override + { + if (callback != nullptr) + if (ImageBaseKnob* const imageKnob = dynamic_cast(widget)) + callback->imageKnobDragStarted(imageKnob); + } + + void knobDragFinished(SubWidget* const widget) override + { + if (callback != nullptr) + if (ImageBaseKnob* const imageKnob = dynamic_cast(widget)) + callback->imageKnobDragFinished(imageKnob); + } + + void knobValueChanged(SubWidget* const widget, const float value) override + { + if (rotationAngle == 0 || alwaysRepaint) + isReady = false; + + if (callback != nullptr) + if (ImageBaseKnob* const imageKnob = dynamic_cast(widget)) + callback->imageKnobValueChanged(imageKnob, value); + } + + // implemented independently per graphics backend + void init(); + void cleanup(); + + DISTRHO_DECLARE_NON_COPYABLE(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +template +ImageBaseKnob::ImageBaseKnob(Widget* const parentWidget, + const ImageType& image, + const Orientation orientation) noexcept + : SubWidget(parentWidget), + KnobEventHandler(this), + pData(new PrivateData(image)) +{ + KnobEventHandler::setCallback(pData); + setOrientation(orientation); + setSize(pData->imgLayerWidth, pData->imgLayerHeight); +} + +template +ImageBaseKnob::ImageBaseKnob(const ImageBaseKnob& imageKnob) + : SubWidget(imageKnob.getParentWidget()), + KnobEventHandler(this, imageKnob), + pData(new PrivateData(imageKnob.pData)) +{ + KnobEventHandler::setCallback(pData); + setOrientation(imageKnob.getOrientation()); + setSize(pData->imgLayerWidth, pData->imgLayerHeight); +} + +template +ImageBaseKnob& ImageBaseKnob::operator=(const ImageBaseKnob& imageKnob) +{ + KnobEventHandler::operator=(imageKnob); + pData->assignFrom(imageKnob.pData); + setSize(pData->imgLayerWidth, pData->imgLayerHeight); + return *this; +} + +template +ImageBaseKnob::~ImageBaseKnob() +{ + delete pData; +} + +template +void ImageBaseKnob::setCallback(Callback* callback) noexcept +{ + pData->callback = callback; +} + +template +void ImageBaseKnob::setImageLayerCount(uint count) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(count > 1,); + + pData->imgLayerCount = count; + + if (pData->isImgVertical) + pData->imgLayerHeight = pData->image.getHeight()/count; + else + pData->imgLayerWidth = pData->image.getWidth()/count; + + setSize(pData->imgLayerWidth, pData->imgLayerHeight); +} + +template +void ImageBaseKnob::setRotationAngle(int angle) +{ + if (pData->rotationAngle == angle) + return; + + pData->rotationAngle = angle; + pData->isReady = false; +} + +template +bool ImageBaseKnob::setValue(float value, bool sendCallback) noexcept +{ + if (KnobEventHandler::setValue(value, sendCallback)) + { + if (pData->rotationAngle == 0 || pData->alwaysRepaint) + pData->isReady = false; + + return true; + } + + return false; +} + +template +bool ImageBaseKnob::onMouse(const MouseEvent& ev) +{ + if (SubWidget::onMouse(ev)) + return true; + return KnobEventHandler::mouseEvent(ev, getTopLevelWidget()->getScaleFactor()); +} + +template +bool ImageBaseKnob::onMotion(const MotionEvent& ev) +{ + if (SubWidget::onMotion(ev)) + return true; + return KnobEventHandler::motionEvent(ev, getTopLevelWidget()->getScaleFactor()); +} + +template +bool ImageBaseKnob::onScroll(const ScrollEvent& ev) +{ + if (SubWidget::onScroll(ev)) + return true; + return KnobEventHandler::scrollEvent(ev); +} + +// -------------------------------------------------------------------------------------------------------------------- + +template +struct ImageBaseSlider::PrivateData { + ImageType image; + float minimum; + float maximum; + float step; + float value; + float valueDef; + float valueTmp; + bool usingDefault; + + bool dragging; + bool checkable; + bool inverted; + bool valueIsSet; + double startedX; + double startedY; + + Callback* callback; + + Point startPos; + Point endPos; + Rectangle sliderArea; + + PrivateData(const ImageType& img) + : image(img), + minimum(0.0f), + maximum(1.0f), + step(0.0f), + value(0.5f), + valueDef(value), + valueTmp(value), + usingDefault(false), + dragging(false), + checkable(false), + inverted(false), + valueIsSet(false), + startedX(0.0), + startedY(0.0), + callback(nullptr), + startPos(), + endPos(), + sliderArea() {} + + void recheckArea() noexcept + { + if (startPos.getY() == endPos.getY()) + { + // horizontal + sliderArea = Rectangle(startPos.getX(), + startPos.getY(), + endPos.getX() + static_cast(image.getWidth()) - startPos.getX(), + static_cast(image.getHeight())); + } + else + { + // vertical + sliderArea = Rectangle(startPos.getX(), + startPos.getY(), + static_cast(image.getWidth()), + endPos.getY() + static_cast(image.getHeight()) - startPos.getY()); + } + } + + DISTRHO_DECLARE_NON_COPYABLE(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +template +ImageBaseSlider::ImageBaseSlider(Widget* const parentWidget, const ImageType& image) noexcept + : SubWidget(parentWidget), + pData(new PrivateData(image)) +{ + setNeedsFullViewportDrawing(); +} + +template +ImageBaseSlider::~ImageBaseSlider() +{ + delete pData; +} + +template +float ImageBaseSlider::getValue() const noexcept +{ + return pData->value; +} + +template +void ImageBaseSlider::setValue(float value, bool sendCallback) noexcept +{ + if (! pData->valueIsSet) + pData->valueIsSet = true; + + if (d_isEqual(pData->value, value)) + return; + + pData->value = value; + + if (d_isZero(pData->step)) + pData->valueTmp = value; + + repaint(); + + if (sendCallback && pData->callback != nullptr) + { + try { + pData->callback->imageSliderValueChanged(this, pData->value); + } DISTRHO_SAFE_EXCEPTION("ImageBaseSlider::setValue"); + } +} + +template +void ImageBaseSlider::setStartPos(const Point& startPos) noexcept +{ + pData->startPos = startPos; + pData->recheckArea(); +} + +template +void ImageBaseSlider::setStartPos(int x, int y) noexcept +{ + setStartPos(Point(x, y)); +} + +template +void ImageBaseSlider::setEndPos(const Point& endPos) noexcept +{ + pData->endPos = endPos; + pData->recheckArea(); +} + +template +void ImageBaseSlider::setEndPos(int x, int y) noexcept +{ + setEndPos(Point(x, y)); +} + +template +void ImageBaseSlider::setCheckable(bool checkable) noexcept +{ + if (pData->checkable == checkable) + return; + + pData->checkable = checkable; + repaint(); +} + +template +void ImageBaseSlider::setInverted(bool inverted) noexcept +{ + if (pData->inverted == inverted) + return; + + pData->inverted = inverted; + repaint(); +} + +template +void ImageBaseSlider::setDefault(float value) noexcept +{ + pData->valueDef = value; + pData->usingDefault = true; +} + +template +void ImageBaseSlider::setRange(float min, float max) noexcept +{ + pData->minimum = min; + pData->maximum = max; + + if (pData->value < min) + { + pData->value = min; + repaint(); + + if (pData->callback != nullptr && pData->valueIsSet) + { + try { + pData->callback->imageSliderValueChanged(this, pData->value); + } DISTRHO_SAFE_EXCEPTION("ImageBaseSlider::setRange < min"); + } + } + else if (pData->value > max) + { + pData->value = max; + repaint(); + + if (pData->callback != nullptr && pData->valueIsSet) + { + try { + pData->callback->imageSliderValueChanged(this, pData->value); + } DISTRHO_SAFE_EXCEPTION("ImageBaseSlider::setRange > max"); + } + } +} + +template +void ImageBaseSlider::setStep(float step) noexcept +{ + pData->step = step; +} + +template +void ImageBaseSlider::setCallback(Callback* callback) noexcept +{ + pData->callback = callback; +} + +template +void ImageBaseSlider::onDisplay() +{ + const GraphicsContext& context(getGraphicsContext()); + +#if 0 // DEBUG, paints slider area + Color(1.0f, 1.0f, 1.0f, 0.5f).setFor(context, true); + Rectangle(pData->sliderArea.getX(), + pData->sliderArea.getY(), + pData->sliderArea.getX()+pData->sliderArea.getWidth(), + pData->sliderArea.getY()+pData->sliderArea.getHeight()).draw(context); + Color(1.0f, 1.0f, 1.0f, 1.0f).setFor(context, true); +#endif + + const float normValue = (pData->value - pData->minimum) / (pData->maximum - pData->minimum); + + int x, y; + + if (pData->startPos.getY() == pData->endPos.getY()) + { + // horizontal + if (pData->inverted) + x = pData->endPos.getX() - static_cast(normValue*static_cast(pData->endPos.getX()-pData->startPos.getX())); + else + x = pData->startPos.getX() + static_cast(normValue*static_cast(pData->endPos.getX()-pData->startPos.getX())); + + y = pData->startPos.getY(); + } + else + { + // vertical + x = pData->startPos.getX(); + + if (pData->inverted) + y = pData->endPos.getY() - static_cast(normValue*static_cast(pData->endPos.getY()-pData->startPos.getY())); + else + y = pData->startPos.getY() + static_cast(normValue*static_cast(pData->endPos.getY()-pData->startPos.getY())); + } + + pData->image.drawAt(context, x, y); +} + +template +bool ImageBaseSlider::onMouse(const MouseEvent& ev) +{ + if (ev.button != 1) + return false; + + if (ev.press) + { + if (! pData->sliderArea.contains(ev.pos)) + return false; + + if ((ev.mod & kModifierShift) != 0 && pData->usingDefault) + { + setValue(pData->valueDef, true); + pData->valueTmp = pData->value; + return true; + } + + if (pData->checkable) + { + const float value = d_isEqual(pData->valueTmp, pData->minimum) ? pData->maximum : pData->minimum; + setValue(value, true); + pData->valueTmp = pData->value; + return true; + } + + float vper; + const double x = ev.pos.getX(); + const double y = ev.pos.getY(); + + if (pData->startPos.getY() == pData->endPos.getY()) + { + // horizontal + vper = float(x - pData->sliderArea.getX()) / float(pData->sliderArea.getWidth()); + } + else + { + // vertical + vper = float(y - pData->sliderArea.getY()) / float(pData->sliderArea.getHeight()); + } + + float value; + + if (pData->inverted) + value = pData->maximum - vper * (pData->maximum - pData->minimum); + else + value = pData->minimum + vper * (pData->maximum - pData->minimum); + + if (value < pData->minimum) + { + pData->valueTmp = value = pData->minimum; + } + else if (value > pData->maximum) + { + pData->valueTmp = value = pData->maximum; + } + else if (d_isNotZero(pData->step)) + { + pData->valueTmp = value; + const float rest = std::fmod(value, pData->step); + value = value - rest + (rest > pData->step/2.0f ? pData->step : 0.0f); + } + + pData->dragging = true; + pData->startedX = x; + pData->startedY = y; + + if (pData->callback != nullptr) + pData->callback->imageSliderDragStarted(this); + + setValue(value, true); + + return true; + } + else if (pData->dragging) + { + if (pData->callback != nullptr) + pData->callback->imageSliderDragFinished(this); + + pData->dragging = false; + return true; + } + + return false; +} + +template +bool ImageBaseSlider::onMotion(const MotionEvent& ev) +{ + if (! pData->dragging) + return false; + + const bool horizontal = pData->startPos.getY() == pData->endPos.getY(); + const double x = ev.pos.getX(); + const double y = ev.pos.getY(); + + if ((horizontal && pData->sliderArea.containsX(x)) || (pData->sliderArea.containsY(y) && ! horizontal)) + { + float vper; + + if (horizontal) + { + // horizontal + vper = float(x - pData->sliderArea.getX()) / float(pData->sliderArea.getWidth()); + } + else + { + // vertical + vper = float(y - pData->sliderArea.getY()) / float(pData->sliderArea.getHeight()); + } + + float value; + + if (pData->inverted) + value = pData->maximum - vper * (pData->maximum - pData->minimum); + else + value = pData->minimum + vper * (pData->maximum - pData->minimum); + + if (value < pData->minimum) + { + pData->valueTmp = value = pData->minimum; + } + else if (value > pData->maximum) + { + pData->valueTmp = value = pData->maximum; + } + else if (d_isNotZero(pData->step)) + { + pData->valueTmp = value; + const float rest = std::fmod(value, pData->step); + value = value - rest + (rest > pData->step/2.0f ? pData->step : 0.0f); + } + + setValue(value, true); + } + else if (horizontal) + { + if (x < pData->sliderArea.getX()) + setValue(pData->inverted ? pData->maximum : pData->minimum, true); + else + setValue(pData->inverted ? pData->minimum : pData->maximum, true); + } + else + { + if (y < pData->sliderArea.getY()) + setValue(pData->inverted ? pData->maximum : pData->minimum, true); + else + setValue(pData->inverted ? pData->minimum : pData->maximum, true); + } + + return true; +} + +// -------------------------------------------------------------------------------------------------------------------- + +template +struct ImageBaseSwitch::PrivateData { + ImageType imageNormal; + ImageType imageDown; + bool isDown; + Callback* callback; + + PrivateData(const ImageType& normal, const ImageType& down) + : imageNormal(normal), + imageDown(down), + isDown(false), + callback(nullptr) + { + DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize()); + } + + PrivateData(PrivateData* const other) + : imageNormal(other->imageNormal), + imageDown(other->imageDown), + isDown(other->isDown), + callback(other->callback) + { + DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize()); + } + + void assignFrom(PrivateData* const other) + { + imageNormal = other->imageNormal; + imageDown = other->imageDown; + isDown = other->isDown; + callback = other->callback; + DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize()); + } + + DISTRHO_DECLARE_NON_COPYABLE(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +template +ImageBaseSwitch::ImageBaseSwitch(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageDown) noexcept + : SubWidget(parentWidget), + pData(new PrivateData(imageNormal, imageDown)) +{ + setSize(imageNormal.getSize()); +} + +template +ImageBaseSwitch::ImageBaseSwitch(const ImageBaseSwitch& imageSwitch) noexcept + : SubWidget(imageSwitch.getParentWidget()), + pData(new PrivateData(imageSwitch.pData)) +{ + setSize(pData->imageNormal.getSize()); +} + +template +ImageBaseSwitch& ImageBaseSwitch::operator=(const ImageBaseSwitch& imageSwitch) noexcept +{ + pData->assignFrom(imageSwitch.pData); + setSize(pData->imageNormal.getSize()); + return *this; +} + +template +ImageBaseSwitch::~ImageBaseSwitch() +{ + delete pData; +} + +template +bool ImageBaseSwitch::isDown() const noexcept +{ + return pData->isDown; +} + +template +void ImageBaseSwitch::setDown(const bool down) noexcept +{ + if (pData->isDown == down) + return; + + pData->isDown = down; + repaint(); +} + +template +void ImageBaseSwitch::setCallback(Callback* const callback) noexcept +{ + pData->callback = callback; +} + +template +void ImageBaseSwitch::onDisplay() +{ + const GraphicsContext& context(getGraphicsContext()); + + if (pData->isDown) + pData->imageDown.draw(context); + else + pData->imageNormal.draw(context); +} + +template +bool ImageBaseSwitch::onMouse(const MouseEvent& ev) +{ + if (ev.press && contains(ev.pos)) + { + pData->isDown = !pData->isDown; + + repaint(); + + if (pData->callback != nullptr) + pData->callback->imageSwitchClicked(this, pData->isDown); + + return true; + } + + return false; +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Layout.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Layout.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,201 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../Layout.hpp" +#include "../SubWidget.hpp" + +START_NAMESPACE_DGL + +typedef std::list::iterator SubWidgetWithSizeHintIterator; +typedef std::list::iterator HorizontalLayoutIterator; +typedef std::list::iterator VerticalLayoutIterator; + +// -------------------------------------------------------------------------------------------------------------------- + +template<> // horizontal +uint Layout::setAbsolutePos(int x, const int y, const uint padding) +{ + uint maxHeight = 0; + + for (SubWidgetWithSizeHintIterator it=widgets.begin(), end=widgets.end(); it != end; ++it) + { + SubWidgetWithSizeHint& s(*it); + maxHeight = std::max(maxHeight, s.widget->getHeight()); + s.widget->setAbsolutePos(x, y); + x += s.widget->getWidth(); + x += padding; + } + + return maxHeight; +} + +template<> // vertical +uint Layout::setAbsolutePos(const int x, int y, const uint padding) +{ + uint maxWidth = 0; + + for (SubWidgetWithSizeHintIterator it=widgets.begin(), end=widgets.end(); it != end; ++it) + { + SubWidgetWithSizeHint& s(*it); + maxWidth = std::max(maxWidth, s.widget->getWidth()); + s.widget->setAbsolutePos(x, y); + y += s.widget->getHeight(); + y += padding; + } + + return maxWidth; +} + +template<> // horizontal +void Layout::setSize(const uint width, const uint padding) +{ + uint maxHeight = 0; + uint nonFixedWidth = width; + uint numDynamiclySizedWidgets = 0; + + for (SubWidgetWithSizeHintIterator it=widgets.begin(), end=widgets.end(); it != end; ++it) + { + SubWidgetWithSizeHint& s(*it); + maxHeight = std::max(maxHeight, s.widget->getHeight()); + + if (s.sizeHint == Fixed) + nonFixedWidth -= s.widget->getWidth(); + else + ++numDynamiclySizedWidgets; + } + + if (const size_t numWidgets = widgets.size()) + nonFixedWidth -= padding * (numWidgets - 1); + + const uint widthPerWidget = numDynamiclySizedWidgets != 0 ? nonFixedWidth / numDynamiclySizedWidgets : 0; + + for (SubWidgetWithSizeHintIterator it=widgets.begin(), end=widgets.end(); it != end; ++it) + { + SubWidgetWithSizeHint& s(*it); + if (s.sizeHint != Fixed) + s.widget->setSize(widthPerWidget, maxHeight); + else + s.widget->setHeight(maxHeight); + } +} + +template<> // vertical +void Layout::setSize(const uint height, const uint padding) +{ + uint biggestWidth = 0; + uint nonFixedHeight = height; + uint numDynamiclySizedWidgets = 0; + + for (SubWidgetWithSizeHintIterator it=widgets.begin(), end=widgets.end(); it != end; ++it) + { + SubWidgetWithSizeHint& s(*it); + biggestWidth = std::max(biggestWidth, s.widget->getWidth()); + + if (s.sizeHint == Fixed) + nonFixedHeight -= s.widget->getHeight(); + else + ++numDynamiclySizedWidgets; + } + + if (const size_t numWidgets = widgets.size()) + nonFixedHeight -= padding * (numWidgets - 1); + + const uint heightPerWidget = numDynamiclySizedWidgets != 0 ? nonFixedHeight / numDynamiclySizedWidgets : 0; + + for (SubWidgetWithSizeHintIterator it=widgets.begin(), end=widgets.end(); it != end; ++it) + { + SubWidgetWithSizeHint& s(*it); + if (s.sizeHint != Fixed) + s.widget->setSize(biggestWidth, heightPerWidget); + else + s.widget->setWidth(biggestWidth); + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +/* TODO +void HorizontallyStackedVerticalLayout::adjustSize(const uint padding) +{ +} +*/ + +void HorizontallyStackedVerticalLayout::setAbsolutePos(int x, const int y, const uint padding) +{ + for (VerticalLayoutIterator it=items.begin(), end=items.end(); it != end; ++it) + { + VerticalLayout* l(*it); + x += l->setAbsolutePos(x, y, padding); + x += padding; + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +Size VerticallyStackedHorizontalLayout::adjustSize(const uint padding) +{ + uint biggestWidth = 0; + uint totalHeight = 0; + + // iterate all widgets to find which one is the biggest (horizontally) + for (HorizontalLayoutIterator it=items.begin(), end=items.end(); it != end; ++it) + { + HorizontalLayout* const l(*it); + uint width = 0; + uint height = 0; + + for (SubWidgetWithSizeHintIterator it=l->widgets.begin(), end=l->widgets.end(); it != end; ++it) + { + SubWidgetWithSizeHint& s(*it); + + if (width != 0) + width += padding; + + width += s.widget->getWidth(); + height = std::max(height, s.widget->getHeight()); + } + + biggestWidth = std::max(biggestWidth, width); + + if (totalHeight != 0) + totalHeight += padding; + + totalHeight += height; + } + + // now make all horizontal lines the same width + for (HorizontalLayoutIterator it=items.begin(), end=items.end(); it != end; ++it) + { + HorizontalLayout* const l(*it); + l->setSize(biggestWidth, padding); + } + + return Size(biggestWidth, totalHeight); +} + +void VerticallyStackedHorizontalLayout::setAbsolutePos(const int x, int y, const uint padding) +{ + for (HorizontalLayoutIterator it=items.begin(), end=items.end(); it != end; ++it) + { + HorizontalLayout* l(*it); + y += l->setAbsolutePos(x, y, padding); + y += padding; + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/NanoVG.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/NanoVG.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1208 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef _MSC_VER +// instantiated template classes whose methods are defined elsewhere +# pragma warning(disable:4661) +#endif + +#include "../NanoVG.hpp" +#include "SubWidgetPrivateData.hpp" + +#ifndef DGL_NO_SHARED_RESOURCES +# include "Resources.hpp" +#endif + +// ----------------------------------------------------------------------- + +#if defined(DISTRHO_OS_WINDOWS) +# include +# define DGL_EXT(PROC, func) static PROC func; +DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) +DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader) +DGL_EXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) +DGL_EXT(PFNGLBINDBUFFERPROC, glBindBuffer) +DGL_EXT(PFNGLBUFFERDATAPROC, glBufferData) +DGL_EXT(PFNGLCOMPILESHADERPROC, glCompileShader) +DGL_EXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) +DGL_EXT(PFNGLCREATESHADERPROC, glCreateShader) +DGL_EXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) +DGL_EXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) +DGL_EXT(PFNGLDELETESHADERPROC, glDeleteShader) +DGL_EXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) +DGL_EXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) +DGL_EXT(PFNGLGENBUFFERSPROC, glGenBuffers) +DGL_EXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) +DGL_EXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) +DGL_EXT(PFNGLGETSHADERIVPROC, glGetShaderiv) +DGL_EXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) +DGL_EXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) +DGL_EXT(PFNGLLINKPROGRAMPROC, glLinkProgram) +DGL_EXT(PFNGLSHADERSOURCEPROC, glShaderSource) +DGL_EXT(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) +DGL_EXT(PFNGLUNIFORM1IPROC, glUniform1i) +DGL_EXT(PFNGLUNIFORM2FVPROC, glUniform2fv) +DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv) +DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram) +DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) +DGL_EXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) +# ifdef DGL_USE_NANOVG_FBO +DGL_EXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) +DGL_EXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) +DGL_EXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) +DGL_EXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) +DGL_EXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) +DGL_EXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) +DGL_EXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) +DGL_EXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) +DGL_EXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) +DGL_EXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) +# endif +# ifdef DGL_USE_OPENGL3 +DGL_EXT(PFNGLBINDBUFFERRANGEPROC, glBindBufferRange) +DGL_EXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray) +DGL_EXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays) +DGL_EXT(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap) +DGL_EXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) +DGL_EXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays) +DGL_EXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) +# endif +# undef DGL_EXT +#endif + +// ----------------------------------------------------------------------- +// Include NanoVG OpenGL implementation + +//#define STB_IMAGE_STATIC +#if defined(DGL_USE_GLES2) +# define NANOVG_GLES2_IMPLEMENTATION +#elif defined(DGL_USE_OPENGL3) +# define NANOVG_GL3_IMPLEMENTATION +#else +# define NANOVG_GL2_IMPLEMENTATION +#endif + +#if defined(DISTRHO_OS_MAC) && defined(NANOVG_GL2_IMPLEMENTATION) +# define glBindVertexArray glBindVertexArrayAPPLE +# define glDeleteVertexArrays glDeleteVertexArraysAPPLE +# define glGenVertexArrays glGenVertexArraysAPPLE +#endif + +#include "nanovg/nanovg_gl.h" + +#ifdef DGL_USE_NANOVG_FBO +# define NANOVG_FBO_VALID 1 +# include "nanovg/nanovg_gl_utils.h" +#endif + +#if defined(NANOVG_GL2) +# define nvgCreateGLfn nvgCreateGL2 +# define nvgDeleteGL nvgDeleteGL2 +# define nvglCreateImageFromHandle nvglCreateImageFromHandleGL2 +# define nvglImageHandle nvglImageHandleGL2 +#elif defined(NANOVG_GL3) +# define nvgCreateGLfn nvgCreateGL3 +# define nvgDeleteGL nvgDeleteGL3 +# define nvglCreateImageFromHandle nvglCreateImageFromHandleGL3 +# define nvglImageHandle nvglImageHandleGL3 +#elif defined(NANOVG_GLES2) +# define nvgCreateGLfn nvgCreateGLES2 +# define nvgDeleteGL nvgDeleteGLES2 +# define nvglCreateImageFromHandle nvglCreateImageFromHandleGLES2 +# define nvglImageHandle nvglImageHandleGLES2 +#elif defined(NANOVG_GLES3) +# define nvgCreateGLfn nvgCreateGLES3 +# define nvgDeleteGL nvgDeleteGLES3 +# define nvglCreateImageFromHandle nvglCreateImageFromHandleGLES3 +# define nvglImageHandle nvglImageHandleGLES3 +#endif + +// ----------------------------------------------------------------------- + +START_NAMESPACE_DGL + +NVGcontext* nvgCreateGL(int flags) +{ +#if defined(DISTRHO_OS_WINDOWS) +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-function-type" +# endif + static bool needsInit = true; +# define DGL_EXT(PROC, func) \ + if (needsInit) func = (PROC) wglGetProcAddress ( #func ); \ + DISTRHO_SAFE_ASSERT_RETURN(func != nullptr, nullptr); +# define DGL_EXT2(PROC, func, fallback) \ + if (needsInit) { \ + func = (PROC) wglGetProcAddress ( #func ); \ + if (func == nullptr) func = (PROC) wglGetProcAddress ( #fallback ); \ + } DISTRHO_SAFE_ASSERT_RETURN(func != nullptr, nullptr); +DGL_EXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) +DGL_EXT(PFNGLATTACHSHADERPROC, glAttachShader) +DGL_EXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) +DGL_EXT(PFNGLBINDBUFFERPROC, glBindBuffer) +DGL_EXT(PFNGLBUFFERDATAPROC, glBufferData) +DGL_EXT(PFNGLCOMPILESHADERPROC, glCompileShader) +DGL_EXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) +DGL_EXT(PFNGLCREATESHADERPROC, glCreateShader) +DGL_EXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) +DGL_EXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) +DGL_EXT(PFNGLDELETESHADERPROC, glDeleteShader) +DGL_EXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) +DGL_EXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) +DGL_EXT(PFNGLGENBUFFERSPROC, glGenBuffers) +DGL_EXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) +DGL_EXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) +DGL_EXT(PFNGLGETSHADERIVPROC, glGetShaderiv) +DGL_EXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) +DGL_EXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) +DGL_EXT(PFNGLLINKPROGRAMPROC, glLinkProgram) +DGL_EXT(PFNGLSHADERSOURCEPROC, glShaderSource) +DGL_EXT(PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate) +DGL_EXT(PFNGLUNIFORM1IPROC, glUniform1i) +DGL_EXT(PFNGLUNIFORM2FVPROC, glUniform2fv) +DGL_EXT(PFNGLUNIFORM4FVPROC, glUniform4fv) +DGL_EXT(PFNGLUSEPROGRAMPROC, glUseProgram) +DGL_EXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) +DGL_EXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) +# ifdef DGL_USE_NANOVG_FBO +DGL_EXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) +DGL_EXT2(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer, glBindFramebufferEXT) +DGL_EXT2(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer, glBindRenderbufferEXT) +DGL_EXT2(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers, glDeleteFramebuffersEXT) +DGL_EXT2(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers, glDeleteRenderbuffersEXT) +DGL_EXT2(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D, glFramebufferTexture2DEXT) +DGL_EXT2(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer, glFramebufferRenderbufferEXT) +DGL_EXT2(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers, glGenFramebuffersEXT) +DGL_EXT2(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers, glGenRenderbuffersEXT) +DGL_EXT2(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage, glRenderbufferStorageEXT) +# endif +# ifdef DGL_USE_OPENGL3 +DGL_EXT(PFNGLBINDBUFFERRANGEPROC, glBindBufferRange) +DGL_EXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray) +DGL_EXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays) +DGL_EXT(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap) +DGL_EXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) +DGL_EXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays) +DGL_EXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) +# endif +# undef DGL_EXT +# undef DGL_EXT2 + needsInit = false; +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic pop +# endif +#endif + return nvgCreateGLfn(flags); +} + +// ----------------------------------------------------------------------- +// DGL Color class conversion + +Color::Color(const NVGcolor& c) noexcept + : red(c.r), green(c.g), blue(c.b), alpha(c.a) +{ + fixBounds(); +} + +Color::operator NVGcolor() const noexcept +{ + NVGcolor nc; + nc.r = red; + nc.g = green; + nc.b = blue; + nc.a = alpha; + return nc; +} + +// ----------------------------------------------------------------------- +// NanoImage + +NanoImage::NanoImage() + : fHandle(), + fSize() {} + +NanoImage::NanoImage(const Handle& handle) + : fHandle(handle), + fSize() +{ + DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0,); + + _updateSize(); +} + +NanoImage::~NanoImage() +{ + if (fHandle.context != nullptr && fHandle.imageId != 0) + nvgDeleteImage(fHandle.context, fHandle.imageId); +} + +NanoImage& NanoImage::operator=(const Handle& handle) +{ + if (fHandle.context != nullptr && fHandle.imageId != 0) + nvgDeleteImage(fHandle.context, fHandle.imageId); + + fHandle.context = handle.context; + fHandle.imageId = handle.imageId; + _updateSize(); + + return *this; +} + +bool NanoImage::isValid() const noexcept +{ + return (fHandle.context != nullptr && fHandle.imageId != 0); +} + +Size NanoImage::getSize() const noexcept +{ + return fSize; +} + +GLuint NanoImage::getTextureHandle() const +{ + DISTRHO_SAFE_ASSERT_RETURN(fHandle.context != nullptr && fHandle.imageId != 0, 0); + + return nvglImageHandle(fHandle.context, fHandle.imageId); +} + +void NanoImage::_updateSize() +{ + int w=0, h=0; + + nvgImageSize(fHandle.context, fHandle.imageId, &w, &h); + + if (w < 0) w = 0; + if (h < 0) h = 0; + + fSize.setSize(static_cast(w), static_cast(h)); +} + +// ----------------------------------------------------------------------- +// Paint + +NanoVG::Paint::Paint() noexcept + : radius(0.0f), feather(0.0f), innerColor(), outerColor(), imageId(0) +{ + std::memset(xform, 0, sizeof(float)*6); + std::memset(extent, 0, sizeof(float)*2); +} + +NanoVG::Paint::Paint(const NVGpaint& p) noexcept + : radius(p.radius), feather(p.feather), innerColor(p.innerColor), outerColor(p.outerColor), imageId(p.image) +{ + std::memcpy(xform, p.xform, sizeof(float)*6); + std::memcpy(extent, p.extent, sizeof(float)*2); +} + +NanoVG::Paint::operator NVGpaint() const noexcept +{ + NVGpaint p; + p.radius = radius; + p.feather = feather; + p.innerColor = innerColor; + p.outerColor = outerColor; + p.image = imageId; + std::memcpy(p.xform, xform, sizeof(float)*6); + std::memcpy(p.extent, extent, sizeof(float)*2); + return p; +} + +// ----------------------------------------------------------------------- +// NanoVG + +NanoVG::NanoVG(int flags) + : fContext(nvgCreateGL(flags)), + fInFrame(false), + fIsSubWidget(false) +{ + DISTRHO_CUSTOM_SAFE_ASSERT("Failed to create NanoVG context, expect a black screen", fContext != nullptr); +} + +NanoVG::NanoVG(NVGcontext* const context) + : fContext(context), + fInFrame(false), + fIsSubWidget(true) +{ + DISTRHO_CUSTOM_SAFE_ASSERT("Failed to create NanoVG context, expect a black screen", fContext != nullptr); +} + +NanoVG::~NanoVG() +{ + DISTRHO_CUSTOM_SAFE_ASSERT("Destroying NanoVG context with still active frame", ! fInFrame); + + if (fContext != nullptr && ! fIsSubWidget) + nvgDeleteGL(fContext); +} + +// ----------------------------------------------------------------------- + +void NanoVG::beginFrame(const uint width, const uint height, const float scaleFactor) +{ + DISTRHO_SAFE_ASSERT_RETURN(scaleFactor > 0.0f,); + DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); + fInFrame = true; + + if (fContext != nullptr) + nvgBeginFrame(fContext, static_cast(width), static_cast(height), scaleFactor); +} + +void NanoVG::beginFrame(Widget* const widget) +{ + DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); + fInFrame = true; + + if (fContext == nullptr) + return; + + if (TopLevelWidget* const tlw = widget->getTopLevelWidget()) + nvgBeginFrame(fContext, + static_cast(tlw->getWidth()), + static_cast(tlw->getHeight()), + tlw->getScaleFactor()); +} + +void NanoVG::cancelFrame() +{ + DISTRHO_SAFE_ASSERT_RETURN(fInFrame,); + + if (fContext != nullptr) + nvgCancelFrame(fContext); + + fInFrame = false; +} + +void NanoVG::endFrame() +{ + DISTRHO_SAFE_ASSERT_RETURN(fInFrame,); + + // Save current blend state + GLboolean blendEnabled; + GLint blendSrc, blendDst; + glGetBooleanv(GL_BLEND, &blendEnabled); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrc); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDst); + + if (fContext != nullptr) + nvgEndFrame(fContext); + + // Restore blend state + if (blendEnabled) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + glBlendFunc(blendSrc, blendDst); + + fInFrame = false; +} + +// ----------------------------------------------------------------------- +// State Handling + +void NanoVG::save() +{ + if (fContext != nullptr) + nvgSave(fContext); +} + +void NanoVG::restore() +{ + if (fContext != nullptr) + nvgRestore(fContext); +} + +void NanoVG::reset() +{ + if (fContext != nullptr) + nvgReset(fContext); +} + +// ----------------------------------------------------------------------- +// Render styles + +void NanoVG::strokeColor(const Color& color) +{ + if (fContext != nullptr) + nvgStrokeColor(fContext, color); +} + +void NanoVG::strokeColor(const int red, const int green, const int blue, const int alpha) +{ + if (fContext != nullptr) + { + DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,); + DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,); + DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,); + DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,); + + nvgStrokeColor(fContext, nvgRGBA(static_cast(red), + static_cast(green), + static_cast(blue), + static_cast(alpha))); + } +} + +void NanoVG::strokeColor(const float red, const float green, const float blue, const float alpha) +{ + if (fContext != nullptr) + nvgStrokeColor(fContext, nvgRGBAf(red, green, blue, alpha)); +} + +void NanoVG::strokePaint(const Paint& paint) +{ + if (fContext != nullptr) + nvgStrokePaint(fContext, paint); +} + +void NanoVG::fillColor(const Color& color) +{ + if (fContext != nullptr) + nvgFillColor(fContext, color); +} + +void NanoVG::fillColor(const int red, const int green, const int blue, const int alpha) +{ + if (fContext != nullptr) + { + DISTRHO_SAFE_ASSERT_RETURN(red >= 0 && red <= 255,); + DISTRHO_SAFE_ASSERT_RETURN(green >= 0 && green <= 255,); + DISTRHO_SAFE_ASSERT_RETURN(blue >= 0 && blue <= 255,); + DISTRHO_SAFE_ASSERT_RETURN(alpha >= 0 && alpha <= 255,); + + nvgFillColor(fContext, nvgRGBA(static_cast(red), + static_cast(green), + static_cast(blue), + static_cast(alpha))); + } +} + +void NanoVG::fillColor(const float red, const float green, const float blue, const float alpha) +{ + if (fContext != nullptr) + nvgFillColor(fContext, nvgRGBAf(red, green, blue, alpha)); +} + +void NanoVG::fillPaint(const Paint& paint) +{ + if (fContext != nullptr) + nvgFillPaint(fContext, paint); +} + +void NanoVG::miterLimit(float limit) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(limit > 0.0f,); + + nvgMiterLimit(fContext, limit); +} + +void NanoVG::strokeWidth(float size) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); + + nvgStrokeWidth(fContext, size); +} + +void NanoVG::lineCap(NanoVG::LineCap cap) +{ + if (fContext != nullptr) + nvgLineCap(fContext, cap); +} + +void NanoVG::lineJoin(NanoVG::LineCap join) +{ + if (fContext != nullptr) + nvgLineJoin(fContext, join); +} + +void NanoVG::globalAlpha(float alpha) +{ + if (fContext != nullptr) + nvgGlobalAlpha(fContext, alpha); +} + +void NanoVG::globalTint(Color tint) +{ + if (fContext != nullptr) + nvgGlobalTint(fContext, tint); +} + +// ----------------------------------------------------------------------- +// Transforms + +void NanoVG::resetTransform() +{ + if (fContext != nullptr) + nvgResetTransform(fContext); +} + +void NanoVG::transform(float a, float b, float c, float d, float e, float f) +{ + if (fContext != nullptr) + nvgTransform(fContext, a, b, c, d, e, f); +} + +void NanoVG::translate(float x, float y) +{ + if (fContext != nullptr) + nvgTranslate(fContext, x, y); +} + +void NanoVG::rotate(float angle) +{ + if (fContext != nullptr) + nvgRotate(fContext, angle); +} + +void NanoVG::skewX(float angle) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); + + nvgSkewX(fContext, angle); +} + +void NanoVG::skewY(float angle) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); + + nvgSkewY(fContext, angle); +} + +void NanoVG::scale(float x, float y) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(x),); + DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(y),); + + nvgScale(fContext, x, y); +} + +void NanoVG::currentTransform(float xform[6]) +{ + if (fContext != nullptr) + nvgCurrentTransform(fContext, xform); +} + +void NanoVG::transformIdentity(float dst[6]) +{ + nvgTransformIdentity(dst); +} + +void NanoVG::transformTranslate(float dst[6], float tx, float ty) +{ + nvgTransformTranslate(dst, tx, ty); +} + +void NanoVG::transformScale(float dst[6], float sx, float sy) +{ + nvgTransformScale(dst, sx, sy); +} + +void NanoVG::transformRotate(float dst[6], float a) +{ + nvgTransformRotate(dst, a); +} + +void NanoVG::transformSkewX(float dst[6], float a) +{ + nvgTransformSkewX(dst, a); +} + +void NanoVG::transformSkewY(float dst[6], float a) +{ + nvgTransformSkewY(dst, a); +} + +void NanoVG::transformMultiply(float dst[6], const float src[6]) +{ + nvgTransformMultiply(dst, src); +} + +void NanoVG::transformPremultiply(float dst[6], const float src[6]) +{ + nvgTransformPremultiply(dst, src); +} + +int NanoVG::transformInverse(float dst[6], const float src[6]) +{ + return nvgTransformInverse(dst, src); +} + +void NanoVG::transformPoint(float& dstx, float& dsty, const float xform[6], float srcx, float srcy) +{ + nvgTransformPoint(&dstx, &dsty, xform, srcx, srcy); +} + +float NanoVG::degToRad(float deg) +{ + return nvgDegToRad(deg); +} + +float NanoVG::radToDeg(float rad) +{ + return nvgRadToDeg(rad); +} + +// ----------------------------------------------------------------------- +// Images + +NanoImage::Handle NanoVG::createImageFromFile(const char* filename, ImageFlags imageFlags) +{ + return createImageFromFile(filename, static_cast(imageFlags)); +} + +NanoImage::Handle NanoVG::createImageFromFile(const char* filename, int imageFlags) +{ + if (fContext == nullptr) return NanoImage::Handle(); + DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', NanoImage::Handle()); + + return NanoImage::Handle(fContext, nvgCreateImage(fContext, filename, imageFlags)); +} + +NanoImage::Handle NanoVG::createImageFromMemory(const uchar* data, uint dataSize, ImageFlags imageFlags) +{ + return createImageFromMemory(data, dataSize, static_cast(imageFlags)); +} + +NanoImage::Handle NanoVG::createImageFromMemory(const uchar* data, uint dataSize, int imageFlags) +{ + if (fContext == nullptr) return NanoImage::Handle(); + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); + DISTRHO_SAFE_ASSERT_RETURN(dataSize > 0, NanoImage::Handle()); + + return NanoImage::Handle(fContext, nvgCreateImageMem(fContext, imageFlags, data, static_cast(dataSize))); +} + +NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, + ImageFlags imageFlags, ImageFormat format) +{ + return createImageFromRawMemory(w, h, data, static_cast(imageFlags), format); +} + +NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, + int imageFlags, ImageFormat format) +{ + if (fContext == nullptr) return NanoImage::Handle(); + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); + + NVGtexture nvgformat; + switch (format) + { + case kImageFormatGrayscale: + nvgformat = NVG_TEXTURE_ALPHA; + break; + case kImageFormatBGR: + nvgformat = NVG_TEXTURE_BGR; + break; + case kImageFormatBGRA: + nvgformat = NVG_TEXTURE_BGRA; + break; + case kImageFormatRGB: + nvgformat = NVG_TEXTURE_RGB; + break; + case kImageFormatRGBA: + nvgformat = NVG_TEXTURE_RGBA; + break; + default: + return NanoImage::Handle(); + } + + return NanoImage::Handle(fContext, nvgCreateImageRaw(fContext, + static_cast(w), + static_cast(h), imageFlags, nvgformat, data)); +} + +NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags) +{ + return createImageFromRGBA(w, h, data, static_cast(imageFlags)); +} + +NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, int imageFlags) +{ + if (fContext == nullptr) return NanoImage::Handle(); + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); + + return NanoImage::Handle(fContext, nvgCreateImageRGBA(fContext, + static_cast(w), + static_cast(h), imageFlags, data)); +} + +NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, + ImageFlags imageFlags, bool deleteTexture) +{ + return createImageFromTextureHandle(textureId, w, h, static_cast(imageFlags), deleteTexture); +} + +NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, + int imageFlags, bool deleteTexture) +{ + if (fContext == nullptr) return NanoImage::Handle(); + DISTRHO_SAFE_ASSERT_RETURN(textureId != 0, NanoImage::Handle()); + + if (! deleteTexture) + imageFlags |= NVG_IMAGE_NODELETE; + + return NanoImage::Handle(fContext, nvglCreateImageFromHandle(fContext, + textureId, + static_cast(w), + static_cast(h), imageFlags)); +} + +// ----------------------------------------------------------------------- +// Paints + +NanoVG::Paint NanoVG::linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol) +{ + if (fContext == nullptr) return Paint(); + return nvgLinearGradient(fContext, sx, sy, ex, ey, icol, ocol); +} + +NanoVG::Paint NanoVG::boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& ocol) +{ + if (fContext == nullptr) return Paint(); + return nvgBoxGradient(fContext, x, y, w, h, r, f, icol, ocol); +} + +NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol) +{ + if (fContext == nullptr) return Paint(); + return nvgRadialGradient(fContext, cx, cy, inr, outr, icol, ocol); +} + +NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage& image, float alpha) +{ + if (fContext == nullptr) return Paint(); + + const int imageId(image.fHandle.imageId); + DISTRHO_SAFE_ASSERT_RETURN(imageId != 0, Paint()); + + return nvgImagePattern(fContext, ox, oy, ex, ey, angle, imageId, alpha); +} + +// ----------------------------------------------------------------------- +// Scissoring + +void NanoVG::scissor(float x, float y, float w, float h) +{ + if (fContext != nullptr) + nvgScissor(fContext, x, y, w, h); +} + +void NanoVG::intersectScissor(float x, float y, float w, float h) +{ + if (fContext != nullptr) + nvgIntersectScissor(fContext, x, y, w, h); +} + +void NanoVG::resetScissor() +{ + if (fContext != nullptr) + nvgResetScissor(fContext); +} + +// ----------------------------------------------------------------------- +// Paths + +void NanoVG::beginPath() +{ + if (fContext != nullptr) + nvgBeginPath(fContext); +} + +void NanoVG::moveTo(float x, float y) +{ + if (fContext != nullptr) + nvgMoveTo(fContext, x, y); +} + +void NanoVG::lineTo(float x, float y) +{ + if (fContext != nullptr) + nvgLineTo(fContext, x, y); +} + +void NanoVG::bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y) +{ + if (fContext != nullptr) + nvgBezierTo(fContext, c1x, c1y, c2x, c2y, x, y); +} + +void NanoVG::quadTo(float cx, float cy, float x, float y) +{ + if (fContext != nullptr) + nvgQuadTo(fContext, cx, cy, x, y); +} + +void NanoVG::arcTo(float x1, float y1, float x2, float y2, float radius) +{ + if (fContext != nullptr) + nvgArcTo(fContext, x1, y1, x2, y2, radius); +} + +void NanoVG::closePath() +{ + if (fContext != nullptr) + nvgClosePath(fContext); +} + +void NanoVG::pathWinding(NanoVG::Winding dir) +{ + if (fContext != nullptr) + nvgPathWinding(fContext, dir); +} + +void NanoVG::arc(float cx, float cy, float r, float a0, float a1, NanoVG::Winding dir) +{ + if (fContext != nullptr) + nvgArc(fContext, cx, cy, r, a0, a1, dir); +} + +void NanoVG::rect(float x, float y, float w, float h) +{ + if (fContext != nullptr) + nvgRect(fContext, x, y, w, h); +} + +void NanoVG::roundedRect(float x, float y, float w, float h, float r) +{ + if (fContext != nullptr) + nvgRoundedRect(fContext, x, y, w, h, r); +} + +void NanoVG::ellipse(float cx, float cy, float rx, float ry) +{ + if (fContext != nullptr) + nvgEllipse(fContext, cx, cy, rx, ry); +} + +void NanoVG::circle(float cx, float cy, float r) +{ + if (fContext != nullptr) + nvgCircle(fContext, cx, cy, r); +} + +void NanoVG::fill() +{ + if (fContext != nullptr) + nvgFill(fContext); +} + +void NanoVG::stroke() +{ + if (fContext != nullptr) + nvgStroke(fContext); +} + +// ----------------------------------------------------------------------- +// Text + +NanoVG::FontId NanoVG::createFontFromFile(const char* name, const char* filename) +{ + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); + DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', -1); + DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr, -1); + + return nvgCreateFont(fContext, name, filename); +} + +NanoVG::FontId NanoVG::createFontFromMemory(const char* name, const uchar* data, uint dataSize, bool freeData) +{ + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, -1); + DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr, -1); + + return nvgCreateFontMem(fContext, name, const_cast(data), static_cast(dataSize), freeData); +} + +NanoVG::FontId NanoVG::findFont(const char* name) +{ + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); + DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr, -1); + + return nvgFindFont(fContext, name); +} + +void NanoVG::fontSize(float size) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); + + nvgFontSize(fContext, size); +} + +void NanoVG::fontBlur(float blur) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(blur >= 0.0f,); + + nvgFontBlur(fContext, blur); +} + +void NanoVG::textLetterSpacing(float spacing) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(spacing >= 0.0f,); + + nvgTextLetterSpacing(fContext, spacing); +} + +void NanoVG::textLineHeight(float lineHeight) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(lineHeight > 0.0f,); + + nvgTextLineHeight(fContext, lineHeight); +} + +void NanoVG::textAlign(NanoVG::Align align) +{ + if (fContext != nullptr) + nvgTextAlign(fContext, align); +} + +void NanoVG::textAlign(int align) +{ + if (fContext != nullptr) + nvgTextAlign(fContext, align); +} + +void NanoVG::fontFaceId(FontId font) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(font >= 0,); + + nvgFontFaceId(fContext, font); +} + +void NanoVG::fontFace(const char* font) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(font != nullptr && font[0] != '\0',); + + nvgFontFace(fContext, font); +} + +float NanoVG::text(float x, float y, const char* string, const char* end) +{ + if (fContext == nullptr) return 0.0f; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f); + + return nvgText(fContext, x, y, string, end); +} + +void NanoVG::textBox(float x, float y, float breakRowWidth, const char* string, const char* end) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',); + + nvgTextBox(fContext, x, y, breakRowWidth, string, end); +} + +float NanoVG::textBounds(float x, float y, const char* string, const char* end, Rectangle& bounds) +{ + if (fContext == nullptr) return 0.0f; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f); + + float b[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + const float ret = nvgTextBounds(fContext, x, y, string, end, b); + bounds = Rectangle(b[0], b[1], b[2] - b[0], b[3] - b[1]); + return ret; +} + +void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float bounds[4]) +{ + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',); + + nvgTextBoxBounds(fContext, x, y, breakRowWidth, string, end, bounds); +} + +int NanoVG::textGlyphPositions(float x, float y, const char* string, const char* end, NanoVG::GlyphPosition& positions, int maxPositions) +{ + if (fContext == nullptr) return 0; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0); + + return nvgTextGlyphPositions(fContext, x, y, string, end, (NVGglyphPosition*)&positions, maxPositions); +} + +void NanoVG::textMetrics(float* ascender, float* descender, float* lineh) +{ + if (fContext != nullptr) + nvgTextMetrics(fContext, ascender, descender, lineh); +} + +int NanoVG::textBreakLines(const char* string, const char* end, float breakRowWidth, NanoVG::TextRow& rows, int maxRows) +{ + if (fContext != nullptr) + return nvgTextBreakLines(fContext, string, end, breakRowWidth, (NVGtextRow*)&rows, maxRows); + return 0; +} + +#ifndef DGL_NO_SHARED_RESOURCES +bool NanoVG::loadSharedResources() +{ + if (fContext == nullptr) return false; + + if (nvgFindFont(fContext, NANOVG_DEJAVU_SANS_TTF) >= 0) + return true; + + using namespace dpf_resources; + + return nvgCreateFontMem(fContext, NANOVG_DEJAVU_SANS_TTF, (uchar*)dejavusans_ttf, dejavusans_ttf_size, 0) >= 0; +} +#endif + +// ----------------------------------------------------------------------- + +template +void NanoBaseWidget::displayChildren() +{ + std::list children(BaseWidget::getChildren()); + + for (std::list::iterator it = children.begin(); it != children.end(); ++it) + { + if (NanoSubWidget* const subwidget = dynamic_cast(*it)) + { + if (subwidget->fUsingParentContext && subwidget->isVisible()) + subwidget->onDisplay(); + } + } +} + +// ----------------------------------------------------------------------- +// NanoSubWidget + +template <> +NanoBaseWidget::NanoBaseWidget(Widget* const parentWidget, int flags) + : SubWidget(parentWidget), + NanoVG(flags), + fUsingParentContext(false) +{ + setNeedsViewportScaling(); +} + +template <> +NanoBaseWidget::NanoBaseWidget(NanoSubWidget* const parentWidget) + : SubWidget(parentWidget), + NanoVG(parentWidget->getContext()), + fUsingParentContext(true) +{ + setSkipDrawing(); +} + +template <> +NanoBaseWidget::NanoBaseWidget(NanoTopLevelWidget* const parentWidget) + : SubWidget(parentWidget), + NanoVG(parentWidget->getContext()), + fUsingParentContext(true) +{ + setSkipDrawing(); +} + +template <> +inline void NanoBaseWidget::onDisplay() +{ + if (fUsingParentContext) + { + NanoVG::save(); + translate(SubWidget::getAbsoluteX(), SubWidget::getAbsoluteY()); + onNanoDisplay(); + NanoVG::restore(); + displayChildren(); + } + else + { + NanoVG::beginFrame(SubWidget::getWidth(), SubWidget::getHeight()); + onNanoDisplay(); + displayChildren(); + NanoVG::endFrame(); + } +} + +template class NanoBaseWidget; + +// ----------------------------------------------------------------------- +// NanoTopLevelWidget + +template <> +NanoBaseWidget::NanoBaseWidget(Window& windowToMapTo, int flags) + : TopLevelWidget(windowToMapTo), + NanoVG(flags), + fUsingParentContext(false) {} + +template <> +inline void NanoBaseWidget::onDisplay() +{ + NanoVG::beginFrame(TopLevelWidget::getWidth(), TopLevelWidget::getHeight()); + onNanoDisplay(); + displayChildren(); + NanoVG::endFrame(); +} + +template class NanoBaseWidget; + +// ----------------------------------------------------------------------- +// NanoStandaloneWindow + +template <> +NanoBaseWidget::NanoBaseWidget(Application& app, int flags) + : StandaloneWindow(app), + NanoVG(flags), + fUsingParentContext(false) {} + +template <> +NanoBaseWidget::NanoBaseWidget(Application& app, Window& parentWindow, int flags) + : StandaloneWindow(app, parentWindow), + NanoVG(flags), + fUsingParentContext(false) {} + +template <> +inline void NanoBaseWidget::onDisplay() +{ + NanoVG::beginFrame(Window::getWidth(), Window::getHeight()); + onNanoDisplay(); + displayChildren(); + NanoVG::endFrame(); +} + +template class NanoBaseWidget; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#undef final + +#if defined(__GNUC__) && (__GNUC__ >= 6) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmisleading-indentation" +# pragma GCC diagnostic ignored "-Wshift-negative-value" +#endif + +extern "C" { +#include "nanovg/nanovg.c" +} + +#if defined(__GNUC__) && (__GNUC__ >= 6) +# pragma GCC diagnostic pop +#endif + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/OpenGL.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/OpenGL.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,816 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef _MSC_VER +// instantiated template classes whose methods are defined elsewhere +# pragma warning(disable:4661) +#endif + +#include "../OpenGL.hpp" +#include "../Color.hpp" +#include "../ImageWidgets.hpp" + +#include "SubWidgetPrivateData.hpp" +#include "TopLevelWidgetPrivateData.hpp" +#include "WidgetPrivateData.hpp" +#include "WindowPrivateData.hpp" + +// templated classes +#include "ImageBaseWidgets.cpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +#ifdef DGL_USE_OPENGL3 +static void notImplemented(const char* const name) +{ + d_stderr2("OpenGL3 function not implemented: %s", name); +} +#else +# define DGL_USE_COMPAT_OPENGL +#endif + +// ----------------------------------------------------------------------- +// Color + +void Color::setFor(const GraphicsContext&, const bool includeAlpha) +{ +#ifdef DGL_USE_COMPAT_OPENGL + if (includeAlpha) + glColor4f(red, green, blue, alpha); + else + glColor3f(red, green, blue); +#else + notImplemented("Color::setFor"); + // unused + (void)includeAlpha; +#endif +} + +// ----------------------------------------------------------------------- +// Line + +#ifdef DGL_USE_COMPAT_OPENGL +template +static void drawLine(const Point& posStart, const Point& posEnd) +{ + DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,); + + glBegin(GL_LINES); + + { + glVertex2d(posStart.getX(), posStart.getY()); + glVertex2d(posEnd.getX(), posEnd.getY()); + } + + glEnd(); +} +#endif + +template +void Line::draw(const GraphicsContext&, const T width) +{ +#ifdef DGL_USE_COMPAT_OPENGL + DISTRHO_SAFE_ASSERT_RETURN(width != 0,); + + glLineWidth(static_cast(width)); + drawLine(posStart, posEnd); +#else + notImplemented("Line::draw"); +#endif +} + +// deprecated calls +template +void Line::draw() +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawLine(posStart, posEnd); +#else + notImplemented("Line::draw"); +#endif +} + +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; + +// ----------------------------------------------------------------------- +// Circle + +#ifdef DGL_USE_COMPAT_OPENGL +template +static void drawCircle(const Point& pos, + const uint numSegments, + const float size, + const float sin, + const float cos, + const bool outline) +{ + DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,); + + const T origx = pos.getX(); + const T origy = pos.getY(); + double t, x = size, y = 0.0; + + glBegin(outline ? GL_LINE_LOOP : GL_POLYGON); + + for (uint i=0; i +void Circle::draw(const GraphicsContext&) +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawCircle(fPos, fNumSegments, fSize, fSin, fCos, false); +#else + notImplemented("Circle::draw"); +#endif +} + +template +void Circle::drawOutline(const GraphicsContext&, const T lineWidth) +{ + DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,); + + glLineWidth(static_cast(lineWidth)); +#ifdef DGL_USE_COMPAT_OPENGL + drawCircle(fPos, fNumSegments, fSize, fSin, fCos, true); +#else + notImplemented("Circle::drawOutline"); +#endif +} + +// deprecated calls +template +void Circle::draw() +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawCircle(fPos, fNumSegments, fSize, fSin, fCos, false); +#else + notImplemented("Circle::draw"); +#endif +} + +template +void Circle::drawOutline() +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawCircle(fPos, fNumSegments, fSize, fSin, fCos, true); +#else + notImplemented("Circle::drawOutline"); +#endif +} + +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; + +// ----------------------------------------------------------------------- +// Triangle + +#ifdef DGL_USE_COMPAT_OPENGL +template +static void drawTriangle(const Point& pos1, + const Point& pos2, + const Point& pos3, + const bool outline) +{ + DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,); + + glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES); + + { + glVertex2d(pos1.getX(), pos1.getY()); + glVertex2d(pos2.getX(), pos2.getY()); + glVertex2d(pos3.getX(), pos3.getY()); + } + + glEnd(); +} +#endif + +template +void Triangle::draw(const GraphicsContext&) +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawTriangle(pos1, pos2, pos3, false); +#else + notImplemented("Triangle::draw"); +#endif +} + +template +void Triangle::drawOutline(const GraphicsContext&, const T lineWidth) +{ + DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,); + + glLineWidth(static_cast(lineWidth)); +#ifdef DGL_USE_COMPAT_OPENGL + drawTriangle(pos1, pos2, pos3, true); +#else + notImplemented("Triangle::drawOutline"); +#endif +} + +// deprecated calls +template +void Triangle::draw() +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawTriangle(pos1, pos2, pos3, false); +#else + notImplemented("Triangle::draw"); +#endif +} + +template +void Triangle::drawOutline() +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawTriangle(pos1, pos2, pos3, true); +#else + notImplemented("Triangle::drawOutline"); +#endif +} + +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; + +// ----------------------------------------------------------------------- +// Rectangle + +#ifdef DGL_USE_COMPAT_OPENGL +template +static void drawRectangle(const Rectangle& rect, const bool outline) +{ + DISTRHO_SAFE_ASSERT_RETURN(rect.isValid(),); + + glBegin(outline ? GL_LINE_LOOP : GL_QUADS); + + { + const T x = rect.getX(); + const T y = rect.getY(); + const T w = rect.getWidth(); + const T h = rect.getHeight(); + + glTexCoord2f(0.0f, 0.0f); + glVertex2d(x, y); + + glTexCoord2f(1.0f, 0.0f); + glVertex2d(x+w, y); + + glTexCoord2f(1.0f, 1.0f); + glVertex2d(x+w, y+h); + + glTexCoord2f(0.0f, 1.0f); + glVertex2d(x, y+h); + } + + glEnd(); +} +#endif + +template +void Rectangle::draw(const GraphicsContext&) +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawRectangle(*this, false); +#else + notImplemented("Rectangle::draw"); +#endif +} + +template +void Rectangle::drawOutline(const GraphicsContext&, const T lineWidth) +{ + DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,); + + glLineWidth(static_cast(lineWidth)); +#ifdef DGL_USE_COMPAT_OPENGL + drawRectangle(*this, true); +#else + notImplemented("Rectangle::drawOutline"); +#endif +} + +// deprecated calls +template +void Rectangle::draw() +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawRectangle(*this, false); +#else + notImplemented("Rectangle::draw"); +#endif +} + +template +void Rectangle::drawOutline() +{ +#ifdef DGL_USE_COMPAT_OPENGL + drawRectangle(*this, true); +#else + notImplemented("Rectangle::drawOutline"); +#endif +} + +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; + +// ----------------------------------------------------------------------- +// OpenGLImage + +static void setupOpenGLImage(const OpenGLImage& image, GLuint textureId) +{ + DISTRHO_SAFE_ASSERT_RETURN(image.isValid(),); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, textureId); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + static_cast(image.getWidth()), + static_cast(image.getHeight()), + 0, + asOpenGLImageFormat(image.getFormat()), GL_UNSIGNED_BYTE, image.getRawData()); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); +} + +static void drawOpenGLImage(const OpenGLImage& image, const Point& pos, const GLuint textureId, bool& setupCalled) +{ + if (textureId == 0 || image.isInvalid()) + return; + + if (! setupCalled) + { + setupOpenGLImage(image, textureId); + setupCalled = true; + } + +#ifdef DGL_USE_COMPAT_OPENGL + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +#endif + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, textureId); + +#ifdef DGL_USE_COMPAT_OPENGL + glBegin(GL_QUADS); + + { + const int x = pos.getX(); + const int y = pos.getY(); + const int w = static_cast(image.getWidth()); + const int h = static_cast(image.getHeight()); + + glTexCoord2f(0.0f, 0.0f); + glVertex2d(x, y); + + glTexCoord2f(1.0f, 0.0f); + glVertex2d(x+w, y); + + glTexCoord2f(1.0f, 1.0f); + glVertex2d(x+w, y+h); + + glTexCoord2f(0.0f, 1.0f); + glVertex2d(x, y+h); + } + + glEnd(); +#endif + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); +} + +OpenGLImage::OpenGLImage() + : ImageBase(), + setupCalled(false), + textureInit(false), + textureId(0) +{ +} + +OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const ImageFormat fmt) + : ImageBase(rdata, w, h, fmt), + setupCalled(false), + textureInit(true), + textureId(0) +{ + glGenTextures(1, &textureId); + DISTRHO_SAFE_ASSERT(textureId != 0); +} + +OpenGLImage::OpenGLImage(const char* const rdata, const Size& s, const ImageFormat fmt) + : ImageBase(rdata, s, fmt), + setupCalled(false), + textureInit(true), + textureId(0) +{ + glGenTextures(1, &textureId); + DISTRHO_SAFE_ASSERT(textureId != 0); +} + +OpenGLImage::OpenGLImage(const OpenGLImage& image) + : ImageBase(image), + setupCalled(false), + textureInit(true), + textureId(0) +{ + glGenTextures(1, &textureId); + DISTRHO_SAFE_ASSERT(textureId != 0); +} + +OpenGLImage::~OpenGLImage() +{ + if (textureId != 0) + glDeleteTextures(1, &textureId); +} + +void OpenGLImage::loadFromMemory(const char* const rdata, const Size& s, const ImageFormat fmt) noexcept +{ + if (!textureInit) + { + textureInit = true; + glGenTextures(1, &textureId); + DISTRHO_SAFE_ASSERT(textureId != 0); + } + setupCalled = false; + ImageBase::loadFromMemory(rdata, s, fmt); +} + +void OpenGLImage::drawAt(const GraphicsContext&, const Point& pos) +{ + drawOpenGLImage(*this, pos, textureId, setupCalled); +} + +OpenGLImage& OpenGLImage::operator=(const OpenGLImage& image) noexcept +{ + rawData = image.rawData; + size = image.size; + format = image.format; + setupCalled = false; + + if (image.isValid() && !textureInit) + { + textureInit = true; + glGenTextures(1, &textureId); + DISTRHO_SAFE_ASSERT(textureId != 0); + } + + return *this; +} + +// deprecated calls +OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const GLenum fmt) + : ImageBase(rdata, w, h, asDISTRHOImageFormat(fmt)), + setupCalled(false), + textureInit(true), + textureId(0) +{ + glGenTextures(1, &textureId); + DISTRHO_SAFE_ASSERT(textureId != 0); +} + +OpenGLImage::OpenGLImage(const char* const rdata, const Size& s, const GLenum fmt) + : ImageBase(rdata, s, asDISTRHOImageFormat(fmt)), + setupCalled(false), + textureInit(true), + textureId(0) +{ + glGenTextures(1, &textureId); + DISTRHO_SAFE_ASSERT(textureId != 0); +} + +void OpenGLImage::draw() +{ + drawOpenGLImage(*this, Point(0, 0), textureId, setupCalled); +} + +void OpenGLImage::drawAt(const int x, const int y) +{ + drawOpenGLImage(*this, Point(x, y), textureId, setupCalled); +} + +void OpenGLImage::drawAt(const Point& pos) +{ + drawOpenGLImage(*this, pos, textureId, setupCalled); +} + +// ----------------------------------------------------------------------- +// ImageBaseAboutWindow + +#if 0 +template <> +void ImageBaseAboutWindow::onDisplay() +{ + const GraphicsContext& context(getGraphicsContext()); + img.draw(context); +} +#endif + +template class ImageBaseAboutWindow; + +// ----------------------------------------------------------------------- +// ImageBaseButton + +template class ImageBaseButton; + +// ----------------------------------------------------------------------- +// ImageBaseKnob + +template <> +void ImageBaseKnob::PrivateData::init() +{ + glTextureId = 0; + glGenTextures(1, &glTextureId); +} + +template <> +void ImageBaseKnob::PrivateData::cleanup() +{ + if (glTextureId == 0) + return; + + glDeleteTextures(1, &glTextureId); + glTextureId = 0; +} + +template <> +void ImageBaseKnob::onDisplay() +{ + const GraphicsContext& context(getGraphicsContext()); + const float normValue = getNormalizedValue(); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, pData->glTextureId); + + if (! pData->isReady) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + uint imageDataOffset = 0; + + if (pData->rotationAngle == 0) + { + DISTRHO_SAFE_ASSERT_RETURN(pData->imgLayerCount > 0,); + DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,); + + const uint& v1(pData->isImgVertical ? pData->imgLayerWidth : pData->imgLayerHeight); + const uint& v2(pData->isImgVertical ? pData->imgLayerHeight : pData->imgLayerWidth); + + // TODO kImageFormatGreyscale + const uint layerDataSize = v1 * v2 * ((pData->image.getFormat() == kImageFormatBGRA || + pData->image.getFormat() == kImageFormatRGBA) ? 4 : 3); + /* */ imageDataOffset = layerDataSize * uint(normValue * float(pData->imgLayerCount-1)); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + static_cast(getWidth()), static_cast(getHeight()), 0, + asOpenGLImageFormat(pData->image.getFormat()), GL_UNSIGNED_BYTE, pData->image.getRawData() + imageDataOffset); + + pData->isReady = true; + } + + const int w = static_cast(getWidth()); + const int h = static_cast(getHeight()); + + if (pData->rotationAngle != 0) + { +#ifdef DGL_USE_COMPAT_OPENGL + glPushMatrix(); +#endif + + const int w2 = w/2; + const int h2 = h/2; + +#ifdef DGL_USE_COMPAT_OPENGL + glTranslatef(static_cast(w2), static_cast(h2), 0.0f); + glRotatef(normValue*static_cast(pData->rotationAngle), 0.0f, 0.0f, 1.0f); +#endif + + Rectangle(-w2, -h2, w, h).draw(context); + +#ifdef DGL_USE_COMPAT_OPENGL + glPopMatrix(); +#endif + } + else + { + Rectangle(0, 0, w, h).draw(context); + } + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); +} + +template class ImageBaseKnob; + +// ----------------------------------------------------------------------- +// ImageBaseSlider + +template class ImageBaseSlider; + +// ----------------------------------------------------------------------- +// ImageBaseSwitch + +template class ImageBaseSwitch; + +// ----------------------------------------------------------------------- + +void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) +{ + if (skipDrawing) + return; + + bool needsDisableScissor = false; + + if (needsViewportScaling) + { + // limit viewport to widget bounds + const int x = absolutePos.getX(); + const int w = static_cast(self->getWidth()); + const int h = static_cast(self->getHeight()); + + if (viewportScaleFactor != 0.0 && viewportScaleFactor != 1.0) + { + glViewport(x, + -static_cast(height * viewportScaleFactor - height + absolutePos.getY() + 0.5), + static_cast(width * viewportScaleFactor + 0.5), + static_cast(height * viewportScaleFactor + 0.5)); + } + else + { + const int y = static_cast(height - self->getHeight()) - absolutePos.getY(); + glViewport(x, y, w, h); + } + } + else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size(width, height))) + { + // full viewport size + glViewport(0, + -static_cast(height * autoScaleFactor - height + 0.5), + static_cast(width * autoScaleFactor + 0.5), + static_cast(height * autoScaleFactor + 0.5)); + } + else + { + // set viewport pos + glViewport(static_cast(absolutePos.getX() * autoScaleFactor + 0.5), + -static_cast(std::round((height * autoScaleFactor - height) + + (absolutePos.getY() * autoScaleFactor))), + static_cast(std::round(width * autoScaleFactor)), + static_cast(std::round(height * autoScaleFactor))); + + // then cut the outer bounds + glScissor(static_cast(absolutePos.getX() * autoScaleFactor + 0.5), + static_cast(height - std::round((static_cast(self->getHeight()) + absolutePos.getY()) + * autoScaleFactor)), + static_cast(std::round(self->getWidth() * autoScaleFactor)), + static_cast(std::round(self->getHeight() * autoScaleFactor))); + + glEnable(GL_SCISSOR_TEST); + needsDisableScissor = true; + } + + // display widget + self->onDisplay(); + + if (needsDisableScissor) + glDisable(GL_SCISSOR_TEST); + + selfw->pData->displaySubWidgets(width, height, autoScaleFactor); +} + +// ----------------------------------------------------------------------- + +void TopLevelWidget::PrivateData::display() +{ + if (! selfw->pData->visible) + return; + + const Size size(window.getSize()); + const uint width = size.getWidth(); + const uint height = size.getHeight(); + + const double autoScaleFactor = window.pData->autoScaleFactor; + + // full viewport size + if (window.pData->autoScaling) + { + glViewport(0, + -static_cast(height * autoScaleFactor - height + 0.5), + static_cast(width * autoScaleFactor + 0.5), + static_cast(height * autoScaleFactor + 0.5)); + } + else + { + glViewport(0, 0, static_cast(width), static_cast(height)); + } + + // main widget drawing + self->onDisplay(); + + // now draw subwidgets if there are any + selfw->pData->displaySubWidgets(width, height, autoScaleFactor); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::renderToPicture(const char* const filename, + const GraphicsContext&, + const uint width, + const uint height) +{ + FILE* const f = fopen(filename, "w"); + DISTRHO_SAFE_ASSERT_RETURN(f != nullptr,); + + GLubyte* const pixels = new GLubyte[width * height * 3 * sizeof(GLubyte)]; + + glFlush(); + glReadPixels(0, 0, static_cast(width), static_cast(height), GL_RGB, GL_UNSIGNED_BYTE, pixels); + + fprintf(f, "P3\n%d %d\n255\n", width, height); + for (uint y = 0; y < height; y++) + { + for (uint i, x = 0; x < width; x++) + { + i = 3 * ((height - y - 1) * width + x); + fprintf(f, "%3d %3d %3d ", pixels[i], pixels[i+1], pixels[i+2]); + } + fprintf(f, "\n"); + } + + delete[] pixels; + fclose(f); +} + +// ----------------------------------------------------------------------- + +const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept +{ + return (const GraphicsContext&)graphicsContext; +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Resources.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Resources.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,18544 @@ +/* (Auto-generated binary data file). */ + +#include "Resources.hpp" + +static const unsigned char temp1[] = {0,1,0,0,0,19,1,0,0,4,0,48,70,70,84,77,102,9,29,176,0,0,1,60,0,0,0,28,71,68,69,70,144,48,138,184,0,0,1,88, + 0,0,2,148,71,80,79,83,63,137,191,2,0,0,3,236,0,0,157,8,71,83,85,66,151,65,114,65,0,0,160,244,0,0,21,114,79,83,47,50, + 89,45,118,45,0,0,182,104,0,0,0,86,99,109,97,112,228,111,14,235,0,0,182,192,0,0,22,6,99,118,116,32,0,105,29,57,0,0,204,200, + 0,0,1,254,102,112,103,109,113,52,118,106,0,0,206,200,0,0,0,171,103,97,115,112,0,7,0,7,0,0,207,116,0,0,0,12,103,108,121,102, + 214,36,202,71,0,0,207,128,0,8,83,136,104,101,97,100,0,250,81,111,0,9,35,8,0,0,0,54,104,104,101,97,12,184,30,45,0,9,35,64, + 0,0,0,36,104,109,116,120,218,186,166,211,0,9,35,100,0,0,95,112,107,101,114,110,4,246,0,37,0,9,130,212,0,0,63,252,108,111,99,97, + 92,176,35,188,0,9,194,208,0,0,95,116,109,97,120,112,28,73,6,113,0,10,34,68,0,0,0,32,110,97,109,101,31,108,77,160,0,10,34,100, + 0,0,61,8,112,111,115,116,187,194,210,49,0,10,95,108,0,0,235,201,112,114,101,112,59,7,241,0,0,11,75,56,0,0,5,104,0,0,0,1, + 0,0,0,0,201,137,111,49,0,0,0,0,206,63,215,63,0,0,0,0,206,63,215,63,0,1,0,0,0,14,0,0,2,40,2,48,0,0,0,2, + 0,89,0,3,2,176,0,1,2,177,2,197,0,3,2,198,2,198,0,1,2,199,2,202,0,3,2,203,2,204,0,1,2,205,2,209,0,3,2,210, + 2,211,0,1,2,212,2,228,0,3,2,229,2,233,0,1,2,234,2,243,0,3,2,244,2,244,0,1,2,245,2,245,0,3,2,246,2,246,0,1, + 2,247,2,255,0,3,3,0,3,0,0,1,3,1,3,4,0,3,3,5,3,5,0,1,3,6,3,6,0,3,3,7,3,7,0,1,3,8,3,9, + 0,3,3,10,3,10,0,1,3,11,3,12,0,3,3,13,4,22,0,1,4,23,4,27,0,3,4,28,5,12,0,1,5,13,5,13,0,2,5,14, + 5,15,0,1,5,16,5,24,0,3,5,25,5,26,0,1,5,27,5,29,0,3,5,30,5,30,0,1,5,31,5,31,0,3,5,32,5,36,0,1, + 5,37,5,37,0,3,5,38,5,74,0,1,5,75,5,75,0,3,5,76,5,78,0,1,5,79,5,83,0,2,5,84,5,114,0,1,5,115,5,127, + 0,3,5,128,5,143,0,1,5,144,5,144,0,3,5,145,6,14,0,1,6,15,6,23,0,3,6,24,6,58,0,1,6,59,6,59,0,3,6,60, + 6,61,0,1,6,62,6,69,0,3,6,70,6,76,0,1,6,77,6,82,0,3,6,83,8,242,0,1,8,243,8,248,0,3,8,249,11,25,0,1, + 11,26,11,26,0,2,11,27,11,36,0,1,11,37,11,39,0,2,11,40,11,122,0,1,11,123,11,123,0,2,11,124,11,139,0,1,11,140,11,146, + 0,3,11,147,11,147,0,2,11,148,11,151,0,1,11,152,11,153,0,2,11,154,11,177,0,1,11,178,11,179,0,2,11,180,11,204,0,1,11,205, + 11,205,0,2,11,206,19,164,0,1,19,165,19,177,0,2,19,178,19,178,0,3,19,179,19,179,0,2,19,180,19,221,0,1,19,222,19,222,0,2, + 19,223,20,81,0,1,20,82,20,82,0,3,20,83,20,83,0,1,20,84,20,84,0,3,20,85,20,87,0,2,20,88,20,88,0,1,20,89,20,99, + 0,2,20,100,20,216,0,1,20,217,20,224,0,2,20,225,22,184,0,1,22,185,22,195,0,3,22,196,23,23,0,1,23,24,23,31,0,3,23,32, + 23,121,0,1,23,122,23,122,0,3,23,123,23,219,0,1,0,4,0,0,0,2,0,0,0,2,0,16,2,177,2,198,0,1,2,199,2,202,0,2, + 2,205,2,215,0,2,2,216,2,216,0,3,2,217,2,217,0,4,2,218,2,228,0,2,2,234,2,237,0,2,2,238,2,245,0,1,2,246,2,246, + 0,2,2,247,2,247,0,1,2,248,2,250,0,2,2,251,2,253,0,1,2,254,2,255,0,2,3,1,3,2,0,1,3,3,3,3,0,2,3,4, + 3,4,0,1,0,1,0,0,0,10,1,220,2,92,0,20,68,70,76,84,0,122,97,114,97,98,0,134,97,114,109,110,0,168,98,114,97,105,0,180, + 99,97,110,115,0,192,99,104,101,114,0,204,99,121,114,108,0,216,103,101,111,114,0,244,103,114,101,107,1,0,104,97,110,105,1,16,104,101,98,114, + 1,28,107,97,110,97,1,42,108,97,111,32,1,54,108,97,116,110,1,70,109,97,116,104,1,134,110,107,111,32,1,146,111,103,97,109,1,160,114,117, + 110,114,1,172,116,102,110,103,1,184,116,104,97,105,1,198,0,4,0,0,0,0,255,255,0,1,0,0,0,22,0,3,75,85,82,32,0,22,83,78, + 68,32,0,22,85,82,68,32,0,22,0,0,255,255,0,3,0,0,0,2,0,6,0,4,0,0,0,0,255,255,0,1,0,0,0,4,0,0,0,0, + 255,255,0,1,0,0,0,4,0,0,0,0,255,255,0,1,0,0,0,4,0,0,0,0,255,255,0,1,0,0,0,16,0,2,77,75,68,32,0,16, + 83,82,66,32,0,16,0,0,255,255,0,3,0,0,0,3,0,7,0,4,0,0,0,0,255,255,0,1,0,0,0,4,0,0,0,0,255,255,0,3, + 0,0,0,3,0,7,0,4,0,0,0,0,255,255,0,1,0,0,0,4,0,0,0,0,255,255,0,2,0,0,0,2,0,4,0,0,0,0,255,255, + 0,1,0,0,0,4,0,0,0,0,255,255,0,3,0,0,0,4,0,8,0,52,0,8,73,83,77,32,0,52,75,83,77,32,0,52,76,83,77,32, + 0,52,77,79,76,32,0,52,78,83,77,32,0,52,82,79,77,32,0,52,83,75,83,32,0,52,83,83,77,32,0,52,0,0,255,255,0,3,0,1, + 0,3,0,7,0,4,0,0,0,0,255,255,0,1,0,0,0,4,0,0,0,0,255,255,0,2,0,0,0,2,0,4,0,0,0,0,255,255,0,1, + 0,0,0,4,0,0,0,0,255,255,0,1,0,0,0,4,0,0,0,0,255,255,0,2,0,0,0,5,0,4,0,0,0,0,255,255,0,1,0,0, + 0,9,107,101,114,110,0,56,107,101,114,110,0,62,109,97,114,107,0,70,109,97,114,107,0,84,109,97,114,107,0,92,109,97,114,107,0,100,109,107, + 109,107,0,106,109,107,109,107,0,114,109,107,109,107,0,120,0,0,0,1,0,15,0,0,0,2,0,14,0,15,0,0,0,5,0,5,0,6,0,7, + 0,8,0,9,0,0,0,2,0,12,0,13,0,0,0,2,0,10,0,11,0,0,0,1,0,13,0,0,0,2,0,0,0,1,0,0,0,1,0,4, + 0,0,0,2,0,2,0,3,0,16,0,34,0,42,0,50,0,58,0,66,0,76,0,84,0,92,0,100,0,108,0,116,0,124,0,132,0,140,0,158, + 0,166,0,6,0,1,0,1,0,140,0,6,0,1,0,1,0,222,0,6,0,0,0,1,2,166,0,6,0,0,0,1,2,216,0,6,0,4,0,2, + 3,102,6,70,0,5,0,1,0,1,10,252,0,4,0,1,0,1,12,102,0,4,0,1,0,1,32,204,0,5,0,1,0,1,33,202,0,4,0,1, + 0,1,35,136,0,4,0,0,0,1,55,202,0,4,0,0,0,1,56,242,0,5,0,0,0,1,58,162,0,4,0,4,0,6,60,84,65,254,66,126, + 70,28,87,126,112,158,0,2,0,0,0,1,113,220,0,2,0,0,0,1,153,138,0,1,0,48,0,38,0,1,0,58,0,12,0,3,0,8,0,14, + 0,20,0,1,2,0,254,12,0,1,2,0,254,212,0,1,2,0,253,243,0,1,0,3,5,117,5,120,5,125,0,1,0,3,5,117,5,120,5,125, + 0,3,0,0,0,14,0,0,0,20,0,0,0,26,0,1,2,0,0,0,0,1,2,0,0,0,0,1,2,0,0,0,0,1,0,218,0,174,0,1, + 1,6,0,12,0,20,0,42,0,48,0,54,0,60,0,66,0,72,0,78,0,84,0,90,0,96,0,102,0,108,0,114,0,120,0,126,0,132,0,138, + 0,144,0,150,0,156,0,1,2,0,7,58,0,1,2,0,6,164,0,1,2,0,7,58,0,1,2,0,5,220,0,1,2,0,7,58,0,1,2,0, + 7,8,0,1,2,0,7,58,0,1,2,0,5,220,0,1,2,0,6,164,0,1,2,0,7,58,0,1,1,254,6,114,0,1,2,0,7,58,0,1, + 2,0,8,252,0,1,2,0,9,196,0,1,2,0,8,252,0,1,2,0,8,52,0,1,2,0,9,196,0,1,2,0,8,52,0,1,2,0,7,208, + 0,1,2,0,9,96,0,1,0,20,5,75,5,115,5,116,5,118,5,119,5,121,5,122,5,123,5,124,5,126,5,127,5,144,23,24,23,25,23,26, + 23,27,23,28,23,29,23,30,23,31,0,1,0,20,5,75,5,115,5,116,5,118,5,119,5,121,5,122,5,123,5,124,5,126,5,127,5,144,23,24, + 23,25,23,26,23,27,23,28,23,29,23,30,23,31,0,20,0,0,0,82,0,0,0,88,0,0,0,94,0,0,0,100,0,0,0,106,0,0,0,112, + 0,0,0,118,0,0,0,124,0,0,0,130,0,0,0,136,0,0,0,142,0,0,0,148,0,0,0,154,0,0,0,160,0,0,0,166,0,0,0,172, + 0,0,0,178,0,0,0,184,0,0,0,190,0,0,0,196,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176, + 0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0, + 4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1, + 2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,0,28,0,22,0,1,0,36,0,12,0,1,0,4,0,1,253,108,253,224,0,1, + 0,1,6,69,0,1,0,2,6,66,6,67,0,2,0,0,0,10,0,0,0,16,0,1,253,168,0,0,0,1,253,168,0,0,0,1,0,78,0,62, + 0,1,0,88,0,12,0,6,0,14,0,20,0,26,0,32,0,38,0,44,0,1,253,132,6,246,0,1,253,108,7,119,0,1,253,108,7,119,0,1, + 253,108,7,119,0,1,253,102,7,110,0,1,253,132,6,246,0,1,0,6,6,59,6,62,6,63,6,64,6,65,6,68,0,2,0,1,6,77,6,82, + 0,0,0,6,0,0,0,26,0,0,0,32,0,0,0,38,0,0,0,44,0,0,0,50,0,0,0,56,0,1,253,108,4,96,0,1,253,108,4,126, + 0,1,253,108,4,126,0,1,253,108,4,96,0,1,253,108,4,126,0,1,253,108,4,96,0,1,1,90,1,38,0,1,1,148,0,12,0,35,0,72, + 0,78,0,84,0,90,0,96,0,102,0,108,0,114,0,120,0,126,0,132,0,138,0,144,0,150,0,156,0,162,0,168,0,174,0,180,0,186,0,192, + 0,198,0,204,0,210,0,216,0,222,0,228,0,234,0,240,0,246,0,252,1,2,1,8,1,14,1,20,0,1,254,0,253,222,0,1,254,0,253,222, + 0,1,254,0,254,21,0,1,254,0,254,21,0,1,254,0,253,218,0,1,254,0,254,21,0,1,254,0,254,21,0,1,254,0,254,21,0,1,254,0, + 254,137,0,1,254,0,254,137,0,1,254,0,254,137,0,1,254,0,253,218,0,1,254,0,254,20,0,1,254,0,254,116,0,1,254,0,254,116,0,1, + 254,0,254,21,0,1,254,0,254,31,0,1,254,0,254,59,0,1,254,0,254,24,0,1,254,0,254,21,0,1,254,0,254,56,0,1,254,0,254,56, + 0,1,254,0,254,56,0,1,254,0,254,191,0,1,254,0,253,218,0,1,254,0,254,31,0,1,254,2,254,19,0,1,254,0,254,11,0,1,254,0, + 254,14,0,1,254,0,254,14,0,1,254,0,254,14,0,1,254,0,254,14,0,1,254,0,254,14,0,1,254,0,254,19,0,1,254,0,253,218,0,2, + 0,8,2,199,2,202,0,0,2,205,2,209,0,4,2,212,2,226,0,9,2,234,2,237,0,24,2,248,2,250,0,28,2,254,2,255,0,31,3,3, + 3,3,0,33,3,6,3,6,0,34,0,2,0,9,2,199,2,202,0,0,2,205,2,209,0,4,2,212,2,215,0,9,2,218,2,226,0,13,2,234, + 2,237,0,22,2,248,2,250,0,26,2,254,2,255,0,29,3,3,3,3,0,31,3,6,3,6,0,32,0,33,0,0,0,134,0,0,0,140,0,0, + 0,146,0,0,0,152,0,0,0,158,0,0,0,164,0,0,0,170,0,0,0,176,0,0,0,182,0,0,0,188,0,0,0,194,0,0,0,200,0,0, + 0,206,0,0,0,212,0,0,0,218,0,0,0,224,0,0,0,230,0,0,0,236,0,0,0,242,0,0,0,248,0,0,0,254,0,0,1,4,0,0, + 1,10,0,0,1,16,0,0,1,22,0,0,1,28,0,0,1,34,0,0,1,40,0,0,1,46,0,0,1,52,0,0,1,58,0,0,1,64,0,0, + 1,70,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1, + 254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0, + 0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0, + 0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,2,0,0,0,1,254,0,0,0,0,1, + 254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0,0,1,254,0,0,0, + 0,1,2,66,1,222,0,1,2,142,0,12,0,58,0,118,0,124,0,130,0,136,0,142,0,148,0,154,0,160,0,166,0,172,0,178,0,184,0,190, + 0,196,0,202,0,208,0,214,0,220,0,226,0,232,0,238,0,244,0,250,1,0,1,6,1,12,1,18,1,24,1,30,1,36,1,42,1,48,1,54, + 1,60,1,66,1,72,1,78,1,84,1,90,1,96,1,102,1,108,1,114,1,120,1,126,1,132,1,138,1,144,1,150,1,156,1,162,1,168,1,174, + 1,180,1,186,1,192,1,198,1,204,0,1,254,0,6,104,0,1,254,0,6,104,0,1,254,0,6,104,0,1,254,0,6,61,0,1,254,0,6,20, + 0,1,254,0,6,20,0,1,254,0,6,68,0,1,254,0,6,20,0,1,254,0,6,20,0,1,254,0,6,197,0,1,254,0,7,4,0,1,254,0, + 6,104,0,1,254,0,6,104,0,1,254,0,6,168,0,1,254,0,6,168,0,1,254,0,6,104,0,1,254,0,7,86,0,1,254,0,6,68,0,1, + 254,0,6,147,0,1,254,0,6,20,0,1,254,0,6,104,0,1,254,0,6,104,0,1,254,0,6,61,0,1,254,0,7,208,0,1,254,0,6,68, + 0,1,254,0,6,68,0,1,254,0,7,4,0,1,254,0,7,4,0,1,254,0,7,4,0,1,254,0,6,218,0,1,254,0,7,4,0,1,0,0, + 7,110,0,1,0,0,7,110,0,1,0,0,7,110,0,1,0,0,7,110,0,1,254,0,6,20,0,1,254,0,6,20,0,1,254,0,6,20,0,1, + 254,0,6,20,0,1,254,0,6,104,0,1,254,0,6,104,0,1,254,0,6,20,0,1,254,0,6,20,0,1,254,0,6,20,0,1,254,0,6,20, + 0,1,254,0,6,20,0,1,254,0,6,20,0,1,254,0,6,20,0,1,254,0,5,248,0,1,254,0,5,248,0,1,254,0,5,248,0,1,254,0, + 5,248,0,1,254,0,5,248,0,1,254,0,5,248,0,1,254,0,5,219,0,1,254,0,5,248,0,1,254,0,5,248,0,1,254,0,6,30,0,2, + 0,16,2,177,2,194,0,0,2,238,2,238,0,18,2,240,2,243,0,19,2,245,2,245,0,23,2,247,2,247,0,24,2,251,2,253,0,25,3,1, + 3,2,0,28,3,4,3,4,0,30,3,8,3,9,0,31,3,11,3,12,0,33,8,243,8,248,0,35,11,140,11,146,0,41,22,185,22,185,0,48, + 22,187,22,187,0,49,22,189,22,195,0,50,23,122,23,122,0,57,0,2,0,12,2,177,2,194,0,0,2,238,2,238,0,18,2,240,2,243,0,19, + 2,245,2,245,0,23,2,247,2,247,0,24,2,251,2,253,0,25,3,1,3,2,0,28,3,4,3,4,0,30,8,243,8,248,0,31,11,140,11,146, + 0,37,22,185,22,195,0,44,23,122,23,122,0,55,0,56,0,0,0,226,0,0,0,232,0,0,0,238,0,0,0,244,0,0,0,250,0,0,1,0, + 0,0,1,6,0,0,1,12,0,0,1,18,0,0,1,24,0,0,1,30,0,0,1,36,0,0,1,42,0,0,1,48,0,0,1,54,0,0,1,60, + 0,0,1,66,0,0,1,72,0,0,1,78,0,0,1,84,0,0,1,90,0,0,1,96,0,0,1,102,0,0,1,108,0,0,1,114,0,0,1,120, + 0,0,1,126,0,0,1,132,0,0,1,138,0,0,1,144,0,0,1,150,0,0,1,156,0,0,1,162,0,0,1,168,0,0,1,174,0,0,1,180, + 0,0,1,186,0,0,1,192,0,0,1,198,0,0,1,204,0,0,1,210,0,0,1,216,0,0,1,222,0,0,1,228,0,0,1,234,0,0,1,240, + 0,0,1,246,0,0,1,252,0,0,2,2,0,0,2,8,0,0,2,14,0,0,2,20,0,0,2,26,0,0,2,32,0,0,2,38,0,0,2,44, + 0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,176,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0, + 5,2,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1, + 254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,5,2, + 0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,176,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0, + 4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,5,2,0,1,254,0,4,123,0,1,254,0,5,2,0,1,254,0,5,2,0,1, + 254,0,5,2,0,1,254,0,5,2,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,5,2, + 0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,5,2,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0, + 4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1, + 254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,0,184,0,174,0,1,0,218,0,12,0,8,0,18,0,36,0,54,0,72,0,90, + 0,108,0,126,0,144,0,2,0,6,0,12,0,1,3,99,255,156,0,1,0,200,255,106,0,2,0,6,0,12,0,1,3,99,255,156,0,1,0,200, + 255,106,0,2,0,6,0,12,0,1,3,99,255,156,0,1,0,200,255,106,0,2,0,6,0,12,0,1,3,99,255,156,0,1,0,200,255,106,0,2, + 0,6,0,12,0,1,3,99,255,156,0,1,0,200,253,218,0,2,0,6,0,12,0,1,3,99,255,156,0,1,0,200,253,218,0,2,0,6,0,12, + 0,1,3,99,255,156,0,1,0,200,255,106,0,2,0,6,0,12,0,1,3,99,255,156,0,1,0,200,255,106,0,2,0,1,20,217,20,224,0,0, + 0,1,0,15,5,16,5,17,5,18,5,19,5,20,5,21,5,22,5,23,5,24,5,27,5,29,5,37,5,117,5,120,5,125,0,15,0,0,0,62, + 0,0,0,68,0,0,0,74,0,0,0,80,0,0,0,86,0,0,0,92,0,0,0,98,0,0,0,104,0,0,0,110,0,0,0,116,0,0,0,122, + 0,0,0,128,0,0,0,134,0,0,0,140,0,0,0,146,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0, + 0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143, + 0,0,0,1,2,143,0,0,0,1,2,0,0,0,0,1,2,0,0,0,0,1,2,0,0,0,0,1,19,168,19,86,0,1,19,204,0,12,2,105, + 4,212,4,218,4,224,4,230,4,236,4,242,4,248,4,254,5,4,5,10,5,16,5,22,5,28,5,34,5,40,5,46,5,52,5,58,5,64,5,70, + 5,76,5,82,5,88,5,94,5,100,5,106,5,112,5,118,5,124,5,130,5,136,5,142,5,148,5,154,5,160,5,166,5,172,5,178,5,184,5,190, + 5,196,5,202,5,208,5,214,5,220,5,226,5,232,5,238,5,244,5,250,6,0,6,6,6,12,6,18,6,24,6,30,6,36,6,42,6,48,6,54, + 6,60,6,66,6,72,6,78,6,84,6,90,6,96,6,102,6,108,6,114,6,120,6,126,6,132,6,138,6,144,6,150,6,156,6,162,6,168,6,174, + 6,180,6,186,6,192,6,198,6,204,6,210,6,216,6,222,6,228,6,234,6,240,6,246,6,252,7,2,7,8,7,14,7,20,7,26,7,32,7,38, + 7,44,7,50,7,56,7,62,7,68,7,74,7,80,7,86,7,92,7,98,7,104,7,110,7,116,7,122,7,128,7,134,7,140,7,146,7,152,7,158, + 7,164,7,170,7,176,7,182,7,188,7,194,7,200,7,206,7,212,7,218,7,224,7,230,7,236,7,242,7,248,7,254,8,4,8,10,8,16,8,22, + 8,28,8,34,8,40,8,46,8,52,8,58,8,64,8,70,8,76,8,82,8,88,8,94,8,100,8,106,8,112,8,118,8,124,8,130,8,136,8,142, + 8,148,8,154,8,160,8,166,8,172,8,178,8,184,8,190,8,196,8,202,8,208,8,214,8,220,8,226,8,232,8,238,8,244,8,250,9,0,9,6, + 9,12,9,18,9,24,9,30,9,36,9,42,9,48,9,54,9,60,9,66,9,72,9,78,9,84,9,90,9,96,9,102,9,108,9,114,9,120,9,126, + 9,132,9,138,9,144,9,150,9,156,9,162,9,168,9,174,9,180,9,186,9,192,9,198,9,204,9,210,9,216,9,222,9,228,9,234,9,240,9,246, + 9,252,10,2,10,8,10,14,10,20,10,26,10,32,10,38,10,44,10,50,10,56,10,62,10,68,10,74,10,80,10,86,10,92,10,98,10,104,10,110, + 10,116,10,122,10,128,10,134,10,140,10,146,10,152,10,158,10,164,10,170,10,176,10,182,10,188,10,194,10,200,10,206,10,212,10,218,10,224,10,230, + 10,236,10,242,10,248,10,254,11,4,11,10,11,16,11,22,11,28,11,34,11,40,11,46,11,52,11,58,11,64,11,70,11,76,11,82,11,88,11,94, + 11,100,11,106,11,112,11,118,11,124,11,130,11,136,11,142,11,148,11,154,11,160,11,166,11,172,11,178,11,184,11,190,11,196,11,202,11,208,11,214, + 11,220,11,226,11,232,11,238,11,244,11,250,12,0,12,6,12,12,12,18,12,24,12,30,12,36,12,42,12,48,12,54,12,60,12,66,12,72,12,78, + 12,84,12,90,12,96,12,102,12,108,12,114,12,120,12,126,12,132,12,138,12,144,12,150,12,156,12,162,12,168,12,174,12,180,12,186,12,192,12,198, + 12,204,12,210,12,216,12,222,12,228,12,234,12,240,12,246,12,252,13,2,13,8,13,14,13,20,13,26,13,32,13,38,13,44,13,50,13,56,13,62, + 13,68,13,74,13,80,13,86,13,92,13,98,13,104,13,110,13,116,13,122,13,128,13,134,13,140,13,146,13,152,13,158,13,164,13,170,13,176,13,182, + 13,188,13,194,13,200,13,206,13,212,13,218,13,224,13,230,13,236,13,242,13,248,13,254,14,4,14,10,14,16,14,22,14,28,14,34,14,40,14,46, + 14,52,14,58,14,64,14,70,14,76,14,82,14,88,14,94,14,100,14,106,14,112,14,118,14,124,14,130,14,136,14,142,14,148,14,154,14,160,14,166, + 14,172,14,178,14,184,14,190,14,196,14,202,14,208,14,214,14,220,14,226,14,232,14,238,14,244,14,250,15,0,15,6,15,12,15,18,15,24,15,30, + 15,36,15,42,15,48,15,54,15,60,15,66,15,72,15,78,15,84,15,90,15,96,15,102,15,108,15,114,15,120,15,126,15,132,15,138,15,144,15,150, + 15,156,15,162,15,168,15,174,15,180,15,186,15,192,15,198,15,204,15,210,15,216,15,222,15,228,15,234,15,240,15,246,15,252,16,2,16,8,16,14, + 16,20,16,26,16,32,16,38,16,44,16,50,16,56,16,62,16,68,16,74,16,80,16,86,16,92,16,98,16,104,16,110,16,116,16,122,16,128,16,134, + 16,140,16,146,16,152,16,158,16,164,16,170,16,176,16,182,16,188,16,194,16,200,16,206,16,212,16,218,16,224,16,230,16,236,16,242,16,248,16,254, + 17,4,17,10,17,16,17,22,17,28,17,34,17,40,17,46,17,52,17,58,17,64,17,70,17,76,17,82,17,88,17,94,17,100,17,106,17,112,17,118, + 17,124,17,130,17,136,17,142,17,148,17,154,17,160,17,166,17,172,17,178,17,184,17,190,17,196,17,202,17,208,17,214,17,220,17,226,17,232,17,238, + 17,244,17,250,18,0,18,6,18,12,18,18,18,24,18,30,18,36,18,42,18,48,18,54,18,60,18,66,18,72,18,78,18,84,18,90,18,96,18,102, + 18,108,18,114,18,120,18,126,18,132,18,138,18,144,18,150,18,156,18,162,18,168,18,174,18,180,18,186,18,192,18,198,18,204,18,210,18,216,18,222, + 18,228,18,234,18,240,18,246,18,252,19,2,19,8,19,14,19,20,19,26,19,32,19,38,19,44,19,50,19,56,19,62,19,68,0,1,2,222,0,0, + 0,1,2,85,0,0,0,1,1,219,0,0,0,1,2,248,0,0,0,1,2,171,0,0,0,1,1,15,0,0,0,1,1,44,0,0,0,1,2,171, + 0,0,0,1,2,193,0,0,0,1,0,229,0,0,0,1,1,163,0,0,0,1,2,33,0,0,0,1,1,236,0,0,0,1,2,184,0,0,0,1, + 2,254,0,0,0,1,0,56,0,0,0,1,1,169,0,0,0,1,3,16,0,0,0,1,3,124,255,250,0,1,2,154,0,0,0,1,2,81,0,0, + 0,1,0,254,0,0,0,1,2,39,0,0,0,1,2,196,0,0,0,1,2,2,0,0,0,1,3,14,0,0,0,1,2,110,0,0,0,1,1,226, + 0,0,0,1,1,226,0,0,0,1,1,226,0,0,0,1,1,29,255,156,0,1,1,29,255,156,0,1,1,244,254,12,0,1,1,29,253,218,0,1, + 2,188,254,112,0,1,1,29,255,156,0,1,3,132,254,112,0,1,1,244,255,106,0,1,3,132,255,106,0,1,3,132,255,106,0,1,3,44,253,118, + 0,1,3,44,253,168,0,1,3,44,253,118,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,244,254,12,0,1,1,244,254,12,0,1,2,88, + 253,168,0,1,2,88,253,168,0,1,2,88,253,168,0,1,2,88,253,68,0,1,2,91,255,106,0,1,2,91,255,106,0,1,2,215,253,168,0,1, + 2,215,253,168,0,1,1,44,255,156,0,1,3,32,255,56,0,1,2,188,253,218,0,1,3,32,255,56,0,1,2,188,254,62,0,1,0,240,253,168, + 0,1,2,238,254,62,0,1,1,244,255,106,0,1,1,244,254,12,0,1,2,188,254,112,0,1,2,188,253,218,0,1,3,132,255,106,0,1,2,188, + 253,218,0,1,3,132,255,106,0,1,3,132,255,106,0,1,3,132,253,168,0,1,3,132,254,94,0,1,3,132,255,106,0,1,3,132,253,168,0,1, + 3,132,255,106,0,1,3,132,253,168,0,1,3,44,253,168,0,1,3,44,253,168,0,1,3,44,253,168,0,1,3,44,253,168,0,1,3,44,253,168, + 0,1,3,44,253,168,0,1,3,44,253,168,0,1,1,194,255,106,0,1,1,244,254,94,0,1,1,244,254,112,0,1,1,244,254,112,0,1,1,194, + 255,106,0,1,1,243,254,162,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,244,254,12,0,1,1,244,254,12,0,1, + 1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12, + 0,1,2,88,253,168,0,1,2,88,253,168,0,1,2,88,253,168,0,1,2,88,253,168,0,1,2,88,253,168,0,1,2,91,255,106,0,1,2,215, + 253,168,0,1,3,32,255,56,0,1,3,182,254,112,0,1,3,182,254,112,0,1,3,32,255,56,0,1,3,182,253,118,0,1,3,32,255,56,0,1, + 2,188,253,218,0,1,2,188,253,218,0,1,3,32,255,106,0,1,3,32,255,106,0,1,3,32,255,106,0,1,3,32,255,56,0,1,3,32,255,56, + 0,1,3,32,253,118,0,1,3,32,255,106,0,1,3,32,255,106,0,1,3,32,255,106,0,1,3,32,254,112,0,1,3,32,253,68,0,1,3,32, + 255,106,0,1,2,188,254,62,0,1,2,188,254,62,0,1,2,188,254,62,0,1,2,238,252,174,0,1,3,7,253,68,0,1,2,238,254,62,0,1, + 2,238,254,62,0,1,3,7,253,18,0,1,2,238,254,62,0,1,3,32,255,106,0,1,3,44,253,168,0,1,1,244,254,12,0,1,2,188,254,112, + 0,1,2,188,254,112,0,1,1,244,255,106,0,1,1,22,0,0,0,1,2,73,0,0,0,1,1,171,0,0,0,1,2,94,0,0,0,1,2,157, + 0,0,0,1,2,157,0,0,0,1,2,96,0,0,0,1,2,157,0,0,0,1,3,146,0,0,0,1,1,22,0,0,0,1,2,107,0,0,0,1, + 2,47,0,0,0,1,3,5,0,0,0,1,1,169,0,0,0,1,3,213,0,0,0,1,1,221,0,0,0,1,3,35,0,0,0,1,2,157,0,0, + 0,1,2,128,0,0,0,1,3,2,0,0,0,1,3,26,0,0,0,1,3,101,0,0,0,1,1,221,0,0,0,1,2,128,0,0,0,1,2,89, + 0,0,0,1,3,26,0,0,0,1,3,26,0,0,0,1,2,27,0,0,0,1,2,89,0,0,0,1,2,89,0,0,0,1,3,132,253,168,0,1, + 3,132,253,168,0,1,1,43,253,218,0,1,1,43,253,218,0,1,3,132,253,168,0,1,3,132,253,168,0,1,1,43,253,218,0,1,1,43,253,218, + 0,1,3,132,253,168,0,1,3,132,253,168,0,1,1,43,253,218,0,1,1,43,253,218,0,1,3,132,255,106,0,1,3,132,255,106,0,1,1,43, + 255,156,0,1,1,43,255,156,0,1,3,132,255,106,0,1,3,132,255,106,0,1,1,43,255,156,0,1,1,43,255,156,0,1,3,132,255,106,0,1, + 3,132,255,106,0,1,1,43,255,156,0,1,1,43,255,156,0,1,3,32,255,56,0,1,3,32,255,56,0,1,1,244,255,106,0,1,2,6,255,106, + 0,1,3,32,255,56,0,1,3,32,255,56,0,1,1,244,255,106,0,1,2,6,255,106,0,1,3,44,253,168,0,1,3,44,253,168,0,1,2,88, + 254,12,0,1,2,88,254,12,0,1,3,44,253,168,0,1,3,44,253,168,0,1,2,88,255,6,0,1,2,88,255,6,0,1,3,44,253,168,0,1, + 3,44,253,168,0,1,2,88,254,12,0,1,2,88,254,12,0,1,3,44,253,168,0,1,3,44,253,168,0,1,2,88,254,12,0,1,2,88,254,12, + 0,1,1,243,254,162,0,1,1,243,254,162,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,194, + 255,106,0,1,1,194,255,106,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,3,32,255,106,0,1, + 3,32,255,106,0,1,1,44,255,106,0,1,1,44,255,106,0,1,3,32,255,106,0,1,3,32,255,106,0,1,1,44,255,106,0,1,1,44,255,106, + 0,1,3,32,253,68,0,1,3,32,253,68,0,1,1,144,253,118,0,1,1,144,253,118,0,1,3,32,255,106,0,1,3,32,255,106,0,1,1,44, + 255,106,0,1,1,44,255,106,0,1,2,238,254,62,0,1,2,238,253,168,0,1,2,238,254,62,0,1,2,238,253,168,0,1,1,43,255,156,0,1, + 1,43,255,156,0,1,3,32,255,106,0,1,3,82,253,168,0,1,1,194,255,106,0,1,1,244,253,168,0,1,3,32,255,56,0,1,3,32,255,56, + 0,1,1,44,255,106,0,1,1,44,255,106,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,43,255,156,0,1,1,43,255,156,0,1,2,188, + 254,112,0,1,2,188,254,112,0,1,1,43,254,162,0,1,1,43,254,162,0,1,1,44,255,156,0,1,1,44,255,156,0,1,1,44,255,156,0,1, + 0,197,255,156,0,1,1,44,254,12,0,1,1,44,255,156,0,1,1,44,255,156,0,1,1,44,255,156,0,1,1,44,255,156,0,1,1,44,254,212, + 0,1,1,44,254,212,0,1,1,44,255,156,0,1,1,44,255,156,0,1,1,44,255,156,0,1,1,44,255,156,0,1,1,244,0,50,0,1,1,29, + 255,156,0,1,1,29,255,156,0,1,1,29,255,156,0,1,1,29,255,156,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,29,253,168,0,1, + 1,29,253,168,0,1,2,188,254,112,0,1,2,188,254,112,0,1,1,43,255,156,0,1,1,43,255,156,0,1,1,29,255,156,0,1,1,29,255,156, + 0,1,3,132,254,112,0,1,3,132,254,112,0,1,1,43,254,162,0,1,1,43,254,162,0,1,1,244,255,106,0,1,1,244,255,106,0,1,3,132, + 255,106,0,1,3,132,255,106,0,1,1,43,255,156,0,1,1,43,255,156,0,1,3,132,255,106,0,1,3,132,255,106,0,1,1,43,255,156,0,1, + 1,43,255,156,0,1,3,44,253,168,0,1,3,44,253,168,0,1,2,88,254,162,0,1,2,88,254,162,0,1,3,44,253,168,0,1,3,44,253,168, + 0,1,2,88,255,156,0,1,2,88,255,156,0,1,3,44,253,168,0,1,3,44,253,168,0,1,2,88,255,156,0,1,2,88,255,156,0,1,1,194, + 255,106,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1, + 1,244,254,12,0,1,2,88,253,168,0,1,2,88,253,168,0,1,2,138,255,106,0,1,2,138,255,106,0,1,2,88,253,168,0,1,2,88,253,168, + 0,1,2,138,255,106,0,1,2,138,255,106,0,1,2,88,253,168,0,1,2,88,253,168,0,1,2,38,255,106,0,1,2,38,255,106,0,1,2,88, + 253,168,0,1,2,88,253,168,0,1,2,38,255,106,0,1,2,38,255,106,0,1,2,91,255,106,0,1,2,91,255,106,0,1,1,83,255,106,0,1, + 1,83,255,106,0,1,2,91,255,106,0,1,2,91,255,106,0,1,1,83,255,106,0,1,1,83,255,106,0,1,2,138,253,168,0,1,2,215,253,168, + 0,1,2,88,255,156,0,1,1,238,255,156,0,1,2,138,253,168,0,1,2,215,253,168,0,1,2,88,255,156,0,1,1,238,255,156,0,1,3,32, + 255,56,0,1,3,32,255,56,0,1,1,244,255,106,0,1,2,6,255,106,0,1,2,188,253,218,0,1,2,188,253,168,0,1,1,244,255,106,0,1, + 2,6,255,106,0,1,3,32,255,56,0,1,3,32,255,56,0,1,1,44,255,106,0,1,1,44,255,106,0,1,2,188,254,62,0,1,2,188,254,62, + 0,1,1,83,255,156,0,1,1,83,255,156,0,1,0,240,253,168,0,1,0,240,253,168,0,1,2,38,255,106,0,1,2,38,255,106,0,1,2,238, + 254,62,0,1,2,238,253,168,0,1,1,43,255,156,0,1,1,43,255,156,0,1,1,244,255,106,0,1,1,244,255,106,0,1,1,194,255,106,0,1, + 1,244,253,168,0,1,1,244,254,12,0,1,1,244,254,12,0,1,2,188,254,112,0,1,2,188,254,112,0,1,2,188,253,218,0,1,2,188,253,218, + 0,1,1,43,254,162,0,1,1,43,254,162,0,1,3,132,255,106,0,1,1,43,255,156,0,1,1,43,255,156,0,1,3,32,255,56,0,1,1,244, + 255,106,0,1,2,6,255,106,0,1,2,188,253,153,0,1,1,244,255,106,0,1,2,6,255,106,0,1,1,43,255,156,0,1,1,43,255,156,0,1, + 3,132,254,94,0,1,1,43,254,194,0,1,1,43,254,194,0,1,3,132,255,106,0,1,1,43,255,156,0,1,1,43,255,156,0,1,3,44,253,168, + 0,1,2,88,255,156,0,1,2,88,255,156,0,1,3,44,253,168,0,1,2,88,255,156,0,1,2,88,255,156,0,1,3,44,253,168,0,1,2,88, + 255,156,0,1,2,88,255,156,0,1,3,44,253,168,0,1,2,88,254,12,0,1,2,88,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1, + 2,188,254,62,0,1,1,83,255,156,0,1,1,83,255,156,0,1,2,188,254,112,0,1,1,43,254,162,0,1,1,43,254,162,0,1,1,244,254,12, + 0,1,1,244,255,106,0,1,1,29,0,0,0,1,1,29,0,0,0,1,1,29,0,0,0,1,2,73,0,0,0,1,2,73,0,0,0,1,2,73, + 0,0,0,1,1,171,0,0,0,1,1,171,0,0,0,1,1,171,0,0,0,1,2,94,0,0,0,1,2,94,0,0,0,1,2,94,0,0,0,1, + 2,157,0,0,0,1,2,157,0,0,0,1,2,157,0,0,0,1,2,157,0,0,0,1,2,157,0,0,0,1,2,157,0,0,0,1,2,96,0,0, + 0,1,2,96,0,0,0,1,2,96,0,0,0,1,2,157,0,0,0,1,2,157,0,0,0,1,2,157,0,0,0,1,3,146,0,0,0,1,3,146, + 0,0,0,1,3,146,0,0,0,1,1,22,0,0,0,1,1,22,0,0,0,1,1,22,0,0,0,1,2,107,0,0,0,1,2,107,0,0,0,1, + 2,107,0,0,0,1,2,47,0,0,0,1,2,47,0,0,0,1,2,47,0,0,0,1,3,5,0,0,0,1,3,5,0,0,0,1,3,5,0,0, + 0,1,1,169,0,0,0,1,1,169,0,0,0,1,1,169,0,0,0,1,3,213,0,0,0,1,3,213,0,0,0,1,3,213,0,0,0,1,1,221, + 0,0,0,1,1,221,0,0,0,1,1,221,0,0,0,1,3,35,0,0,0,1,3,35,0,0,0,1,3,35,0,0,0,1,2,157,0,0,0,1, + 2,157,0,0,0,1,2,157,0,0,0,1,2,128,0,0,0,1,2,128,0,0,0,1,2,128,0,0,0,1,3,2,0,0,0,1,3,2,0,0, + 0,1,3,2,0,0,0,1,3,26,0,0,0,1,3,26,0,0,0,1,3,26,0,0,0,1,3,101,0,0,0,1,3,101,0,0,0,1,3,101, + 0,0,0,1,1,221,0,0,0,1,1,221,0,0,0,1,1,221,0,0,0,1,2,128,0,0,0,1,2,128,0,0,0,1,2,128,0,0,0,1, + 2,89,0,0,0,1,2,89,0,0,0,1,2,89,0,0,0,1,3,26,0,0,0,1,3,26,0,0,0,1,3,26,0,0,0,1,3,26,0,0, + 0,1,3,26,0,0,0,1,3,26,0,0,0,1,2,27,0,0,0,1,2,27,0,0,0,1,2,27,0,0,0,1,2,89,0,0,0,1,2,89, + 0,0,0,1,2,89,0,0,0,1,2,89,0,0,0,1,2,89,0,0,0,1,2,89,0,0,0,1,1,244,254,94,0,1,1,244,254,112,0,1, + 1,244,254,112,0,1,1,194,255,106,0,1,1,194,255,106,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12,0,1,1,244,254,12, + 0,1,1,244,254,12,0,1,2,88,253,168,0,1,3,232,254,112,0,1,3,232,254,112,0,1,2,88,253,168,0,1,3,232,253,218,0,1,3,232, + 253,218,0,1,2,88,253,168,0,1,3,232,253,218,0,1,3,232,253,218,0,1,2,88,253,168,0,1,3,32,254,112,0,1,3,32,254,112,0,1, + 2,88,253,168,0,1,2,38,255,106,0,1,2,38,255,106,0,1,2,91,255,106,0,1,1,83,255,106,0,1,1,83,255,106,0,1,2,215,253,168, + 0,1,2,88,255,156,0,1,1,238,255,156,0,1,3,182,254,112,0,1,1,243,254,162,0,1,1,243,254,162,0,1,3,182,254,112,0,1,1,243, + 254,162,0,1,1,243,254,162,0,1,3,182,253,118,0,1,1,244,253,168,0,1,1,244,253,168,0,1,2,188,253,153,0,1,1,244,255,106,0,1, + 2,6,255,106,0,1,2,188,253,153,0,1,1,244,255,106,0,1,2,6,255,106,0,1,3,32,255,106,0,1,1,164,255,106,0,1,1,164,255,106, + 0,1,3,32,255,106,0,1,1,44,255,106,0,1,1,44,255,106,0,1,3,32,255,56,0,1,1,44,255,106,0,1,1,44,255,106,0,1,3,32, + 253,118,0,1,1,144,253,168,0,1,1,144,253,168,0,1,3,32,255,106,0,1,1,44,255,106,0,1,1,44,255,106,0,1,3,32,254,112,0,1, + 1,144,254,162,0,1,1,144,254,162,0,1,3,32,255,106,0,1,1,44,255,106,0,1,1,44,255,106,0,1,2,188,254,62,0,1,1,83,255,156, + 0,1,1,83,255,156,0,1,2,188,254,62,0,1,1,83,255,156,0,1,1,83,255,156,0,1,2,238,252,174,0,1,1,43,253,218,0,1,1,73, + 253,218,0,1,3,7,252,149,0,1,1,43,254,162,0,1,1,43,254,162,0,1,3,7,252,99,0,1,1,43,254,194,0,1,1,43,254,194,0,1, + 2,238,253,168,0,1,1,43,255,156,0,1,1,43,255,156,0,2,0,13,5,38,5,67,0,0,5,79,5,114,0,30,5,142,5,143,0,66,5,146, + 5,220,0,68,5,241,6,14,0,143,19,223,20,64,0,173,20,85,20,216,1,15,22,202,22,212,1,147,22,214,22,231,1,158,23,3,23,11,1,176, + 23,13,23,13,1,185,23,32,23,121,1,186,23,135,23,219,2,20,0,1,0,16,5,16,5,17,5,18,5,19,5,20,5,21,5,22,5,23,5,24, + 5,27,5,29,5,37,5,117,5,120,5,125,6,22,0,16,0,0,0,66,0,0,0,72,0,0,0,78,0,0,0,84,0,0,0,90,0,0,0,96, + 0,0,0,102,0,0,0,108,0,0,0,114,0,0,0,120,0,0,0,126,0,0,0,132,0,0,0,138,0,0,0,144,0,0,0,150,0,0,0,156, + 0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143, + 0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,143,0,0,0,1,2,0,0,0,0,1, + 2,0,0,0,0,1,2,0,0,0,0,1,2,0,255,255,0,1,0,244,0,198,0,1,0,250,0,12,0,23,0,48,0,54,0,60,0,66,0,72, + 0,78,0,84,0,90,0,96,0,102,0,108,0,114,0,120,0,126,0,132,0,138,0,144,0,150,0,156,0,162,0,168,0,174,0,180,0,1,2,99, + 0,140,0,1,1,209,2,48,0,1,0,242,2,48,0,1,1,172,2,48,0,1,2,153,2,48,0,1,0,56,3,27,0,1,0,20,2,48,0,1, + 2,181,2,48,0,1,0,6,3,27,0,1,1,127,2,48,0,1,1,113,2,61,0,1,1,105,2,48,0,1,2,213,2,48,0,1,0,232,2,48, + 0,1,2,171,2,48,0,1,2,216,1,49,0,1,3,20,2,48,0,1,1,18,1,205,0,1,2,102,2,48,0,1,1,228,2,48,0,1,3,106, + 2,61,0,1,2,198,2,48,0,1,0,80,3,27,0,2,0,7,5,38,5,44,0,0,5,46,5,50,0,7,5,52,5,52,0,12,5,54,5,55, + 0,13,5,57,5,58,0,15,5,60,5,64,0,17,19,177,19,177,0,22,0,1,0,1,5,28,0,1,0,0,0,6,0,1,2,153,2,48,0,1, + 0,184,0,174,0,1,0,232,0,12,0,8,0,18,0,36,0,54,0,72,0,90,0,108,0,126,0,144,0,2,0,6,0,12,0,1,3,99,6,114, + 0,1,0,150,7,8,0,2,0,6,0,12,0,1,3,99,6,114,0,1,0,150,7,8,0,2,0,6,0,12,0,1,3,99,6,114,0,1,0,150, + 7,228,0,2,0,6,0,12,0,1,3,99,6,114,0,1,0,150,7,228,0,2,0,6,0,12,0,1,3,99,6,114,0,1,0,150,5,220,0,2, + 0,6,0,12,0,1,3,99,6,114,0,1,0,150,5,220,0,2,0,6,0,12,0,1,3,99,6,114,0,1,0,150,5,220,0,2,0,6,0,12, + 0,1,3,99,6,114,0,1,0,150,5,220,0,2,0,1,20,217,20,224,0,0,0,1,0,22,5,31,5,75,5,115,5,116,5,118,5,119,5,121, + 5,122,5,123,5,124,5,126,5,127,5,144,19,178,23,24,23,25,23,26,23,27,23,28,23,29,23,30,23,31,0,22,0,0,0,90,0,0,0,96, + 0,0,0,102,0,0,0,108,0,0,0,114,0,0,0,120,0,0,0,126,0,0,0,132,0,0,0,138,0,0,0,144,0,0,0,150,0,0,0,156, + 0,0,0,162,0,0,0,168,0,0,0,174,0,0,0,180,0,0,0,186,0,0,0,192,0,0,0,198,0,0,0,204,0,0,0,210,0,0,0,216, + 0,1,2,143,4,96,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0, + 4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1, + 2,143,4,96,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176, + 0,1,2,0,4,176,0,1,2,0,4,176,0,1,18,220,18,126,0,1,19,28,0,12,2,78,4,158,4,164,4,170,4,176,4,182,4,188,4,194, + 4,200,4,206,4,212,4,218,4,224,4,230,4,236,4,242,4,248,4,254,5,4,5,10,5,16,5,22,5,28,5,34,5,40,5,46,5,52,5,58, + 5,64,5,70,5,76,5,82,5,88,5,94,5,100,5,106,5,112,5,118,5,124,5,130,5,136,5,142,5,148,5,154,5,160,5,166,5,172,5,178, + 5,184,5,190,5,196,5,202,5,208,5,214,5,220,5,226,5,232,5,238,5,244,5,250,6,0,6,6,6,12,6,18,6,24,6,30,6,36,6,42, + 6,48,6,54,6,60,6,66,6,72,6,78,6,84,6,90,6,96,6,102,6,108,6,114,6,120,6,126,6,132,6,138,6,144,6,150,6,156,6,162, + 6,168,6,174,6,180,6,186,6,192,6,198,6,204,6,210,6,216,6,222,6,228,6,234,6,240,6,246,6,252,7,2,7,8,7,14,7,20,7,26, + 7,32,7,38,7,44,7,50,7,56,7,62,7,68,7,74,7,80,7,86,7,92,7,98,7,104,7,110,7,116,7,122,7,128,7,134,7,140,7,146, + 7,152,7,158,7,164,7,170,7,176,7,182,7,188,7,194,7,200,7,206,7,212,7,218,7,224,7,230,7,236,7,242,7,248,7,254,8,4,8,10, + 8,16,8,22,8,28,8,34,8,40,8,46,8,52,8,58,8,64,8,70,8,76,8,82,8,88,8,94,8,100,8,106,8,112,8,118,8,124,8,130, + 8,136,8,142,8,148,8,154,8,160,8,166,8,172,8,178,8,184,8,190,8,196,8,202,8,208,8,214,8,220,8,226,8,232,8,238,8,244,8,250, + 9,0,9,6,9,12,9,18,9,24,9,30,9,36,9,42,9,48,9,54,9,60,9,66,9,72,9,78,9,84,9,90,9,96,9,102,9,108,9,114, + 9,120,9,126,9,132,9,138,9,144,9,150,9,156,9,162,9,168,9,174,9,180,9,186,9,192,9,198,9,204,9,210,9,216,9,222,9,228,9,234, + 9,240,9,246,9,252,10,2,10,8,10,14,10,20,10,26,10,32,10,38,10,44,10,50,10,56,10,62,10,68,10,74,10,80,10,86,10,92,10,98, + 10,104,10,110,10,116,10,122,10,128,10,134,10,140,10,146,10,152,10,158,10,164,10,170,10,176,10,182,10,188,10,194,10,200,10,206,10,212,10,218, + 10,224,10,230,10,236,10,242,10,248,10,254,11,4,11,10,11,16,11,22,11,28,11,34,11,40,11,46,11,52,11,58,11,64,11,70,11,76,11,82, + 11,88,11,94,11,100,11,106,11,112,11,118,11,124,11,130,11,136,11,142,11,148,11,154,11,160,11,166,11,172,11,178,11,184,11,190,11,196,11,202, + 11,208,11,214,11,220,11,226,11,232,11,238,11,244,11,250,12,0,12,6,12,12,12,18,12,24,12,30,12,36,12,42,12,48,12,54,12,60,12,66, + 12,72,12,78,12,84,12,90,12,96,12,102,12,108,12,114,12,120,12,126,12,132,12,138,12,144,12,150,12,156,12,162,12,168,12,174,12,180,12,186, + 12,192,12,198,12,204,12,210,12,216,12,222,12,228,12,234,12,240,12,246,12,252,13,2,13,8,13,14,13,20,13,26,13,32,13,38,13,44,13,50, + 13,56,13,62,13,68,13,74,13,80,13,86,13,92,13,98,13,104,13,110,13,116,13,122,13,128,13,134,13,140,13,146,13,152,13,158,13,164,13,170, + 13,176,13,182,13,188,13,194,13,200,13,206,13,212,13,218,13,224,13,230,13,236,13,242,13,248,13,254,14,4,14,10,14,16,14,22,14,28,14,34, + 14,40,14,46,14,52,14,58,14,64,14,70,14,76,14,82,14,88,14,94,14,100,14,106,14,112,14,118,14,124,14,130,14,136,14,142,14,148,14,154, + 14,160,14,166,14,172,14,178,14,184,14,190,14,196,14,202,14,208,14,214,14,220,14,226,14,232,14,238,14,244,14,250,15,0,15,6,15,12,15,18, + 15,24,15,30,15,36,15,42,15,48,15,54,15,60,15,66,15,72,15,78,15,84,15,90,15,96,15,102,15,108,15,114,15,120,15,126,15,132,15,138, + 15,144,15,150,15,156,15,162,15,168,15,174,15,180,15,186,15,192,15,198,15,204,15,210,15,216,15,222,15,228,15,234,15,240,15,246,15,252,16,2, + 16,8,16,14,16,20,16,26,16,32,16,38,16,44,16,50,16,56,16,62,16,68,16,74,16,80,16,86,16,92,16,98,16,104,16,110,16,116,16,122, + 16,128,16,134,16,140,16,146,16,152,16,158,16,164,16,170,16,176,16,182,16,188,16,194,16,200,16,206,16,212,16,218,16,224,16,230,16,236,16,242, + 16,248,16,254,17,4,17,10,17,16,17,22,17,28,17,34,17,40,17,46,17,52,17,58,17,64,17,70,17,76,17,82,17,88,17,94,17,100,17,106, + 17,112,17,118,17,124,17,130,17,136,17,142,17,148,17,154,17,160,17,166,17,172,17,178,17,184,17,190,17,196,17,202,17,208,17,214,17,220,17,226, + 17,232,17,238,17,244,17,250,18,0,18,6,18,12,18,18,18,24,18,30,18,36,18,42,18,48,18,54,18,60,18,66,18,72,18,78,18,84,18,90, + 18,96,18,102,18,108,0,1,2,82,4,96,0,1,2,25,4,96,0,1,2,83,4,96,0,1,1,29,7,158,0,1,1,29,8,52,0,1,1,194, + 4,226,0,1,1,29,6,114,0,1,1,244,5,20,0,1,1,29,6,114,0,1,3,132,3,232,0,1,1,194,4,76,0,1,3,132,3,82,0,1, + 3,132,4,76,0,1,2,138,3,232,0,1,2,138,3,232,0,1,2,138,4,226,0,1,1,144,3,232,0,1,1,144,4,226,0,1,2,188,2,238, + 0,1,2,188,3,232,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,91,6,114,0,1,2,91, + 6,114,0,1,1,194,4,126,0,1,1,194,5,120,0,1,1,44,4,176,0,1,2,188,4,76,0,1,1,244,4,76,0,1,2,188,5,220,0,1, + 2,138,5,20,0,1,2,138,3,182,0,1,2,138,3,232,0,1,1,194,3,82,0,1,1,244,2,238,0,1,1,244,2,238,0,1,1,244,2,238, + 0,1,3,132,3,232,0,1,1,244,4,76,0,1,3,132,4,226,0,1,3,132,4,76,0,1,3,132,3,232,0,1,3,132,3,82,0,1,3,132, + 3,232,0,1,3,132,3,232,0,1,3,132,4,76,0,1,3,132,3,232,0,1,2,138,6,14,0,1,2,138,5,220,0,1,2,138,3,232,0,1, + 2,138,3,232,0,1,2,138,5,220,0,1,2,138,3,232,0,1,2,138,3,232,0,1,1,194,6,64,0,1,1,144,3,232,0,1,1,144,3,232, + 0,1,1,194,6,64,0,1,1,194,4,226,0,1,1,144,3,232,0,1,1,194,5,220,0,1,1,194,5,170,0,1,1,194,5,220,0,1,2,188, + 5,120,0,1,2,188,4,176,0,1,2,188,2,238,0,1,2,188,2,238,0,1,2,188,2,238,0,1,2,188,2,238,0,1,2,188,3,232,0,1, + 2,188,4,226,0,1,2,188,4,226,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,88,3,32, + 0,1,2,91,6,114,0,1,1,244,6,114,0,1,2,188,4,76,0,1,2,188,4,76,0,1,2,188,4,76,0,1,2,188,4,76,0,1,2,188, + 4,76,0,1,2,188,4,76,0,1,1,244,4,76,0,1,1,244,4,76,0,1,1,244,5,120,0,1,1,244,5,120,0,1,1,244,5,120,0,1, + 3,57,6,14,0,1,3,57,7,8,0,1,2,188,5,220,0,1,1,244,5,120,0,1,1,244,5,120,0,1,1,244,5,120,0,1,1,244,5,120, + 0,1,1,244,5,120,0,1,1,244,5,120,0,1,4,188,8,52,0,1,4,188,8,52,0,1,4,188,8,102,0,1,2,138,5,20,0,1,2,138, + 3,232,0,1,2,138,2,238,0,1,2,188,5,95,0,1,2,138,3,232,0,1,2,188,4,226,0,1,3,82,4,76,0,1,2,138,4,226,0,1, + 1,244,4,226,0,1,1,244,2,238,0,1,1,244,4,226,0,1,1,194,3,82,0,1,1,22,5,240,0,1,2,73,5,240,0,1,1,171,5,240, + 0,1,2,94,5,240,0,1,2,157,5,240,0,1,2,157,5,240,0,1,2,96,5,240,0,1,2,157,5,240,0,1,1,224,5,240,0,1,2,19, + 5,240,0,1,1,110,5,240,0,1,1,22,5,240,0,1,2,167,5,240,0,1,1,169,5,240,0,1,3,203,5,240,0,1,1,221,5,240,0,1, + 3,35,5,240,0,1,2,157,5,242,0,1,2,128,5,242,0,1,3,2,5,240,0,1,3,26,5,240,0,1,2,148,5,240,0,1,1,221,5,240, + 0,1,2,128,5,242,0,1,2,89,5,240,0,1,3,26,5,240,0,1,3,26,5,240,0,1,2,27,5,240,0,1,2,89,5,240,0,1,2,89, + 5,240,0,1,3,132,3,232,0,1,3,132,3,232,0,1,1,43,3,232,0,1,1,43,3,232,0,1,3,132,3,232,0,1,3,132,3,232,0,1, + 1,43,3,232,0,1,1,43,3,232,0,1,3,132,3,232,0,1,3,132,3,232,0,1,1,43,3,232,0,1,1,43,3,232,0,1,3,132,4,76, + 0,1,3,132,4,76,0,1,1,43,5,20,0,1,1,43,5,20,0,1,3,132,4,76,0,1,3,132,4,76,0,1,1,43,5,20,0,1,1,43, + 5,20,0,1,3,132,4,226,0,1,3,132,4,226,0,1,1,43,5,170,0,1,1,43,5,170,0,1,2,188,4,76,0,1,2,188,4,76,0,1, + 1,244,6,64,0,1,2,6,5,170,0,1,2,188,4,76,0,1,2,188,4,76,0,1,1,244,6,64,0,1,2,6,5,170,0,1,2,138,3,232, + 0,1,2,138,3,232,0,1,2,88,3,232,0,1,2,88,3,232,0,1,2,138,3,232,0,1,2,138,3,232,0,1,2,88,3,232,0,1,2,88, + 3,232,0,1,2,138,3,232,0,1,2,138,3,232,0,1,2,88,3,232,0,1,2,88,3,232,0,1,2,138,3,232,0,1,2,138,3,232,0,1, + 2,88,3,232,0,1,2,88,3,232,0,1,1,144,3,232,0,1,1,144,3,232,0,1,1,194,4,226,0,1,1,194,4,226,0,1,1,194,5,220, + 0,1,1,194,5,220,0,1,1,194,6,64,0,1,1,194,6,64,0,1,2,188,4,226,0,1,2,188,4,226,0,1,2,188,5,120,0,1,2,188, + 5,120,0,1,1,244,5,120,0,1,1,244,5,120,0,1,0,250,6,14,0,1,0,250,6,14,0,1,1,244,5,120,0,1,1,244,5,120,0,1, + 0,250,6,164,0,1,0,250,6,164,0,1,1,244,5,120,0,1,1,244,5,120,0,1,0,250,6,164,0,1,0,250,6,164,0,1,1,244,5,120, + 0,1,1,244,5,120,0,1,1,19,7,108,0,1,1,19,7,108,0,1,2,138,2,238,0,1,2,138,2,138,0,1,2,188,5,95,0,1,2,188, + 4,101,0,1,1,43,5,170,0,1,1,43,5,170,0,1,3,82,4,76,0,1,3,82,3,32,0,1,1,244,4,76,0,1,1,244,3,32,0,1, + 3,57,7,8,0,1,3,57,7,8,0,1,1,19,7,158,0,1,1,19,7,158,0,1,1,244,4,226,0,1,1,244,4,226,0,1,1,43,3,232, + 0,1,1,43,3,232,0,1,1,244,2,238,0,1,2,88,2,86,0,1,1,43,3,232,0,1,1,43,3,232,0,1,1,44,6,164,0,1,1,44, + 6,164,0,1,1,44,7,58,0,1,0,197,4,176,0,1,1,44,4,176,0,1,1,44,5,220,0,1,1,44,5,220,0,1,1,44,7,58,0,1, + 1,44,7,58,0,1,1,44,4,176,0,1,1,44,4,176,0,1,1,44,7,8,0,1,1,44,7,8,0,1,1,44,7,58,0,1,1,44,7,58, + 0,1,1,194,4,76,0,1,1,29,7,208,0,1,1,29,7,208,0,1,1,29,8,152,0,1,1,29,8,152,0,1,1,194,4,226,0,1,1,194, + 4,226,0,1,1,29,6,114,0,1,1,29,6,114,0,1,1,244,5,20,0,1,2,88,4,26,0,1,1,43,5,70,0,1,1,43,5,70,0,1, + 1,29,6,114,0,1,1,29,6,114,0,1,3,132,3,232,0,1,3,132,3,232,0,1,1,43,3,232,0,1,1,43,3,232,0,1,1,194,4,76, + 0,1,2,38,4,76,0,1,3,132,3,82,0,1,3,132,3,82,0,1,1,43,4,26,0,1,1,43,4,26,0,1,3,132,4,76,0,1,3,132, + 4,76,0,1,1,43,5,20,0,1,1,43,5,20,0,1,2,138,3,232,0,1,2,138,3,232,0,1,2,88,3,232,0,1,2,88,3,232,0,1, + 2,138,3,232,0,1,2,138,3,232,0,1,2,88,3,232,0,1,2,88,3,232,0,1,2,138,4,226,0,1,2,138,4,226,0,1,2,88,4,126, + 0,1,2,88,4,126,0,1,1,144,3,232,0,1,1,144,3,232,0,1,1,144,4,226,0,1,1,144,4,226,0,1,2,188,2,238,0,1,2,188, + 2,238,0,1,2,188,3,232,0,1,2,188,3,232,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,138,3,132,0,1,2,138,3,132,0,1, + 2,88,3,32,0,1,2,88,3,32,0,1,3,82,4,226,0,1,3,82,4,226,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,38,3,32, + 0,1,2,38,3,32,0,1,2,88,3,32,0,1,2,88,3,32,0,1,2,38,3,232,0,1,2,38,3,232,0,1,2,91,6,114,0,1,2,91, + 6,114,0,1,1,83,6,114,0,1,1,83,6,114,0,1,2,91,6,114,0,1,2,91,6,114,0,1,1,83,6,114,0,1,1,83,6,114,0,1, + 1,194,4,126,0,1,1,244,3,232,0,1,1,194,4,126,0,1,1,238,3,232,0,1,1,194,5,120,0,1,1,244,4,126,0,1,1,194,5,120, + 0,1,1,238,4,126,0,1,2,188,4,76,0,1,2,188,4,76,0,1,1,244,5,70,0,1,2,6,4,176,0,1,1,244,4,76,0,1,1,244, + 3,82,0,1,1,244,5,70,0,1,2,6,4,176,0,1,2,188,5,220,0,1,2,188,5,220,0,1,0,250,6,14,0,1,0,250,6,14,0,1, + 2,138,5,20,0,1,2,138,5,20,0,1,1,83,6,114,0,1,1,83,6,114,0,1,2,138,3,182,0,1,2,138,3,82,0,1,2,38,3,82, + 0,1,2,38,3,82,0,1,2,138,3,232,0,1,2,138,2,238,0,1,1,43,4,26,0,1,1,43,4,26,0,1,1,194,3,82,0,1,2,38, + 3,82,0,1,1,244,4,76,0,1,1,244,3,32,0,1,1,244,2,238,0,1,1,244,2,238,0,1,1,244,2,238,0,1,2,88,2,86,0,1, + 1,244,2,238,0,1,2,88,2,238,0,1,1,43,3,232,0,1,1,43,3,232,0,1,3,132,3,232,0,1,1,43,3,232,0,1,1,43,3,232, + 0,1,2,188,4,76,0,1,1,244,4,76,0,1,2,6,3,182,0,1,1,244,3,82,0,1,1,244,4,76,0,1,2,6,3,182,0,1,1,43, + 4,26,0,1,1,43,4,26,0,1,3,132,3,82,0,1,1,43,4,26,0,1,1,43,4,26,0,1,3,132,3,232,0,1,1,43,5,20,0,1, + 1,43,5,20,0,1,2,138,6,14,0,1,2,88,5,170,0,1,2,88,5,170,0,1,2,138,5,220,0,1,2,88,5,120,0,1,2,88,5,120, + 0,1,2,138,5,220,0,1,2,88,5,120,0,1,2,88,5,120,0,1,2,138,4,226,0,1,2,88,4,126,0,1,2,88,4,126,0,1,2,188, + 2,238,0,1,2,188,2,238,0,1,4,188,8,52,0,1,1,83,8,52,0,1,1,83,8,52,0,1,2,188,3,182,0,1,1,43,4,176,0,1, + 1,43,4,176,0,1,2,188,4,176,0,1,2,38,3,82,0,1,1,29,5,240,0,1,1,29,5,240,0,1,1,29,5,240,0,1,2,73,5,240, + 0,1,2,73,5,240,0,1,2,73,5,240,0,1,1,171,5,240,0,1,1,171,5,240,0,1,1,171,5,240,0,1,2,94,5,240,0,1,2,94, + 5,240,0,1,2,94,5,240,0,1,2,157,5,240,0,1,2,157,5,240,0,1,2,157,5,240,0,1,2,157,5,240,0,1,2,157,5,240,0,1, + 2,157,5,240,0,1,2,96,5,240,0,1,2,96,5,240,0,1,2,96,5,240,0,1,2,157,5,240,0,1,2,157,5,240,0,1,2,157,5,240, + 0,1,1,224,5,240,0,1,1,224,5,240,0,1,1,224,5,240,0,1,2,19,5,240,0,1,2,19,5,240,0,1,2,19,5,240,0,1,1,110, + 5,240,0,1,1,110,5,240,0,1,1,110,5,240,0,1,1,22,5,240,0,1,1,22,5,240,0,1,1,22,5,240,0,1,2,167,5,240,0,1, + 2,167,5,240,0,1,2,167,5,240,0,1,1,169,5,240,0,1,1,169,5,240,0,1,1,169,5,240,0,1,3,203,5,240,0,1,3,203,5,240, + 0,1,3,203,5,240,0,1,1,221,5,240,0,1,1,221,5,240,0,1,1,221,5,240,0,1,3,35,5,240,0,1,3,35,5,240,0,1,3,35, + 5,240,0,1,2,157,5,242,0,1,2,157,5,242,0,1,2,157,5,242,0,1,2,128,5,242,0,1,2,128,5,242,0,1,2,128,5,242,0,1, + 3,2,5,240,0,1,3,2,5,240,0,1,3,2,5,240,0,1,3,26,5,240,0,1,3,26,5,240,0,1,3,26,5,240,0,1,2,148,5,240, + 0,1,2,148,5,240,0,1,2,148,5,240,0,1,1,221,5,240,0,1,1,221,5,240,0,1,1,221,5,240,0,1,2,128,5,242,0,1,2,128, + 5,242,0,1,2,128,5,242,0,1,2,89,5,240,0,1,2,89,5,240,0,1,2,89,5,240,0,1,3,26,5,240,0,1,3,26,5,240,0,1, + 3,26,5,240,0,1,3,26,5,240,0,1,3,26,5,240,0,1,3,26,5,240,0,1,2,27,5,240,0,1,2,27,5,240,0,1,2,27,5,240, + 0,1,2,89,5,240,0,1,2,89,5,240,0,1,2,89,5,240,0,1,2,89,5,240,0,1,2,89,5,240,0,1,2,89,5,240,0,1,1,144, + 3,232,0,1,1,144,3,232,0,1,1,194,6,64,0,1,1,194,5,170,0,1,1,194,5,220,0,1,2,188,2,238,0,1,2,188,2,238,0,1, + 2,188,2,238,0,1,2,188,3,232,0,1,2,188,4,226,0,1,2,88,3,32,0,1,3,82,4,26,0,1,3,82,4,26,0,1,2,88,3,32, + 0,1,2,138,3,132,0,1,2,138,3,132,0,1,2,88,3,32,0,1,3,82,4,226,0,1,3,82,4,226,0,1,2,88,3,32,0,1,2,38, + 3,32,0,1,2,38,3,32,0,1,2,88,3,32,0,1,2,88,4,226,0,1,2,88,4,226,0,1,2,91,6,114,0,1,1,83,6,114,0,1, + 1,83,6,114,0,1,1,244,5,120,0,1,1,244,6,114,0,1,1,238,5,120,0,1,2,188,4,76,0,1,1,244,4,76,0,1,2,6,3,182, + 0,1,2,188,4,76,0,1,1,244,5,70,0,1,2,6,4,176,0,1,2,188,4,76,0,1,1,244,4,76,0,1,2,6,3,182,0,1,1,244, + 3,82,0,1,1,244,5,70,0,1,2,6,4,176,0,1,1,244,3,82,0,1,1,244,6,64,0,1,2,6,5,170,0,1,1,244,5,120,0,1, + 0,120,5,120,0,1,0,120,5,120,0,1,1,244,5,120,0,1,0,250,6,14,0,1,0,250,6,14,0,1,3,57,6,14,0,1,1,19,6,164, + 0,1,1,19,6,164,0,1,2,188,5,220,0,1,0,250,6,14,0,1,0,250,6,14,0,1,1,244,5,120,0,1,0,250,6,164,0,1,0,250, + 6,164,0,1,1,244,5,120,0,1,0,250,6,164,0,1,0,250,6,164,0,1,1,244,5,120,0,1,1,19,8,102,0,1,1,19,8,102,0,1, + 4,188,8,52,0,1,1,83,8,52,0,1,1,83,8,52,0,1,4,188,8,102,0,1,1,83,8,102,0,1,1,83,8,102,0,1,2,138,5,20, + 0,1,1,83,6,114,0,1,1,83,6,114,0,1,2,138,2,238,0,1,1,43,4,26,0,1,1,43,4,26,0,1,2,138,2,238,0,1,1,43, + 4,26,0,1,1,43,4,26,0,1,2,188,3,232,0,1,1,43,5,20,0,1,1,43,5,20,0,2,0,15,5,39,5,39,0,0,5,49,5,49, + 0,1,5,58,5,58,0,2,5,79,5,114,0,3,5,142,5,143,0,39,5,146,5,220,0,41,5,241,6,14,0,116,19,223,20,64,0,146,20,85, + 20,216,0,244,22,202,22,212,1,120,22,214,22,231,1,131,23,3,23,11,1,149,23,13,23,13,1,158,23,32,23,121,1,159,23,135,23,219,1,249, + 0,1,0,30,5,31,5,75,5,115,5,116,5,118,5,119,5,121,5,122,5,123,5,124,5,126,5,127,5,144,6,15,6,16,6,17,6,18,6,19, + 6,20,6,21,6,23,19,178,23,24,23,25,23,26,23,27,23,28,23,29,23,30,23,31,0,30,0,0,0,122,0,0,0,128,0,0,0,134,0,0, + 0,140,0,0,0,146,0,0,0,152,0,0,0,158,0,0,0,164,0,0,0,170,0,0,0,176,0,0,0,182,0,0,0,188,0,0,0,194,0,0, + 0,200,0,0,0,206,0,0,0,212,0,0,0,218,0,0,0,224,0,0,0,230,0,0,0,236,0,0,0,242,0,0,0,248,0,0,0,254,0,0, + 1,4,0,0,1,10,0,0,1,16,0,0,1,22,0,0,1,28,0,0,1,34,0,0,1,40,0,1,2,143,4,96,0,1,2,0,4,176,0,1, + 2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176, + 0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,123,0,1,2,0,4,123,0,1,2,0, + 4,123,0,1,2,0,4,123,0,1,2,0,4,123,0,1,2,0,4,123,0,1,2,0,4,123,0,1,2,0,4,123,0,1,2,143,4,96,0,1, + 2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176,0,1,2,0,4,176, + 0,1,2,0,4,176,0,1,1,6,0,246,0,1,1,16,0,12,0,29,0,60,0,66,0,72,0,78,0,84,0,90,0,96,0,102,0,108,0,114, + 0,120,0,126,0,132,0,138,0,144,0,150,0,156,0,162,0,168,0,174,0,180,0,186,0,192,0,198,0,204,0,210,0,216,0,222,0,228,0,1, + 5,93,0,0,0,1,5,120,0,0,0,1,5,129,0,0,0,1,3,220,254,29,0,1,5,6,0,0,0,1,5,120,255,64,0,1,5,128,0,0, + 0,1,5,91,0,0,0,1,5,34,0,0,0,1,5,41,255,64,0,1,5,62,0,0,0,1,5,69,0,0,0,1,5,0,0,0,0,1,5,0, + 0,0,0,1,5,246,0,0,0,1,6,34,0,0,0,1,5,126,0,0,0,1,5,126,0,0,0,1,5,157,0,0,0,1,5,128,0,0,0,1, + 5,120,0,0,0,1,5,50,0,0,0,1,5,15,0,0,0,1,5,160,0,0,0,1,6,141,0,0,0,1,5,16,0,0,0,1,5,120,0,0, + 0,1,8,58,0,0,0,1,8,58,0,0,0,2,0,2,6,30,6,56,0,0,6,93,6,94,0,27,0,1,0,3,6,66,6,67,6,69,0,3, + 0,0,0,14,0,0,0,20,0,0,0,26,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,34,1,6,0,1,1,62, + 0,12,0,31,0,64,0,70,0,76,0,82,0,88,0,94,0,100,0,106,0,112,0,118,0,124,0,130,0,136,0,142,0,148,0,154,0,160,0,166, + 0,172,0,178,0,184,0,190,0,196,0,202,0,208,0,214,0,220,0,226,0,232,0,238,0,244,0,1,5,93,4,107,0,1,5,120,4,121,0,1, + 5,129,4,121,0,1,3,220,4,121,0,1,5,6,4,154,0,1,5,120,4,121,0,1,5,128,4,122,0,1,5,91,4,102,0,1,5,34,4,119, + 0,1,5,41,4,104,0,1,5,62,4,121,0,1,5,69,4,121,0,1,5,0,4,96,0,1,5,0,5,80,0,1,5,246,4,91,0,1,6,34, + 5,25,0,1,5,126,4,91,0,1,5,126,5,116,0,1,5,157,4,96,0,1,5,128,4,122,0,1,5,120,4,121,0,1,5,50,4,123,0,1, + 5,15,4,96,0,1,5,160,4,148,0,1,6,141,4,136,0,1,5,16,4,117,0,1,5,120,4,144,0,1,0,0,4,74,0,1,0,0,4,74, + 0,1,8,58,4,136,0,1,8,58,4,136,0,2,0,4,6,30,6,56,0,0,6,76,6,76,0,27,6,91,6,91,0,28,6,93,6,94,0,29, + 0,1,0,12,6,59,6,62,6,63,6,64,6,65,6,68,6,77,6,78,6,79,6,80,6,81,6,82,0,12,0,0,0,50,0,0,0,56,0,0, + 0,62,0,0,0,68,0,0,0,74,0,0,0,80,0,0,0,86,0,0,0,92,0,0,0,98,0,0,0,104,0,0,0,110,0,0,0,116,0,1, + 0,0,4,116,0,1,0,0,4,98,0,1,0,0,4,98,0,1,0,0,4,98,0,1,0,0,4,98,0,1,0,0,4,116,0,1,0,0,4,96, + 0,1,0,0,4,126,0,1,0,0,4,126,0,1,0,0,4,96,0,1,0,0,4,126,0,1,0,0,4,96,0,1,0,32,0,26,0,1,0,90, + 0,12,0,1,0,4,0,1,0,4,0,1,2,166,254,82,0,1,0,1,0,169,0,2,0,9,2,199,2,202,0,0,2,205,2,209,0,4,2,212, + 2,215,0,9,2,218,2,228,0,13,2,234,2,237,0,24,2,248,2,250,0,28,2,254,2,255,0,31,3,3,3,3,0,33,3,6,3,6,0,34, + 0,35,0,0,0,142,0,0,0,148,0,0,0,154,0,0,0,160,0,0,0,166,0,0,0,172,0,0,0,178,0,0,0,184,0,0,0,190,0,0, + 0,196,0,0,0,202,0,0,0,208,0,0,0,214,0,0,0,220,0,0,0,226,0,0,0,232,0,0,0,238,0,0,0,244,0,0,0,250,0,0, + 1,0,0,0,1,6,0,0,1,12,0,0,1,18,0,0,1,24,0,0,1,30,0,0,1,36,0,0,1,42,0,0,1,48,0,0,1,54,0,0, + 1,60,0,0,1,66,0,0,1,72,0,0,1,78,0,0,1,84,0,0,1,90,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,0,0, + 0,1,254,0,0,0,0,1,254,0,255,254,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0, + 255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1, + 254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255, + 0,1,254,0,255,255,0,1,254,0,255,254,0,1,254,0,255,255,0,1,254,2,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0, + 255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,5,140,4,182,0,1, + 5,148,0,12,0,149,1,44,1,50,1,56,1,62,1,68,1,74,1,80,1,86,1,92,1,98,1,104,1,110,1,116,1,122,1,128,1,134,1,140, + 1,146,1,152,1,158,1,164,1,170,1,176,1,182,1,188,1,194,1,200,1,206,1,212,1,218,1,224,1,230,1,236,1,242,1,248,1,254,2,4, + 2,10,2,16,2,22,2,28,2,34,2,40,2,46,2,52,2,58,2,64,2,70,2,76,2,82,2,88,2,94,2,100,2,106,2,112,2,118,2,124, + 2,130,2,136,2,142,2,148,2,154,2,160,2,166,2,172,2,178,2,184,2,190,2,196,2,202,2,208,2,214,2,220,2,226,2,232,2,238,2,244, + 2,250,3,0,3,6,3,12,3,18,3,24,3,30,3,36,3,42,3,48,3,54,3,60,3,66,3,72,3,78,3,84,3,90,3,96,3,102,3,108, + 3,114,3,120,3,126,3,132,3,138,3,144,3,150,3,156,3,162,3,168,3,174,3,180,3,186,3,192,3,198,3,204,3,210,3,216,3,222,3,228, + 3,234,3,240,3,246,3,252,4,2,4,8,4,14,4,20,4,26,4,32,4,38,4,44,4,50,4,56,4,62,4,68,4,74,4,80,4,86,4,92, + 4,98,4,104,4,110,4,116,4,122,4,128,4,134,4,140,4,146,4,152,4,158,4,164,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1, + 0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240, + 0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1, + 0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240, + 0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1, + 0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240, + 0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1, + 0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240, + 0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1, + 0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240, + 0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1, + 0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240, + 0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1, + 0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240, + 0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,1,0,0,5,240,0,2, + 0,35,0,36,0,61,0,0,0,68,0,93,0,26,0,154,0,154,0,52,0,186,0,186,0,53,0,198,0,199,0,54,0,208,0,209,0,56,0,243, + 0,243,0,58,1,40,1,41,0,59,1,65,1,65,0,61,1,72,1,72,0,62,1,81,1,82,0,63,1,89,1,89,0,65,1,97,1,97,0,66, + 1,121,1,123,0,67,2,18,2,18,0,70,2,22,2,22,0,71,2,27,2,27,0,72,2,29,2,29,0,73,2,42,2,42,0,74,2,55,2,55, + 0,75,2,84,2,84,0,76,8,204,8,204,0,77,9,3,9,12,0,78,17,225,17,227,0,88,17,230,17,231,0,91,17,237,17,237,0,93,17,241, + 17,242,0,94,18,254,19,1,0,96,19,7,19,17,0,100,19,20,19,29,0,111,19,31,19,35,0,121,19,40,19,43,0,126,19,50,19,62,0,130, + 19,64,19,68,0,143,22,234,22,234,0,148,0,1,0,2,20,82,20,84,0,2,0,0,0,10,0,0,0,16,0,1,0,0,5,240,0,1,0,0, + 5,240,0,1,0,98,0,78,0,1,0,106,0,12,0,8,0,18,0,24,0,30,0,36,0,42,0,48,0,54,0,60,0,1,2,74,6,20,0,1, + 2,236,7,109,0,1,2,150,6,20,0,1,1,31,6,20,0,1,2,115,6,20,0,1,2,125,6,20,0,1,2,236,7,80,0,1,3,254,7,137, + 0,1,0,8,0,195,0,208,0,213,0,237,1,15,1,45,9,3,9,4,0,1,0,2,2,177,2,178,0,2,0,0,0,10,0,0,0,16,0,1, + 254,0,4,123,0,1,254,0,4,123,0,1,3,140,2,214,0,1,3,146,0,12,0,89,0,180,0,186,0,192,0,198,0,204,0,210,0,216,0,222, + 0,228,0,234,0,240,0,246,0,252,1,2,1,8,1,14,1,20,1,26,1,32,1,38,1,44,1,50,1,56,1,62,1,68,1,74,1,80,1,86, + 1,92,1,98,1,104,1,110,1,116,1,122,1,128,1,134,1,140,1,146,1,152,1,158,1,164,1,170,1,176,1,182,1,188,1,194,1,200,1,206, + 1,212,1,218,1,224,1,230,1,236,1,242,1,248,1,254,2,4,2,10,2,16,2,22,2,28,2,34,2,40,2,46,2,52,2,58,2,64,2,70, + 2,76,2,82,2,88,2,94,2,100,2,106,2,112,2,118,2,124,2,130,2,136,2,142,2,148,2,154,2,160,2,166,2,172,2,178,2,184,2,190, + 2,196,0,1,4,255,0,0,0,1,3,76,0,0,0,1,2,45,0,0,0,1,2,158,0,0,0,1,1,46,0,0,0,1,1,47,0,0,0,1, + 1,43,0,0,0,1,1,43,0,0,0,1,3,39,0,0,0,1,2,162,0,0,0,1,2,238,0,0,0,1,2,190,0,0,0,1,3,209,0,0, + 0,1,2,166,0,0,0,1,2,102,0,0,0,1,2,150,0,0,0,1,1,22,0,0,0,1,1,31,0,0,0,1,1,22,0,0,0,1,1,22, + 0,0,0,1,2,115,0,0,0,1,2,46,0,0,0,1,2,125,0,0,0,1,2,23,0,0,0,1,1,47,0,0,0,1,1,47,0,0,0,1, + 1,47,0,0,0,1,1,47,0,0,0,1,3,39,0,0,0,1,1,31,0,0,0,1,1,31,0,0,0,1,1,31,0,0,0,1,1,31,0,0, + 0,1,2,115,0,0,0,1,3,209,0,0,0,1,4,255,254,128,0,1,3,209,254,128,0,1,2,150,0,0,0,1,1,47,0,0,0,1,1,31, + 0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1, + 2,115,0,0,0,1,2,125,0,0,0,1,2,92,0,0,0,1,3,39,0,0,0,1,2,196,0,0,0,1,1,47,0,0,0,1,3,39,0,0, + 0,1,2,190,0,0,0,1,2,150,0,0,0,1,2,136,254,82,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31, + 0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,2,135,0,0,0,1,1,194,0,0,0,1,2,82,0,0,0,1,2,74,0,0,0,1, + 1,30,0,0,0,1,2,115,0,0,0,1,2,23,254,82,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31,0,0, + 0,1,3,39,0,0,0,1,2,115,0,0,0,1,6,123,0,0,0,1,5,121,0,0,0,1,6,53,0,0,0,1,5,68,0,0,0,1,3,59, + 0,0,0,1,2,205,0,0,0,1,1,43,0,0,0,1,1,22,0,0,0,1,2,162,0,0,0,1,2,46,0,0,0,1,1,146,0,0,0,1, + 1,47,0,0,0,1,1,30,0,0,0,1,2,125,254,82,0,1,0,89,0,36,0,38,0,39,0,40,0,43,0,44,0,48,0,49,0,50,0,54, + 0,56,0,61,0,68,0,70,0,71,0,72,0,75,0,76,0,80,0,81,0,82,0,86,0,88,0,93,0,142,0,143,0,144,0,145,0,154,0,174, + 0,175,0,176,0,177,0,186,0,195,0,198,0,199,0,213,0,234,0,235,0,236,0,237,0,238,0,239,0,242,0,243,1,15,1,45,1,72,1,81, + 1,82,1,89,1,97,1,121,1,122,1,123,1,145,1,146,1,202,1,203,1,204,1,205,2,18,2,22,2,27,2,29,2,42,2,55,2,84,9,39, + 9,40,9,193,9,194,17,225,17,237,19,8,19,9,19,10,19,11,19,26,19,27,19,56,19,57,19,60,19,61,19,62,19,67,22,234,23,134,0,1, + 0,1,2,216,0,1,0,0,0,6,0,1,254,23,0,0,0,1,15,200,13,150,0,1,16,2,0,12,1,177,3,100,3,106,3,112,3,118,3,124, + 3,130,3,136,3,142,3,148,3,154,3,160,3,166,3,172,3,178,3,184,3,190,3,196,3,202,3,208,3,214,3,220,3,226,3,232,3,238,3,244, + 3,250,4,0,4,6,4,12,4,18,4,24,4,30,4,36,4,42,4,48,4,54,4,60,4,66,4,72,4,78,4,84,4,90,4,96,4,102,4,108, + 4,114,4,120,4,126,4,132,4,138,4,144,4,150,4,156,4,162,4,168,4,174,4,180,4,186,4,192,4,198,4,204,4,210,4,216,4,222,4,228, + 4,234,4,240,4,246,4,252,5,2,5,8,5,14,5,20,5,26,5,32,5,38,5,44,5,50,5,56,5,62,5,68,5,74,5,80,5,86,5,92, + 5,98,5,104,5,110,5,116,5,122,5,128,5,134,5,140,5,146,5,152,5,158,5,164,5,170,5,176,5,182,5,188,5,194,5,200,5,206,5,212, + 5,218,5,224,5,230,5,236,5,242,5,248,5,254,6,4,6,10,6,16,6,22,6,28,6,34,6,40,6,46,6,52,6,58,6,64,6,70,6,76, + 6,82,6,88,6,94,6,100,6,106,6,112,6,118,6,124,6,130,6,136,6,142,6,148,6,154,6,160,6,166,6,172,6,178,6,184,6,190,6,196, + 6,202,6,208,6,214,6,220,6,226,6,232,6,238,6,244,6,250,7,0,7,6,7,12,7,18,7,24,7,30,7,36,7,42,7,48,7,54,7,60, + 7,66,7,72,7,78,7,84,7,90,7,96,7,102,7,108,7,114,7,120,7,126,7,132,7,138,7,144,7,150,7,156,7,162,7,168,7,174,7,180, + 7,186,7,192,7,198,7,204,7,210,7,216,7,222,7,228,7,234,7,240,7,246,7,252,8,2,8,8,8,14,8,20,8,26,8,32,8,38,8,44, + 8,50,8,56,8,62,8,68,8,74,8,80,8,86,8,92,8,98,8,104,8,110,8,116,8,122,8,128,8,134,8,140,8,146,8,152,8,158,8,164, + 8,170,8,176,8,182,8,188,8,194,8,200,8,206,8,212,8,218,8,224,8,230,8,236,8,242,8,248,8,254,9,4,9,10,9,16,9,22,9,28, + 9,34,9,40,9,46,9,52,9,58,9,64,9,70,9,76,9,82,9,88,9,94,9,100,9,106,9,112,9,118,9,124,9,130,9,136,9,142,9,148, + 9,154,9,160,9,166,9,172,9,178,9,184,9,190,9,196,9,202,9,208,9,214,9,220,9,226,9,232,9,238,9,244,9,250,10,0,10,6,10,12, + 10,18,10,24,10,30,10,36,10,42,10,48,10,54,10,60,10,66,10,72,10,78,10,84,10,90,10,96,10,102,10,108,10,114,10,120,10,126,10,132, + 10,138,10,144,10,150,10,156,10,162,10,168,10,174,10,180,10,186,10,192,10,198,10,204,10,210,10,216,10,222,10,228,10,234,10,240,10,246,10,252, + 11,2,11,8,11,14,11,20,11,26,11,32,11,38,11,44,11,50,11,56,11,62,11,68,11,74,11,80,11,86,11,92,11,98,11,104,11,110,11,116, + 11,122,11,128,11,134,11,140,11,146,11,152,11,158,11,164,11,170,11,176,11,182,11,188,11,194,11,200,11,206,11,212,11,218,11,224,11,230,11,236, + 11,242,11,248,11,254,12,4,12,10,12,16,12,22,12,28,12,34,12,40,12,46,12,52,12,58,12,64,12,70,12,76,12,82,12,88,12,94,12,100, + 12,106,12,112,12,118,12,124,12,130,12,136,12,142,12,148,12,154,12,160,12,166,12,172,12,178,12,184,12,190,12,196,12,202,12,208,12,214,12,220, + 12,226,12,232,12,238,12,244,12,250,13,0,13,6,13,12,13,18,13,24,13,30,13,36,13,42,13,48,13,54,13,60,13,66,13,72,13,78,13,84, + 13,90,13,96,13,102,13,108,13,114,13,120,13,126,13,132,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0, + 0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,188, + 0,0,0,1,2,188,0,0,0,1,3,76,0,0,0,1,2,236,0,0,0,1,2,158,0,0,0,1,2,158,0,0,0,1,3,92,0,0,0,1, + 3,2,0,0,0,1,1,47,0,0,0,1,1,46,254,82,0,1,2,158,0,0,0,1,2,153,0,0,0,1,3,115,0,0,0,1,2,245,0,0, + 0,1,3,39,0,0,0,1,2,158,0,0,0,1,3,39,0,0,0,1,2,125,0,0,0,1,2,147,0,0,0,1,2,115,0,0,0,1,2,238, + 0,0,0,1,2,188,0,0,0,1,3,245,0,0,0,1,2,205,0,0,0,1,2,114,0,0,0,1,2,190,0,0,0,1,2,74,0,0,0,1, + 2,183,0,0,0,1,2,164,0,0,0,1,2,102,0,0,0,1,2,150,0,0,0,1,1,59,0,0,0,1,2,166,254,82,0,1,2,166,0,0, + 0,1,1,31,0,0,0,1,1,31,254,82,0,1,2,166,0,0,0,1,1,22,0,0,0,1,3,233,0,0,0,1,2,166,0,0,0,1,2,115, + 0,0,0,1,2,166,254,82,0,1,2,136,254,82,0,1,2,23,0,0,0,1,2,37,0,0,0,1,1,244,0,0,0,1,2,125,0,0,0,1, + 2,94,0,0,0,1,3,71,0,0,0,1,2,98,0,0,0,1,2,96,254,82,0,1,2,23,0,0,0,1,1,47,0,0,0,1,1,47,0,0, + 0,1,1,47,0,0,0,1,1,47,0,0,0,1,3,39,0,0,0,1,3,227,0,0,0,1,1,31,0,0,0,1,1,31,0,0,0,1,1,31, + 0,0,0,1,1,31,0,0,0,1,2,125,0,0,0,1,2,115,0,0,0,1,2,74,0,0,0,1,4,255,254,128,0,1,3,209,254,128,0,1, + 2,236,0,0,0,1,2,102,0,0,0,1,2,150,0,0,0,1,2,208,0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0, + 0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,2,166,0,0,0,1,2,137, + 254,82,0,1,2,115,0,0,0,1,2,115,0,0,0,1,1,244,0,0,0,1,2,125,0,0,0,1,1,59,0,0,0,1,2,183,0,0,0,1, + 2,92,0,0,0,1,2,102,0,0,0,1,3,39,0,0,0,1,2,196,0,0,0,1,1,55,254,82,0,1,1,47,0,0,0,1,3,39,0,0, + 0,1,1,22,254,122,0,1,2,96,254,82,0,1,2,190,0,0,0,1,2,150,0,0,0,1,2,136,254,82,0,1,1,47,0,0,0,1,1,31, + 0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,15,0,0,0,1,2,166,0,0,0,1, + 1,244,0,0,0,1,2,188,0,0,0,1,2,238,0,0,0,1,2,188,0,0,0,1,2,158,0,0,0,1,2,148,0,0,0,1,1,46,254,82, + 0,1,1,31,254,82,0,1,3,39,0,0,0,1,2,125,0,0,0,1,2,23,0,0,0,1,2,114,0,0,0,1,2,96,254,82,0,1,2,135, + 0,0,0,1,2,84,0,0,0,1,2,214,0,0,0,1,2,141,0,0,0,1,1,194,0,0,0,1,2,166,0,0,0,1,2,84,254,82,0,1, + 2,84,0,0,0,1,2,99,0,0,0,1,2,82,0,0,0,1,2,82,0,0,0,1,2,74,0,0,0,1,2,64,0,0,0,1,2,64,0,0, + 0,1,2,238,0,0,0,1,1,31,254,82,0,1,2,106,254,82,0,1,2,106,254,82,0,1,2,166,0,0,0,1,2,98,254,82,0,1,2,98, + 0,0,0,1,2,125,254,82,0,1,2,166,0,0,0,1,2,166,254,82,0,1,1,30,0,0,0,1,1,7,0,0,0,1,1,128,0,0,0,1, + 1,153,0,0,0,1,1,254,0,0,0,1,1,22,254,82,0,1,2,238,254,82,0,1,3,233,0,0,0,1,3,233,254,82,0,1,3,233,254,82, + 0,1,2,137,254,82,0,1,2,137,254,82,0,1,2,137,0,0,0,1,2,115,0,0,0,1,4,141,0,0,0,1,2,233,0,0,0,1,2,166, + 254,82,0,1,2,53,0,0,0,1,2,53,0,0,0,1,2,53,254,82,0,1,1,28,254,82,0,1,2,97,254,82,0,1,1,131,0,0,0,1, + 2,116,0,0,0,1,2,59,0,0,0,1,2,81,0,0,0,1,2,39,254,82,0,1,1,22,254,82,0,1,1,22,254,82,0,1,1,241,254,82, + 0,1,1,22,254,82,0,1,2,14,254,82,0,1,1,244,254,82,0,1,2,125,0,0,0,1,2,125,0,0,0,1,2,94,0,0,0,1,3,71, + 0,0,0,1,2,94,0,0,0,1,2,100,0,0,0,1,2,23,254,82,0,1,2,23,0,0,0,1,2,23,254,82,0,1,2,23,254,82,0,1, + 1,176,0,0,0,1,2,58,0,0,0,1,1,176,0,0,0,1,2,58,254,82,0,1,3,39,0,0,0,1,2,97,0,0,0,1,2,72,0,0, + 0,1,2,166,0,0,0,1,2,163,255,246,0,1,1,31,254,82,0,1,2,171,254,82,0,1,2,95,0,0,0,1,2,136,254,82,0,1,1,176, + 0,0,0,1,2,58,0,0,0,1,3,254,0,0,0,1,3,254,254,82,0,1,3,254,0,0,0,1,3,71,254,82,0,1,4,142,0,0,0,1, + 3,32,254,82,0,1,1,22,0,0,0,1,2,126,254,82,0,1,2,74,0,0,0,1,2,125,0,0,0,1,3,39,0,0,0,1,1,47,0,0, + 0,1,1,31,0,0,0,1,1,31,0,0,0,1,3,39,0,0,0,1,2,125,0,0,0,1,2,158,0,0,0,1,2,166,0,0,0,1,3,2, + 0,0,0,1,3,39,0,0,0,1,2,125,0,0,0,1,2,94,0,0,0,1,2,26,0,0,0,1,2,84,0,0,0,1,2,166,0,0,0,1, + 2,84,0,0,0,1,2,84,0,0,0,1,2,25,0,0,0,1,2,64,0,0,0,1,2,166,0,0,0,1,2,88,0,0,0,1,3,5,0,0, + 0,1,2,130,0,0,0,1,2,125,0,0,0,1,1,177,0,0,0,1,2,189,0,0,0,1,2,189,0,0,0,1,2,189,0,0,0,1,2,22, + 0,0,0,1,2,144,0,0,0,1,2,144,0,0,0,1,2,84,0,0,0,1,2,103,0,0,0,1,2,94,0,0,0,1,3,71,0,0,0,1, + 2,23,0,0,0,1,1,254,0,0,0,1,2,88,0,0,0,1,2,94,0,0,0,1,2,166,254,82,0,1,2,236,0,0,0,1,2,102,0,0, + 0,1,2,236,254,137,0,1,2,102,254,137,0,1,2,236,254,191,0,1,2,102,254,191,0,1,2,236,254,116,0,1,2,102,254,116,0,1,2,236, + 254,21,0,1,2,102,254,21,0,1,1,47,0,0,0,1,1,31,0,0,0,1,1,47,0,0,0,1,1,31,0,0,0,1,3,147,0,0,0,1, + 1,232,0,0,0,1,3,76,0,0,0,1,4,66,0,0,0,1,3,82,254,82,0,1,3,102,0,0,0,1,2,14,0,0,0,1,1,214,0,0, + 0,1,2,222,0,0,0,1,3,44,0,0,0,1,3,52,0,0,0,1,3,36,254,82,0,1,3,14,0,0,0,1,3,39,0,0,0,1,3,132, + 0,0,0,1,3,152,0,0,0,1,3,95,0,0,0,1,2,250,0,0,0,1,2,122,254,82,0,1,3,102,0,0,0,1,3,52,0,0,0,1, + 1,247,0,0,0,1,2,198,0,0,0,1,3,142,0,0,0,1,4,76,0,0,0,1,3,22,0,0,0,1,2,198,0,0,0,1,1,243,0,8, + 0,1,2,157,0,7,0,1,1,125,0,0,0,1,2,247,0,0,0,1,3,96,254,82,0,1,2,252,0,0,0,1,3,101,0,0,0,1,2,183, + 0,0,0,1,2,153,0,0,0,1,2,153,0,0,0,1,2,158,0,0,0,1,2,84,0,0,0,1,1,244,0,0,0,1,3,2,0,0,0,1, + 2,166,0,0,0,1,2,158,0,0,0,1,2,166,0,0,0,1,2,190,0,0,0,1,2,23,0,0,0,1,3,39,0,0,0,1,3,115,254,82, + 0,1,2,188,0,0,0,1,2,195,255,228,0,1,2,94,0,0,0,1,3,245,0,0,0,1,3,71,0,0,0,1,2,94,0,0,0,1,3,2, + 0,0,0,1,2,163,0,0,0,1,2,53,0,0,0,1,2,115,0,0,0,1,1,212,0,0,0,1,2,147,254,82,0,1,2,190,254,82,0,1, + 1,47,0,0,0,1,3,2,254,82,0,1,2,137,254,82,0,1,3,119,254,82,0,1,2,158,254,82,0,1,2,74,254,86,0,1,2,25,0,0, + 0,1,5,0,0,0,0,1,3,209,0,0,0,1,4,49,0,0,0,1,3,215,0,0,0,1,4,197,0,0,0,1,3,209,0,0,0,1,3,252, + 0,0,0,1,3,118,0,0,0,1,3,252,0,0,0,1,3,118,255,246,0,1,3,252,0,0,0,1,3,118,254,82,0,1,2,158,0,0,0,1, + 2,174,0,0,0,1,3,149,0,0,0,1,1,146,0,0,0,1,2,203,0,0,0,1,1,174,0,0,0,1,3,59,0,0,0,1,2,205,0,0, + 0,1,5,110,0,0,0,1,4,19,0,0,0,1,2,158,0,0,0,1,2,166,254,82,0,1,3,170,0,0,0,1,3,196,254,82,0,1,3,39, + 0,0,0,1,2,136,254,82,0,1,1,219,0,0,0,1,1,31,254,82,0,1,3,13,254,82,0,1,2,166,254,82,0,1,1,247,254,82,0,1, + 2,245,0,0,0,1,2,166,0,0,0,1,3,92,0,0,0,1,2,166,254,82,0,1,2,158,0,0,0,1,2,166,0,0,0,1,2,245,0,0, + 0,1,2,166,0,0,0,1,2,125,0,0,0,1,2,23,0,0,0,1,2,147,0,0,0,1,2,37,0,0,0,1,3,102,0,0,0,1,3,169, + 0,0,0,1,2,76,0,0,0,1,2,53,0,0,0,1,3,115,0,0,0,1,1,47,0,0,0,1,4,204,0,0,0,1,2,245,0,0,0,1, + 2,238,0,0,0,1,3,60,0,0,0,1,3,7,0,0,0,1,3,7,0,0,0,1,3,92,0,0,0,1,1,146,0,0,0,1,1,145,254,82, + 0,1,3,2,0,0,0,1,2,244,0,0,0,1,4,25,0,0,0,1,3,38,0,0,0,1,2,129,0,0,0,1,2,213,0,0,0,1,3,82, + 0,0,0,1,2,228,0,0,0,1,4,120,0,0,0,1,3,57,0,0,0,1,2,212,0,0,0,1,2,180,0,0,0,1,2,92,0,0,0,1, + 2,139,0,0,0,1,2,139,0,0,0,1,2,119,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0, + 0,1,2,139,0,0,0,1,2,139,0,0,0,1,2,139,0,0,0,1,1,30,0,0,0,1,1,31,254,82,0,1,1,138,0,1,0,1,1,22, + 0,0,0,1,1,199,0,0,0,1,2,125,254,82,0,2,0,93,0,19,0,28,0,0,0,36,0,61,0,10,0,68,0,93,0,36,0,142,0,145, + 0,62,0,154,0,154,0,66,0,168,0,168,0,67,0,174,0,178,0,68,0,186,0,186,0,73,0,195,0,195,0,74,0,198,0,199,0,75,0,208, + 0,209,0,77,0,213,0,213,0,79,0,233,0,239,0,80,0,242,0,243,0,87,0,250,0,250,0,89,1,13,1,13,0,90,1,15,1,15,0,91, + 1,40,1,41,0,92,1,45,1,45,0,94,1,65,1,65,0,95,1,69,1,69,0,96,1,72,1,72,0,97,1,78,1,78,0,98,1,81,1,82, + 0,99,1,84,1,84,0,101,1,89,1,89,0,102,1,97,1,97,0,103,1,108,1,108,0,104,1,118,1,118,0,105,1,121,1,123,0,106,1,145, + 1,146,0,109,1,202,1,205,0,111,1,246,1,248,0,115,2,5,2,12,0,118,2,14,2,74,0,126,2,76,2,103,0,187,2,105,2,107,0,215, + 2,109,2,109,0,218,3,70,3,70,0,219,3,73,3,73,0,220,3,76,3,76,0,221,3,136,3,136,0,222,3,154,3,154,0,223,3,234,3,235, + 0,224,4,6,4,7,0,226,4,34,4,34,0,228,4,51,4,51,0,229,4,54,4,54,0,230,4,124,4,125,0,231,8,99,8,100,0,233,8,102, + 8,107,0,235,8,110,8,118,0,241,8,122,8,126,0,250,8,130,8,135,0,255,8,204,8,204,1,5,9,3,9,12,1,6,9,39,9,40,1,16, + 9,193,9,194,1,18,9,243,9,244,1,20,11,149,11,149,1,22,11,157,11,160,1,23,11,162,11,164,1,27,11,167,11,167,1,30,11,170,11,175, + 1,31,11,182,11,182,1,37,11,186,11,186,1,38,11,190,11,191,1,39,11,193,11,195,1,41,11,197,11,197,1,44,11,199,11,203,1,45,11,206, + 11,209,1,50,13,198,13,198,1,54,17,212,17,212,1,55,17,214,17,215,1,56,17,217,17,234,1,58,17,236,17,238,1,76,17,241,17,242,1,79, + 18,56,18,56,1,81,18,254,19,1,1,82,19,3,19,4,1,86,19,6,19,17,1,88,19,20,19,35,1,100,19,40,19,43,1,116,19,49,19,68, + 1,120,21,97,21,115,1,140,21,139,21,139,1,159,21,141,21,141,1,160,21,194,21,203,1,161,22,234,22,235,1,171,23,2,23,2,1,173,23,12, + 23,12,1,174,23,22,23,22,1,175,23,134,23,134,1,176,0,2,0,9,2,199,2,202,0,0,2,205,2,209,0,4,2,212,2,215,0,9,2,218, + 2,228,0,13,2,234,2,237,0,24,2,248,2,250,0,28,2,254,2,255,0,31,3,3,3,3,0,33,3,6,3,6,0,34,0,35,0,0,0,142, + 0,0,0,148,0,0,0,154,0,0,0,160,0,0,0,166,0,0,0,172,0,0,0,178,0,0,0,184,0,0,0,190,0,0,0,196,0,0,0,202, + 0,0,0,208,0,0,0,214,0,0,0,220,0,0,0,226,0,0,0,232,0,0,0,238,0,0,0,244,0,0,0,250,0,0,1,0,0,0,1,6, + 0,0,1,12,0,0,1,18,0,0,1,24,0,0,1,30,0,0,1,36,0,0,1,42,0,0,1,48,0,0,1,54,0,0,1,60,0,0,1,66, + 0,0,1,72,0,0,1,78,0,0,1,84,0,0,1,90,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,0,0,0,1,254,0,0,0, + 0,1,254,0,255,254,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0, + 255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1, + 254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255, + 0,1,254,0,255,254,0,1,254,0,255,255,0,1,254,2,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0, + 255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,254,0,255,255,0,1,22,56,19,106,0,1,22,132,0,12,2,103, + 4,208,4,214,4,220,4,226,4,232,4,238,4,244,4,250,5,0,5,6,5,12,5,18,5,24,5,30,5,36,5,42,5,48,5,54,5,60,5,66, + 5,72,5,78,5,84,5,90,5,96,5,102,5,108,5,114,5,120,5,126,5,132,5,138,5,144,5,150,5,156,5,162,5,168,5,176,5,182,5,190, + 5,196,5,204,5,210,5,216,5,222,5,228,5,234,5,240,5,246,5,252,6,2,6,10,6,16,6,22,6,28,6,34,6,40,6,48,6,54,6,60, + 6,66,6,72,6,78,6,84,6,90,6,96,6,102,6,110,6,116,6,122,6,130,6,136,6,142,6,148,6,156,6,162,6,168,6,174,6,180,6,186, + 6,192,6,198,6,204,6,210,6,216,6,222,6,228,6,234,6,240,6,246,6,252,7,2,7,8,7,14,7,20,7,26,7,32,7,38,7,44,7,50, + 7,56,7,62,7,68,7,74,7,80,7,86,7,92,7,98,7,104,7,110,7,116,7,122,7,128,7,134,7,140,7,146,7,152,7,158,7,164,7,170, + 7,176,7,182,7,188,7,194,7,200,7,206,7,212,7,218,7,224,7,230,7,236,7,242,7,248,7,254,8,4,8,10,8,16,8,22,8,30,8,36, + 8,42,8,48,8,54,8,60,8,66,8,74,8,80,8,86,8,92,8,98,8,104,8,110,8,116,8,122,8,128,8,134,8,140,8,146,8,152,8,158, + 8,164,8,170,8,176,8,182,8,188,8,194,8,200,8,206,8,212,8,218,8,224,8,232,8,238,8,244,8,250,9,0,9,6,9,12,9,18,9,24, + 9,30,9,36,9,42,9,48,9,54,9,60,9,66,9,72,9,78,9,84,9,90,9,96,9,102,9,108,9,114,9,120,9,126,9,132,9,138,9,144, + 9,150,9,156,9,162,9,168,9,174,9,180,9,186,9,192,9,198,9,204,9,210,9,216,9,222,9,228,9,234,9,240,9,246,9,252,10,2,10,8, + 10,14,10,20,10,26,10,32,10,38,10,44,10,50,10,58,10,64,10,70,10,76,10,82,10,88,10,94,10,100,10,106,10,112,10,118,10,124,10,130, + 10,136,10,142,10,148,10,154,10,160,10,166,10,172,10,178,10,184,10,190,10,196,10,202,10,208,10,214,10,220,10,226,10,232,10,238,10,244,10,250, + 11,0,11,6,11,12,11,18,11,24,11,30,11,36,11,42,11,48,11,54,11,60,11,66,11,72,11,78,11,84,11,90,11,96,11,102,11,108,11,114, + 11,120,11,126,11,132,11,138,11,144,11,150,11,156,11,162,11,168,11,174,11,180,11,186,11,192,11,198,11,204,11,210,11,216,11,222,11,228,11,234, + 11,240,11,246,11,252,12,2,12,8,12,14,12,20,12,26,12,32,12,38,12,44,12,50,12,56,12,62,12,68,12,74,12,80,12,86,12,92,12,98, + 12,104,12,110,12,116,12,122,12,128,12,134,12,140,12,146,12,152,12,158,12,164,12,170,12,176,12,182,12,188,12,194,12,200,12,206,12,212,12,218, + 12,224,12,230,12,236,12,242,12,248,12,254,13,4,13,10,13,16,13,22,13,28,13,34,13,40,13,46,13,52,13,58,13,64,13,70,13,76,13,82, + 13,88,13,94,13,100,13,106,13,112,13,118,13,124,13,130,13,136,13,142,13,148,13,154,13,160,13,166,13,172,13,178,13,184,13,190,13,196,13,202, + 13,208,13,214,13,220,13,226,13,232,13,238,13,244,13,250,14,0,14,6,14,12,14,18,14,24,14,30,14,36,14,42,14,48,14,54,14,60,14,66, + 14,72,14,78,14,84,14,90,14,96,14,102,14,108,14,114,14,120,14,126,14,132,14,138,14,144,14,150,14,156,14,162,14,168,14,174,14,180,14,186, + 14,192,14,198,14,204,14,210,14,216,14,222,14,228,14,234,14,240,14,246,14,252,15,2,15,10,15,16,15,22,15,28,15,34,15,40,15,46,15,52, + 15,58,15,64,15,70,15,78,15,84,15,90,15,96,15,102,15,108,15,114,15,120,15,126,15,132,15,138,15,144,15,150,15,156,15,162,15,168,15,174, + 15,180,15,186,15,192,15,198,15,204,15,210,15,216,15,222,15,228,15,234,15,240,15,246,15,252,16,2,16,8,16,14,16,20,16,26,16,32,16,38, + 16,44,16,50,16,56,16,62,16,68,16,74,16,80,16,86,16,92,16,98,16,104,16,110,16,116,16,122,16,128,16,134,16,140,16,146,16,152,16,158, + 16,164,16,170,16,176,16,182,16,188,16,194,16,200,16,206,16,212,16,218,16,224,16,230,16,236,16,242,16,248,16,254,17,4,17,10,17,18,17,24, + 17,30,17,36,17,42,17,48,17,54,17,60,17,66,17,72,17,78,17,84,17,90,17,96,17,102,17,108,17,114,17,120,17,126,17,132,17,138,17,146, + 17,152,17,158,17,164,17,170,17,176,17,182,17,188,17,194,17,200,17,206,17,212,17,220,17,226,17,232,17,238,17,244,17,250,18,0,18,6,18,12, + 18,18,18,24,18,30,18,36,18,42,18,48,18,54,18,60,18,66,18,72,18,78,18,84,18,90,18,96,18,102,18,108,18,114,18,120,18,126,18,132, + 18,138,18,144,18,150,18,156,18,162,18,168,18,174,18,180,18,186,18,192,18,198,18,204,18,210,18,216,18,222,18,228,18,234,18,240,18,246,18,252, + 19,2,19,8,19,14,19,20,19,26,19,32,19,38,19,44,19,50,19,56,19,62,19,68,19,74,19,80,19,86,0,1,2,139,5,240,0,1,2,139, + 5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1, + 2,139,5,240,0,1,2,139,5,240,0,1,2,188,5,240,0,1,2,188,5,240,0,1,3,76,5,240,0,1,2,236,5,240,0,1,2,158,5,240, + 0,1,2,158,5,240,0,1,3,92,5,240,0,1,3,2,5,240,0,1,1,47,5,240,0,1,1,46,5,240,0,1,2,158,5,240,0,1,1,42, + 5,240,0,1,3,115,5,240,0,1,2,245,5,240,0,1,3,39,5,240,0,1,2,158,5,240,0,1,3,39,5,240,0,1,2,125,5,240,0,1, + 2,147,5,240,0,1,2,115,5,240,0,1,2,238,5,240,0,1,2,188,5,240,0,1,3,245,5,240,0,1,2,205,5,240,0,1,2,114,5,240, + 0,1,2,190,5,240,0,2,2,74,4,123,0,35,0,1,1,22,5,240,0,2,2,164,4,123,0,23,0,1,3,254,5,240,0,2,2,150,4,123, + 0,18,0,1,1,224,5,240,0,1,2,106,4,123,0,1,1,22,5,240,0,1,1,31,6,47,0,1,1,31,6,47,0,1,1,22,5,240,0,1, + 1,22,5,240,0,1,3,233,4,123,0,1,2,137,4,123,0,2,2,115,4,123,0,12,0,1,2,166,4,123,0,1,2,111,4,123,0,1,2,23, + 4,123,0,1,2,39,4,123,0,1,1,26,5,240,0,2,2,125,4,123,0,20,0,1,2,94,4,123,0,1,3,71,4,123,0,1,2,98,4,123, + 0,1,2,96,4,123,0,1,2,23,4,123,0,1,3,39,5,240,0,1,3,227,4,123,0,1,2,166,4,123,0,1,2,125,5,240,0,2,2,115, + 4,123,0,26,0,1,1,22,5,240,0,1,2,188,5,240,0,2,2,74,4,123,0,35,0,1,3,254,5,240,0,1,3,170,5,240,0,1,1,81, + 5,240,0,2,1,29,4,123,0,4,0,1,2,166,4,123,0,1,2,137,4,123,0,1,4,20,4,123,0,1,2,115,5,240,0,1,1,26,5,240, + 0,1,2,125,4,123,0,1,1,224,5,240,0,1,1,22,5,240,0,1,1,22,5,240,0,1,2,92,5,240,0,1,3,76,5,240,0,1,3,254, + 5,240,0,1,2,88,5,240,0,1,3,39,5,240,0,1,2,196,5,240,0,1,2,158,5,240,0,1,1,59,5,240,0,1,3,92,5,240,0,1, + 2,191,5,240,0,1,1,47,5,240,0,1,1,47,5,240,0,1,1,23,5,240,0,1,1,22,5,240,0,1,2,130,5,240,0,1,2,245,5,240, + 0,1,3,39,5,240,0,1,3,2,5,240,0,1,2,192,5,240,0,1,2,39,4,123,0,1,1,22,5,240,0,1,1,26,5,240,0,1,2,115, + 5,240,0,1,1,26,5,240,0,1,2,115,5,240,0,1,2,167,5,240,0,1,2,114,5,240,0,1,2,96,4,123,0,1,2,190,5,240,0,1, + 2,23,4,123,0,1,2,190,5,240,0,1,2,150,5,240,0,1,2,136,4,123,0,1,3,39,5,240,0,1,1,15,5,240,0,1,2,137,4,123, + 0,1,1,26,5,240,0,1,1,31,4,123,0,1,2,188,5,240,0,1,2,238,5,240,0,1,2,188,5,240,0,1,2,158,5,240,0,1,2,141, + 4,123,0,1,1,46,5,240,0,1,1,31,6,47,0,1,3,39,5,240,0,1,2,125,5,240,0,1,2,23,4,123,0,1,2,114,5,240,0,1, + 2,96,4,123,0,1,2,135,4,123,0,1,2,84,4,123,0,1,2,214,4,123,0,1,1,22,5,240,0,2,1,206,4,123,0,3,0,1,2,166, + 4,123,0,1,3,254,5,240,0,1,3,254,5,240,0,1,2,99,4,123,0,1,2,82,4,123,0,1,2,82,4,123,0,2,2,74,4,124,0,8, + 0,1,2,64,4,123,0,1,2,64,4,123,0,1,2,238,4,123,0,1,1,31,4,123,0,1,2,106,5,240,0,1,2,106,4,123,0,1,2,166, + 4,123,0,1,2,98,4,123,0,1,2,98,4,123,0,1,2,125,4,123,0,1,1,22,5,240,0,1,1,22,5,240,0,1,1,30,6,47,0,1, + 1,7,4,123,0,1,1,128,4,123,0,1,1,153,5,240,0,1,1,254,5,240,0,1,1,22,5,240,0,1,1,22,5,240,0,1,3,233,4,123, + 0,1,3,233,4,123,0,1,3,233,4,123,0,1,2,137,4,123,0,1,2,137,4,123,0,1,2,137,4,123,0,2,2,115,4,123,0,14,0,1, + 4,141,4,123,0,1,2,233,4,123,0,1,2,166,5,240,0,1,2,51,4,123,0,1,2,51,5,240,0,1,2,51,4,123,0,1,2,94,4,123, + 0,1,2,97,4,123,0,1,2,112,4,123,0,1,1,130,4,123,0,1,2,59,4,123,0,1,2,81,4,123,0,1,2,39,4,123,0,1,1,22, + 5,240,0,1,1,22,5,240,0,1,1,241,4,123,0,1,1,22,5,240,0,1,2,14,4,123,0,1,1,26,5,240,0,1,2,125,4,123,0,1, + 2,125,4,123,0,1,2,94,4,123,0,1,3,71,4,123,0,1,2,94,5,240,0,1,2,100,4,123,0,1,2,23,4,123,0,1,2,23,4,123, + 0,1,2,23,4,123,0,1,2,23,4,123,0,1,1,176,5,240,0,1,2,58,5,240,0,1,1,176,5,240,0,1,2,58,5,240,0,1,3,39, + 5,240,0,1,2,97,4,123,0,1,2,72,4,123,0,1,2,166,5,240,0,1,2,163,4,123,0,1,1,31,6,47,0,1,2,171,4,123,0,1, + 1,31,4,123,0,1,2,106,5,240,0,1,1,176,5,240,0,1,2,58,5,240,0,1,3,254,5,240,0,1,3,254,5,240,0,1,3,254,5,240, + 0,1,3,71,5,240,0,1,4,142,4,123,0,1,3,32,5,240,0,1,1,22,5,240,0,1,2,74,4,123,0,1,2,126,5,240,0,1,2,94, + 4,123,0,1,2,125,5,240,0,2,2,74,4,124,0,8,0,1,2,69,5,240,0,1,2,137,4,123,0,1,2,125,5,240,0,1,1,16,4,123, + 0,1,2,163,4,123,0,1,2,130,5,240,0,1,2,135,4,123,0,1,2,22,4,123,0,1,2,69,5,240,0,1,2,125,4,123,0,1,2,112, + 4,123,0,1,2,166,4,123,0,1,2,116,4,123,0,1,2,125,4,123,0,1,2,106,4,123,0,1,2,26,4,123,0,1,2,170,4,123,0,1, + 2,98,4,123,0,1,2,164,4,123,0,1,3,94,4,123,0,1,2,126,5,240,0,1,2,126,5,240,0,1,2,160,5,240,0,1,2,238,4,123, + 0,1,2,125,4,123,0,1,2,116,4,123,0,1,3,94,4,123,0,1,2,239,4,123,0,1,2,166,4,123,0,1,2,166,4,123,0,1,1,31, + 6,47,0,1,3,39,5,240,0,1,2,166,4,123,0,1,1,242,4,123,0,1,1,22,5,240,0,1,2,166,4,123,0,1,3,72,5,240,0,1, + 2,147,5,240,0,1,1,47,5,240,0,1,4,213,5,240,0,1,4,114,5,240,0,1,3,2,5,240,0,1,2,188,5,240,0,1,2,188,5,240, + 0,1,2,188,5,240,0,1,2,153,5,240,0,1,3,116,5,240,0,1,2,158,5,240,0,1,4,79,5,240,0,1,2,115,5,240,0,1,2,245, + 5,240,0,1,2,238,5,240,0,1,3,125,5,240,0,1,3,115,5,240,0,1,3,2,5,240,0,1,3,39,5,240,0,1,3,2,5,240,0,1, + 2,158,5,240,0,1,3,76,5,240,0,1,2,115,5,240,0,1,2,111,5,240,0,1,3,113,5,240,0,1,2,205,5,240,0,1,3,2,5,240, + 0,1,2,178,5,240,0,1,4,71,5,240,0,1,4,71,5,240,0,1,2,89,5,240,0,1,3,135,5,240,0,1,2,188,5,240,0,1,2,78, + 5,240,0,1,3,115,5,240,0,1,2,224,5,240,0,1,2,84,4,123,0,1,2,155,5,240,0,1,2,97,4,123,0,1,2,69,4,123,0,1, + 2,246,4,123,0,1,2,141,4,123,0,1,3,155,4,123,0,1,2,64,4,123,0,1,2,130,4,123,0,1,2,116,4,123,0,1,2,248,4,123, + 0,1,3,5,4,123,0,1,2,130,4,123,0,1,2,125,4,123,0,1,2,157,4,123,0,1,2,166,4,123,0,1,2,166,4,123,0,1,2,84, + 4,123,0,1,2,96,4,123,0,1,3,107,5,240,0,1,2,98,4,123,0,1,2,157,4,123,0,1,2,75,4,123,0,1,3,169,4,123,0,1, + 3,169,4,123,0,1,2,6,4,123,0,1,3,29,4,123,0,1,1,22,4,123,0,1,1,178,4,123,0,1,2,246,4,123,0,1,2,116,4,123, + 0,1,2,166,4,123,0,1,2,39,4,123,0,1,1,31,6,47,0,1,1,31,6,47,0,1,1,31,6,47,0,1,3,250,4,123,0,1,3,243, + 4,123,0,1,1,52,5,240,0,1,2,157,4,123,0,1,3,188,5,240,0,1,3,94,4,123,0,1,1,243,5,240,0,1,3,99,4,123,0,1, + 3,115,5,240,0,1,2,246,4,123,0,1,3,132,5,240,0,1,3,34,4,123,0,1,4,79,5,240,0,1,3,150,4,123,0,1,3,44,5,240, + 0,1,2,115,4,123,0,1,4,79,5,240,0,1,3,150,4,123,0,1,3,20,5,240,0,1,3,37,5,250,0,1,3,39,5,240,0,1,2,125, + 4,123,0,1,3,31,5,240,0,1,2,149,4,123,0,1,2,158,5,240,0,1,2,166,4,123,0,1,4,79,5,240,0,1,3,155,4,123,0,1, + 2,238,5,240,0,1,2,116,4,123,0,1,2,238,5,240,0,1,2,116,4,123,0,1,2,238,5,240,0,1,1,22,5,240,0,1,4,26,5,240, + 0,1,3,101,4,123,0,1,3,2,5,240,0,1,2,115,5,240,0,1,2,75,4,123,0,1,2,163,4,123,0,1,2,137,4,123,0,1,3,5, + 4,123,0,1,3,39,5,240,0,1,2,125,4,123,0,1,2,69,4,123,0,1,2,205,5,240,0,1,2,98,4,123,0,1,2,248,4,123,0,1, + 2,238,5,240,0,1,2,116,4,123,0,1,2,248,4,123,0,1,2,130,4,123,0,1,2,94,4,123,0,1,2,26,4,123,0,1,4,20,4,123, + 0,1,2,84,4,123,0,1,2,166,4,123,0,1,2,84,4,131,0,1,2,84,4,123,0,1,2,25,4,123,0,1,2,64,4,123,0,1,2,166, + 4,123,0,1,1,24,4,123,0,1,3,5,4,123,0,1,2,130,4,123,0,1,2,125,4,123,0,1,1,177,4,123,0,1,2,189,4,123,0,1, + 2,189,4,123,0,1,2,189,4,123,0,1,4,20,4,123,0,1,2,22,4,123,0,1,2,144,4,123,0,1,2,144,4,123,0,1,2,84,4,123, + 0,1,2,103,4,123,0,1,2,98,4,123,0,1,2,94,4,123,0,1,3,71,4,123,0,1,2,23,4,123,0,1,1,254,4,123,0,1,1,24, + 4,123,0,1,2,94,4,123,0,1,2,248,4,123,0,1,2,166,4,123,0,1,2,236,5,240,0,1,3,254,5,240,0,1,2,236,5,240,0,1, + 3,254,5,240,0,1,2,236,5,240,0,1,3,254,5,240,0,1,2,236,5,240,0,1,3,254,5,240,0,1,3,147,5,240,0,1,1,232,5,240, + 0,2,3,76,5,240,0,22,0,1,4,66,5,240,0,1,3,82,5,240,0,1,3,102,5,240,0,1,1,198,5,240,0,1,1,214,5,240,0,1, + 2,222,5,240,0,1,3,44,5,240,0,1,3,52,5,226,0,1,3,36,4,123,0,1,3,14,5,240,0,2,3,39,5,240,0,12,0,1,3,132, + 5,240,0,1,3,152,5,240,0,1,3,95,5,226,0,1,2,250,5,226,0,1,2,122,5,240,0,1,3,102,5,240,0,1,3,52,5,240,0,1, + 2,202,4,68,0,1,2,198,5,240,0,1,3,142,5,240,0,1,4,76,5,240,0,1,3,22,5,240,0,1,2,198,5,240,0,1,1,243,5,231, + 0,1,2,157,5,231,0,1,1,125,6,49,0,1,2,247,4,123,0,1,3,96,4,123,0,1,2,252,5,240,0,1,3,101,5,240,0,1,1,22, + 5,240,0,1,1,42,5,240,0,1,1,22,5,240,0,1,1,42,5,240,0,1,2,158,5,240,0,1,2,125,5,240,0,1,2,84,4,123,0,1, + 1,26,5,240,0,1,3,2,5,240,0,1,1,22,5,240,0,1,2,158,5,240,0,1,1,22,5,240,0,1,2,190,5,240,0,1,2,23,4,123, + 0,1,3,39,5,240,0,1,3,115,5,240,0,1,2,188,5,240,0,1,2,195,5,211,0,1,2,94,4,123,0,1,3,245,5,240,0,1,3,71, + 4,123,0,1,2,94,4,123,0,1,3,2,5,240,0,1,2,163,4,123,0,1,2,170,4,123,0,1,2,51,5,240,0,1,2,115,4,123,0,1, + 1,212,4,123,0,1,2,147,5,240,0,1,2,190,5,240,0,1,2,136,5,240,0,1,2,158,5,240,0,1,1,47,5,240,0,1,4,179,5,240, + 0,1,4,12,4,123,0,1,5,48,5,240,0,1,3,198,4,123,0,1,2,153,5,240,0,1,2,246,4,123,0,1,4,213,5,240,0,1,4,24, + 4,123,0,1,2,153,5,240,0,1,3,5,4,123,0,1,3,39,5,240,0,1,3,108,5,240,0,1,2,218,4,123,0,1,5,110,5,240,0,1, + 4,19,4,123,0,1,2,84,4,123,0,1,2,84,4,123,0,1,3,2,5,240,0,1,1,22,5,240,0,1,3,119,5,240,0,1,2,158,5,240, + 0,2,2,74,4,123,0,8,0,1,2,25,4,123,0,1,5,0,5,240,0,1,3,209,4,123,0,1,4,49,5,240,0,1,3,215,4,123,0,1, + 4,197,5,240,0,1,3,209,4,123,0,1,3,252,5,240,0,1,3,118,4,123,0,1,3,252,5,240,0,1,3,118,4,113,0,1,3,252,5,240, + 0,1,3,118,4,123,0,1,2,158,5,240,0,1,1,30,5,240,0,1,1,42,5,240,0,1,1,146,5,240,0,1,1,92,5,240,0,1,1,174, + 5,240,0,1,3,59,5,240,0,2,2,205,4,123,0,0,0,1,5,110,5,240,0,1,4,19,4,123,0,1,2,158,5,240,0,1,2,166,4,123, + 0,1,3,170,5,240,0,1,3,196,4,123,0,1,3,39,5,240,0,1,2,111,4,123,0,1,1,22,5,240,0,1,1,22,5,240,0,1,1,219, + 5,240,0,2,1,29,4,123,0,0,0,1,2,240,5,240,0,1,2,137,4,123,0,1,2,178,5,240,0,1,1,247,5,240,0,1,2,245,5,240, + 0,1,2,137,4,123,0,1,3,92,5,240,0,1,2,106,4,123,0,1,2,158,5,240,0,1,1,22,5,240,0,1,2,245,5,240,0,1,2,137, + 4,123,0,1,2,125,5,240,0,1,2,23,4,123,0,1,2,147,5,240,0,1,2,39,4,123,0,1,3,102,5,240,0,1,3,169,4,123,0,1, + 2,76,5,240,0,1,2,53,5,240,0,1,3,115,5,240,0,1,1,47,7,136,0,1,4,204,5,240,0,1,2,245,5,240,0,1,2,238,5,240, + 0,1,3,60,6,4,0,1,3,7,5,240,0,1,3,7,5,240,0,1,3,92,5,240,0,1,1,146,5,240,0,1,1,145,5,240,0,1,3,2, + 5,240,0,1,2,244,5,240,0,1,4,25,5,240,0,1,3,38,5,240,0,1,2,129,5,240,0,1,2,213,5,240,0,1,3,82,5,240,0,1, + 2,228,5,240,0,1,4,120,5,247,0,1,3,57,5,247,0,1,2,212,5,247,0,1,2,180,4,123,0,1,2,92,4,123,0,1,2,139,5,240, + 0,1,2,139,5,240,0,1,2,119,5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,139, + 5,240,0,1,2,139,5,240,0,1,2,139,5,240,0,1,2,245,5,240,0,1,1,30,4,123,0,1,1,31,4,123,0,1,2,234,5,240,0,1, + 1,22,5,240,0,1,1,31,4,123,0,1,1,31,4,123,0,1,1,31,4,123,0,1,1,199,5,240,0,2,2,125,4,123,0,0,0,2,0,119, + 0,19,0,28,0,0,0,36,0,61,0,10,0,68,0,93,0,36,0,154,0,154,0,62,0,168,0,169,0,63,0,178,0,178,0,65,0,186,0,186, + 0,66,0,192,0,192,0,67,0,198,0,199,0,68,0,209,0,209,0,70,0,232,0,233,0,71,0,243,0,243,0,73,0,250,0,250,0,74,1,13, + 1,13,0,75,1,21,1,21,0,76,1,40,1,41,0,77,1,53,1,53,0,79,1,65,1,66,0,80,1,69,1,69,0,82,1,72,1,73,0,83, + 1,78,1,78,0,85,1,80,1,86,0,86,1,88,1,89,0,93,1,91,1,93,0,95,1,95,1,95,0,98,1,97,1,97,0,99,1,102,1,102, + 0,100,1,105,1,106,0,101,1,108,1,112,0,103,1,116,1,123,0,108,1,172,1,172,0,116,1,246,1,249,0,117,2,5,2,12,0,121,2,14, + 2,74,0,129,2,76,2,103,0,190,2,105,2,107,0,218,2,109,2,109,0,221,3,69,3,93,0,222,3,100,3,101,0,247,3,105,3,105,0,249, + 3,107,3,107,0,250,3,109,3,109,0,251,3,111,3,111,0,252,3,119,3,119,0,253,3,132,3,138,0,254,3,140,3,140,1,5,3,144,3,144, + 1,6,3,152,3,154,1,7,3,157,3,158,1,10,3,163,3,172,1,12,3,174,3,204,1,22,3,206,3,227,1,53,3,232,3,239,1,75,3,243, + 4,1,1,83,4,4,4,9,1,98,4,34,4,35,1,104,4,42,4,43,1,106,4,46,4,54,1,108,4,64,4,64,1,117,4,77,4,77,1,118, + 4,88,4,88,1,119,4,94,4,94,1,120,4,98,4,98,1,121,4,124,4,125,1,122,4,139,4,139,1,124,4,146,4,147,1,125,4,167,4,167, + 1,127,4,178,4,179,1,128,4,181,4,181,1,130,4,183,4,183,1,131,8,99,8,107,1,132,8,110,8,119,1,141,8,122,8,126,1,151,8,129, + 8,135,1,156,8,139,8,139,1,163,8,204,8,204,1,164,9,5,9,12,1,165,9,243,9,244,1,173,11,149,11,149,1,175,11,157,11,160,1,176, + 11,162,11,164,1,180,11,167,11,167,1,183,11,170,11,175,1,184,11,182,11,182,1,190,11,186,11,186,1,191,11,190,11,191,1,192,11,193,11,195, + 1,194,11,197,11,197,1,197,11,199,11,203,1,198,11,206,11,209,1,203,13,198,13,198,1,207,17,212,17,238,1,208,17,241,17,242,1,235,18,30, + 18,30,1,237,18,50,18,50,1,238,18,56,18,56,1,239,18,205,18,208,1,240,18,211,18,217,1,244,18,219,18,222,1,251,18,225,18,225,1,255, + 18,227,18,227,2,0,18,254,19,1,2,1,19,3,19,4,2,5,19,6,19,17,2,7,19,20,19,35,2,19,19,37,19,37,2,35,19,39,19,43, + 2,36,19,48,19,68,2,41,21,97,21,115,2,62,21,139,21,139,2,81,21,141,21,141,2,82,21,194,21,203,2,83,22,233,22,235,2,93,23,2, + 23,2,2,96,23,12,23,12,2,97,23,16,23,16,2,98,23,19,23,20,2,99,23,22,23,22,2,101,23,134,23,134,2,102,0,2,0,12,2,177, + 2,197,0,0,2,238,2,243,0,21,2,245,2,245,0,27,2,247,2,247,0,28,2,251,2,253,0,29,3,1,3,2,0,32,3,4,3,4,0,34, + 4,23,4,27,0,35,8,243,8,248,0,40,11,140,11,146,0,46,22,185,22,195,0,53,23,122,23,122,0,64,0,65,0,0,1,6,0,0,1,14, + 0,0,1,22,0,0,1,30,0,0,1,36,0,0,1,42,0,0,1,48,0,0,1,54,0,0,1,62,0,0,1,70,0,0,1,76,0,0,1,82, + 0,0,1,88,0,0,1,96,0,0,1,102,0,0,1,108,0,0,1,114,0,0,1,120,0,0,1,126,0,0,1,132,0,0,1,138,0,0,1,144, + 0,0,1,150,0,0,1,156,0,0,1,162,0,0,1,168,0,0,1,174,0,0,1,180,0,0,1,186,0,0,1,192,0,0,1,198,0,0,1,204, + 0,0,1,210,0,0,1,216,0,0,1,222,0,0,1,228,0,0,1,234,0,0,1,240,0,0,1,246,0,0,1,252,0,0,2,2,0,0,2,8, + 0,0,2,14,0,0,2,20,0,0,2,26,0,0,2,32,0,0,2,38,0,0,2,44,0,0,2,50,0,0,2,56,0,0,2,62,0,0,2,70, + 0,0,2,78,0,0,2,84,0,0,2,90,0,0,2,96,0,0,2,102,0,0,2,108,0,0,2,114,0,0,2,120,0,0,2,126,0,0,2,132, + 0,0,2,138,0,0,2,144,0,0,2,150,0,2,254,0,4,123,0,4,0,2,254,0,4,123,0,4,0,2,254,0,4,123,0,7,0,1,254,0, + 4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,2,254,0,4,123,0,4,0,2,254,0,4,123,0,8,0,1,254,0, + 4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,2,254,0,4,123,0,7,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123, + 0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,138,3,111,0,1,254,0,4,114,0,1,254,0,4,114,0,1,254,0,4,123,0,1,254,138, + 4,114,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1, + 254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,253,142,4,123, + 0,1,254,127,4,123,0,1,254,65,4,123,0,1,254,23,4,123,0,1,252,234,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0, + 4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1, + 254,0,4,123,0,2,254,0,4,123,0,12,0,2,254,0,4,123,0,16,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1, + 254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123, + 0,1,254,0,4,123,0,1,254,0,4,123,0,1,254,0,4,123,0,1,1,62,0,254,0,1,1,68,0,12,0,30,0,62,0,68,0,74,0,80, + 0,86,0,92,0,98,0,104,0,110,0,116,0,122,0,128,0,134,0,140,0,146,0,152,0,158,0,164,0,170,0,176,0,182,0,188,0,194,0,200, + 0,206,0,212,0,218,0,224,0,230,0,236,0,1,4,216,0,0,0,1,3,192,0,0,0,1,1,88,0,0,0,1,3,40,0,0,0,1,2,238, + 0,0,0,1,2,156,0,0,0,1,2,190,255,254,0,1,3,179,0,0,0,1,3,108,0,0,0,1,1,62,0,0,0,1,2,116,0,0,0,1, + 4,27,0,0,0,1,0,250,254,86,0,1,2,23,0,0,0,1,3,40,0,0,0,1,2,116,0,0,0,1,1,62,0,0,0,1,2,92,0,0, + 0,1,1,88,0,0,0,1,3,40,0,0,0,1,2,190,0,0,0,1,2,150,0,0,0,1,2,136,254,82,0,1,2,135,0,0,0,1,1,194, + 0,0,0,1,1,68,0,0,0,1,2,116,0,0,0,1,2,23,254,82,0,1,5,60,0,0,0,1,1,68,0,0,0,1,0,30,0,36,0,40, + 0,44,0,50,0,56,0,60,0,61,0,68,0,72,0,76,0,82,0,88,0,92,0,93,0,154,0,186,0,243,1,72,1,89,1,97,1,121,1,122, + 1,123,2,18,2,22,2,42,2,55,2,84,17,225,22,234,0,1,0,1,2,217,0,1,0,0,0,6,0,1,253,244,0,0,0,2,38,240,0,4, + 0,0,33,48,35,32,0,53,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,211,255,183,0,0,0,0,0,0,0,75,0,114,0,57,0,75,0,0,255,68, + 0,0,255,136,255,173,255,154,255,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,0,0,0,0,0,0,0,0, + 255,201,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,0,0,255,211,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,211,255,220,255,220,0,57,0,0,255,220,0,0,0,0,255,220,0,0,255,220,255,220,0,0,255,97, + 0,0,255,125,255,144,0,0,255,97,0,0,0,0,255,220,255,220,255,220,255,183,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,220,0,0, + 255,136,255,173,0,0,255,117,255,183,0,0,0,0,255,220,0,0,255,220,0,0,255,220,0,0,0,57,0,0,255,220,255,220,255,220,255,220,255,220, + 255,220,255,220,255,220,0,0,0,0,255,220,255,220,255,97,0,0,0,0,255,144,255,173,255,97,255,117,255,220,255,220,255,97,0,0,255,97,255,117, + 255,173,255,144,254,248,255,3,0,47,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,220,0,0,255,220,0,0,255,220,0,0, + 0,0,255,193,255,183,0,0,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,193,255,220,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0, + 0,0,0,0,255,220,255,220,0,0,0,0,255,220,0,0,0,0,0,0,255,183,0,0,255,144,0,0,255,220,0,0,0,0,0,0,0,0,0,0, + 0,0,255,183,255,144,255,144,255,173,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,255,220,0,0, + 0,0,0,0,0,0,0,38,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,220,0,0,0,0,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,144,0,0,0,0,0,0,0,0,0,0,255,144,0,0, + 0,0,0,0,255,211,255,201,255,68,0,0,0,0,254,183,255,97,255,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220,255,220, + 0,0,0,0,0,0,0,0,0,0,0,0,255,68,0,0,0,0,255,144,0,0,0,0,255,107,0,0,0,0,255,183,255,107,0,0,0,0,255,144, + 0,0,0,0,0,0,255,68,0,0,0,0,0,0,0,0,255,68,255,144,0,0,255,183,255,144,255,68,255,68,0,0,0,0,0,0,0,0,0,0, + 0,0,255,144,0,0,0,0,255,107,255,183,0,0,255,220,255,220,255,144,0,0,0,0,0,0,255,68,0,0,255,183,255,220,255,183,0,0,255,68, + 0,0,0,0,255,211,0,0,254,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,183, + 0,0,0,0,0,0,0,0,255,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,211,255,211,255,201,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,183,255,193,255,183,0,0,255,183,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,183,255,193,255,144,0,0,255,41,0,0,0,0,255,220,0,0,255,144,0,0,0,0,0,0,0,0,255,144,0,0,0,0,255,97, + 255,201,0,0,255,183,0,0,255,183,0,0,255,220,0,0,0,0,255,154,0,0,0,0,0,0,0,0,0,0,255,154,0,0,0,0,0,0,255,154, + 0,0,0,0,0,0,255,107,255,125,0,0,0,0,255,144,255,220,255,154,0,0,255,154,255,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,193,255,193,0,0,0,0,255,220,0,0,0,0,0,47,0,0,0,0,0,0,0,0,0,0,0,0,255,183,0,0,0,0,254,230, + 255,154,255,31,255,68,0,0,254,240,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,255,220, + 0,0,0,0,0,0,255,68,0,0,0,0,0,0,0,0,0,0,255,220,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,254,97,253,230,0,0,0,0,0,57,255,173,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,220,0,0,255,125,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,211,255,220,255,68,0,0,255,211,254,193,0,0,255,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,211,0,0,255,164,0,0,0,0,255,183,0,0,0,0,255,211,0,0,255,220,255,183,255,220,255,220,0,0,255,220, + 0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,255,164,255,183,0,0,255,183,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,38,0,38,254,183,0,0,0,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,211,255,220,255,125,0,0,255,173,255,183,255,193,255,173,0,0,255,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,107, + 0,0,255,144,255,173,0,0,255,125,0,0,255,211,0,0,0,0,255,164,0,0,0,0,0,0,0,0,0,0,255,164,0,0,0,0,0,0,255,164, + 0,0,0,0,0,0,255,144,255,144,255,220,0,0,255,154,255,211,255,164,0,0,255,164,255,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,107,255,125,255,220,0,0,0,0,0,0,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,68,255,13,255,31,255,97,0,0,255,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220, + 0,0,0,0,0,0,0,0,0,0,0,0,254,173,254,164,0,0,254,164,0,0,0,0,255,193,0,0,0,0,254,164,254,211,254,173,0,0,254,201, + 0,0,254,173,0,0,254,193,255,68,255,144,0,0,255,136,255,17,254,224,0,0,254,244,254,231,0,0,0,0,254,164,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,211,254,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,136,254,248,255,89,255,125,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,97,0,0,0,0,255,97,0,0,0,0,255,211,0,0,0,0,255,97,0,0,0,0,0,0,255,117, + 0,0,0,0,0,0,255,201,255,78,255,144,0,0,0,0,255,97,255,97,0,0,255,97,255,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,254,230,0,0,255,173,255,21,255,136,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,125,0,0,0,0,255,136,0,0,0,0,255,211,0,0,0,0,255,136,255,164,0,0,0,0,255,183, + 0,0,0,0,0,0,255,220,255,144,255,220,0,0,0,0,255,125,255,136,0,0,255,136,255,183,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,220,0,0,254,248,0,0,255,154,0,0,0,0,0,0,0,0,255,107,0,0,0,0,0,0,0,0,255,125,0,0,0,0,255,220, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,144,0,0,0,0,255,107,0,0,255,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,97,255,173,255,211,0,0,255,13,254,97,254,240,255,97,0,0,255,144,0,0,0,0,0,0,0,0,255,144,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,254,230,0,0,0,0,254,240,0,0,0,0,255,183,0,0,0,0,254,240,0,0,0,0,0,0,255,21, + 0,0,0,0,0,0,0,0,255,31,255,107,0,0,255,144,254,230,254,240,0,0,254,240,255,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,144,255,220,254,248,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,220,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,144,255,107,255,183,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0, + 0,0,255,220,0,0,255,220,255,183,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,65,0,0,255,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,183,0,0,0,0,0,0,0,0,0,0,255,183,0,0,0,0,0,0,255,193, + 0,0,0,0,0,0,255,183,0,0,0,0,0,0,0,0,255,220,255,183,0,0,255,183,255,193,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,107,255,144,255,164,0,0,0,38,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,193,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,107,255,183,255,125,0,0,255,125,255,68,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,211,255,220,255,211,0,0,255,220,0,0,0,0,255,220,255,211,255,220,0,0,0,0,0,0, + 0,0,0,0,255,201,0,0,255,183,0,0,0,0,0,0,0,0,255,211,0,0,255,211,0,0,0,0,0,0,255,211,0,0,0,0,0,0,0,72, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,86,254,201,0,0,255,201,255,97,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,220,254,240,0,0,0,0,255,68,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220,0,0,255,193,0,0,0,0,0,0,0,0,0,0,255,193,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,193,0,0,255,193,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,220,254,220,255,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,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,254,211,0,0,0,0,0,0,0,0,0,0,255,220,255,220,255,220,0,0,255,220,255,220,0,0,0,0,0,0,255,144, + 0,0,255,144,255,220,0,0,255,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, + 255,220,255,220,0,0,255,220,0,0,0,0,0,151,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,183,255,183,255,220,255,220,0,0,0,0,255,220,255,220,0,0,0,0,255,68, + 0,0,255,78,255,144,255,144,255,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 255,220,255,220,0,0,255,220,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,211,255,220,255,220,0,57,0,0,255,220,0,0,0,0,255,220,0,0,255,220,255,220,0,0,255,97, + 0,0,255,125,255,144,0,0,255,97,0,0,0,0,255,220,255,220,255,220,255,183,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,220,0,0, + 255,136,255,173,0,0,255,117,255,183,0,0,0,0,255,220,0,0,255,220,0,0,255,220,0,0,0,57,0,0,255,220,255,220,0,0,255,220,255,220, + 0,0,255,220,255,220,0,0,0,0,255,220,255,220,255,97,0,0,0,0,255,144,255,173,255,97,255,117,0,0,0,0,0,0,255,220,0,0,0,0, + 0,0,0,0,254,248,255,3,0,47,0,0,255,211,255,220,255,220,0,57,0,0,255,220,0,0,0,0,255,220,0,0,255,220,255,220,0,0,255,97, + 0,0,255,125,255,144,0,0,255,97,0,0,0,0,255,220,255,220,255,220,255,183,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,220,0,0, + 255,136,255,173,0,0,255,117,255,183,0,0,0,0,255,220,0,0,255,220,0,0,255,220,0,0,0,57,0,0,255,220,255,220,0,0,255,220,255,220, + 0,0,255,220,255,220,0,0,0,0,255,220,255,220,255,97,0,0,0,0,255,144,255,173,255,97,255,117,0,0,0,0,0,0,255,220,0,0,0,0, + 0,0,255,144,254,248,255,3,0,47,0,0,255,211,255,220,255,220,0,57,0,0,255,220,0,0,0,0,255,220,0,0,255,220,255,220,0,0,255,97, + 0,0,255,125,255,144,0,0,255,97,0,0,0,0,255,220,255,220,255,220,255,183,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,220,0,0, + 255,136,255,173,0,0,255,117,255,183,0,0,0,0,255,220,0,0,255,220,0,0,255,220,0,0,0,57,0,0,255,220,255,220,0,0,255,220,255,220, + 0,0,255,220,255,220,0,0,0,0,255,220,255,220,255,97,0,0,0,0,255,144,255,173,255,97,255,117,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,144,254,248,255,3,0,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,173,255,164,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,38,0,0,0,0,0,0,255,107,255,183,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,220,0,0,255,68,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,144,255,144,255,173,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,164,255,144,255,183,0,0,255,211,255,220,255,220,0,57,0,0,255,220,0,0,0,0,255,220,0,0,255,220,255,220,0,0,255,97, + 0,0,255,125,255,144,0,0,255,97,0,0,0,0,255,220,255,220,255,220,255,183,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,220,0,0, + 255,136,255,173,0,0,255,117,255,183,0,0,0,0,0,0,0,0,255,220,0,0,255,220,0,0,0,57,0,0,0,0,255,220,0,0,255,220,255,220, + 255,220,255,220,0,0,0,0,0,0,255,220,255,220,255,97,0,0,0,0,255,144,255,173,255,97,255,117,0,0,0,0,0,0,255,220,0,0,0,0, + 0,0,255,144,254,248,255,2,0,47,0,0,255,211,255,220,255,220,0,57,0,0,255,220,0,0,0,0,255,220,0,0,255,220,255,220,0,0,255,97, + 0,0,255,125,255,144,0,0,255,97,0,0,0,0,255,220,255,220,255,220,255,183,0,0,0,0,0,0,0,0,255,220,0,0,0,0,255,220,0,0, + 255,136,255,173,0,0,0,0,255,183,0,0,0,0,0,0,0,0,255,220,0,0,255,220,0,0,0,57,0,0,0,0,255,220,0,0,255,220,255,220, + 255,220,255,220,0,0,0,0,0,0,255,220,0,0,255,97,0,0,0,0,255,144,255,173,255,97,0,0,0,0,0,0,0,0,255,220,0,0,0,0, + 0,0,255,144,254,248,255,2,0,47,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,255,220,0,0,0,0,255,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,255,220,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,211,255,201,255,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,255,63,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,255,125,255,68,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,211,255,220,255,211,0,0,255,220,0,0,0,0,255,220,255,211,255,220,0,0,0,0,0,0, + 0,0,0,0,255,201,0,0,255,183,0,0,0,0,0,0,0,0,255,211,0,0,255,211,0,0,0,0,0,0,255,211,0,0,0,0,0,0,255,220, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,86,254,201,0,0,255,68,255,13,255,31,255,97,0,0,255,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,220, + 0,0,0,0,0,0,0,0,0,0,0,0,254,173,254,164,0,0,254,164,0,0,0,0,255,193,0,0,0,0,254,164,254,211,254,173,0,0,254,201, + 0,0,254,173,0,0,254,193,255,68,255,144,0,0,255,136,254,173,254,164,0,0,254,164,254,201,0,0,0,0,254,164,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,255,211,254,248,0,0,0,0,0,0,0,0,255,211,255,183,0,0,0,0,0,0,0,75,0,114,0,57,0,75,0,0,255,68, + 0,0,255,136,255,173,255,154,255,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,0,0,0,0,0,0,0,0, + 255,201,0,0,0,0,255,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,248,255,193,255,183,255,193,255,193,255,183,255,193,255,183,255,183,0,0,0,0, + 0,0,0,0,0,0,255,136,0,0,255,220,0,0,0,0,0,0,0,0,255,183,0,0,0,0,0,0,255,144,255,107,255,144,0,0,0,0,0,0, + 255,183,255,183,0,0,255,183,0,0,0,0,254,125,255,183,0,0,0,0,255,183,255,107,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,183,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,255,183,255,144,255,183,255,183,255,183,0,47,255,144,255,144,0,0,254,230, + 0,0,254,136,255,3,255,183,254,136,0,0,0,0,0,0,0,0,0,0,255,220,0,0,0,0,0,0,255,183,255,183,255,183,0,0,0,0,0,0, + 255,21,255,60,0,0,255,144,0,0,0,0,0,38,255,144,0,0,0,0,255,183,255,183,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,255,183,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,82,0,16,0,16,0,1,0,36,0,36,0,2,0,37,0,37,0,3,0,38,0,38,0,4,0,39, + 0,39,0,5,0,41,0,41,0,6,0,42,0,42,0,7,0,43,0,43,0,8,0,45,0,45,0,9,0,46,0,46,0,10,0,47,0,47,0,11, + 0,50,0,50,0,12,0,51,0,51,0,13,0,52,0,52,0,14,0,53,0,53,0,15,0,54,0,54,0,16,0,55,0,55,0,17,0,56,0,56, + 0,18,0,57,0,57,0,19,0,58,0,58,0,20,0,59,0,59,0,21,0,60,0,60,0,22,0,61,0,61,0,23,0,72,0,72,0,24,0,73, + 0,73,0,25,0,78,0,78,0,26,0,81,0,81,0,27,0,82,0,82,0,28,0,85,0,85,0,29,0,89,0,89,0,30,0,90,0,90,0,31, + 0,91,0,91,0,32,0,92,0,92,0,33,0,109,0,109,0,34,0,125,0,125,0,35,0,130,0,130,0,36,0,131,0,132,0,37,0,133,0,133, + 0,38,0,134,0,134,0,37,0,136,0,136,0,39,0,137,0,137,0,40,0,146,0,146,0,5,0,148,0,152,0,12,0,155,0,158,0,18,0,159, + 0,159,0,22,0,160,0,160,0,41,0,161,0,161,0,42,0,170,0,173,0,24,0,178,0,178,0,43,0,179,0,179,0,27,0,180,0,184,0,28, + 0,191,0,191,0,33,0,193,0,193,0,33,0,194,0,194,0,44,0,196,0,196,0,44,0,198,0,198,0,45,0,200,0,200,0,40,0,206,0,206, + 0,40,0,208,0,208,0,5,0,210,0,210,0,46,0,221,0,221,0,24,0,224,0,224,0,7,0,251,0,251,0,11,0,255,0,255,0,11,1,2, + 1,2,0,47,1,10,1,10,0,27,1,22,1,22,0,15,1,23,1,23,0,29,1,26,1,26,0,15,1,27,1,27,0,48,1,32,1,32,0,16, + 1,34,1,34,0,16,1,38,1,38,0,49,1,48,1,48,0,18,1,58,1,58,0,22,1,63,1,63,0,23,10,238,10,238,0,50,10,250,10,250, + 0,51,10,252,10,252,0,52,18,252,18,252,0,17,19,20,19,20,0,10,19,21,19,21,0,26,0,2,0,162,0,16,0,16,0,1,0,17,0,17, + 0,2,0,29,0,29,0,3,0,36,0,36,0,4,0,37,0,37,0,5,0,38,0,38,0,6,0,39,0,39,0,7,0,41,0,41,0,8,0,42, + 0,42,0,9,0,43,0,43,0,8,0,45,0,45,0,10,0,46,0,47,0,8,0,50,0,50,0,11,0,51,0,51,0,8,0,52,0,52,0,12, + 0,53,0,53,0,8,0,54,0,54,0,13,0,55,0,55,0,14,0,56,0,56,0,15,0,57,0,57,0,16,0,58,0,58,0,17,0,59,0,59, + 0,18,0,60,0,60,0,19,0,61,0,61,0,20,0,68,0,68,0,21,0,70,0,70,0,22,0,71,0,71,0,23,0,72,0,72,0,24,0,73, + 0,73,0,25,0,74,0,75,0,26,0,76,0,76,0,27,0,79,0,79,0,28,0,80,0,80,0,26,0,81,0,81,0,29,0,82,0,82,0,30, + 0,84,0,84,0,23,0,85,0,85,0,31,0,86,0,86,0,32,0,87,0,87,0,33,0,88,0,88,0,34,0,89,0,89,0,35,0,90,0,90, + 0,36,0,91,0,91,0,37,0,92,0,92,0,38,0,109,0,109,0,39,0,125,0,125,0,40,0,130,0,134,0,4,0,136,0,136,0,41,0,137, + 0,137,0,42,0,148,0,152,0,11,0,155,0,158,0,15,0,159,0,159,0,19,0,160,0,161,0,8,0,162,0,162,0,43,0,163,0,163,0,21, + 0,164,0,167,0,43,0,169,0,169,0,22,0,170,0,170,0,44,0,171,0,171,0,24,0,172,0,173,0,44,0,178,0,178,0,45,0,179,0,179, + 0,29,0,180,0,180,0,46,0,181,0,181,0,30,0,182,0,184,0,46,0,187,0,187,0,47,0,188,0,188,0,34,0,189,0,190,0,47,0,191, + 0,191,0,38,0,193,0,193,0,38,0,194,0,194,0,48,0,195,0,195,0,49,0,196,0,196,0,48,0,197,0,197,0,49,0,198,0,198,0,48, + 0,199,0,199,0,49,0,200,0,200,0,6,0,201,0,201,0,50,0,202,0,202,0,51,0,203,0,203,0,52,0,204,0,204,0,51,0,205,0,205, + 0,53,0,206,0,206,0,6,0,207,0,207,0,50,0,208,0,208,0,7,0,209,0,209,0,54,0,211,0,211,0,55,0,213,0,213,0,56,0,215, + 0,215,0,56,0,217,0,217,0,56,0,219,0,219,0,56,0,221,0,221,0,24,0,222,0,222,0,51,0,224,0,224,0,57,0,225,0,225,0,26, + 0,226,0,226,0,51,0,228,0,228,0,58,0,241,0,241,0,59,0,245,0,245,0,59,0,251,0,251,0,8,0,255,0,255,0,8,1,10,1,10, + 0,29,1,14,1,14,0,51,1,15,1,15,0,60,1,16,1,16,0,51,1,17,1,17,0,60,1,18,1,18,0,61,1,19,1,19,0,60,1,22, + 1,22,0,8,1,23,1,23,0,31,1,25,1,25,0,59,1,26,1,26,0,8,1,27,1,27,0,31,1,28,1,28,0,13,1,30,1,30,0,13, + 1,32,1,32,0,13,1,33,1,33,0,32,1,34,1,34,0,13,1,35,1,35,0,32,1,36,1,36,0,62,1,37,1,37,0,53,1,38,1,38, + 0,14,1,39,1,39,0,33,1,40,1,40,0,63,1,43,1,43,0,64,1,45,1,45,0,64,1,47,1,47,0,64,1,48,1,48,0,15,1,49, + 1,49,0,34,1,51,1,51,0,64,1,53,1,53,0,64,1,54,1,54,0,65,1,55,1,55,0,66,1,56,1,56,0,67,1,57,1,57,0,68, + 1,58,1,58,0,19,1,63,1,63,0,20,1,136,1,136,0,52,1,172,1,172,0,69,1,173,1,173,0,70,1,174,1,174,0,69,1,175,1,175, + 0,70,1,218,1,218,0,13,1,220,1,220,0,71,1,221,1,221,0,52,1,240,1,240,0,51,1,241,1,241,0,72,1,243,1,243,0,52,1,244, + 1,244,0,73,1,245,1,245,0,74,9,121,9,121,0,65,9,122,9,122,0,75,9,123,9,123,0,76,9,124,9,124,0,66,9,125,9,125,0,65, + 9,126,9,126,0,66,9,235,9,235,0,67,9,236,9,236,0,68,10,250,10,250,0,77,10,251,10,251,0,78,10,252,10,252,0,79,19,20,19,20, + 0,8,0,1,0,97,0,16,0,36,0,37,0,38,0,39,0,41,0,42,0,43,0,45,0,46,0,47,0,50,0,51,0,52,0,53,0,54,0,55, + 0,56,0,57,0,58,0,59,0,60,0,61,0,72,0,73,0,78,0,81,0,82,0,85,0,89,0,90,0,91,0,92,0,109,0,125,0,130,0,131, + 0,132,0,133,0,134,0,136,0,137,0,146,0,148,0,149,0,150,0,151,0,152,0,155,0,156,0,157,0,158,0,159,0,160,0,161,0,170,0,171, + 0,172,0,173,0,178,0,179,0,180,0,181,0,182,0,183,0,184,0,191,0,193,0,194,0,196,0,198,0,200,0,206,0,208,0,210,0,221,0,224, + 0,251,0,255,1,2,1,10,1,22,1,23,1,26,1,27,1,32,1,34,1,38,1,48,1,58,1,63,10,238,10,250,10,252,18,252,19,20,19,21, + 0,2,0,96,0,4,0,0,0,36,0,88,0,5,0,2,0,0,0,0,0,0,255,216,0,0,255,177,0,0,255,163,0,0,255,156,0,1,19,70, + 0,23,0,1,0,2,0,3,0,4,0,1,0,0,0,1,0,2,0,3,0,2,0,1,0,0,0,1,0,2,0,3,0,2,0,1,0,0,0,1, + 0,4,0,3,0,2,0,1,0,1,19,94,0,1,0,1,0,2,0,4,19,70,19,74,0,0,19,76,19,80,0,5,19,82,19,86,0,10,19,88, + 19,92,0,15,0,1,0,0,0,10,2,26,3,124,0,20,68,70,76,84,0,122,97,114,97,98,0,136,97,114,109,110,0,194,98,114,97,105,0,208, + 99,97,110,115,0,220,99,104,101,114,0,232,99,121,114,108,0,244,103,101,111,114,1,22,103,114,101,107,1,34,104,97,110,105,1,50,104,101,98,114, + 1,62,107,97,110,97,1,80,108,97,111,32,1,92,108,97,116,110,1,104,109,97,116,104,1,194,110,107,111,32,1,206,111,103,97,109,1,224,114,117, + 110,114,1,236,116,102,110,103,1,248,116,104,97,105,2,4,0,4,0,0,0,0,0,0,0,2,0,4,0,8,0,22,0,3,75,85,82,32,0,22, + 83,78,68,32,0,40,85,82,68,32,0,40,0,0,255,255,0,6,0,5,0,11,0,15,0,17,0,21,0,23,0,0,255,255,0,6,0,5,0,11, + 0,15,0,17,0,21,0,24,0,4,0,0,0,0,255,255,0,2,0,4,0,9,0,4,0,0,0,0,255,255,0,1,0,4,0,4,0,0,0,0, + 255,255,0,1,0,4,0,4,0,0,0,0,255,255,0,1,0,4,0,16,0,2,77,75,68,32,0,24,83,82,66,32,0,24,0,0,255,255,0,1, + 0,6,0,0,255,255,0,2,0,6,0,19,0,4,0,0,0,0,255,255,0,1,0,4,0,4,0,0,0,0,255,255,0,3,0,1,0,6,0,25, + 0,4,0,0,0,0,255,255,0,1,0,4,0,4,0,0,0,0,255,255,0,4,0,2,0,7,0,13,0,26,0,4,0,0,0,0,255,255,0,1, + 0,4,0,4,0,0,0,0,255,255,0,1,0,4,0,52,0,8,73,83,77,32,0,70,75,83,77,32,0,70,76,83,77,32,0,70,77,79,76,32, + 0,52,78,83,77,32,0,70,82,79,77,32,0,52,83,75,83,32,0,70,83,83,77,32,0,70,0,0,255,255,0,6,0,3,0,6,0,10,0,14, + 0,18,0,27,0,0,255,255,0,7,0,3,0,6,0,10,0,14,0,18,0,20,0,27,0,4,0,0,0,0,255,255,0,1,0,4,0,4,0,0, + 0,0,0,0,0,4,0,5,0,12,0,16,0,22,0,4,0,0,0,0,255,255,0,1,0,4,0,4,0,0,0,0,255,255,0,1,0,4,0,4, + 0,0,0,0,255,255,0,1,0,4,0,4,0,0,0,0,255,255,0,1,0,4,0,28,32,82,81,68,0,170,97,97,108,116,0,176,97,97,108,116, + 0,182,97,97,108,116,0,188,99,99,109,112,0,194,99,99,109,112,0,200,99,99,109,112,0,208,99,99,109,112,0,216,100,108,105,103,0,226,100,108, + 105,103,0,232,100,108,105,103,0,238,102,105,110,97,0,244,102,105,110,97,0,250,104,108,105,103,1,0,104,108,105,103,1,6,105,110,105,116,1,12, + 105,110,105,116,1,18,108,105,103,97,1,24,108,105,103,97,1,32,108,111,99,108,1,38,108,111,99,108,1,44,109,101,100,105,1,50,109,101,100,105, + 1,56,114,108,105,103,1,62,114,108,105,103,1,72,115,97,108,116,1,80,115,97,108,116,1,86,115,97,108,116,1,92,0,0,0,1,0,0,0,0, + 0,1,0,25,0,0,0,1,0,23,0,0,0,1,0,28,0,0,0,1,0,3,0,0,0,2,0,1,0,3,0,0,0,2,0,2,0,3,0,0, + 0,3,0,1,0,3,0,4,0,0,0,1,0,22,0,0,0,1,0,19,0,0,0,1,0,20,0,0,0,1,0,8,0,0,0,1,0,7,0,0, + 0,1,0,38,0,0,0,1,0,21,0,0,0,1,0,12,0,0,0,1,0,11,0,0,0,2,0,16,0,18,0,0,0,1,0,17,0,0,0,1, + 0,5,0,0,0,1,0,6,0,0,0,1,0,10,0,0,0,1,0,9,0,0,0,3,0,13,0,14,0,15,0,0,0,2,0,14,0,15,0,0, + 0,1,0,26,0,0,0,1,0,24,0,0,0,1,0,27,0,39,0,80,0,88,0,96,0,104,0,130,0,138,0,146,0,154,0,162,0,170,0,178, + 0,186,0,194,0,202,0,210,0,218,0,226,0,234,0,242,0,250,1,2,1,10,1,18,1,26,1,34,1,42,1,50,1,58,1,66,1,74,1,82, + 1,90,1,98,1,106,1,114,1,122,1,130,1,138,1,146,0,6,0,9,0,1,1,74,0,6,0,1,0,1,1,190,0,6,0,0,0,1,2,6, + 0,6,0,0,0,10,5,122,5,210,6,42,6,130,6,218,7,50,7,116,7,188,8,4,8,76,0,4,0,1,0,1,8,116,0,1,0,0,0,1, + 8,146,0,1,0,0,0,1,8,150,0,1,0,9,0,1,8,154,0,1,0,9,0,1,8,222,0,1,0,9,0,1,9,216,0,1,0,9,0,1, + 10,28,0,1,0,9,0,1,10,252,0,1,0,9,0,1,11,64,0,4,0,1,0,1,12,32,0,4,0,1,0,1,12,84,0,4,0,9,0,1, + 12,218,0,4,0,9,0,1,12,248,0,4,0,0,0,1,13,54,0,4,0,1,0,1,13,106,0,4,0,0,0,1,14,34,0,4,0,0,0,1, + 14,102,0,4,0,0,0,1,14,118,0,4,0,0,0,1,14,134,0,1,0,1,0,1,15,26,0,1,0,1,0,1,15,30,0,1,0,0,0,1, + 15,34,0,1,0,0,0,1,15,64,0,1,0,0,0,1,15,94,0,3,0,0,0,1,15,116,0,1,0,0,0,1,15,166,0,1,0,0,0,1, + 15,216,0,1,0,0,0,1,16,14,0,1,0,0,0,1,16,22,0,1,0,0,0,1,16,30,0,1,0,0,0,1,16,38,0,1,0,0,0,1, + 16,46,0,1,0,0,0,1,16,54,0,1,0,1,0,1,16,72,0,4,0,1,0,1,16,76,0,2,0,16,0,44,0,44,0,44,0,2,0,0, + 0,72,0,2,0,4,5,241,6,14,0,0,6,28,6,28,0,30,10,235,10,235,0,31,23,32,23,121,0,32,0,2,0,4,5,241,6,14,0,1, + 6,28,6,28,0,1,10,235,10,235,0,1,23,32,23,121,0,1,0,3,0,8,0,24,0,38,0,1,0,1,0,1,0,1,0,1,0,1,0,0, + 0,9,0,1,0,1,0,1,0,0,0,1,0,0,0,7,0,0,0,1,0,1,0,1,0,1,0,0,0,11,0,2,0,18,0,24,0,32,0,32, + 0,3,0,0,0,66,0,0,0,1,0,1,5,56,0,1,0,0,0,1,0,0,0,2,0,5,5,16,5,24,0,2,5,27,5,27,0,2,5,29, + 5,29,0,2,5,37,5,37,0,2,5,56,5,56,0,1,0,1,0,4,0,0,0,1,0,1,0,2,0,0,0,2,0,22,0,140,0,140,0,140, + 0,5,0,0,3,12,3,68,0,0,0,0,0,1,0,57,0,76,0,77,0,241,2,11,2,42,2,95,2,177,2,178,2,179,2,180,2,181,2,182, + 2,183,2,184,2,185,2,186,2,187,2,188,2,189,2,190,2,191,2,192,2,193,2,194,2,195,2,196,2,197,2,238,2,239,2,240,2,241,2,242, + 2,243,2,244,2,245,2,247,2,251,2,252,2,253,3,1,3,2,3,4,3,135,3,234,3,236,4,23,4,24,4,25,4,26,9,38,9,196,11,140, + 11,141,11,142,11,143,11,218,11,219,0,2,0,106,0,36,0,61,0,3,0,69,0,69,0,3,0,71,0,71,0,3,0,73,0,73,0,3,0,75, + 0,75,0,3,0,76,0,77,0,1,0,78,0,79,0,3,0,87,0,87,0,3,0,130,0,152,0,3,0,154,0,161,0,3,0,194,0,194,0,3, + 0,196,0,196,0,3,0,198,0,198,0,3,0,200,0,200,0,3,0,202,0,202,0,3,0,204,0,204,0,3,0,206,0,206,0,3,0,208,0,208, + 0,3,0,210,0,210,0,3,0,212,0,212,0,3,0,214,0,214,0,3,0,216,0,216,0,3,0,218,0,218,0,3,0,220,0,220,0,3,0,222, + 0,222,0,3,0,224,0,224,0,3,0,226,0,226,0,3,0,228,0,228,0,3,0,230,0,234,0,3,0,236,0,236,0,3,0,238,0,238,0,3, + 0,240,0,240,0,3,0,241,0,241,0,1,0,242,0,242,0,3,0,244,0,244,0,3,0,246,0,246,0,3,0,248,0,248,0,3,0,251,1,5, + 0,3,1,7,1,7,0,3,1,9,1,9,0,3,1,12,1,12,0,3,1,14,1,14,0,3,1,16,1,16,0,3,1,18,1,18,0,3,1,20, + 1,20,0,3,1,22,1,22,0,3,1,24,1,24,0,3,1,26,1,26,0,3,1,28,1,28,0,3,1,30,1,30,0,3,1,32,1,32,0,3, + 1,34,1,34,0,3,1,36,1,36,0,3,1,38,1,38,0,3,1,40,1,40,0,3,1,42,1,42,0,3,1,44,1,44,0,3,1,46,1,46, + 0,3,1,48,1,48,0,3,1,50,1,50,0,3,1,52,1,52,0,3,1,54,1,54,0,3,1,56,1,56,0,3,1,58,1,59,0,3,1,61, + 1,61,0,3,1,63,1,63,0,3,1,65,1,65,0,3,1,72,1,72,0,3,1,82,1,82,0,3,1,84,1,84,0,3,1,86,1,86,0,3, + 1,121,1,122,0,3,1,143,1,143,0,3,1,145,1,147,0,3,1,149,1,149,0,3,1,164,1,164,0,3,1,172,1,172,0,3,1,174,1,174, + 0,3,1,218,1,218,0,3,1,220,1,220,0,3,1,240,1,240,0,3,1,244,1,244,0,3,2,11,2,11,0,1,2,42,2,42,0,1,2,95, + 2,95,0,1,2,177,2,197,0,2,2,199,2,202,0,4,2,205,2,228,0,4,2,234,2,237,0,4,2,238,2,245,0,2,2,246,2,246,0,4, + 2,247,2,247,0,2,2,248,2,250,0,4,2,251,2,253,0,2,2,254,2,255,0,4,3,1,3,2,0,2,3,3,3,3,0,4,3,4,3,4, + 0,2,3,135,3,135,0,1,3,234,3,234,0,1,3,236,3,236,0,1,4,23,4,26,0,2,9,38,9,38,0,1,9,196,9,196,0,1,11,140, + 11,143,0,2,11,218,11,219,0,1,0,3,0,8,0,22,0,38,0,0,0,1,0,1,0,2,0,1,0,0,0,30,0,0,0,1,0,2,0,4, + 0,2,0,1,0,0,0,30,0,0,0,1,0,3,0,4,0,4,0,2,0,1,0,0,0,30,0,3,0,8,0,22,0,38,0,1,0,3,0,1, + 0,0,0,1,0,0,0,29,0,2,0,4,0,3,0,1,0,0,0,1,0,0,0,29,0,3,0,4,0,4,0,3,0,1,0,0,0,1,0,0, + 0,29,0,2,0,18,0,28,0,36,0,36,0,3,0,0,0,52,0,70,0,2,0,1,2,167,2,171,0,0,0,1,0,0,0,1,0,0,0,2, + 0,2,2,167,2,167,0,1,2,168,2,171,0,2,0,1,0,4,0,0,0,1,0,1,0,1,0,1,0,0,0,31,0,1,0,4,0,0,0,1, + 0,1,0,1,0,1,0,0,0,31,0,2,0,18,0,28,0,36,0,36,0,3,0,0,0,52,0,70,0,2,0,1,2,167,2,171,0,0,0,1, + 0,0,0,1,0,0,0,1,2,167,0,5,0,2,0,1,0,2,0,2,0,2,0,1,0,4,0,0,0,1,0,1,0,1,0,1,0,0,0,32, + 0,1,0,4,0,0,0,1,0,1,0,1,0,1,0,0,0,32,0,2,0,18,0,28,0,36,0,36,0,3,0,0,0,52,0,70,0,2,0,1, + 2,167,2,171,0,0,0,1,0,0,0,1,0,0,0,1,2,167,0,5,0,2,0,2,0,1,0,2,0,2,0,1,0,4,0,0,0,1,0,1, + 0,1,0,1,0,0,0,33,0,1,0,4,0,0,0,1,0,1,0,1,0,1,0,0,0,33,0,2,0,18,0,28,0,36,0,36,0,3,0,0, + 0,52,0,70,0,2,0,1,2,167,2,171,0,0,0,1,0,0,0,1,0,0,0,1,2,167,0,5,0,2,0,2,0,2,0,1,0,2,0,1, + 0,4,0,0,0,1,0,1,0,1,0,1,0,0,0,34,0,1,0,4,0,0,0,1,0,1,0,1,0,1,0,0,0,34,0,2,0,18,0,28, + 0,36,0,36,0,3,0,0,0,52,0,70,0,2,0,1,2,167,2,171,0,0,0,1,0,0,0,1,0,0,0,2,0,2,2,167,2,170,0,2, + 2,171,2,171,0,1,0,1,0,4,0,0,0,1,0,1,0,1,0,1,0,0,0,35,0,1,0,4,0,0,0,1,0,1,0,1,0,1,0,0, + 0,35,0,2,0,18,0,24,0,24,0,40,0,3,0,0,0,48,0,0,0,1,0,1,2,167,0,2,0,2,2,167,2,167,0,1,19,70,19,73, + 0,2,0,1,0,0,0,1,0,0,0,1,0,4,0,1,0,2,0,1,0,0,0,1,0,0,0,36,0,2,0,18,0,24,0,24,0,46,0,3, + 0,0,0,54,0,0,0,1,0,1,2,168,0,2,0,3,2,168,2,168,0,1,19,74,19,74,0,2,19,76,19,78,0,2,0,1,0,0,0,1, + 0,0,0,1,0,4,0,1,0,2,0,1,0,0,0,1,0,0,0,36,0,2,0,18,0,24,0,24,0,46,0,3,0,0,0,54,0,0,0,1, + 0,1,2,169,0,2,0,3,2,169,2,169,0,1,19,79,19,80,0,2,19,82,19,83,0,2,0,1,0,0,0,1,0,0,0,1,0,4,0,1, + 0,2,0,1,0,0,0,1,0,0,0,36,0,2,0,18,0,24,0,24,0,46,0,3,0,0,0,54,0,0,0,1,0,1,2,170,0,2,0,3, + 2,170,2,170,0,1,19,84,19,86,0,2,19,88,19,88,0,2,0,1,0,0,0,1,0,0,0,1,0,4,0,1,0,2,0,1,0,0,0,1, + 0,0,0,36,0,2,0,18,0,24,0,24,0,40,0,3,0,0,0,48,0,0,0,1,0,1,2,171,0,2,0,2,2,171,2,171,0,1,19,89, + 19,92,0,2,0,1,0,0,0,1,0,0,0,1,0,4,0,1,0,2,0,1,0,0,0,1,0,0,0,36,0,1,0,30,0,2,0,10,0,20, + 0,1,0,4,19,177,0,2,5,20,0,1,0,4,19,179,0,2,5,23,0,1,0,2,5,47,5,67,0,1,0,6,15,223,0,1,0,1,3,197, + 0,1,0,6,21,221,0,1,0,1,1,12,0,2,0,66,0,30,23,32,23,35,23,38,23,41,23,44,23,47,23,50,23,53,23,56,23,59,23,62, + 23,65,23,68,23,71,23,74,23,77,23,80,23,83,23,86,23,89,23,92,23,95,23,98,23,101,23,104,23,107,23,110,23,113,23,116,23,119,0,2, + 0,1,5,241,6,14,0,0,0,2,0,230,0,112,20,102,20,104,20,106,20,108,20,110,20,114,20,116,20,120,20,122,20,126,20,130,20,134,20,138, + 20,142,20,144,20,146,20,148,20,150,20,154,20,158,20,162,20,166,20,170,20,174,20,178,20,182,20,186,20,190,20,194,20,198,20,202,20,206,20,210, + 20,212,20,214,22,202,22,208,19,244,19,236,19,224,22,214,22,217,19,228,19,240,19,232,22,220,22,223,20,4,20,0,22,226,20,8,20,12,20,22, + 23,135,23,136,23,137,20,18,20,16,20,20,23,138,23,139,20,26,23,11,23,140,23,141,23,3,23,142,23,143,20,24,23,144,23,145,23,148,23,151, + 23,154,23,157,23,160,23,163,22,205,23,166,23,169,19,248,23,172,19,252,23,175,23,178,20,28,23,181,23,184,23,187,20,54,23,190,20,32,23,193, + 20,40,23,196,20,36,23,199,23,5,23,202,23,205,23,208,23,211,20,44,20,46,23,214,23,217,20,50,22,229,20,58,20,62,23,8,23,13,0,2, + 0,4,5,79,5,103,0,0,5,105,5,114,0,25,5,142,5,143,0,35,5,146,5,220,0,37,0,2,0,66,0,30,23,33,23,36,23,39,23,42, + 23,45,23,48,23,51,23,54,23,57,23,60,23,63,23,66,23,69,23,72,23,75,23,78,23,81,23,84,23,87,23,90,23,93,23,96,23,99,23,102, + 23,105,23,108,23,111,23,114,23,117,23,120,0,2,0,1,5,241,6,14,0,0,0,2,0,168,0,81,20,112,20,118,20,124,20,128,20,132,20,136, + 20,140,20,152,20,156,20,160,20,164,20,168,20,172,20,176,20,180,20,184,20,188,20,192,20,196,20,200,20,204,20,208,20,60,20,216,22,204,22,210, + 19,246,19,238,19,226,22,216,22,219,19,230,19,242,19,234,22,222,22,225,20,6,20,2,22,228,20,10,20,14,23,147,23,150,23,153,23,156,23,159, + 23,162,23,165,22,207,23,168,23,171,19,250,23,174,19,254,23,177,23,180,20,30,23,183,23,186,23,189,20,56,23,192,20,34,23,195,20,42,23,198, + 20,38,23,201,23,7,23,204,23,207,23,210,23,213,22,212,20,48,23,216,23,219,20,52,22,231,20,64,23,10,0,2,0,10,5,83,5,83,0,0, + 5,85,5,85,0,1,5,87,5,91,0,2,5,96,5,103,0,7,5,105,5,111,0,15,5,113,5,114,0,22,5,142,5,143,0,24,5,146,5,160, + 0,26,5,179,5,216,0,41,5,218,5,219,0,79,0,2,0,66,0,30,23,34,23,37,23,40,23,43,23,46,23,49,23,52,23,55,23,58,23,61, + 23,64,23,67,23,70,23,73,23,76,23,79,23,82,23,85,23,88,23,91,23,94,23,97,23,100,23,103,23,106,23,109,23,112,23,115,23,118,23,121, + 0,2,0,1,5,241,6,14,0,0,0,2,0,168,0,81,20,111,20,117,20,123,20,127,20,131,20,135,20,139,20,151,20,155,20,159,20,163,20,167, + 20,171,20,175,20,179,20,183,20,187,20,191,20,195,20,199,20,203,20,207,20,59,20,215,22,203,22,209,19,245,19,237,19,225,22,215,22,218,19,229, + 19,241,19,233,22,221,22,224,20,5,20,1,22,227,20,9,20,13,23,146,23,149,23,152,23,155,23,158,23,161,23,164,22,206,23,167,23,170,19,249, + 23,173,19,253,23,176,23,179,20,29,23,182,23,185,23,188,20,55,23,191,20,33,23,194,20,41,23,197,20,37,23,200,23,6,23,203,23,206,23,209, + 23,212,22,211,20,47,23,215,23,218,20,51,22,230,20,63,23,9,0,2,0,10,5,83,5,83,0,0,5,85,5,85,0,1,5,87,5,91,0,2, + 5,96,5,103,0,7,5,105,5,111,0,15,5,113,5,114,0,22,5,142,5,143,0,24,5,146,5,160,0,26,5,179,5,216,0,41,5,218,5,219, + 0,79,0,1,0,50,0,3,0,12,0,22,0,32,0,1,0,4,23,26,0,2,5,121,0,1,0,4,23,29,0,2,5,121,0,2,0,6,0,12, + 23,29,0,2,5,120,23,26,0,2,5,117,0,1,0,3,5,117,5,120,5,121,0,1,0,126,0,6,0,18,0,28,0,38,0,56,0,74,0,108, + 0,1,0,4,23,24,0,2,5,121,0,1,0,4,23,25,0,2,5,121,0,2,0,6,0,12,23,30,0,2,5,124,23,27,0,2,5,121,0,2, + 0,6,0,12,23,31,0,2,5,124,23,28,0,2,5,121,0,4,0,10,0,16,0,22,0,28,23,28,0,2,5,119,23,27,0,2,5,118,23,25, + 0,2,5,116,23,24,0,2,5,115,0,2,0,6,0,12,23,31,0,2,5,119,23,30,0,2,5,118,0,1,0,6,5,115,5,116,5,118,5,119, + 5,121,5,124,0,1,0,30,0,2,0,10,0,20,0,1,0,4,20,223,0,2,20,114,0,1,0,4,20,224,0,2,20,114,0,1,0,2,20,195, + 20,196,0,1,0,62,0,2,0,10,0,36,0,3,0,8,0,14,0,20,20,221,0,2,20,108,20,219,0,2,20,104,20,217,0,2,20,102,0,3, + 0,8,0,14,0,20,20,222,0,2,20,108,20,220,0,2,20,104,20,218,0,2,20,102,0,1,0,2,20,195,20,196,0,1,0,54,0,1,0,8, + 0,5,0,12,0,20,0,28,0,34,0,40,19,169,0,3,0,73,0,79,19,168,0,3,0,73,0,76,19,167,0,2,0,79,19,166,0,2,0,76, + 19,165,0,2,0,73,0,1,0,1,0,73,0,1,0,178,0,5,0,16,0,82,0,108,0,158,0,168,0,8,0,18,0,24,0,30,0,36,0,42, + 0,48,0,54,0,60,20,98,0,2,5,122,20,96,0,2,5,121,20,94,0,2,5,120,20,92,0,2,5,119,20,90,0,2,5,118,20,89,0,2, + 5,117,20,87,0,2,5,116,20,85,0,2,5,115,0,3,0,8,0,14,0,20,5,82,0,2,5,125,5,80,0,2,5,124,5,79,0,2,5,123, + 0,6,0,14,0,20,0,26,0,32,0,38,0,44,20,99,0,2,5,122,20,97,0,2,5,121,20,95,0,2,5,120,20,93,0,2,5,119,20,91, + 0,2,5,118,20,86,0,2,5,115,0,1,0,4,5,81,0,2,5,124,0,1,0,4,5,83,0,2,5,124,0,1,0,5,0,3,5,84,5,104, + 5,112,5,114,0,1,0,66,0,3,0,12,0,22,0,56,0,1,0,4,5,13,0,2,5,8,0,4,0,10,0,16,0,22,0,28,19,176,0,2, + 4,243,19,174,0,2,4,241,19,173,0,2,4,235,19,172,0,2,4,252,0,1,0,4,19,175,0,2,4,252,0,1,0,3,4,235,4,250,5,4, + 0,1,0,18,0,1,0,8,0,1,0,4,19,171,0,2,0,87,0,1,0,1,0,86,0,1,0,18,0,1,0,8,0,1,0,4,19,170,0,2, + 0,87,0,1,0,1,1,65,0,1,0,136,0,8,0,22,0,40,0,58,0,70,0,80,0,90,0,102,0,114,0,2,0,6,0,12,11,39,0,2, + 0,34,11,26,0,2,0,4,0,2,0,6,0,12,11,38,0,2,0,4,11,37,0,2,0,34,0,1,0,4,11,205,0,3,0,36,0,59,0,1, + 0,4,11,123,0,2,0,86,0,1,0,4,11,178,0,2,0,48,0,1,0,4,11,179,0,3,0,40,0,47,0,1,0,4,11,147,0,3,0,18, + 0,70,0,2,0,6,0,14,11,153,0,3,0,18,0,88,11,152,0,3,0,18,0,82,0,1,0,8,0,4,0,34,0,41,0,53,0,54,0,55, + 0,68,0,70,0,1,0,6,14,147,0,1,0,1,5,31,0,1,0,6,14,147,0,1,0,1,5,31,0,2,0,20,0,7,3,103,3,102,3,104, + 3,100,3,101,3,106,3,105,0,1,0,7,3,35,3,57,3,63,3,70,3,76,3,84,3,90,0,2,0,20,0,7,3,103,3,102,3,104,3,100, + 3,101,3,106,3,105,0,1,0,7,3,35,3,57,3,63,3,70,3,76,3,84,3,90,0,2,0,16,0,5,23,22,23,2,2,19,23,12,22,233, + 0,1,0,5,0,44,0,45,0,68,0,79,1,12,0,1,0,42,0,6,0,18,0,22,0,26,0,30,0,34,0,38,0,1,23,22,0,1,23,2, + 0,1,2,19,0,1,23,12,0,1,23,134,0,1,22,233,0,1,0,6,0,44,0,45,0,68,0,79,0,92,1,12,0,2,0,30,0,12,22,188, + 22,186,22,189,22,187,22,192,22,193,22,185,23,122,22,194,22,190,22,195,22,191,0,1,0,12,2,177,2,178,2,179,2,180,2,183,2,184,2,185, + 2,187,2,188,2,189,2,192,2,194,0,2,0,32,0,13,0,243,1,249,23,16,2,33,22,234,22,235,1,249,0,243,1,249,23,19,23,20,23,17, + 23,18,0,1,0,13,0,76,0,77,0,241,2,11,2,42,2,95,3,135,3,234,3,236,9,38,9,196,11,218,11,219,0,1,0,6,16,158,0,2, + 0,1,2,167,2,171,0,0,0,1,0,6,16,163,0,2,0,1,2,167,2,171,0,0,0,1,0,6,16,168,0,2,0,1,2,167,2,171,0,0, + 0,1,0,6,16,173,0,2,0,1,2,167,2,171,0,0,0,1,0,6,16,178,0,2,0,1,2,167,2,171,0,0,0,2,0,16,0,5,19,94, + 19,94,19,94,19,94,19,94,0,2,0,1,2,167,2,171,0,0,0,1,0,6,14,124,0,1,0,1,5,56,0,1,0,18,0,1,0,8,0,1, + 0,4,19,222,0,2,5,50,0,1,0,1,5,38,0,0,0,1,4,14,1,144,0,5,0,0,5,51,5,153,0,0,1,30,5,51,5,153,0,0, + 3,215,0,102,2,18,0,0,2,11,6,3,3,8,4,2,2,4,231,0,110,255,210,0,253,255,10,36,96,41,4,0,32,12,80,102,69,100,0,64, + 0,32,255,255,6,20,254,20,1,154,7,109,1,227,96,0,1,255,223,255,0,0,0,0,0,0,0,5,0,0,0,3,0,0,0,44,0,0,0,4, + 0,0,7,188,0,1,0,0,0,0,19,252,0,3,0,1,0,0,0,44,0,3,0,10,0,0,7,188,0,4,7,144,0,0,1,224,1,0,0,7, + 0,224,0,0,0,126,2,233,2,238,2,243,2,247,3,79,3,83,3,88,3,90,3,98,3,119,3,126,3,138,3,140,3,161,5,37,5,86,5,95, + 5,135,5,138,5,195,5,199,5,234,5,244,6,7,6,10,6,12,6,21,6,27,6,31,6,58,6,85,6,87,6,90,6,112,6,116,6,191,6,198, + 6,204,6,206,6,213,6,249,7,231,7,245,7,250,14,63,14,130,14,132,14,136,14,138,14,141,14,151,14,159,14,163,14,165,14,167,14,171,14,185, + 14,189,14,196,14,198,14,205,14,217,14,221,16,197,16,252,20,7,20,27,20,53,20,74,20,82,20,189,20,234,21,7,21,62,21,80,21,106,21,133, + 21,150,21,175,21,222,21,225,22,71,22,118,22,156,29,20,29,35,29,46,29,91,29,106,29,120,29,123,29,125,29,133,29,191,29,201,30,251,31,21, + 31,29,31,69,31,77,31,87,31,89,31,91,31,93,31,125,31,180,31,196,31,211,31,219,31,239,31,244,31,254,32,100,32,113,32,142,32,156,32,181, + 32,186,32,209,32,215,32,220,32,225,33,9,33,73,33,75,33,78,33,133,33,137,35,17,35,25,35,33,35,40,35,44,35,117,35,122,35,125,35,135, + 35,148,35,174,35,207,35,227,35,229,35,232,36,35,36,105,38,156,38,184,38,195,38,226,39,4,39,9,39,39,39,75,39,77,39,82,39,86,39,94, + 39,148,39,175,39,190,39,198,39,224,39,235,40,255,41,7,41,11,41,65,41,132,41,213,41,235,41,251,42,2,42,28,42,47,42,107,42,160,42,186, + 42,250,43,26,43,36,43,84,44,119,44,127,45,37,45,101,45,111,46,24,46,30,46,37,46,46,77,255,164,255,166,71,166,77,166,81,166,87,166,110, + 166,141,166,149,167,22,167,31,167,43,167,65,167,75,167,83,167,87,167,103,167,131,167,142,167,145,167,170,167,255,239,25,240,3,244,38,244,65,246,197, + 251,6,251,23,251,54,251,60,251,62,251,65,251,68,251,79,251,163,251,173,251,214,251,218,251,233,251,255,254,15,254,35,254,116,254,252,254,255,255,253, + 255,255,0,0,0,0,0,32,0,160,2,236,2,243,2,247,3,0,3,81,3,87,3,90,3,92,3,112,3,122,3,132,3,140,3,142,3,163,5,49, + 5,89,5,97,5,137,5,176,5,198,5,208,5,240,6,6,6,9,6,12,6,21,6,27,6,31,6,33,6,64,6,87,6,90,6,96,6,116,6,121, + 6,198,6,204,6,206,6,213,6,240,7,192,7,235,7,248,14,63,14,129,14,132,14,135,14,138,14,141,14,148,14,153,14,161,14,165,14,167,14,170, + 14,173,14,187,14,192,14,198,14,200,14,208,14,220,16,160,16,208,20,1,20,9,20,29,20,55,20,76,20,84,20,192,20,236,21,16,21,64,21,82, + 21,116,21,138,21,160,21,222,21,225,22,70,22,110,22,128,29,0,29,22,29,38,29,48,29,93,29,119,29,123,29,125,29,133,29,155,29,196,30,0, + 31,0,31,24,31,32,31,72,31,80,31,89,31,91,31,93,31,95,31,128,31,182,31,198,31,214,31,221,31,242,31,246,32,0,32,106,32,116,32,144, + 32,160,32,184,32,208,32,214,32,219,32,225,33,0,33,11,33,75,33,78,33,80,33,137,33,144,35,24,35,28,35,36,35,43,35,115,35,122,35,125, + 35,135,35,148,35,155,35,206,35,227,35,229,35,232,36,34,36,96,37,0,38,160,38,192,38,226,39,1,39,6,39,12,39,41,39,77,39,79,39,86, + 39,88,39,97,39,152,39,177,39,197,39,224,39,230,39,240,41,6,41,10,41,64,41,131,41,206,41,235,41,250,42,0,42,12,42,47,42,106,42,125, + 42,174,42,249,43,0,43,31,43,83,44,96,44,121,45,0,45,48,45,111,46,24,46,30,46,34,46,46,77,192,164,208,166,68,166,76,166,80,166,84, + 166,98,166,138,166,148,167,8,167,27,167,34,167,48,167,70,167,78,167,86,167,100,167,128,167,137,167,144,167,160,167,250,239,0,240,0,244,0,244,40, + 246,197,251,0,251,19,251,29,251,56,251,62,251,64,251,67,251,70,251,82,251,170,251,211,251,217,251,232,251,252,254,0,254,32,254,112,254,118,254,255, + 255,249,255,255,0,0,255,227,255,194,255,192,255,188,255,185,255,177,255,176,255,173,255,172,255,171,255,158,255,156,255,151,255,150,255,149,255,148,255,137, + 255,135,255,134,255,133,255,96,255,94,255,86,255,81,255,64,255,63,255,62,255,54,255,49,255,46,255,45,255,40,255,39,255,37,255,32,255,29,255,25, + 255,19,255,14,255,13,255,7,254,237,254,39,254,36,254,34,247,222,247,157,247,156,247,154,247,153,247,151,247,145,247,144,247,143,247,142,247,141,247,139, + 247,138,247,137,247,135,247,134,247,133,247,131,247,129,245,191,245,181,242,177,242,176,242,175,242,174,242,173,242,172,242,170,242,169,242,161,242,160,242,159, + 242,150,242,146,242,137,242,91,242,89,241,245,241,207,241,198,235,99,235,98,235,96,235,95,235,94,235,82,235,80,235,79,235,72,235,51,235,47,234,249, + 234,245,234,243,234,241,234,239,234,237,234,236,234,235,234,234,234,233,234,231,234,230,234,229,234,227,234,226,234,224,234,223,234,222,234,217,234,215,234,214, + 234,211,234,209,234,188,234,184,234,181,234,177,234,147,234,146,234,145,234,143,234,142,234,139,234,133,234,127,234,125,234,123,234,121,234,51,234,47,234,45, + 234,36,234,24,234,18,233,243,233,224,233,223,233,221,233,164,233,104,232,210,232,207,232,200,232,170,232,140,232,139,232,137,232,136,232,135,232,134,232,131, + 232,130,232,128,232,125,232,124,232,118,232,93,232,88,232,84,232,78,232,76,232,24,231,215,231,142,231,121,231,107,231,103,231,94,231,76,231,18,231,1, + 230,244,230,182,230,177,230,173,230,127,229,116,229,115,228,243,228,233,228,224,228,56,228,51,228,48,228,40,196,151,109,199,108,131,108,127,108,125,108,123, + 108,113,108,86,108,80,107,222,107,218,107,216,107,212,107,208,107,206,107,204,107,192,107,168,107,163,107,162,107,148,107,69,36,69,35,95,31,99,31,98, + 28,223,24,165,24,153,24,148,24,147,24,146,24,145,24,144,24,143,24,141,24,135,24,98,24,96,24,83,24,65,22,65,22,49,21,229,21,228,21,226, + 20,233,0,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,12,0,0,0,0,12,64,0,0,0,0,0,0,1,4,0,0,0,32,0,0,0,126,0,0,0,3,0,0,0,160,0,0,2,233, + 0,0,0,98,0,0,2,236,0,0,2,238,0,0,2,172,0,0,2,243,0,0,2,243,0,0,2,175,0,0,2,247,0,0,2,247,0,0,2,176, + 0,0,3,0,0,0,3,79,0,0,2,177,0,0,3,81,0,0,3,83,0,0,3,1,0,0,3,87,0,0,3,88,0,0,3,4,0,0,3,90, + 0,0,3,90,0,0,3,6,0,0,3,92,0,0,3,98,0,0,3,7,0,0,3,112,0,0,3,119,0,0,3,14,0,0,3,122,0,0,3,126, + 0,0,3,22,0,0,3,132,0,0,3,138,0,0,3,27,0,0,3,140,0,0,3,140,0,0,3,34,0,0,3,142,0,0,3,161,0,0,3,35, + 0,0,3,163,0,0,5,37,0,0,3,55,0,0,5,49,0,0,5,86,0,0,4,186,0,0,5,89,0,0,5,95,0,0,4,224,0,0,5,97, + 0,0,5,135,0,0,4,231,0,0,5,137,0,0,5,138,0,0,5,14,0,0,5,176,0,0,5,195,0,0,5,16,0,0,5,198,0,0,5,199, + 0,0,5,36,0,0,5,208,0,0,5,234,0,0,5,38,0,0,5,240,0,0,5,244,0,0,5,65,0,0,6,6,0,0,6,7,0,0,5,70, + 0,0,6,9,0,0,6,10,0,0,5,72,0,0,6,12,0,0,6,12,0,0,5,74,0,0,6,21,0,0,6,21,0,0,5,75,0,0,6,27, + 0,0,6,27,0,0,5,76,0,0,6,31,0,0,6,31,0,0,5,77,0,0,6,33,0,0,6,58,0,0,5,78,0,0,6,64,0,0,6,85, + 0,0,5,104,0,0,6,87,0,0,6,87,0,0,5,126,0,0,6,90,0,0,6,90,0,0,5,127,0,0,6,96,0,0,6,112,0,0,5,128, + 0,0,6,116,0,0,6,116,0,0,5,145,0,0,6,121,0,0,6,191,0,0,5,146,0,0,6,198,0,0,6,198,0,0,5,217,0,0,6,204, + 0,0,6,204,0,0,5,218,0,0,6,206,0,0,6,206,0,0,5,219,0,0,6,213,0,0,6,213,0,0,5,220,0,0,6,240,0,0,6,249, + 0,0,5,221,0,0,7,192,0,0,7,231,0,0,5,231,0,0,7,235,0,0,7,245,0,0,6,15,0,0,7,248,0,0,7,250,0,0,6,26, + 0,0,14,63,0,0,14,63,0,0,6,29,0,0,14,129,0,0,14,130,0,0,6,30,0,0,14,132,0,0,14,132,0,0,6,32,0,0,14,135, + 0,0,14,136,0,0,6,33,0,0,14,138,0,0,14,138,0,0,6,35,0,0,14,141,0,0,14,141,0,0,6,36,0,0,14,148,0,0,14,151, + 0,0,6,37,0,0,14,153,0,0,14,159,0,0,6,41,0,0,14,161,0,0,14,163,0,0,6,48,0,0,14,165,0,0,14,165,0,0,6,51, + 0,0,14,167,0,0,14,167,0,0,6,52,0,0,14,170,0,0,14,171,0,0,6,53,0,0,14,173,0,0,14,185,0,0,6,55,0,0,14,187, + 0,0,14,189,0,0,6,68,0,0,14,192,0,0,14,196,0,0,6,71,0,0,14,198,0,0,14,198,0,0,6,76,0,0,14,200,0,0,14,205, + 0,0,6,77,0,0,14,208,0,0,14,217,0,0,6,83,0,0,14,220,0,0,14,221,0,0,6,93,0,0,16,160,0,0,16,197,0,0,6,95, + 0,0,16,208,0,0,16,252,0,0,6,133,0,0,20,1,0,0,20,7,0,0,6,178,0,0,20,9,0,0,20,27,0,0,6,185,0,0,20,29, + 0,0,20,53,0,0,6,204,0,0,20,55,0,0,20,74,0,0,6,229,0,0,20,76,0,0,20,82,0,0,6,249,0,0,20,84,0,0,20,189, + 0,0,7,0,0,0,20,192,0,0,20,234,0,0,7,106,0,0,20,236,0,0,21,7,0,0,7,149,0,0,21,16,0,0,21,62,0,0,7,177, + 0,0,21,64,0,0,21,80,0,0,7,224,0,0,21,82,0,0,21,106,0,0,7,241,0,0,21,116,0,0,21,133,0,0,8,10,0,0,21,138, + 0,0,21,150,0,0,8,28,0,0,21,160,0,0,21,175,0,0,8,41,0,0,21,222,0,0,21,222,0,0,8,57,0,0,21,225,0,0,21,225, + 0,0,8,58,0,0,22,70,0,0,22,71,0,0,8,59,0,0,22,110,0,0,22,118,0,0,8,61,0,0,22,128,0,0,22,156,0,0,8,70, + 0,0,29,0,0,0,29,20,0,0,8,99,0,0,29,22,0,0,29,35,0,0,8,120,0,0,29,38,0,0,29,46,0,0,8,134,0,0,29,48, + 0,0,29,91,0,0,8,143,0,0,29,93,0,0,29,106,0,0,8,187,0,0,29,119,0,0,29,120,0,0,8,201,0,0,29,123,0,0,29,123, + 0,0,8,203,0,0,29,125,0,0,29,125,0,0,8,204,0,0,29,133,0,0,29,133,0,0,8,205,0,0,29,155,0,0,29,191,0,0,8,206, + 0,0,29,196,0,0,29,201,0,0,8,243,0,0,30,0,0,0,30,251,0,0,8,249,0,0,31,0,0,0,31,21,0,0,9,245,0,0,31,24, + 0,0,31,29,0,0,10,11,0,0,31,32,0,0,31,69,0,0,10,17,0,0,31,72,0,0,31,77,0,0,10,55,0,0,31,80,0,0,31,87, + 0,0,10,61,0,0,31,89,0,0,31,89,0,0,10,69,0,0,31,91,0,0,31,91,0,0,10,70,0,0,31,93,0,0,31,93,0,0,10,71, + 0,0,31,95,0,0,31,125,0,0,10,72,0,0,31,128,0,0,31,180,0,0,10,103,0,0,31,182,0,0,31,196,0,0,10,156,0,0,31,198, + 0,0,31,211,0,0,10,171,0,0,31,214,0,0,31,219,0,0,10,185,0,0,31,221,0,0,31,239,0,0,10,191,0,0,31,242,0,0,31,244, + 0,0,10,210,0,0,31,246,0,0,31,254,0,0,10,213,0,0,32,0,0,0,32,100,0,0,10,222,0,0,32,106,0,0,32,113,0,0,11,67, + 0,0,32,116,0,0,32,142,0,0,11,75,0,0,32,144,0,0,32,156,0,0,11,102,0,0,32,160,0,0,32,181,0,0,11,115,0,0,32,184, + 0,0,32,186,0,0,11,137,0,0,32,208,0,0,32,209,0,0,11,140,0,0,32,214,0,0,32,215,0,0,11,142,0,0,32,219,0,0,32,220, + 0,0,11,144,0,0,32,225,0,0,32,225,0,0,11,146,0,0,33,0,0,0,33,9,0,0,11,147,0,0,33,11,0,0,33,73,0,0,11,157, + 0,0,33,75,0,0,33,75,0,0,11,220,0,0,33,78,0,0,33,78,0,0,11,221,0,0,33,80,0,0,33,133,0,0,11,222,0,0,33,137, + 0,0,33,137,0,0,12,20,0,0,33,144,0,0,35,17,0,0,12,21,0,0,35,24,0,0,35,25,0,0,13,151,0,0,35,28,0,0,35,33, + 0,0,13,153,0,0,35,36,0,0,35,40,0,0,13,159,0,0,35,43,0,0,35,44,0,0,13,164,0,0,35,115,0,0,35,117,0,0,13,166, + 0,0,35,122,0,0,35,122,0,0,13,169,0,0,35,125,0,0,35,125,0,0,13,170,0,0,35,135,0,0,35,135,0,0,13,171,0,0,35,148, + 0,0,35,148,0,0,13,172,0,0,35,155,0,0,35,174,0,0,13,173,0,0,35,206,0,0,35,207,0,0,13,193,0,0,35,227,0,0,35,227, + 0,0,13,195,0,0,35,229,0,0,35,229,0,0,13,196,0,0,35,232,0,0,35,232,0,0,13,197,0,0,36,34,0,0,36,35,0,0,13,198, + 0,0,36,96,0,0,36,105,0,0,13,200,0,0,37,0,0,0,38,156,0,0,13,210,0,0,38,160,0,0,38,184,0,0,15,111,0,0,38,192, + 0,0,38,195,0,0,15,136,0,0,38,226,0,0,38,226,0,0,15,140,0,0,39,1,0,0,39,4,0,0,15,141,0,0,39,6,0,0,39,9, + 0,0,15,145,0,0,39,12,0,0,39,39,0,0,15,149,0,0,39,41,0,0,39,75,0,0,15,177,0,0,39,77,0,0,39,77,0,0,15,212, + 0,0,39,79,0,0,39,82,0,0,15,213,0,0,39,86,0,0,39,86,0,0,15,217,0,0,39,88,0,0,39,94,0,0,15,218,0,0,39,97, + 0,0,39,148,0,0,15,225,0,0,39,152,0,0,39,175,0,0,16,21,0,0,39,177,0,0,39,190,0,0,16,45,0,0,39,197,0,0,39,198, + 0,0,16,59,0,0,39,224,0,0,39,224,0,0,16,61,0,0,39,230,0,0,39,235,0,0,16,62,0,0,39,240,0,0,40,255,0,0,16,68, + 0,0,41,6,0,0,41,7,0,0,17,84,0,0,41,10,0,0,41,11,0,0,17,86,0,0,41,64,0,0,41,65,0,0,17,88,0,0,41,131, + 0,0,41,132,0,0,17,90,0,0,41,206,0,0,41,213,0,0,17,92,0,0,41,235,0,0,41,235,0,0,17,100,0,0,41,250,0,0,41,251, + 0,0,17,101,0,0,42,0,0,0,42,2,0,0,17,103,0,0,42,12,0,0,42,28,0,0,17,106,0,0,42,47,0,0,42,47,0,0,17,123, + 0,0,42,106,0,0,42,107,0,0,17,124,0,0,42,125,0,0,42,160,0,0,17,126,0,0,42,174,0,0,42,186,0,0,17,162,0,0,42,249, + 0,0,42,250,0,0,17,175,0,0,43,0,0,0,43,26,0,0,17,177,0,0,43,31,0,0,43,36,0,0,17,204,0,0,43,83,0,0,43,84, + 0,0,17,210,0,0,44,96,0,0,44,119,0,0,17,212,0,0,44,121,0,0,44,127,0,0,17,236,0,0,45,0,0,0,45,37,0,0,17,243, + 0,0,45,48,0,0,45,101,0,0,18,25,0,0,45,111,0,0,45,111,0,0,18,79,0,0,46,24,0,0,46,24,0,0,18,80,0,0,46,30, + 0,0,46,30,0,0,18,81,0,0,46,34,0,0,46,37,0,0,18,82,0,0,46,46,0,0,46,46,0,0,18,86,0,0,77,192,0,0,77,255, + 0,0,18,87,0,0,164,208,0,0,164,255,0,0,18,151,0,0,166,68,0,0,166,71,0,0,18,199,0,0,166,76,0,0,166,77,0,0,18,203, + 0,0,166,80,0,0,166,81,0,0,18,205,0,0,166,84,0,0,166,87,0,0,18,207,0,0,166,98,0,0,166,110,0,0,18,211,0,0,166,138, + 0,0,166,141,0,0,18,224,0,0,166,148,0,0,166,149,0,0,18,228,0,0,167,8,0,0,167,22,0,0,18,230,0,0,167,27,0,0,167,31, + 0,0,18,245,0,0,167,34,0,0,167,43,0,0,18,250,0,0,167,48,0,0,167,65,0,0,19,4,0,0,167,70,0,0,167,75,0,0,19,22, + 0,0,167,78,0,0,167,83,0,0,19,28,0,0,167,86,0,0,167,87,0,0,19,34,0,0,167,100,0,0,167,103,0,0,19,36,0,0,167,128, + 0,0,167,131,0,0,19,40,0,0,167,137,0,0,167,142,0,0,19,44,0,0,167,144,0,0,167,145,0,0,19,50,0,0,167,160,0,0,167,170, + 0,0,19,52,0,0,167,250,0,0,167,255,0,0,19,63,0,0,239,0,0,0,239,25,0,0,19,69,0,0,240,0,0,0,240,3,0,0,19,95, + 0,0,244,0,0,0,244,38,0,0,19,99,0,0,244,40,0,0,244,65,0,0,19,138,0,0,246,197,0,0,246,197,0,0,19,164,0,0,251,0, + 0,0,251,6,0,0,19,165,0,0,251,19,0,0,251,23,0,0,19,172,0,0,251,29,0,0,251,54,0,0,19,177,0,0,251,56,0,0,251,60, + 0,0,19,203,0,0,251,62,0,0,251,62,0,0,19,208,0,0,251,64,0,0,251,65,0,0,19,209,0,0,251,67,0,0,251,68,0,0,19,211, + 0,0,251,70,0,0,251,79,0,0,19,213,0,0,251,82,0,0,251,163,0,0,19,223,0,0,251,170,0,0,251,173,0,0,20,49,0,0,251,211, + 0,0,251,214,0,0,20,53,0,0,251,217,0,0,251,218,0,0,20,57,0,0,251,232,0,0,251,233,0,0,20,59,0,0,251,252,0,0,251,255, + 0,0,20,61,0,0,254,0,0,0,254,15,0,0,20,65,0,0,254,32,0,0,254,35,0,0,20,81,0,0,254,112,0,0,254,116,0,0,20,85, + 0,0,254,118,0,0,254,252,0,0,20,90,0,0,254,255,0,0,254,255,0,0,20,225,0,0,255,249,0,0,255,253,0,0,20,226,0,1,3,0, + 0,1,3,30,0,0,20,231,0,1,3,32,0,1,3,35,0,0,21,6,0,1,211,0,0,1,211,86,0,0,21,10,0,1,213,56,0,1,213,57, + 0,0,21,97,0,1,213,59,0,1,213,62,0,0,21,99,0,1,213,64,0,1,213,68,0,0,21,103,0,1,213,70,0,1,213,70,0,0,21,108, + 0,1,213,74,0,1,213,80,0,0,21,109,0,1,213,82,0,1,213,107,0,0,21,116,0,1,213,160,0,1,213,211,0,0,21,142,0,1,215,216, + 0,1,215,235,0,0,21,194,0,1,240,48,0,1,240,147,0,0,21,214,0,1,240,160,0,1,240,174,0,0,22,58,0,1,240,177,0,1,240,190, + 0,0,22,73,0,1,240,193,0,1,240,207,0,0,22,87,0,1,240,209,0,1,240,223,0,0,22,102,0,1,244,45,0,1,244,46,0,0,22,117, + 0,1,244,49,0,1,244,49,0,0,22,119,0,1,244,53,0,1,244,53,0,0,22,120,0,1,246,0,0,1,246,35,0,0,22,121,0,1,246,37, + 0,1,246,43,0,0,22,157,0,1,246,45,0,1,246,64,0,0,22,164,0,6,2,10,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,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,0,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,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,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55, + 0,56,0,57,0,58,0,59,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75, + 0,76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92,0,93,0,94,0,95, + 0,96,0,97,0,0,0,134,0,135,0,137,0,139,0,147,0,152,0,158,0,163,0,162,0,164,0,166,0,165,0,167,0,169,0,171,0,170,0,172, + 0,173,0,175,0,174,0,176,0,177,0,179,0,181,0,180,0,182,0,184,0,183,0,188,0,187,0,189,0,190,10,254,0,114,0,100,0,101,0,105, + 11,0,0,120,0,161,0,112,0,107,11,180,0,118,0,106,12,229,0,136,0,154,12,163,0,115,12,233,12,234,0,103,0,119,12,135,12,150,12,148, + 3,84,12,176,0,108,0,124,3,61,0,168,0,186,0,129,0,99,0,110,12,159,1,84,12,205,12,139,0,109,0,125,11,4,0,98,0,130,0,133, + 0,151,1,20,1,21,10,241,10,242,10,250,10,251,10,246,10,247,0,185,14,156,0,193,1,58,11,34,11,127,11,23,11,24,19,166,19,167,10,255, + 0,121,10,248,10,252,11,14,0,132,0,140,0,131,0,141,0,138,0,143,0,144,0,145,0,142,0,149,0,150,0,0,0,148,0,156,0,157,0,155, + 0,243,2,136,2,158,0,113,2,154,2,155,2,156,0,122,2,159,2,157,2,137,0,0,1,53,0,184,0,203,0,203,0,193,0,170,0,156,1,166, + 0,184,0,102,0,0,0,113,0,203,0,160,2,178,0,133,0,117,0,184,0,195,1,203,1,137,2,45,0,203,0,166,0,240,0,211,0,170,0,135, + 0,203,3,170,4,0,1,74,0,51,0,203,0,0,0,217,5,2,0,244,1,84,0,180,0,156,1,57,1,20,1,57,7,6,4,0,4,78,4,180, + 4,82,4,184,4,231,4,205,0,55,4,115,4,205,4,96,4,115,1,51,3,162,5,86,5,166,5,86,5,57,3,197,2,18,0,201,0,31,0,184, + 1,223,0,115,0,186,3,233,3,51,3,188,4,68,4,14,0,223,3,205,3,170,0,229,3,170,4,4,0,0,0,203,0,143,0,164,0,123,0,184, + 0,20,1,111,0,127,2,123,2,82,0,143,0,199,5,205,0,154,0,154,0,111,0,203,0,205,1,158,1,211,0,240,0,186,1,131,0,213,0,152, + 3,4,2,72,0,158,1,213,0,193,0,203,0,246,0,131,3,84,2,127,0,0,3,51,2,102,0,211,0,199,0,164,0,205,0,143,0,154,0,115, + 4,0,5,213,1,10,0,254,2,43,0,164,0,180,0,156,0,0,0,98,0,156,0,0,0,29,3,45,5,213,5,213,5,213,5,240,0,127,0,123, + 0,84,0,164,6,184,6,20,7,35,1,211,0,184,0,203,0,166,1,195,1,236,6,147,0,160,0,211,3,92,3,113,3,219,1,133,4,35,4,168, + 4,72,0,143,1,57,1,20,1,57,3,96,0,143,5,213,1,154,6,20,7,35,6,102,1,121,4,96,4,96,4,96,4,123,0,156,0,0,2,119, + 4,96,1,170,0,233,4,96,7,98,0,123,0,197,0,127,2,123,0,0,0,180,2,82,5,205,0,102,0,188,0,102,0,119,6,16,0,205,1,59, + 1,133,3,137,0,143,0,123,0,0,0,29,0,205,7,74,4,47,0,156,0,156,0,0,7,125,0,111,0,0,0,111,3,53,0,106,0,111,0,123, + 0,174,0,178,0,45,3,150,0,143,2,123,0,246,0,131,3,84,6,55,5,246,0,143,0,156,4,225,2,102,0,143,1,141,2,246,0,205,3,68, + 0,41,0,102,4,238,0,115,0,0,20,0,0,150,0,0,183,7,6,5,4,3,2,1,0,44,32,16,176,2,37,73,100,176,64,81,88,32,200,89, + 33,45,44,176,2,37,73,100,176,64,81,88,32,200,89,33,45,44,32,16,7,32,176,0,80,176,13,121,32,184,255,255,80,88,4,27,5,89,176,5, + 28,176,3,37,8,176,4,37,35,225,32,176,0,80,176,13,121,32,184,255,255,80,88,4,27,5,89,176,5,28,176,3,37,8,225,45,44,75,80,88, + 32,176,253,69,68,89,33,45,44,176,2,37,69,96,68,45,44,75,83,88,176,2,37,176,2,37,69,68,89,33,33,45,44,69,68,45,44,176,2,37, + 176,2,37,73,176,5,37,176,5,37,73,96,176,32,99,104,32,138,16,138,35,58,138,16,101,58,45,0,0,0,0,2,0,8,0,2,255,255,0,3, + 0,2,0,102,254,150,4,102,5,164,0,3,0,7,0,26,64,12,4,251,0,6,251,1,8,5,127,2,4,0,47,196,212,236,49,0,16,212,236,212, + 236,48,19,17,33,17,37,33,17,33,102,4,0,252,115,3,27,252,229,254,150,7,14,248,242,114,6,41,0,2,1,53,0,0,2,0,5,213,0,3, + 0,9,0,53,64,15,7,0,131,4,129,2,8,7,5,1,3,4,0,0,10,16,252,75,176,11,84,88,185,0,0,255,192,56,89,60,236,50,57,57, + 49,0,47,228,252,204,48,1,182,0,11,32,11,80,11,3,93,37,51,21,35,17,51,17,3,35,3,1,53,203,203,203,20,162,21,254,254,5,213,253, + 113,254,155,1,101,0,0,0,0,2,0,197,3,170,2,233,5,213,0,3,0,7,0,66,64,15,5,1,132,4,0,129,8,4,5,6,0,5,2,4, + 8,16,252,75,176,18,84,75,176,19,84,91,88,185,0,2,255,192,56,89,252,220,236,49,0,16,244,60,236,50,48,1,64,15,48,9,64,9,80,9, + 96,9,112,9,160,9,191,9,7,93,1,17,35,17,33,17,35,17,1,111,170,2,36,170,5,213,253,213,2,43,253,213,2,43,0,0,0,2,0,158, + 0,0,6,23,5,190,0,3,0,31,0,96,64,49,27,11,0,135,7,4,29,9,5,25,13,2,135,23,19,15,21,17,31,30,28,27,26,23,22,21, + 20,19,18,17,16,14,13,12,9,8,7,6,5,4,3,2,1,0,26,10,24,6,32,16,252,204,23,57,49,0,47,60,212,60,60,252,60,60,212,60, + 60,196,50,236,50,50,48,64,17,11,1,11,2,11,12,11,13,20,4,26,17,26,18,20,31,8,1,93,1,33,3,33,11,1,33,19,51,3,33,21, + 33,3,33,21,33,3,35,19,33,3,35,19,33,53,33,19,33,53,33,19,4,23,254,221,84,1,37,68,104,1,36,105,160,103,1,56,254,161,82,1, + 62,254,155,104,160,103,254,219,103,161,104,254,197,1,96,84,254,190,1,105,102,3,133,254,178,3,135,254,97,1,159,254,97,154,254,178,153,254,98,1, + 158,254,98,1,158,153,1,78,154,1,159,0,0,3,0,170,254,211,4,109,6,20,0,33,0,40,0,47,0,189,64,85,34,2,10,11,10,39,1,38, + 40,2,11,11,10,29,1,30,28,2,47,41,47,27,2,41,41,47,66,19,17,16,34,10,27,41,4,23,6,9,42,33,5,2,23,134,22,6,134,5, + 17,35,26,138,22,137,16,0,42,138,5,137,2,45,8,22,10,30,7,41,26,18,3,0,9,34,16,9,3,1,7,38,8,13,5,6,48,16,252,75, + 176,9,84,88,185,0,5,255,192,56,89,75,176,12,84,75,176,16,84,91,75,176,15,84,91,88,185,0,5,0,64,56,89,60,236,244,23,60,252,23, + 60,244,228,236,49,0,47,228,236,196,212,228,236,50,196,16,238,16,238,17,18,57,17,57,17,18,23,57,17,18,57,48,75,83,88,7,16,4,237,7, + 16,14,237,17,23,57,7,16,14,237,17,23,57,7,16,4,237,89,34,1,35,3,46,1,39,53,30,1,23,17,46,1,53,52,54,55,53,51,21,30, + 1,23,21,46,1,39,17,30,1,21,20,6,7,3,17,14,1,21,20,22,23,17,62,1,53,52,38,2,180,100,1,105,210,106,102,209,111,221,201,218, + 204,100,93,174,83,83,175,92,227,214,227,214,100,116,122,113,225,127,129,123,254,211,1,45,2,45,45,180,64,65,1,1,200,36,172,150,163,188,14,235, + 232,4,31,27,175,42,46,4,254,85,35,180,156,169,195,15,3,0,1,154,13,106,88,86,96,213,254,79,17,110,90,88,104,0,0,0,0,5,0,113, + 255,227,7,41,5,240,0,11,0,23,0,35,0,39,0,51,0,137,64,54,36,15,37,38,37,38,15,39,36,39,66,0,146,12,30,146,46,141,24,146, + 36,6,146,12,141,38,18,140,40,36,145,52,39,33,27,37,9,3,13,21,14,9,13,15,33,13,43,14,27,13,15,49,11,52,16,252,75,176,9,84, + 75,176,11,84,91,75,176,12,84,91,75,176,20,84,91,75,176,14,84,91,75,176,13,84,91,88,185,0,49,255,192,56,89,196,236,244,236,16,238,246, + 238,17,57,17,18,57,49,0,16,228,50,244,60,228,236,16,238,246,238,16,238,48,75,83,88,7,16,5,237,7,16,5,237,89,34,1,34,6,21,20, + 22,51,50,54,53,52,38,39,50,22,21,20,6,35,34,38,53,52,54,1,34,6,21,20,22,51,50,54,53,52,38,37,51,1,35,19,50,22,21,20, + 6,35,34,38,53,52,54,5,209,87,99,99,87,85,99,99,85,158,186,187,157,160,186,187,252,151,86,99,98,87,87,99,100,3,49,160,252,90,160,31, + 158,188,187,159,159,185,186,2,145,148,132,130,149,149,130,131,149,127,220,187,187,219,219,187,188,219,2,97,149,130,132,148,148,132,129,150,127,249,243,6, + 13,219,187,189,218,219,188,186,220,0,0,0,0,2,0,129,255,227,5,254,5,240,0,9,0,48,1,205,64,150,13,1,14,12,134,17,18,17,11,134, + 10,11,18,18,17,9,134,0,9,21,22,21,7,1,6,8,134,22,22,21,2,1,3,1,134,29,30,29,0,134,9,0,30,30,29,32,31,2,33,30, + 17,10,19,10,23,22,21,3,24,20,17,19,10,7,8,2,6,9,17,19,19,10,2,1,2,3,0,17,10,19,10,23,22,2,24,21,17,19,10,20, + 17,19,19,10,66,18,11,9,3,6,0,10,30,3,40,21,14,6,40,39,6,149,24,43,149,39,148,36,145,24,140,14,19,10,46,11,14,9,0,46, + 18,21,39,14,30,3,46,18,39,33,14,17,15,19,33,3,18,27,16,49,16,252,236,196,212,212,236,16,198,238,17,57,17,18,57,57,17,57,57,17, + 57,17,57,49,0,47,198,228,246,230,238,16,238,16,198,17,18,57,17,23,57,17,23,57,48,75,83,88,7,16,5,237,7,5,237,17,23,57,7,16, + 5,237,17,23,57,7,16,5,237,17,23,57,7,5,237,17,23,57,7,16,5,237,17,23,57,7,16,8,237,7,16,14,237,17,23,57,7,16,14,237, + 17,23,57,7,16,8,237,7,16,8,237,7,16,14,237,17,23,57,89,34,178,15,50,1,1,93,64,178,7,11,5,34,9,41,28,0,28,1,31,2, + 23,11,42,0,42,1,38,18,58,0,52,18,68,11,94,0,89,1,90,10,85,18,90,26,90,31,89,48,103,30,123,0,155,0,154,1,153,2,151,8, + 149,11,147,21,149,22,149,34,153,45,31,9,11,9,12,8,17,12,39,12,40,24,2,27,9,25,11,25,12,25,17,28,20,28,21,22,29,31,50,39, + 0,39,1,41,9,35,18,42,19,42,20,40,21,47,50,59,9,52,18,57,19,63,50,74,9,76,20,75,21,70,25,79,50,86,1,90,9,89,12,85, + 18,89,19,92,31,95,50,106,12,105,17,96,50,117,1,121,12,122,17,147,0,147,1,151,2,149,5,156,7,156,8,159,8,154,9,155,11,154,12,144, + 50,160,50,176,50,57,93,0,93,1,14,1,21,20,22,51,50,54,55,9,1,62,1,55,51,6,2,7,1,35,39,14,1,35,34,0,53,52,54,55, + 46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,1,242,91,85,212,160,95,166,73,254,123,1,252,59,66,6,186,12,104,93,1,23, + 252,143,104,228,131,241,254,206,134,134,48,50,222,184,83,165,85,87,158,68,105,131,59,3,35,81,161,88,146,194,63,64,2,143,253,248,89,203,114,132, + 254,254,126,254,227,147,89,87,1,19,215,128,225,99,63,125,60,162,197,36,36,182,47,49,111,88,51,103,0,1,0,197,3,170,1,111,5,213,0,3, + 0,55,64,10,1,132,0,129,4,0,5,2,4,4,16,252,75,176,18,84,75,176,19,84,91,88,185,0,2,255,192,56,89,236,49,0,16,244,236,48, + 1,64,13,64,5,80,5,96,5,112,5,144,5,160,5,6,93,1,17,35,17,1,111,170,5,213,253,213,2,43,0,0,0,1,0,176,254,242,2,123, + 6,18,0,13,0,55,64,15,6,152,0,151,14,13,7,0,3,18,6,0,19,10,14,16,220,75,176,19,84,88,185,0,10,255,192,56,89,75,176,15, + 84,88,185,0,10,0,64,56,89,228,50,236,17,57,57,49,0,16,252,236,48,1,6,2,21,20,18,23,35,38,2,53,52,18,55,2,123,134,130,131, + 133,160,150,149,148,151,6,18,230,254,62,231,231,254,59,229,235,1,198,224,223,1,196,236,0,1,0,164,254,242,2,111,6,18,0,13,0,31,64,15, + 7,152,0,151,14,7,1,0,11,18,4,19,8,0,14,16,220,60,244,236,17,57,57,49,0,16,252,236,48,19,51,22,18,21,20,2,7,35,54,18, + 53,52,2,164,160,150,149,149,150,160,133,131,131,6,18,236,254,60,223,224,254,58,235,229,1,197,231,231,1,194,0,0,0,1,0,61,2,74,3,195, + 5,240,0,17,0,78,64,44,16,13,11,0,4,12,9,7,4,2,4,8,3,153,5,17,12,153,10,1,14,145,18,8,12,10,3,9,6,17,3,1, + 3,2,0,20,15,4,11,9,20,13,6,18,16,212,60,228,50,220,60,228,50,23,57,17,18,23,57,49,0,16,244,212,60,236,50,196,236,50,23,57, + 18,23,57,48,1,13,1,7,37,17,35,17,5,39,45,1,55,5,17,51,17,37,3,195,254,153,1,103,58,254,176,114,254,176,58,1,103,254,153,58, + 1,80,114,1,80,4,223,194,195,98,203,254,135,1,121,203,98,195,194,99,203,1,121,254,135,203,0,0,0,1,0,217,0,0,5,219,5,4,0,11, + 0,35,64,17,0,9,1,156,7,3,5,2,21,4,0,23,10,6,21,8,12,16,220,252,60,252,60,236,49,0,47,212,60,252,60,196,48,1,17,33, + 21,33,17,35,17,33,53,33,17,3,174,2,45,253,211,168,253,211,2,45,5,4,253,211,170,253,211,2,45,170,2,45,0,1,0,158,255,18,1,195, + 0,254,0,5,0,25,64,12,3,158,0,131,6,3,4,1,25,0,24,6,16,252,236,212,204,49,0,16,252,236,48,55,51,21,3,35,19,240,211,164, + 129,82,254,172,254,192,1,64,0,1,0,100,1,223,2,127,2,131,0,3,0,17,182,0,156,2,4,1,0,4,16,220,204,49,0,16,212,236,48,19, + 33,21,33,100,2,27,253,229,2,131,164,0,0,1,0,219,0,0,1,174,0,254,0,3,0,17,183,0,131,2,1,25,0,24,4,16,252,236,49,0, + 47,236,48,55,51,21,35,219,211,211,254,254,0,1,0,0,255,66,2,178,5,213,0,3,0,45,64,20,0,26,1,2,1,2,26,3,0,3,66,2, + 159,0,129,4,2,0,1,3,47,196,57,57,49,0,16,244,236,48,75,83,88,7,16,5,237,7,16,5,237,89,34,1,51,1,35,2,8,170,253,248, + 170,5,213,249,109,0,0,0,0,2,0,135,255,227,4,143,5,240,0,11,0,23,0,35,64,19,6,160,18,0,160,12,145,18,140,24,9,28,15,30, + 3,28,21,27,24,16,252,236,244,236,49,0,16,228,244,236,16,238,48,1,34,2,17,16,18,51,50,18,17,16,2,39,50,0,17,16,0,35,34,0, + 17,16,0,2,139,156,157,157,156,157,157,157,157,251,1,9,254,247,251,251,254,247,1,9,5,80,254,205,254,204,254,205,254,205,1,51,1,51,1,52, + 1,51,160,254,115,254,134,254,135,254,115,1,141,1,121,1,122,1,141,0,0,1,0,225,0,0,4,90,5,213,0,10,0,64,64,21,66,3,160,4, + 2,160,5,129,7,0,160,9,8,31,6,28,3,0,31,1,11,16,212,75,176,15,84,88,185,0,1,0,64,56,89,236,196,252,236,49,0,47,236,50, + 244,236,212,236,48,75,83,88,89,34,1,180,15,3,15,4,2,93,55,33,17,5,53,37,51,17,33,21,33,254,1,74,254,153,1,101,202,1,74,252, + 164,170,4,115,72,184,72,250,213,170,0,0,0,1,0,150,0,0,4,74,5,240,0,28,0,158,64,39,25,26,27,3,24,28,17,5,4,0,17,5, + 5,4,66,16,161,17,148,13,160,20,145,4,0,160,2,0,16,10,2,1,10,28,23,16,3,6,29,16,252,75,176,21,84,75,176,22,84,91,75,176, + 20,84,91,88,185,0,3,255,192,56,89,196,212,236,192,192,17,18,57,49,0,47,236,50,244,236,244,236,48,75,83,88,7,16,5,237,7,5,237,1, + 176,28,16,17,23,57,89,34,1,64,50,85,4,86,5,86,7,122,4,122,5,118,27,135,25,7,4,0,4,25,4,26,4,27,5,28,116,0,118,6, + 117,26,115,27,116,28,130,0,134,25,130,26,130,27,130,28,168,0,168,27,17,93,0,93,37,33,21,33,53,54,0,55,62,1,53,52,38,35,34,6, + 7,53,62,1,51,50,4,21,20,6,7,6,0,1,137,2,193,252,76,115,1,141,51,97,77,167,134,95,211,120,122,212,88,232,1,20,69,91,25,254, + 244,170,170,170,119,1,145,58,109,151,73,119,150,66,67,204,49,50,232,194,92,165,112,29,254,235,0,0,0,1,0,156,255,227,4,115,5,240,0,40, + 0,112,64,46,0,21,19,10,134,9,31,134,32,19,160,21,13,160,9,147,6,28,160,32,147,35,145,6,140,21,163,41,22,28,19,0,3,20,25,28, + 38,32,16,28,3,20,31,9,6,41,16,252,75,176,22,84,75,176,20,84,91,88,185,0,9,255,192,56,89,196,196,212,236,244,236,17,23,57,57,49, + 0,16,236,228,244,228,236,16,230,238,16,238,16,238,16,238,17,18,57,48,1,64,9,100,30,97,31,97,32,100,33,4,0,93,1,30,1,21,20,4, + 33,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,4,21,20,6,3,63,145,163,254, + 208,254,232,94,199,106,84,200,109,190,199,185,165,174,182,149,158,163,152,83,190,114,115,201,89,230,1,12,142,3,37,31,196,144,221,242,37,37,195,49, + 50,150,143,132,149,166,119,112,115,123,36,38,180,32,32,209,178,124,171,0,0,2,0,100,0,0,4,164,5,213,0,2,0,13,0,129,64,29,1,13, + 3,13,0,3,3,13,66,0,3,11,7,160,5,1,3,129,9,1,12,10,0,28,6,8,4,12,14,16,220,75,176,11,84,75,176,13,84,91,88,185, + 0,12,255,192,56,89,212,60,196,236,50,17,57,49,0,47,228,212,60,236,50,18,57,48,75,83,88,7,16,4,201,7,16,5,201,89,34,1,64,42, + 11,0,42,0,72,0,89,0,105,0,119,0,138,0,7,22,1,43,0,38,1,43,3,54,1,78,1,79,12,79,13,86,1,102,1,117,1,122,3,133, + 1,13,93,0,93,9,1,33,3,51,17,51,21,35,17,35,17,33,53,3,6,254,2,1,254,53,254,213,213,201,253,94,5,37,252,227,3,205,252,51, + 168,254,160,1,96,195,0,0,0,1,0,158,255,227,4,100,5,213,0,29,0,94,64,35,4,26,7,17,134,16,29,26,160,7,20,160,16,137,13,2, + 160,0,129,13,140,7,164,30,23,28,1,10,3,28,0,10,16,6,30,16,252,1,75,176,22,84,75,176,20,84,91,88,185,0,16,255,192,56,89,75, + 176,15,84,88,185,0,16,0,64,56,89,196,212,236,16,196,238,49,0,16,228,228,244,236,16,230,238,16,254,196,16,238,17,18,57,48,19,33,21,33, + 17,62,1,51,50,0,21,20,0,33,34,38,39,53,30,1,51,50,54,53,52,38,35,34,6,7,221,3,25,253,160,44,88,44,250,1,36,254,212,254, + 239,94,195,104,90,192,107,173,202,202,173,81,161,84,5,213,170,254,146,15,15,254,238,234,241,254,245,32,32,203,49,48,182,156,156,182,36,38,0,0, + 0,2,0,143,255,227,4,150,5,240,0,11,0,36,0,88,64,36,19,6,0,13,134,12,0,160,22,6,160,28,22,165,16,160,12,137,34,145,28,140, + 37,12,34,9,28,25,30,19,28,3,33,31,27,37,16,252,236,236,244,236,228,49,0,16,228,244,228,252,228,16,238,16,238,16,238,17,18,57,48,64, + 20,203,0,203,1,205,2,205,3,205,4,203,5,203,6,7,164,30,178,30,2,93,1,93,1,34,6,21,20,22,51,50,54,53,52,38,1,21,46,1, + 35,34,2,3,62,1,51,50,0,21,20,0,35,32,0,17,16,0,33,50,22,2,164,136,159,159,136,136,159,159,1,9,76,155,76,200,211,15,59,178, + 107,225,1,5,254,240,226,254,253,254,238,1,80,1,27,76,155,3,59,186,162,161,187,187,161,162,186,2,121,184,36,38,254,242,254,239,87,93,254,239, + 235,230,254,234,1,141,1,121,1,98,1,165,30,0,0,0,0,1,0,168,0,0,4,104,5,213,0,6,0,99,64,24,5,17,2,3,2,3,17,4, + 5,4,66,5,160,0,129,3,5,3,1,4,1,0,6,7,16,252,204,196,17,57,57,49,0,47,244,236,48,75,83,88,7,16,5,237,7,16,5,237, + 89,34,1,75,176,22,84,88,189,0,7,0,64,0,1,0,7,0,7,255,192,56,17,55,56,89,64,18,88,2,1,6,3,26,5,57,5,72,5,103, + 3,176,0,176,6,7,93,0,93,19,33,21,1,35,1,33,168,3,192,253,226,211,1,254,253,51,5,213,86,250,129,5,43,0,0,0,0,3,0,139, + 255,227,4,139,5,240,0,11,0,35,0,47,0,67,64,37,24,12,0,160,39,6,160,30,45,160,18,145,30,140,39,163,48,24,12,36,42,28,21,36, + 28,15,9,28,21,27,30,3,28,15,33,27,48,16,252,196,236,244,196,236,16,238,16,238,17,57,57,49,0,16,236,228,244,236,16,238,16,238,57,57, + 48,1,34,6,21,20,22,51,50,54,53,52,38,37,46,1,53,52,36,51,50,22,21,20,6,7,30,1,21,20,4,35,34,36,53,52,54,19,20,22, + 51,50,54,53,52,38,35,34,6,2,139,144,165,165,144,144,166,165,254,165,130,145,0,255,222,223,254,145,129,146,163,254,247,247,247,254,247,164,72,145, + 131,130,147,147,130,131,145,2,197,154,135,135,154,155,134,135,154,86,32,178,128,179,208,208,179,128,178,32,34,198,143,217,232,232,217,143,198,1,97,116, + 130,130,116,116,130,130,0,0,0,2,0,129,255,227,4,135,5,240,0,24,0,36,0,88,64,35,7,31,25,1,134,0,25,160,10,165,4,160,0,137, + 22,31,160,16,145,22,140,37,7,28,28,33,19,30,0,34,34,28,13,27,37,16,252,236,228,244,236,236,49,0,16,228,244,236,16,230,254,245,238,16, + 238,17,18,57,48,64,22,196,25,194,26,192,27,192,28,192,29,194,30,196,31,7,170,18,188,18,233,18,3,93,1,93,55,53,30,1,51,50,18,19, + 14,1,35,34,0,53,52,0,51,32,0,17,16,0,33,34,38,1,50,54,53,52,38,35,34,6,21,20,22,225,76,156,75,200,211,15,58,178,108,224, + 254,251,1,16,226,1,3,1,17,254,177,254,229,76,156,1,62,136,159,159,136,136,159,159,31,184,36,38,1,13,1,18,86,92,1,15,235,230,1,22, + 254,115,254,134,254,159,254,91,30,2,151,186,162,161,187,187,161,162,186,0,0,2,0,240,0,0,1,195,4,35,0,3,0,7,0,28,64,14,6,131, + 4,166,0,131,2,5,1,3,4,0,24,8,16,252,60,236,50,49,0,47,236,244,236,48,55,51,21,35,17,51,21,35,240,211,211,211,211,254,254,4, + 35,254,0,0,0,2,0,158,255,18,1,195,4,35,0,3,0,9,0,37,64,19,2,131,0,7,158,4,131,0,166,10,7,8,5,1,25,4,0,24, + 10,16,252,60,236,50,212,204,49,0,16,228,252,236,16,238,48,19,51,21,35,17,51,21,3,35,19,240,211,211,211,164,129,82,4,35,254,253,217,172, + 254,192,1,64,0,1,0,217,0,94,5,219,4,166,0,6,0,77,64,42,2,156,3,4,3,1,156,0,1,4,4,3,1,156,2,1,5,6,5,0, + 156,6,5,66,5,4,2,1,0,5,3,168,6,167,7,1,2,0,36,4,35,7,16,252,236,50,57,49,0,16,244,236,23,57,48,75,83,88,7,4, + 237,7,16,8,237,7,16,8,237,7,16,4,237,89,34,9,2,21,1,53,1,5,219,251,248,4,8,250,254,5,2,3,240,254,145,254,147,182,1,209, + 166,1,209,0,0,2,0,217,1,96,5,219,3,162,0,3,0,7,0,28,64,13,0,156,2,6,156,4,8,5,1,4,0,35,8,16,252,60,196,50, + 49,0,16,212,236,212,236,48,19,33,21,33,21,33,21,33,217,5,2,250,254,5,2,250,254,3,162,168,240,170,0,0,0,1,0,217,0,94,5,219, + 4,166,0,6,0,79,64,43,6,156,0,6,3,4,3,5,156,4,4,3,0,156,1,2,1,6,156,5,6,2,2,1,66,6,5,3,2,0,5,4, + 168,1,167,7,6,2,36,4,0,35,7,16,252,60,236,57,49,0,16,244,236,23,57,48,75,83,88,7,16,8,237,7,16,4,237,7,16,4,237,7, + 16,8,237,89,34,19,53,1,21,1,53,1,217,5,2,250,254,4,6,3,240,182,254,47,166,254,47,182,1,109,0,0,0,2,0,147,0,0,3,176, + 5,240,0,3,0,36,0,101,64,43,36,30,9,6,4,10,29,19,4,0,20,134,19,136,16,149,23,145,0,131,2,29,26,13,9,5,4,10,30,1, + 13,28,26,4,28,5,1,3,0,38,26,19,37,16,220,75,176,12,84,88,185,0,19,255,192,56,89,196,252,236,212,236,16,238,17,57,57,17,18,57, + 17,18,57,49,0,47,238,246,254,244,238,16,205,17,57,57,23,57,48,1,182,121,9,122,10,122,32,3,93,37,51,21,35,19,35,53,52,54,63,1, + 62,1,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,15,1,14,1,7,14,1,21,1,135,203,203,197,191,56,90,90,57,51,131,108,79, + 179,97,94,193,103,184,223,72,90,88,47,39,8,6,6,254,254,1,145,154,101,130,86,89,53,94,49,89,110,70,67,188,57,56,194,159,76,137,86,86, + 47,53,25,21,60,52,0,0,0,2,0,135,254,156,7,113,5,162,0,11,0,76,0,149,64,50,24,12,3,9,169,25,21,27,3,169,76,15,52,51, + 15,172,48,169,55,21,172,36,169,55,67,77,51,52,30,26,0,40,18,6,24,12,40,26,43,30,40,73,18,43,42,40,73,44,61,77,16,220,236,252, + 236,16,254,253,254,60,198,16,238,17,18,57,57,49,0,16,212,196,252,236,16,254,237,212,198,16,197,238,50,16,196,238,17,57,57,48,0,75,176,9, + 84,75,176,12,84,91,75,176,16,84,91,75,176,19,84,91,75,176,20,84,91,88,189,0,77,255,192,0,1,0,77,0,77,0,64,56,17,55,56,89, + 64,9,15,78,31,78,47,78,63,78,4,1,93,1,20,22,51,50,54,53,52,38,35,34,6,1,14,1,35,34,38,53,52,54,51,50,22,23,53,51, + 17,62,1,53,52,38,39,38,36,35,34,6,7,6,2,21,20,18,23,22,4,51,50,54,55,23,6,4,35,34,36,39,38,2,53,52,18,55,54,36, + 51,50,4,23,30,1,21,16,0,5,2,250,142,124,123,141,144,122,121,143,2,33,60,155,103,172,215,216,171,103,156,59,143,146,165,63,64,104,254,213, + 176,123,226,96,157,177,115,109,105,1,20,157,129,249,104,90,125,254,217,152,185,254,184,128,128,134,136,126,129,1,82,189,212,1,107,123,75,79,254,194, + 254,232,2,25,143,163,164,142,140,165,164,254,72,77,73,249,200,200,250,75,76,131,253,32,22,223,177,107,188,80,131,139,65,64,102,254,181,193,159,254, + 234,106,104,109,87,81,111,97,103,131,125,125,1,73,189,182,1,74,125,127,135,174,160,98,230,123,254,249,254,208,6,0,0,2,0,16,0,0,5,104, + 5,213,0,2,0,10,0,194,64,65,0,17,1,0,4,5,4,2,17,5,5,4,1,17,10,3,10,0,17,2,0,3,3,10,7,17,5,4,6,17, + 5,5,4,9,17,3,10,8,17,10,3,10,66,0,3,7,149,1,3,129,9,5,9,8,7,6,4,3,2,1,0,9,5,10,11,16,212,196,23,57, + 49,0,47,60,228,212,236,18,57,48,75,83,88,7,16,5,237,7,5,237,7,16,5,237,7,5,237,7,16,8,237,7,16,5,237,7,16,5,237,7, + 16,8,237,89,34,178,32,12,1,1,93,64,66,15,1,15,2,15,7,15,8,15,0,88,0,118,0,112,0,140,0,9,7,1,8,2,6,3,9,4, + 22,1,25,2,86,1,88,2,80,12,103,1,104,2,120,1,118,2,124,3,114,4,119,7,120,8,135,1,136,2,128,12,152,2,153,3,150,4,23,93, + 0,93,9,1,33,1,51,1,35,3,33,3,35,2,188,254,238,2,37,254,123,229,2,57,210,136,253,95,136,213,5,14,253,25,3,174,250,43,1,127, + 254,129,0,0,0,3,0,201,0,0,4,236,5,213,0,8,0,17,0,32,0,67,64,35,25,0,149,10,9,149,18,129,1,149,10,173,31,17,11,8, + 2,19,25,31,5,0,14,28,22,5,25,28,46,9,0,28,18,4,33,16,252,236,50,252,236,212,236,17,23,57,57,57,49,0,47,236,236,244,236,16, + 238,57,48,178,15,34,1,1,93,1,17,33,50,54,53,52,38,35,1,17,33,50,54,53,52,38,35,37,33,50,22,21,20,6,7,30,1,21,20,4, + 35,33,1,147,1,68,163,157,157,163,254,188,1,43,148,145,145,148,254,11,2,4,231,250,128,124,149,165,254,240,251,253,232,2,201,253,221,135,139,140, + 133,2,102,254,62,111,114,113,112,166,192,177,137,162,20,32,203,152,200,218,0,1,0,115,255,227,5,39,5,240,0,25,0,54,64,26,13,161,14,174, + 10,149,17,1,161,0,174,4,149,23,145,17,140,26,7,25,13,0,48,20,16,26,16,252,236,50,236,49,0,16,228,244,236,244,236,16,238,246,238,48, + 180,15,27,31,27,2,1,93,1,21,46,1,35,32,0,17,16,0,33,50,54,55,21,14,1,35,32,0,17,16,0,33,50,22,5,39,102,231,130,255, + 0,254,240,1,16,1,0,130,231,102,106,237,132,254,173,254,122,1,134,1,83,134,237,5,98,213,95,94,254,199,254,216,254,217,254,199,94,95,211,72, + 72,1,159,1,103,1,104,1,159,71,0,0,0,2,0,201,0,0,5,176,5,213,0,8,0,17,0,46,64,21,0,149,9,129,1,149,16,8,2,16, + 10,0,5,25,13,50,0,28,9,4,18,16,252,236,244,236,17,57,57,57,57,49,0,47,236,244,236,48,178,96,19,1,1,93,1,17,51,32,0,17, + 16,0,33,37,33,32,0,17,16,0,41,1,1,147,244,1,53,1,31,254,225,254,203,254,66,1,159,1,178,1,150,254,104,254,80,254,97,5,47,251, + 119,1,24,1,46,1,44,1,23,166,254,151,254,128,254,126,254,150,0,0,0,1,0,201,0,0,4,139,5,213,0,11,0,46,64,21,6,149,4,2, + 149,0,129,8,149,4,173,10,5,1,9,7,3,28,0,4,12,16,252,236,50,212,196,196,49,0,47,236,236,244,236,16,238,48,178,31,13,1,1,93, + 19,33,21,33,17,33,21,33,17,33,21,33,201,3,176,253,26,2,199,253,57,2,248,252,62,5,213,170,254,70,170,253,227,170,0,0,0,1,0,201, + 0,0,4,35,5,213,0,9,0,41,64,18,6,149,4,2,149,0,129,4,173,8,5,1,7,3,28,0,4,10,16,252,236,50,212,196,49,0,47,236, + 244,236,16,238,48,178,15,11,1,1,93,19,33,21,33,17,33,21,33,17,35,201,3,90,253,112,2,80,253,176,202,5,213,170,254,72,170,253,55,0, + 0,1,0,115,255,227,5,139,5,240,0,29,0,57,64,32,0,5,27,1,149,3,27,149,8,18,161,17,174,21,149,14,145,8,140,30,2,0,28,17, + 52,4,51,24,25,11,16,30,16,252,236,252,228,252,196,49,0,16,228,244,236,244,236,16,254,212,238,17,57,57,48,37,17,33,53,33,17,6,4,35, + 32,0,17,16,0,33,50,4,23,21,46,1,35,32,0,17,16,0,33,50,54,4,195,254,182,2,18,117,254,230,160,254,162,254,117,1,139,1,94,146, + 1,7,111,112,252,139,254,238,254,237,1,19,1,18,107,168,213,1,145,166,253,127,83,85,1,153,1,109,1,110,1,153,72,70,215,95,96,254,206,254, + 209,254,210,254,206,37,0,0,0,1,0,201,0,0,5,59,5,213,0,11,0,44,64,20,8,149,2,173,4,0,129,10,6,7,3,28,5,56,9,1, + 28,0,4,12,16,252,236,50,252,236,50,49,0,47,60,228,50,252,236,48,178,80,13,1,1,93,19,51,17,33,17,51,17,35,17,33,17,35,201,202, + 2,222,202,202,253,34,202,5,213,253,156,2,100,250,43,2,199,253,57,0,0,1,0,201,0,0,1,147,5,213,0,3,0,46,183,0,175,2,1,28, + 0,4,4,16,252,75,176,16,84,88,185,0,0,0,64,56,89,236,49,0,47,236,48,1,64,13,48,5,64,5,80,5,96,5,143,5,159,5,6,93, + 19,51,17,35,201,202,202,5,213,250,43,0,0,1,255,150,254,102,1,147,5,213,0,11,0,66,64,19,11,2,0,7,149,5,176,0,129,12,5,8, + 6,57,1,28,0,4,12,16,252,75,176,16,84,88,185,0,0,0,64,56,89,236,228,57,57,49,0,16,228,252,236,17,57,57,48,1,64,13,48,13, + 64,13,80,13,96,13,143,13,159,13,6,93,19,51,17,16,6,43,1,53,51,50,54,53,201,202,205,227,77,63,134,110,5,213,250,147,254,242,244,170, + 150,194,0,0,0,1,0,201,0,0,5,106,5,213,0,10,0,239,64,40,8,17,5,6,5,7,17,6,6,5,3,17,4,5,4,2,17,5,5,4, + 66,8,5,2,3,3,0,175,9,6,5,1,4,6,8,1,28,0,4,11,16,252,236,50,212,196,17,57,49,0,47,60,236,50,23,57,48,75,83,88, + 7,16,4,237,7,16,5,237,7,16,5,237,7,16,4,237,89,34,178,8,3,1,1,93,64,146,20,2,1,4,2,9,8,22,2,40,5,40,8,55, + 2,54,5,52,8,71,2,70,5,67,8,85,2,103,2,118,2,119,5,131,2,136,5,143,8,148,2,155,8,231,2,21,6,3,9,5,9,6,27,3, + 25,7,5,10,3,10,7,24,3,40,5,43,6,42,7,54,4,54,5,54,6,53,7,48,12,65,3,64,4,69,5,64,6,64,7,64,12,98,3,96, + 4,104,5,103,7,119,5,112,12,139,3,139,5,142,6,143,7,143,12,154,3,157,6,157,7,182,3,181,7,197,3,197,7,215,3,214,7,232,3,233, + 4,232,5,234,6,247,3,248,5,249,6,44,93,113,0,93,113,19,51,17,1,33,9,1,33,1,17,35,201,202,2,158,1,4,253,27,3,26,254,246, + 253,51,202,5,213,253,137,2,119,253,72,252,227,2,207,253,49,0,0,0,0,1,0,201,0,0,4,106,5,213,0,5,0,37,64,12,2,149,0,129, + 4,1,28,3,58,0,4,6,16,252,236,236,49,0,47,228,236,48,64,9,48,7,80,7,128,3,128,4,4,1,93,19,51,17,33,21,33,201,202,2, + 215,252,95,5,213,250,213,170,0,1,0,201,0,0,6,31,5,213,0,12,0,191,64,52,3,17,7,8,7,2,17,1,2,8,8,7,2,17,3,2, + 9,10,9,1,17,10,10,9,66,10,7,2,3,8,3,0,175,8,11,5,9,8,3,2,1,5,10,6,28,4,62,10,28,0,4,13,16,252,236,252, + 236,17,23,57,49,0,47,60,196,236,50,17,23,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,178,112,14,1, + 1,93,64,86,3,7,15,8,15,9,2,10,21,2,20,7,19,10,38,2,38,7,32,7,38,10,32,10,52,7,53,10,105,2,124,2,123,7,121,10, + 128,2,130,7,130,10,144,2,22,4,1,11,3,19,1,27,3,35,1,44,3,39,8,40,9,52,1,60,3,86,8,89,9,101,8,106,9,118,8,121, + 9,129,1,141,3,149,1,155,3,20,93,0,93,19,33,9,1,33,17,35,17,1,35,1,17,35,201,1,45,1,125,1,127,1,45,197,254,127,203,254, + 127,196,5,213,252,8,3,248,250,43,5,31,252,0,4,0,250,225,0,0,0,1,0,201,0,0,5,51,5,213,0,9,0,121,64,30,7,17,1,2, + 1,2,17,6,7,6,66,7,2,3,0,175,8,5,6,1,7,2,28,4,54,7,28,0,4,10,16,252,236,252,236,17,57,57,49,0,47,60,236,50, + 57,57,48,75,83,88,7,16,4,237,7,16,4,237,89,34,178,31,11,1,1,93,64,48,54,2,56,7,72,2,71,7,105,2,102,7,128,2,7,6, + 1,9,6,21,1,26,6,70,1,73,6,87,1,88,6,101,1,105,6,121,6,133,1,138,6,149,1,154,6,159,11,16,93,0,93,19,33,1,17,51, + 17,33,1,17,35,201,1,16,2,150,196,254,240,253,106,196,5,213,251,31,4,225,250,43,4,225,251,31,0,2,0,115,255,227,5,217,5,240,0,11, + 0,23,0,35,64,19,6,149,18,0,149,12,145,18,140,24,9,25,15,51,3,25,21,16,24,16,252,236,252,236,49,0,16,228,244,236,16,238,48,1, + 34,0,17,16,0,51,50,0,17,16,0,39,32,0,17,16,0,33,32,0,17,16,0,3,39,220,254,253,1,3,220,220,1,1,254,255,220,1,58,1, + 120,254,136,254,198,254,197,254,135,1,121,5,76,254,184,254,229,254,230,254,184,1,72,1,26,1,27,1,72,164,254,91,254,158,254,159,254,91,1,164, + 1,98,1,98,1,165,0,0,0,2,0,201,0,0,4,141,5,213,0,8,0,19,0,58,64,24,1,149,16,0,149,9,129,18,16,10,8,2,4,0, + 5,25,13,63,17,0,28,9,4,20,16,252,236,50,252,236,17,23,57,49,0,47,244,236,212,236,48,64,11,15,21,31,21,63,21,95,21,175,21,5, + 1,93,1,17,51,50,54,53,52,38,35,37,33,50,4,21,20,4,43,1,17,35,1,147,254,141,154,154,141,254,56,1,200,251,1,1,254,255,251,254, + 202,5,47,253,207,146,135,134,146,166,227,219,221,226,253,168,0,2,0,115,254,248,5,217,5,240,0,11,0,29,0,82,64,42,17,16,2,15,1,12, + 13,12,14,1,13,13,12,66,15,30,12,6,149,18,0,149,24,145,18,140,13,30,13,27,15,12,3,9,25,27,51,3,25,21,16,30,16,252,236,252, + 236,17,57,57,17,57,49,0,16,196,228,244,236,16,238,57,18,57,48,75,83,88,7,16,5,237,7,16,5,237,23,57,89,34,1,34,0,17,16,0, + 51,50,0,17,16,0,19,1,35,39,14,1,35,32,0,17,16,0,33,32,0,17,16,2,3,39,220,254,253,1,3,220,220,1,1,254,255,63,1,10, + 244,221,33,35,16,254,197,254,135,1,121,1,59,1,58,1,120,209,5,76,254,184,254,229,254,230,254,184,1,72,1,26,1,27,1,72,250,207,254,221, + 239,2,2,1,165,1,97,1,98,1,165,254,91,254,158,254,252,254,142,0,0,2,0,201,0,0,5,84,5,213,0,19,0,28,0,177,64,53,9,8, + 7,3,10,6,17,3,4,3,5,17,4,4,3,66,6,4,0,21,3,4,21,149,9,20,149,13,129,11,4,5,6,3,17,9,0,28,22,14,5,10, + 25,25,4,17,63,20,10,28,12,4,29,16,252,236,50,252,196,236,17,23,57,17,57,57,57,49,0,47,60,244,236,212,236,18,57,18,57,18,57,48, + 75,83,88,7,16,5,237,7,16,5,237,17,23,57,89,34,178,64,30,1,1,93,64,66,122,19,1,5,0,5,1,5,2,6,3,7,4,21,0,21, + 1,20,2,22,3,23,4,37,0,37,1,37,2,38,3,39,6,38,7,38,8,38,9,32,30,54,1,54,2,70,1,70,2,104,5,117,4,117,5,119, + 19,136,6,136,7,152,6,152,7,31,93,0,93,1,30,1,23,19,35,3,46,1,43,1,17,35,17,33,32,22,21,20,6,1,17,51,50,54,53,52, + 38,35,3,141,65,123,62,205,217,191,74,139,120,220,202,1,200,1,0,252,131,253,137,254,146,149,149,146,2,188,22,144,126,254,104,1,127,150,98,253, + 137,5,213,214,216,141,186,2,79,253,238,135,131,131,133,0,0,1,0,135,255,227,4,162,5,240,0,39,0,126,64,60,13,12,2,14,11,2,30,31, + 30,8,9,2,7,10,2,31,31,30,66,10,11,30,31,4,21,1,0,21,161,20,148,24,149,17,4,149,0,148,37,145,17,140,40,30,10,11,31,27, + 7,0,34,27,25,14,45,7,25,20,34,40,16,220,196,236,252,236,228,17,18,57,57,57,57,49,0,16,228,244,228,236,16,238,246,238,16,198,17,23, + 57,48,75,83,88,7,16,14,237,17,23,57,7,16,14,237,17,23,57,89,34,178,15,41,1,1,93,182,31,41,47,41,79,41,3,93,1,21,46,1, + 35,34,6,21,20,22,31,1,30,1,21,20,4,33,34,38,39,53,30,1,51,50,54,53,52,38,47,1,46,1,53,52,36,51,50,22,4,72,115,204, + 95,165,179,119,166,122,226,215,254,221,254,231,106,239,128,123,236,114,173,188,135,154,123,226,202,1,23,245,105,218,5,164,197,55,54,128,118,99,101,31, + 25,43,217,182,217,224,48,47,208,69,70,136,126,110,124,31,24,45,192,171,198,228,38,0,0,1,255,250,0,0,4,233,5,213,0,7,0,74,64,14, + 6,2,149,0,129,4,1,64,3,28,0,64,5,8,16,212,228,252,228,49,0,47,244,236,50,48,1,75,176,10,84,88,189,0,8,0,64,0,1,0, + 8,0,8,255,192,56,17,55,56,89,64,19,0,9,31,0,16,1,16,2,31,7,16,9,64,9,112,9,159,9,9,93,3,33,21,33,17,35,17,33, + 6,4,239,253,238,203,253,238,5,213,170,250,213,5,43,0,0,1,0,178,255,227,5,41,5,213,0,17,0,64,64,22,8,2,17,11,0,5,149,14, + 140,9,0,129,18,8,28,10,56,1,28,0,65,18,16,252,75,176,16,84,88,185,0,0,255,192,56,89,236,252,236,49,0,16,228,50,244,236,17,57, + 57,57,57,48,1,182,31,19,143,19,159,19,3,93,19,51,17,20,22,51,50,54,53,17,51,17,16,0,33,32,0,17,178,203,174,195,194,174,203,254, + 223,254,230,254,229,254,223,5,213,252,117,240,211,211,240,3,139,252,92,254,220,254,214,1,42,1,36,0,0,1,0,16,0,0,5,104,5,213,0,6, + 0,183,64,39,4,17,5,6,5,3,17,2,3,6,6,5,3,17,4,3,0,1,0,2,17,1,1,0,66,3,4,1,175,0,6,4,3,2,0,5, + 5,1,7,16,212,196,23,57,49,0,47,236,50,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,178,80,8,1, + 1,93,64,98,0,3,42,3,71,4,71,5,90,3,125,3,131,3,7,6,0,7,2,8,4,9,6,21,1,20,2,26,4,26,5,42,0,38,1,38, + 2,41,4,41,5,37,6,32,8,56,0,51,1,51,2,60,4,60,5,55,6,72,0,69,1,69,2,73,4,73,5,71,6,89,0,86,6,102,2,105, + 4,105,5,122,0,118,1,118,2,121,4,121,5,117,6,128,8,152,0,151,6,41,93,0,93,33,1,51,9,1,51,1,2,74,253,198,211,1,217,1, + 218,210,253,199,5,213,251,23,4,233,250,43,0,1,0,68,0,0,7,166,5,213,0,12,1,123,64,73,5,26,6,5,9,10,9,4,26,10,9,3, + 26,10,11,10,2,26,1,2,11,11,10,6,17,7,8,7,5,17,4,5,8,8,7,2,17,3,2,12,0,12,1,17,0,0,12,66,10,5,2,3, + 6,3,0,175,11,8,12,11,10,9,8,6,5,4,3,2,1,11,7,0,13,16,212,204,23,57,49,0,47,60,236,50,50,23,57,48,75,83,88,7, + 16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,8,237,7,16,5,237,7,5,237,7,16,8,237,89,34,178,0,14,1,1,93,64,242, + 6,2,6,5,2,10,0,10,0,10,18,10,40,5,36,10,32,10,62,2,62,5,52,10,48,10,76,2,77,5,66,10,64,10,89,2,106,2,107,5, + 103,10,96,10,123,2,127,2,124,5,127,5,128,10,150,2,149,5,29,7,0,9,2,8,3,0,4,6,5,0,5,0,6,1,7,4,8,0,8,7, + 9,0,9,4,10,10,12,0,14,26,3,21,4,21,8,25,12,16,14,32,4,33,5,32,6,32,7,32,8,35,9,36,10,37,11,32,14,32,14,60, + 2,58,3,53,4,51,5,48,8,54,9,57,11,63,12,48,14,70,0,70,1,74,2,64,4,69,5,64,5,66,6,66,7,66,8,64,8,64,9,68, + 10,77,12,64,14,64,14,88,2,86,8,89,12,80,14,102,2,103,3,97,4,98,5,96,6,96,7,96,8,100,9,100,10,100,11,119,0,118,1,123, + 2,120,3,119,4,116,5,121,6,121,7,119,8,112,8,120,12,127,12,127,14,134,2,135,3,136,4,137,5,133,9,138,11,143,14,151,4,159,14,175, + 14,91,93,0,93,19,51,9,1,51,9,1,51,1,35,9,1,35,68,204,1,58,1,57,227,1,58,1,57,205,254,137,254,254,197,254,194,254,5,213, + 251,18,4,238,251,18,4,238,250,43,5,16,250,240,0,0,0,1,0,61,0,0,5,59,5,213,0,11,0,102,64,6,13,4,6,0,10,12,16,212, + 196,220,196,196,49,180,128,0,127,10,2,93,0,64,5,3,0,175,9,6,47,60,236,50,48,75,176,66,80,88,64,20,7,17,6,6,5,9,17,10, + 11,10,3,17,4,5,4,1,17,0,11,0,5,7,16,236,7,16,236,7,16,236,7,16,236,64,20,11,10,3,7,0,8,9,4,7,0,5,9,4, + 6,1,2,10,3,6,1,15,15,15,15,89,19,51,9,1,51,9,1,35,9,1,35,1,129,217,1,115,1,117,217,254,32,2,0,217,254,92,254,89, + 218,2,21,5,213,253,213,2,43,253,51,252,248,2,123,253,133,3,29,0,0,1,255,252,0,0,4,231,5,213,0,8,0,148,64,40,3,17,4,5, + 4,2,17,1,2,5,5,4,2,17,3,2,8,0,8,1,17,0,0,8,66,2,3,0,175,6,2,7,4,64,5,28,0,64,7,9,16,212,228,252, + 228,18,57,49,0,47,236,50,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,178,0,10,1,1,93,64,60,5, + 2,20,2,53,2,48,2,48,5,48,8,70,2,64,2,64,5,64,8,81,2,81,5,81,8,101,2,132,2,147,2,16,22,1,26,3,31,10,38,1, + 41,3,55,1,56,3,64,10,103,1,104,3,120,3,112,10,159,10,13,93,0,93,3,51,9,1,51,1,17,35,17,4,217,1,158,1,155,217,253,240, + 203,5,213,253,154,2,102,252,242,253,57,2,199,0,0,0,0,1,0,92,0,0,5,31,5,213,0,9,0,144,64,27,3,17,7,8,7,8,17,2, + 3,2,66,8,149,0,129,3,149,5,8,3,0,1,66,4,0,6,10,16,220,75,176,9,84,75,176,10,84,91,88,185,0,6,255,192,56,89,196,212, + 228,17,57,57,49,0,47,236,244,236,48,75,83,88,7,16,5,237,7,16,5,237,89,34,1,64,64,5,2,10,7,24,7,41,2,38,7,56,7,72, + 2,71,7,72,8,9,5,3,11,8,0,11,22,3,26,8,16,11,47,11,53,3,57,8,63,11,71,3,74,8,79,11,85,3,89,8,102,3,105,8, + 111,11,119,3,120,8,127,11,159,11,22,93,0,93,19,33,21,1,33,21,33,53,1,33,115,4,149,252,80,3,199,251,61,3,176,252,103,5,213,154, + 251,111,170,154,4,145,0,0,0,1,0,176,254,242,2,88,6,20,0,7,0,59,64,15,4,169,6,178,2,169,0,177,8,5,1,3,67,0,8,16, + 220,75,176,12,84,88,185,0,0,0,64,56,89,75,176,18,84,75,176,19,84,91,88,185,0,0,255,192,56,89,252,204,50,49,0,16,252,236,244,236, + 48,19,33,21,35,17,51,21,33,176,1,168,240,240,254,88,6,20,143,249,252,143,0,0,0,1,0,0,255,66,2,178,5,213,0,3,0,45,64,20, + 2,26,1,1,0,0,26,3,3,2,66,1,159,0,129,4,2,0,1,3,47,196,57,57,49,0,16,244,236,48,75,83,88,7,16,5,237,7,16,5, + 237,89,34,19,1,35,1,170,2,8,170,253,248,5,213,249,109,6,147,0,0,1,0,199,254,242,2,111,6,20,0,7,0,48,64,16,3,169,1,178, + 5,169,0,177,8,0,67,4,6,2,4,8,16,252,75,176,15,84,75,176,16,84,91,88,185,0,2,0,64,56,89,60,220,236,49,0,16,252,236,244, + 236,48,1,17,33,53,51,17,35,53,2,111,254,88,239,239,6,20,248,222,143,6,4,143,0,1,0,217,3,168,5,219,5,213,0,6,0,24,64,10, + 3,4,1,0,129,7,3,1,5,7,16,220,204,57,49,0,16,244,204,50,57,48,9,1,35,9,1,35,1,3,188,2,31,201,254,72,254,72,201,2, + 31,5,213,253,211,1,139,254,117,2,45,0,0,1,255,236,254,29,4,20,254,172,0,3,0,15,181,0,169,1,0,2,4,16,196,196,49,0,212,236, + 48,1,21,33,53,4,20,251,216,254,172,143,143,0,0,0,0,1,0,170,4,240,2,137,6,102,0,3,0,49,64,9,1,180,0,179,4,3,68,1, + 4,16,220,236,49,0,16,244,236,48,0,75,176,9,84,75,176,14,84,91,88,189,0,4,255,192,0,1,0,4,0,4,0,64,56,17,55,56,89,9, + 1,35,1,1,111,1,26,153,254,186,6,102,254,138,1,118,0,2,0,123,255,227,4,45,4,123,0,10,0,37,0,188,64,39,25,31,11,23,9,14, + 0,169,23,6,185,14,17,32,134,31,186,28,185,35,184,17,140,23,12,0,23,3,24,13,9,8,11,31,3,8,20,69,38,16,252,236,204,212,236,50, + 50,17,57,57,49,0,47,196,228,244,252,244,236,16,198,238,16,238,17,57,17,57,18,57,48,64,110,48,29,48,30,48,31,48,32,48,33,48,34,63, + 39,64,29,64,30,64,31,64,32,64,33,64,34,80,29,80,30,80,31,80,32,80,33,80,34,80,39,112,39,133,29,135,30,135,31,135,32,135,33,133, + 34,144,39,160,39,240,39,30,48,30,48,31,48,32,48,33,64,30,64,31,64,32,64,33,80,30,80,31,80,32,80,33,96,30,96,31,96,32,96,33, + 112,30,112,31,112,32,112,33,128,30,128,31,128,32,128,33,24,93,1,93,1,34,6,21,20,22,51,50,54,61,1,55,17,35,53,14,1,35,34,38, + 53,52,54,51,33,53,52,38,35,34,6,7,53,62,1,51,50,22,2,190,223,172,129,111,153,185,184,184,63,188,136,172,203,253,251,1,2,167,151,96, + 182,84,101,190,90,243,240,2,51,102,123,98,115,217,180,41,76,253,129,170,102,97,193,162,189,192,18,127,139,46,46,170,39,39,252,0,0,2,0,186, + 255,227,4,164,6,20,0,11,0,28,0,56,64,25,3,185,12,15,9,185,24,21,140,15,184,27,151,25,0,18,18,71,24,12,6,8,26,70,29,16, + 252,236,50,50,244,236,49,0,47,236,228,244,196,236,16,198,238,48,182,96,30,128,30,160,30,3,1,93,1,52,38,35,34,6,21,20,22,51,50,54, + 1,62,1,51,50,0,17,16,2,35,34,38,39,21,35,17,51,3,229,167,146,146,167,167,146,146,167,253,142,58,177,123,204,0,255,255,204,123,177,58, + 185,185,2,47,203,231,231,203,203,231,231,2,82,100,97,254,188,254,248,254,248,254,188,97,100,168,6,20,0,1,0,113,255,227,3,231,4,123,0,25, + 0,63,64,27,0,134,1,136,4,14,134,13,136,10,185,17,4,185,23,184,17,140,26,7,18,13,0,72,20,69,26,16,252,228,50,236,49,0,16,228, + 244,236,16,254,244,238,16,245,238,48,64,11,15,27,16,27,128,27,144,27,160,27,5,1,93,1,21,46,1,35,34,6,21,20,22,51,50,54,55,21, + 14,1,35,34,0,17,16,0,33,50,22,3,231,78,157,80,179,198,198,179,80,157,78,77,165,93,253,254,214,1,45,1,6,85,162,4,53,172,43,43, + 227,205,205,227,43,43,170,36,36,1,62,1,14,1,18,1,58,35,0,0,0,2,0,113,255,227,4,90,6,20,0,16,0,28,0,56,64,25,26,185, + 0,14,20,185,5,8,140,14,184,1,151,3,23,4,0,8,2,71,17,18,11,69,29,16,252,236,244,236,50,50,49,0,47,236,228,244,196,236,16,196, + 238,48,182,96,30,128,30,160,30,3,1,93,1,17,51,17,35,53,14,1,35,34,2,17,16,0,51,50,22,1,20,22,51,50,54,53,52,38,35,34, + 6,3,162,184,184,58,177,124,203,255,0,255,203,124,177,253,199,167,146,146,168,168,146,146,167,3,182,2,94,249,236,168,100,97,1,68,1,8,1,8, + 1,68,97,254,21,203,231,231,203,203,231,231,0,2,0,113,255,227,4,127,4,123,0,20,0,27,0,112,64,36,0,21,1,9,134,8,136,5,21,169, + 1,5,185,12,1,187,24,185,18,184,12,140,28,27,21,2,8,21,8,0,75,2,18,15,69,28,16,252,236,244,236,196,17,18,57,49,0,16,228,244, + 236,228,16,238,16,238,16,244,238,17,18,57,48,64,41,63,29,112,29,160,29,208,29,240,29,5,63,0,63,1,63,2,63,21,63,27,5,44,7,47, + 8,47,9,44,10,111,0,111,1,111,2,111,21,111,27,9,93,113,1,93,1,21,33,30,1,51,50,54,55,21,14,1,35,32,0,17,16,0,51,50, + 0,7,46,1,35,34,6,7,4,127,252,178,12,205,183,106,199,98,99,208,107,254,244,254,199,1,41,252,226,1,7,184,2,165,136,154,185,14,2,94, + 90,190,199,52,52,174,42,44,1,56,1,10,1,19,1,67,254,221,196,151,180,174,158,0,0,1,0,47,0,0,2,248,6,20,0,19,0,89,64,28, + 5,16,1,12,8,169,6,1,135,0,151,14,6,188,10,2,19,7,0,7,9,5,8,13,15,11,76,20,16,252,75,176,10,84,88,185,0,11,0,64, + 56,89,75,176,14,84,88,185,0,11,255,192,56,89,60,196,252,60,196,196,18,57,57,49,0,47,228,50,252,236,16,238,50,18,57,57,48,1,182,64, + 21,80,21,160,21,3,93,1,21,35,34,6,29,1,33,21,33,17,35,17,35,53,51,53,52,54,51,2,248,176,99,77,1,47,254,209,185,176,176,174, + 189,6,20,153,80,104,99,143,252,47,3,209,143,78,187,171,0,2,0,113,254,86,4,90,4,123,0,11,0,40,0,74,64,35,25,12,29,9,18,134, + 19,22,185,15,3,185,38,35,184,39,188,9,185,15,189,26,29,38,25,0,8,12,71,6,18,18,32,69,41,16,252,196,236,244,236,50,50,49,0,47, + 196,228,236,228,244,196,236,16,254,213,238,17,18,57,57,48,182,96,42,128,42,160,42,3,1,93,1,52,38,35,34,6,21,20,22,51,50,54,23,16, + 2,33,34,38,39,53,30,1,51,50,54,61,1,14,1,35,34,2,17,16,18,51,50,22,23,53,51,3,162,165,149,148,165,165,148,149,165,184,254,254, + 250,97,172,81,81,158,82,181,180,57,178,124,206,252,252,206,124,178,57,184,2,61,200,220,220,200,199,220,220,235,254,226,254,233,29,30,179,44,42,189, + 191,91,99,98,1,58,1,3,1,4,1,58,98,99,170,0,0,1,0,186,0,0,4,100,6,20,0,19,0,52,64,25,3,9,0,3,14,1,6,135, + 14,17,184,12,151,10,1,2,8,0,78,13,9,8,11,70,20,16,252,236,50,244,236,49,0,47,60,236,244,196,236,17,18,23,57,48,178,96,21,1, + 1,93,1,17,35,17,52,38,35,34,6,21,17,35,17,51,17,62,1,51,50,22,4,100,184,124,124,149,172,185,185,66,179,117,193,198,2,164,253,92, + 2,158,159,158,190,164,253,135,6,20,253,158,101,100,239,0,0,2,0,193,0,0,1,121,6,20,0,3,0,7,0,43,64,14,6,190,4,177,0,188, + 2,5,1,8,4,0,70,8,16,252,60,236,50,49,0,47,228,252,236,48,64,11,16,9,64,9,80,9,96,9,112,9,5,1,93,19,51,17,35,17, + 51,21,35,193,184,184,184,184,4,96,251,160,6,20,233,0,0,2,255,219,254,86,1,121,6,20,0,11,0,15,0,68,64,28,11,2,7,0,14,190, + 12,7,135,5,189,0,188,12,177,16,8,16,5,6,79,13,1,8,12,0,70,16,16,252,60,236,50,228,57,18,57,49,0,16,236,228,244,236,16,238, + 17,18,57,57,48,64,11,16,17,64,17,80,17,96,17,112,17,5,1,93,19,51,17,20,6,43,1,53,51,50,54,53,17,51,21,35,193,184,163,181, + 70,49,105,76,184,184,4,96,251,140,214,192,156,97,153,6,40,233,0,0,0,1,0,186,0,0,4,156,6,20,0,10,0,188,64,41,8,17,5,6, + 5,7,17,6,6,5,3,17,4,5,4,2,17,5,5,4,66,8,5,2,3,3,188,0,151,9,6,5,1,4,6,8,1,8,0,70,11,16,252,236, + 50,212,196,17,57,49,0,47,60,236,228,23,57,48,75,83,88,7,16,4,237,7,16,5,237,7,16,5,237,7,16,4,237,89,34,178,16,12,1,1, + 93,64,95,4,2,10,8,22,2,39,2,41,5,43,8,86,2,102,2,103,8,115,2,119,5,130,2,137,5,142,8,147,2,150,5,151,8,163,2,18, + 9,5,9,6,2,11,3,10,7,40,3,39,4,40,5,43,6,43,7,64,12,104,3,96,12,137,3,133,4,137,5,141,6,143,7,154,3,151,7,170, + 3,167,5,182,7,197,7,214,7,247,3,240,3,247,4,240,4,26,93,113,0,93,19,51,17,1,51,9,1,35,1,17,35,186,185,2,37,235,253,174, + 2,107,240,253,199,185,6,20,252,105,1,227,253,244,253,172,2,35,253,221,0,1,0,193,0,0,1,121,6,20,0,3,0,34,183,0,151,2,1,8, + 0,70,4,16,252,236,49,0,47,236,48,64,13,16,5,64,5,80,5,96,5,112,5,240,5,6,1,93,19,51,17,35,193,184,184,6,20,249,236,0, + 0,1,0,186,0,0,7,29,4,123,0,34,0,90,64,38,6,18,9,24,15,0,6,29,7,21,12,135,29,32,3,184,27,188,25,16,7,0,17,15, + 8,8,6,80,17,8,15,80,28,24,8,26,70,35,16,252,236,50,252,252,252,236,17,18,57,49,0,47,60,60,228,244,60,196,236,50,17,18,23,57, + 48,64,19,48,36,80,36,112,36,144,36,160,36,160,36,191,36,223,36,255,36,9,1,93,1,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21, + 17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,4,41,69,192,130,175,190,185,114,117,143,166,185,114,119,141,166,185,185,63,176, + 121,122,171,3,137,124,118,245,226,253,92,2,158,161,156,190,164,253,135,2,158,162,155,191,163,253,135,4,96,174,103,98,124,0,0,0,0,1,0,186, + 0,0,4,100,4,123,0,19,0,54,64,25,3,9,0,3,14,1,6,135,14,17,184,12,188,10,1,2,8,0,78,13,9,8,11,70,20,16,252,236, + 50,244,236,49,0,47,60,228,244,196,236,17,18,23,57,48,180,96,21,207,21,2,1,93,1,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62, + 1,51,50,22,4,100,184,124,124,149,172,185,185,66,179,117,193,198,2,164,253,92,2,158,159,158,190,164,253,135,4,96,174,101,100,239,0,2,0,113, + 255,227,4,117,4,123,0,11,0,23,0,74,64,19,6,185,18,0,185,12,184,18,140,24,9,18,15,81,3,18,21,69,24,16,252,236,244,236,49,0, + 16,228,244,236,16,238,48,64,35,63,25,123,0,123,6,127,7,127,8,127,9,127,10,127,11,123,12,127,13,127,14,127,15,127,16,127,17,123,18,160, + 25,240,25,17,1,93,1,34,6,21,20,22,51,50,54,53,52,38,39,50,0,17,16,0,35,34,0,17,16,0,2,115,148,172,171,149,147,172,172,147, + 240,1,18,254,238,240,241,254,239,1,17,3,223,231,201,201,231,232,200,199,233,156,254,200,254,236,254,237,254,199,1,57,1,19,1,20,1,56,0,0, + 0,2,0,186,254,86,4,164,4,123,0,16,0,28,0,62,64,27,26,185,0,14,20,185,5,8,184,14,140,1,189,3,188,29,17,18,11,71,23,4, + 0,8,2,70,29,16,252,236,50,50,244,236,49,0,16,228,228,228,244,196,236,16,196,238,48,64,9,96,30,128,30,160,30,224,30,4,1,93,37,17, + 35,17,51,21,62,1,51,50,0,17,16,2,35,34,38,1,52,38,35,34,6,21,20,22,51,50,54,1,115,185,185,58,177,123,204,0,255,255,204,123, + 177,2,56,167,146,146,167,167,146,146,167,168,253,174,6,10,170,100,97,254,188,254,248,254,248,254,188,97,1,235,203,231,231,203,203,231,231,0,0,0, + 0,2,0,113,254,86,4,90,4,123,0,11,0,28,0,62,64,27,3,185,12,15,9,185,24,21,184,15,140,27,189,25,188,29,24,12,6,8,26,71, + 0,18,18,69,29,16,252,236,244,236,50,50,49,0,16,228,228,228,244,196,236,16,198,238,48,64,9,96,30,128,30,160,30,224,30,4,1,93,1,20, + 22,51,50,54,53,52,38,35,34,6,1,14,1,35,34,2,17,16,0,51,50,22,23,53,51,17,35,1,47,167,146,146,168,168,146,146,167,2,115,58, + 177,124,203,255,0,255,203,124,177,58,184,184,2,47,203,231,231,203,203,231,231,253,174,100,97,1,68,1,8,1,8,1,68,97,100,170,249,246,0,0, + 0,1,0,186,0,0,3,74,4,123,0,17,0,48,64,20,6,11,7,0,17,11,3,135,14,184,9,188,7,10,6,8,0,8,70,18,16,252,196,236, + 50,49,0,47,228,244,236,196,212,204,17,18,57,48,180,80,19,159,19,2,1,93,1,46,1,35,34,6,21,17,35,17,51,21,62,1,51,50,22,23, + 3,74,31,73,44,156,167,185,185,58,186,133,19,46,28,3,180,18,17,203,190,253,178,4,96,174,102,99,5,5,0,0,0,1,0,111,255,227,3,199, + 4,123,0,39,0,231,64,60,13,12,2,14,11,83,31,30,8,9,2,7,10,83,31,31,30,66,10,11,30,31,4,21,0,134,1,137,4,20,134,21, + 137,24,185,17,4,185,37,184,17,140,40,30,10,11,31,27,7,0,82,27,8,14,7,8,20,34,69,40,16,252,196,236,212,236,228,17,18,57,57,57, + 57,49,0,16,228,244,236,16,254,245,238,16,245,238,18,23,57,48,75,83,88,7,16,14,237,17,23,57,7,14,237,17,23,57,89,34,178,0,39,1, + 1,93,64,109,28,10,28,11,28,12,46,9,44,10,44,11,44,12,59,9,59,10,59,11,59,12,11,32,0,32,1,36,2,40,10,40,11,42,19,47, + 20,47,21,42,22,40,30,40,31,41,32,41,33,36,39,134,10,134,11,134,12,134,13,18,0,0,0,1,2,2,6,10,6,11,3,12,3,13,3,14, + 3,15,3,16,3,25,3,26,3,27,3,28,4,29,9,39,47,41,63,41,95,41,127,41,128,41,144,41,160,41,240,41,24,93,0,93,113,1,21,46, + 1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,47,1,46,1,53,52,54,51,50,22,3,139,78, + 168,90,137,137,98,148,63,196,165,247,216,90,195,108,102,198,97,130,140,101,171,64,171,152,224,206,102,180,4,63,174,40,40,84,84,64,73,33,14,42, + 153,137,156,182,35,35,190,53,53,89,81,75,80,37,15,36,149,130,158,172,30,0,0,0,0,1,0,55,0,0,2,242,5,158,0,19,0,56,64,25, + 14,5,8,15,3,169,0,17,1,188,8,135,10,11,8,9,2,4,0,8,16,18,14,70,20,16,252,60,196,252,60,196,50,57,57,49,0,47,236,244, + 60,196,236,50,17,57,57,48,178,175,21,1,1,93,1,17,33,21,33,17,20,22,59,1,21,35,34,38,53,17,35,53,51,17,1,119,1,123,254,133, + 75,115,189,189,213,162,135,135,5,158,254,194,143,253,160,137,78,154,159,210,2,96,143,1,62,0,0,0,0,2,0,174,255,227,4,88,4,123,0,19, + 0,20,0,59,64,28,3,9,0,3,14,1,6,135,14,17,140,10,1,188,20,184,12,13,9,8,20,11,78,2,8,0,70,21,16,252,236,244,57,236, + 50,49,0,47,228,228,50,244,196,236,17,18,23,57,48,180,111,21,192,21,2,1,93,19,17,51,17,20,22,51,50,54,53,17,51,17,35,53,14,1, + 35,34,38,1,174,184,124,124,149,173,184,184,67,177,117,193,200,1,207,1,186,2,166,253,97,159,159,190,164,2,123,251,160,172,102,99,240,3,168,0, + 0,1,0,61,0,0,4,127,4,96,0,6,0,251,64,39,3,17,4,5,4,2,17,1,2,5,5,4,2,17,3,2,6,0,6,1,17,0,0,6, + 66,2,3,0,191,5,6,5,3,2,1,5,4,0,7,16,212,75,176,10,84,88,185,0,0,0,64,56,89,75,176,20,84,75,176,21,84,91,88,185, + 0,0,255,192,56,89,196,23,57,49,0,47,236,50,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,1,64,142, + 72,2,106,2,123,2,127,2,134,2,128,2,145,2,164,2,8,6,0,6,1,9,3,9,4,21,0,21,1,26,3,26,4,38,0,38,1,41,3,41, + 4,32,8,53,0,53,1,58,3,58,4,48,8,70,0,70,1,73,3,73,4,70,5,72,6,64,8,86,0,86,1,89,3,89,4,80,8,102,0,102, + 1,105,3,105,4,103,5,104,6,96,8,117,0,116,1,123,3,123,4,117,5,122,6,133,0,133,1,137,3,137,4,137,5,134,6,150,0,150,1,151, + 2,154,3,152,4,152,5,151,6,168,5,167,6,176,8,192,8,223,8,255,8,62,93,0,93,19,51,9,1,51,1,35,61,195,1,94,1,94,195,254, + 92,250,4,96,252,84,3,172,251,160,0,0,0,1,0,86,0,0,6,53,4,96,0,12,1,235,64,73,5,85,6,5,9,10,9,4,85,10,9,3, + 85,10,11,10,2,85,1,2,11,11,10,6,17,7,8,7,5,17,4,5,8,8,7,2,17,3,2,12,0,12,1,17,0,0,12,66,10,5,2,3, + 6,3,0,191,11,8,12,11,10,9,8,6,5,4,3,2,1,11,7,0,13,16,212,75,176,10,84,75,176,17,84,91,75,176,18,84,91,75,176,19, + 84,91,75,176,11,84,91,88,185,0,0,0,64,56,89,1,75,176,12,84,75,176,13,84,91,75,176,16,84,91,88,185,0,0,255,192,56,89,204,23, + 57,49,0,47,60,236,50,50,23,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,8,237,7,16,5,237,7,5, + 237,7,16,8,237,89,34,1,64,255,5,2,22,2,22,5,34,10,53,10,73,2,73,5,70,10,64,10,91,2,91,5,85,10,80,10,110,2,110,5, + 102,10,121,2,127,2,121,5,127,5,135,2,153,2,152,5,148,10,188,2,188,5,206,2,199,3,207,5,29,5,2,9,3,6,4,11,5,10,8,11, + 9,4,11,5,12,21,2,25,3,22,4,26,5,27,8,27,9,20,11,21,12,37,0,37,1,35,2,39,3,33,4,37,5,34,6,34,7,37,8,39, + 9,36,10,33,11,35,12,57,3,54,4,54,8,57,12,48,14,70,2,72,3,70,4,64,4,66,5,64,6,64,7,64,8,68,9,68,10,68,11,64, + 14,64,14,86,0,86,1,86,2,80,4,81,5,82,6,82,7,80,8,83,9,84,10,85,11,99,0,100,1,101,2,106,3,101,4,106,5,106,6,106, + 7,110,9,97,11,103,12,111,14,117,0,117,1,121,2,125,3,120,4,125,5,122,6,127,6,122,7,127,7,120,8,121,9,127,9,123,10,118,11,125, + 12,135,2,136,5,143,14,151,0,151,1,148,2,147,3,156,4,155,5,152,6,152,7,153,8,64,47,150,12,159,14,166,0,166,1,164,2,164,3,171, + 4,171,5,169,6,169,7,171,8,164,12,175,14,181,2,177,3,189,4,187,5,184,9,191,14,196,2,195,3,204,4,202,5,121,93,0,93,19,51,27, + 1,51,27,1,51,1,35,11,1,35,86,184,230,229,217,230,229,184,254,219,217,241,242,217,4,96,252,150,3,106,252,150,3,106,251,160,3,150,252,106, + 0,1,0,59,0,0,4,121,4,96,0,11,1,67,64,70,5,17,6,7,6,4,17,3,4,7,7,6,4,17,5,4,1,2,1,3,17,2,2,1, + 11,17,0,1,0,10,17,9,10,1,1,0,10,17,11,10,7,8,7,9,17,8,8,7,66,10,7,4,1,4,8,0,191,5,2,10,7,4,1,4, + 8,0,2,8,6,12,16,212,75,176,10,84,75,176,15,84,91,75,176,16,84,91,75,176,17,84,91,88,185,0,6,0,64,56,89,75,176,20,84,88, + 185,0,6,255,192,56,89,196,212,196,17,23,57,49,0,47,60,236,50,23,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5, + 237,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,1,64,152,10,4,4,10,26,4,21,10,38,10,61,4,49,10,85,4,87,7, + 88,10,102,10,118,1,122,4,118,7,116,10,141,4,130,10,153,4,159,4,151,7,146,10,144,10,166,1,169,4,175,4,165,7,163,10,160,10,28,10, + 3,4,5,5,9,10,11,26,3,21,5,21,9,26,11,41,3,38,5,37,9,42,11,32,13,58,1,57,3,55,5,52,7,54,9,57,11,48,13,73, + 3,70,5,69,9,74,11,64,13,89,0,86,1,89,2,89,3,87,5,86,6,89,7,86,8,86,9,89,11,80,13,111,13,120,1,127,13,155,1,148, + 7,171,1,164,7,176,13,207,13,223,13,255,13,47,93,0,93,9,2,35,9,1,35,9,1,51,9,1,4,100,254,107,1,170,217,254,186,254,186,217, + 1,179,254,114,217,1,41,1,41,4,96,253,223,253,193,1,184,254,72,2,74,2,22,254,113,1,143,0,0,1,0,61,254,86,4,127,4,96,0,15, + 1,139,64,67,7,8,2,9,17,0,15,10,17,11,10,0,0,15,14,17,15,0,15,13,17,12,13,0,0,15,13,17,14,13,10,11,10,12,17,11, + 11,10,66,13,11,9,16,0,11,5,135,3,189,14,11,188,16,14,13,12,10,9,6,3,0,8,15,4,15,11,16,16,212,75,176,10,84,75,176,8, + 84,91,88,185,0,11,0,64,56,89,75,176,20,84,88,185,0,11,255,192,56,89,196,196,17,23,57,49,0,16,228,50,244,236,17,57,17,57,18,57, + 48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,8,237,7,5,237,23,50,89,34,1,64,240,6,0,5,8,6,9, + 3,13,22,10,23,13,16,13,35,13,53,13,73,10,79,10,78,13,90,9,90,10,106,10,135,13,128,13,147,13,18,10,0,10,9,6,11,5,12,11, + 14,11,15,23,1,21,2,16,4,16,5,23,10,20,11,20,12,26,14,26,15,39,0,36,1,36,2,32,4,32,5,41,8,40,9,37,10,36,11,36, + 12,39,13,42,14,42,15,32,17,55,0,53,1,53,2,48,4,48,5,56,10,54,11,54,12,56,13,57,14,57,15,48,17,65,0,64,1,64,2,64, + 3,64,4,64,5,64,6,64,7,64,8,66,9,69,10,71,13,73,14,73,15,64,17,84,0,81,1,81,2,85,3,80,4,80,5,86,6,85,7,86, + 8,87,9,87,10,85,11,85,12,89,14,89,15,80,17,102,1,102,2,104,10,105,14,105,15,96,17,123,8,120,14,120,15,137,0,138,9,133,11,133, + 12,137,13,137,14,137,15,153,9,149,11,149,12,154,14,154,15,164,11,164,12,171,14,171,15,176,17,207,17,223,17,255,17,101,93,0,93,5,14,1, + 43,1,53,51,50,54,63,1,1,51,9,1,51,2,147,78,148,124,147,108,76,84,51,33,254,59,195,1,94,1,94,195,104,200,122,154,72,134,84,4, + 78,252,148,3,108,0,0,0,0,1,0,88,0,0,3,219,4,96,0,9,0,157,64,26,8,17,2,3,2,3,17,7,8,7,66,8,169,0,188,3, + 169,5,8,3,1,0,4,1,6,10,16,220,75,176,11,84,75,176,12,84,91,88,185,0,6,255,192,56,89,75,176,19,84,88,185,0,6,0,64,56, + 89,196,50,196,17,57,57,49,0,47,236,244,236,48,75,83,88,7,16,5,237,7,16,5,237,89,34,1,64,66,5,2,22,2,38,2,71,2,73,7, + 5,11,8,15,11,24,3,27,8,43,8,32,11,54,3,57,8,48,11,64,1,64,2,69,3,64,4,64,5,67,8,87,3,89,8,95,11,96,1,96, + 2,102,3,96,4,96,5,98,8,127,11,128,11,175,11,27,93,0,93,19,33,21,1,33,21,33,53,1,33,113,3,106,253,76,2,180,252,125,2,180, + 253,101,4,96,168,252,219,147,168,3,37,0,0,1,1,0,254,178,4,23,6,20,0,36,0,119,64,52,25,15,21,11,6,37,9,26,16,21,29,11, + 5,32,33,3,0,11,169,9,0,169,1,192,9,21,169,19,177,37,12,9,10,5,36,22,25,0,29,10,5,19,2,20,0,32,25,67,10,15,5,37, + 16,212,75,176,12,84,88,185,0,5,0,64,56,89,60,196,252,60,196,50,57,57,17,18,57,17,18,57,57,17,18,57,57,49,0,16,252,236,196,244, + 236,16,238,18,23,57,18,57,17,57,57,17,18,57,17,18,57,57,48,1,178,0,38,1,93,5,21,35,34,38,61,1,52,38,43,1,53,51,50,54, + 61,1,52,54,59,1,21,35,34,6,29,1,20,6,7,30,1,29,1,20,22,51,4,23,62,249,169,108,142,61,61,143,107,169,249,62,68,141,86,91, + 110,111,90,86,141,190,144,148,221,239,151,116,143,115,149,240,221,147,143,88,141,248,157,142,25,27,142,156,248,141,88,0,0,1,1,4,254,29,1,174, + 6,29,0,3,0,18,183,1,0,177,4,0,5,2,4,16,212,236,49,0,16,252,204,48,1,17,35,17,1,174,170,6,29,248,0,8,0,0,0,0, + 0,1,1,0,254,178,4,23,6,20,0,36,0,135,64,54,31,37,27,22,12,15,8,27,11,21,25,15,4,5,32,3,0,25,169,27,0,169,35,192, + 27,15,169,17,177,37,28,25,26,21,15,1,4,0,8,26,21,35,18,4,0,26,31,21,67,16,0,11,4,37,16,212,75,176,10,84,88,185,0,4, + 255,192,56,89,75,176,14,84,88,185,0,4,0,64,56,89,60,196,50,252,60,196,17,18,57,57,17,18,57,17,18,57,57,17,18,57,57,49,0,16, + 252,236,196,244,236,16,238,18,23,57,17,18,57,57,17,57,17,57,57,17,18,57,48,1,178,0,38,1,93,5,51,50,54,61,1,52,54,55,46,1, + 61,1,52,38,43,1,53,51,50,22,29,1,20,22,59,1,21,35,34,6,29,1,20,6,43,1,1,0,70,140,85,90,111,111,90,85,140,70,63,249, + 167,108,142,62,62,142,108,167,249,63,190,86,143,248,156,142,27,25,142,157,248,142,87,143,147,221,240,149,115,143,116,151,239,221,148,0,0,1,0,217, + 1,211,5,219,3,49,0,29,0,35,64,16,1,16,27,12,0,19,4,156,27,19,156,12,30,0,15,30,16,212,196,49,0,16,212,252,212,236,16,192, + 17,18,57,57,48,1,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,5,219,105,179,97, + 110,146,11,5,7,15,155,94,88,172,98,105,179,97,110,147,10,5,8,14,155,94,86,169,3,49,178,79,68,59,4,2,3,5,62,77,83,178,79,69, + 60,4,2,3,5,62,76,0,0,2,1,53,0,0,2,0,5,213,0,3,0,9,0,98,64,15,7,0,131,2,129,4,8,7,4,0,3,5,1,0, + 10,16,252,60,236,50,57,57,49,0,47,244,252,204,48,1,75,176,11,84,88,189,0,10,0,64,0,1,0,10,0,10,255,192,56,17,55,56,89,1, + 75,176,15,84,75,176,16,84,91,75,176,19,84,91,88,189,0,10,255,192,0,1,0,10,0,10,0,64,56,17,55,56,89,182,0,11,32,11,80,11, + 3,93,1,35,53,51,17,35,17,19,51,19,2,0,203,203,203,21,162,20,4,215,254,250,43,2,143,1,101,254,155,0,0,2,0,172,254,199,4,35, + 5,152,0,6,0,33,0,81,64,43,19,22,20,0,15,12,1,11,7,134,8,136,11,16,134,15,136,12,185,20,22,11,185,29,31,28,184,22,140,34, + 28,21,0,9,30,19,11,15,7,4,18,25,34,16,220,236,212,60,212,60,60,236,50,50,49,0,16,228,244,60,196,236,16,196,254,244,238,16,245,238, + 18,57,17,18,57,17,18,57,48,37,17,14,1,21,20,22,1,21,46,1,39,3,62,1,55,21,14,1,7,17,35,17,38,0,17,16,0,55,17,51, + 19,30,1,2,166,147,164,164,2,16,74,136,68,1,70,137,72,65,137,77,102,241,254,247,1,9,241,102,1,73,137,131,3,88,18,226,184,185,226,3, + 161,172,41,42,3,252,160,5,42,39,170,30,35,7,254,228,1,32,20,1,51,1,1,1,2,1,50,22,1,31,254,225,4,33,0,0,0,1,0,129, + 0,0,4,98,5,240,0,27,0,96,64,33,7,22,8,1,134,0,18,10,169,20,8,12,4,160,0,148,25,145,16,12,160,14,0,13,9,11,7,28, + 19,15,21,17,28,16,220,60,204,204,252,60,196,212,196,49,0,47,236,50,244,228,236,16,212,60,238,50,16,238,17,57,57,48,1,75,176,12,84,88, + 189,0,28,255,192,0,1,0,28,0,28,0,64,56,17,55,56,89,180,54,1,54,2,2,0,93,1,21,46,1,35,34,6,29,1,33,21,33,17,33, + 21,33,53,51,17,35,53,51,53,16,54,51,50,22,4,78,76,136,61,148,116,1,135,254,121,2,45,252,31,236,199,199,214,232,61,151,5,180,182,41, + 41,155,212,215,143,254,47,170,170,1,209,143,238,1,5,243,31,0,0,0,0,2,0,94,0,82,4,188,4,178,0,35,0,47,0,131,64,73,3,9, + 27,21,4,45,30,0,39,28,2,33,29,12,18,45,20,11,10,3,19,15,1,29,45,185,19,235,15,236,39,185,29,235,33,48,30,12,0,18,4,42, + 36,20,48,28,21,27,42,29,19,28,24,9,3,36,11,10,1,3,2,36,40,2,115,6,116,42,40,28,115,24,48,16,220,228,236,244,228,236,18,23, + 57,18,57,57,17,18,57,57,18,57,57,17,18,57,17,18,23,57,49,0,16,212,228,236,244,228,236,16,192,17,18,23,57,18,57,57,17,18,57,57, + 17,57,57,18,23,57,48,1,55,23,7,30,1,21,20,6,7,23,7,39,14,1,35,34,38,39,7,39,55,46,1,53,52,54,55,39,55,23,62,1, + 51,50,22,19,52,38,35,34,6,21,20,22,51,50,54,3,123,207,114,206,37,36,38,40,209,114,207,59,116,61,58,120,61,207,113,207,37,37,38,38, + 207,115,207,55,116,64,60,117,92,155,114,112,158,157,113,113,156,3,225,209,115,206,59,119,62,63,115,57,207,113,207,40,38,37,37,207,115,206,62,118, + 58,64,116,56,206,115,207,39,37,36,254,124,112,154,154,112,114,156,157,0,0,1,0,82,0,0,4,195,5,213,0,24,0,198,64,70,16,2,17,22, + 17,15,2,14,15,22,22,17,15,2,16,15,8,13,8,14,2,13,13,8,66,15,11,9,4,0,211,23,6,18,11,211,20,9,16,13,129,2,12,9, + 14,3,5,22,15,3,21,18,16,3,0,17,102,19,0,101,1,28,13,102,10,5,101,7,3,25,16,212,60,236,50,236,252,236,50,236,18,23,57,18, + 57,57,17,23,57,49,0,47,228,50,212,60,236,50,212,60,236,50,17,18,57,48,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5, + 237,89,34,1,75,176,12,84,88,189,0,25,255,192,0,1,0,25,0,25,0,64,56,17,55,56,89,64,40,134,15,144,15,166,15,160,15,181,15,5, + 39,12,39,13,39,14,41,16,40,17,40,18,55,14,57,16,135,12,136,18,166,13,165,14,170,16,169,17,14,93,0,93,1,33,17,35,17,33,53,33, + 53,39,33,53,33,1,51,9,1,51,1,33,21,33,7,21,33,4,141,254,99,201,254,96,1,160,84,254,180,1,8,254,195,190,1,123,1,121,191,254, + 194,1,8,254,181,84,1,159,1,199,254,57,1,199,123,51,155,123,2,74,253,68,2,188,253,182,123,155,51,0,0,0,0,2,1,4,254,162,1,174, + 5,152,0,3,0,7,0,28,64,13,1,245,0,4,245,5,8,4,0,5,6,2,8,16,220,60,236,50,49,0,16,212,236,212,236,48,1,17,35,17, + 19,17,35,17,1,174,170,170,170,1,152,253,10,2,246,4,0,253,10,2,246,0,0,0,0,2,0,92,255,61,3,162,5,240,0,11,0,62,0,145, + 64,60,47,48,42,6,0,23,29,48,54,4,13,39,138,38,13,138,12,42,198,38,197,35,16,198,12,197,60,145,35,63,47,6,0,23,48,4,19,29, + 45,9,54,3,19,87,57,45,87,32,9,87,12,34,26,57,38,34,3,87,51,63,16,220,236,228,196,212,228,236,212,236,16,238,17,57,17,18,57,17, + 23,57,57,49,0,16,196,244,228,236,16,230,238,16,238,16,238,17,23,57,57,57,17,18,57,48,1,75,176,10,84,75,176,11,84,91,75,176,12,84, + 91,75,176,14,84,91,88,189,0,63,0,64,0,1,0,63,0,63,255,192,56,17,55,56,89,1,14,1,21,20,22,23,62,1,53,52,38,19,21,46, + 1,35,34,6,21,20,23,22,23,30,1,21,20,6,7,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,47,1,46,1,53,52,54,55, + 46,1,53,52,54,51,50,22,1,123,63,62,139,250,63,62,143,204,83,143,56,97,108,206,26,14,211,131,92,93,62,57,204,173,73,154,88,87,148,58, + 102,113,221,25,214,128,93,91,59,59,200,166,73,153,3,168,46,90,46,76,133,135,45,91,46,75,136,2,147,164,39,39,80,71,90,115,15,8,119,154, + 101,90,140,53,52,109,64,142,168,29,29,164,39,39,84,76,102,123,14,120,153,102,91,143,49,44,112,69,130,159,29,0,0,2,0,215,5,70,3,41, + 6,16,0,3,0,7,0,146,64,14,6,2,206,4,0,205,8,1,100,0,5,100,4,8,16,220,252,212,236,49,0,16,252,60,236,50,48,0,75,176, + 10,84,75,176,13,84,91,88,189,0,8,0,64,0,1,0,8,0,8,255,192,56,17,55,56,89,1,75,176,12,84,75,176,13,84,91,75,176,14,84, + 91,75,176,23,84,91,88,189,0,8,255,192,0,1,0,8,0,8,0,64,56,17,55,56,89,1,75,176,15,84,75,176,25,84,91,88,189,0,8,0, + 64,0,1,0,8,0,8,255,192,56,17,55,56,89,64,17,96,1,96,2,96,5,96,6,112,1,112,2,112,5,112,6,8,93,1,51,21,35,37,51, + 21,35,2,94,203,203,254,121,203,203,6,16,202,202,202,0,0,3,1,27,0,0,6,229,5,205,0,23,0,47,0,73,0,67,64,38,61,203,62,58, + 204,65,202,36,49,203,48,52,204,71,202,24,201,0,200,36,201,12,55,97,68,61,48,94,42,9,6,68,94,30,9,6,18,74,16,220,204,252,236,16, + 254,237,50,16,238,49,0,47,238,246,254,253,238,214,238,16,253,238,214,238,48,1,50,4,23,22,18,21,20,2,7,6,4,35,34,36,39,38,2,53, + 52,18,55,54,36,23,34,6,7,14,1,21,20,22,23,30,1,51,50,54,55,62,1,53,52,38,39,46,1,23,21,46,1,35,34,6,21,20,22,51, + 50,54,55,21,14,1,35,34,38,53,52,54,51,50,22,4,0,152,1,7,109,109,108,108,109,109,254,249,152,152,254,249,109,109,108,108,109,109,1,7, + 152,131,226,94,94,96,96,94,94,226,131,132,227,94,93,93,94,92,94,227,167,66,130,66,149,167,171,155,64,122,66,67,137,70,216,251,251,216,73,136, + 5,205,110,109,109,254,250,154,152,254,251,109,109,110,110,109,109,1,5,152,154,1,6,109,109,110,103,94,94,94,229,130,129,227,94,94,95,95,94,93, + 226,131,133,227,93,94,94,245,129,33,32,175,157,159,174,31,34,127,29,28,244,208,209,242,28,0,0,0,0,3,0,115,1,213,3,59,5,240,0,3, + 0,30,0,41,0,95,64,51,40,7,37,4,31,18,24,16,2,227,0,31,221,16,0,225,37,221,5,10,25,223,24,222,21,221,10,224,28,145,42,0, + 24,13,31,16,34,6,2,1,40,17,6,107,4,108,24,34,107,13,42,16,220,236,204,252,236,50,50,192,192,17,18,57,57,17,18,57,49,0,16,244, + 228,252,244,236,16,196,238,237,214,238,16,238,17,18,57,18,57,17,57,57,48,19,33,21,33,1,17,35,53,14,1,35,34,38,53,52,54,59,1,53, + 52,38,35,34,6,7,53,62,1,51,50,22,5,34,6,21,20,22,51,50,54,61,1,139,2,176,253,80,2,174,149,44,144,93,128,152,191,188,182,117, + 117,62,136,68,73,145,69,183,179,254,236,161,126,98,82,104,130,2,80,123,2,184,254,64,112,63,68,135,113,135,138,4,91,91,34,34,127,28,28,176, + 240,67,79,64,77,144,114,29,0,2,0,158,0,141,4,37,4,35,0,6,0,13,0,134,64,73,3,232,4,5,4,2,232,1,2,5,5,4,2,232, + 3,2,6,0,6,1,232,0,0,6,10,232,11,12,11,9,232,8,9,12,12,11,9,232,10,9,13,7,13,8,232,7,7,13,66,9,2,11,4,231, + 7,0,166,14,9,12,5,2,7,3,0,111,5,10,7,111,12,110,14,16,252,252,60,212,236,50,17,57,17,18,57,49,0,16,244,60,236,50,57,57, + 48,75,83,88,7,16,4,237,7,16,8,237,7,16,8,237,7,16,4,237,7,16,4,237,7,16,8,237,7,16,8,237,7,16,4,237,89,34,1,21, + 9,1,21,1,53,19,21,9,1,21,1,53,4,37,254,211,1,45,254,43,35,254,211,1,45,254,43,4,35,191,254,244,254,244,191,1,162,82,1,162, + 191,254,244,254,244,191,1,162,82,0,0,0,0,1,0,217,1,31,5,219,3,94,0,5,0,23,64,10,4,156,2,0,6,3,23,1,0,6,16,220, + 212,236,49,0,16,212,196,236,48,19,33,17,35,17,33,217,5,2,168,251,166,3,94,253,193,1,149,0,0,1,0,100,1,223,2,127,2,131,0,3, + 0,17,182,0,156,2,4,1,0,4,16,220,204,49,0,16,212,236,48,19,33,21,33,100,2,27,253,229,2,131,164,0,0,4,1,27,0,0,6,229, + 5,205,0,23,0,47,0,56,0,76,0,96,64,54,69,66,67,63,50,201,72,48,201,57,74,67,202,12,57,202,0,201,24,200,12,201,36,72,69,51, + 48,4,49,66,60,63,57,54,73,49,96,75,54,96,67,60,94,18,9,30,75,94,6,9,30,95,42,77,16,220,228,252,236,16,254,253,196,238,16,238, + 50,17,57,57,18,57,18,23,57,49,0,47,238,246,254,237,16,237,50,16,238,214,238,57,18,57,57,48,1,34,6,7,14,1,21,20,22,23,30,1, + 51,50,54,55,62,1,53,52,38,39,46,1,39,50,4,23,22,18,21,20,2,7,6,4,35,34,36,39,38,2,53,52,18,55,54,36,19,35,17,51, + 50,54,53,52,38,39,50,22,21,20,6,7,30,1,31,1,35,39,46,1,43,1,17,35,17,4,0,131,226,94,94,96,96,94,94,226,131,132,227,94, + 93,93,94,92,94,227,132,152,1,7,109,109,108,108,109,109,254,249,152,152,254,249,109,109,108,108,109,109,1,7,125,123,123,110,87,88,102,176,174,105, + 96,24,67,46,137,172,129,59,73,54,66,155,5,102,94,94,94,229,130,129,227,94,94,95,95,94,93,226,131,133,227,93,94,94,103,110,109,109,254,250, + 154,152,254,251,109,109,110,110,109,109,1,5,152,154,1,6,109,109,110,254,98,254,236,62,75,76,63,103,119,121,86,112,17,8,77,73,223,209,96,51, + 254,156,3,68,0,1,0,213,5,98,3,43,5,246,0,3,0,47,183,2,239,0,238,4,1,0,4,16,212,204,49,0,16,252,236,48,0,75,176,9, + 84,75,176,14,84,91,88,189,0,4,255,192,0,1,0,4,0,4,0,64,56,17,55,56,89,19,33,21,33,213,2,86,253,170,5,246,148,0,0,0, + 0,2,0,195,3,117,3,61,5,240,0,11,0,26,0,32,64,17,6,195,21,196,0,195,12,145,27,9,90,18,91,3,90,24,27,16,220,236,252,236, + 49,0,16,244,236,252,236,48,1,34,6,21,20,22,51,50,54,53,52,38,39,50,22,23,30,1,21,20,6,35,34,38,53,52,54,2,0,80,110,110, + 80,80,110,111,79,64,118,43,46,46,185,134,135,180,184,5,111,111,80,79,109,109,79,79,112,129,49,46,45,114,66,132,183,180,135,134,186,0,0,0, + 0,2,0,217,0,0,5,219,5,4,0,11,0,15,0,46,64,24,5,208,7,3,156,0,208,9,1,12,156,14,13,2,21,4,0,23,12,8,21,10, + 6,16,16,212,60,236,50,252,60,236,50,49,0,47,236,212,60,236,252,60,236,48,1,17,33,21,33,17,35,17,33,53,33,17,1,33,21,33,3,174, + 2,45,253,211,168,253,211,2,45,253,211,5,2,250,254,5,4,254,125,170,254,125,1,131,170,1,131,251,166,170,0,0,0,1,0,94,2,156,2,180, + 5,240,0,24,0,74,64,36,0,125,6,4,0,23,125,6,6,4,66,4,2,0,14,221,15,0,221,2,247,11,221,15,18,145,25,0,14,8,126,1, + 21,14,3,25,16,220,196,212,196,236,17,57,49,0,16,244,196,236,252,236,16,238,17,18,57,48,75,83,88,7,16,5,237,23,50,7,5,237,89,34, + 1,33,21,33,53,54,55,0,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,1,6,1,12,1,168,253,170,34,63,1,88,104,85,52,122,72, + 77,133,57,145,174,254,181,56,3,14,114,110,31,56,1,49,94,66,81,35,35,123,28,28,132,108,139,254,228,48,0,0,0,1,0,98,2,141,2,205, + 5,240,0,40,0,72,64,39,0,21,19,10,221,9,31,221,32,19,221,21,13,221,9,248,6,247,28,221,32,248,35,145,41,22,19,0,20,25,126,38, + 16,126,3,20,31,9,41,16,220,196,196,212,236,212,236,17,57,57,57,49,0,16,244,228,236,252,228,236,212,236,16,238,16,238,17,18,57,48,1,30, + 1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,2, + 12,92,101,190,177,57,125,70,52,119,67,109,120,111,108,86,94,94,97,100,95,40,102,81,73,128,55,144,169,90,4,96,18,109,82,124,134,21,20,121, + 27,26,79,70,74,76,108,63,60,58,61,18,23,115,17,18,118,99,69,96,0,1,1,115,4,238,3,82,6,102,0,3,0,49,64,9,2,180,0,179, + 4,3,68,1,4,16,212,236,49,0,16,244,236,48,0,75,176,9,84,75,176,14,84,91,88,189,0,4,255,192,0,1,0,4,0,4,0,64,56,17, + 55,56,89,1,51,1,35,2,139,199,254,186,153,6,102,254,136,0,0,0,0,1,0,174,254,86,4,229,4,96,0,32,0,77,64,37,19,25,31,3, + 22,6,3,9,12,3,1,18,15,6,135,28,22,140,10,1,188,0,189,33,25,9,18,9,8,11,78,31,2,8,0,70,33,16,252,236,50,244,236,196, + 18,57,49,0,16,228,228,50,244,60,236,220,196,17,23,57,17,18,23,57,48,182,31,34,96,34,207,34,3,1,93,19,17,51,17,20,22,51,50,54, + 53,17,51,17,20,22,51,50,54,55,21,14,1,35,34,38,39,14,1,35,34,38,39,17,174,184,138,135,148,149,184,35,37,9,32,28,41,73,35,69, + 82,15,50,145,98,102,143,42,254,86,6,10,253,72,145,148,168,168,2,141,252,162,60,57,11,12,148,23,22,78,80,79,79,78,78,253,215,0,0,0, + 0,1,0,158,255,59,4,57,5,213,0,13,0,37,64,18,8,2,4,193,0,129,6,2,14,0,7,93,5,3,93,1,11,14,16,212,212,252,220,236, + 57,49,0,16,196,50,244,236,17,57,48,1,33,17,35,17,35,17,35,17,46,1,53,52,36,2,121,1,192,141,190,142,215,235,1,4,5,213,249,102, + 6,31,249,225,3,78,17,221,184,190,232,0,0,1,0,219,2,72,1,174,3,70,0,3,0,18,183,2,131,0,4,1,25,0,4,16,212,236,49,0, + 16,212,236,48,19,51,21,35,219,211,211,3,70,254,0,0,0,1,1,35,254,117,2,193,0,0,0,19,0,31,64,14,9,6,10,13,243,6,0,19, + 0,16,39,3,9,20,16,220,212,236,212,204,49,0,47,212,252,196,18,57,48,33,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38, + 39,2,84,55,54,120,118,46,87,43,34,74,47,59,60,43,45,62,105,48,89,91,12,12,131,17,15,48,46,30,87,61,0,1,0,137,2,156,2,197, + 5,223,0,10,0,44,64,24,7,0,221,9,3,221,4,2,221,9,247,5,145,11,8,124,6,93,3,124,1,124,0,11,16,220,244,228,252,228,49,0, + 16,244,236,236,212,236,16,238,50,48,19,51,17,7,53,55,51,17,51,21,33,156,204,223,230,137,205,253,215,3,10,2,99,41,116,39,253,43,110,0, + 0,3,0,96,1,213,3,100,5,240,0,3,0,15,0,27,0,46,64,25,2,227,0,225,22,221,10,224,16,221,4,145,28,0,19,13,1,25,107,7, + 108,19,107,13,28,16,220,236,252,236,57,17,18,57,49,0,16,244,236,244,236,252,236,48,19,33,21,33,1,50,22,21,20,6,35,34,38,53,52,54, + 23,34,6,21,20,22,51,50,54,53,52,38,139,2,176,253,80,1,88,179,206,206,179,179,208,208,179,105,126,127,104,105,125,124,2,80,123,4,27,221, + 191,191,219,220,190,191,221,115,161,136,133,160,160,133,137,160,0,2,0,193,0,141,4,72,4,35,0,6,0,13,0,134,64,73,12,232,13,12,9,10, + 9,11,232,10,10,9,13,232,7,8,7,12,232,11,12,8,8,7,5,232,6,5,2,3,2,4,232,3,3,2,6,232,0,1,0,5,232,4,5,1, + 1,0,66,12,5,10,3,231,7,0,166,14,12,8,1,5,0,8,111,10,7,1,111,3,0,112,14,16,252,60,252,212,60,236,18,57,17,18,57,49, + 0,16,244,60,236,50,57,57,48,75,83,88,7,16,8,237,7,16,4,237,7,16,4,237,7,16,8,237,7,16,8,237,7,16,4,237,7,16,4,237, + 7,16,8,237,89,34,19,1,21,1,53,9,1,37,1,21,1,53,9,1,193,1,213,254,43,1,45,254,211,1,178,1,213,254,43,1,45,254,211,4, + 35,254,94,82,254,94,191,1,12,1,12,191,254,94,82,254,94,191,1,12,1,12,0,0,255,255,0,137,255,227,7,127,5,240,16,38,0,123,0,0, + 16,39,11,75,4,139,253,100,16,7,11,34,3,53,0,0,255,255,0,137,255,227,7,63,5,240,16,38,0,123,0,0,16,39,0,116,4,139,253,100, + 16,7,11,34,3,53,0,0,255,255,0,98,255,227,7,127,5,240,16,38,0,117,0,0,16,39,11,75,4,139,253,100,16,7,11,34,3,53,0,0, + 0,2,0,143,255,227,3,172,5,213,0,32,0,36,0,134,64,47,32,26,5,2,4,6,25,0,16,134,15,136,12,0,33,131,35,12,149,19,140,35, + 129,37,6,34,25,22,9,5,1,0,26,34,9,0,28,1,34,28,33,38,15,9,28,22,37,16,220,236,212,252,236,212,236,17,18,57,17,18,57,17, + 18,57,18,57,49,0,16,228,244,236,16,254,205,16,244,238,18,57,57,23,57,48,1,75,176,16,84,75,176,18,84,91,75,176,19,84,91,88,189,0, + 37,255,192,0,1,0,37,0,37,0,64,56,17,55,56,89,64,11,116,4,116,5,116,6,116,7,118,28,5,93,1,51,21,20,6,15,1,14,1,21, + 20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,63,1,62,1,55,62,1,53,19,35,53,51,1,244,190,55,90,90,58,51,131,109,78,180,96, + 94,192,103,184,224,73,89,88,48,38,8,7,6,196,202,202,4,68,156,101,130,87,88,53,94,49,89,110,70,67,188,57,56,194,159,76,137,86,86,47, + 53,25,21,60,54,1,14,254,255,255,0,16,0,0,5,104,7,107,18,38,0,36,0,0,16,7,22,188,4,188,1,117,255,255,0,16,0,0,5,104, + 7,107,18,38,0,36,0,0,16,7,22,186,4,188,1,117,255,255,0,16,0,0,5,104,7,109,18,38,0,36,0,0,17,7,22,189,4,188,1,117, + 0,16,180,5,13,17,10,7,43,64,5,15,13,0,17,2,93,49,0,0,255,255,0,16,0,0,5,104,7,94,18,38,0,36,0,0,17,7,22,187, + 4,188,1,117,0,20,180,10,20,35,5,7,43,64,9,64,20,79,35,32,20,47,35,4,93,49,0,0,255,255,0,16,0,0,5,104,7,78,18,38, + 0,36,0,0,17,7,22,185,4,188,1,117,0,20,180,10,18,13,5,7,43,64,9,48,18,63,13,0,18,15,13,4,93,49,0,0,0,3,0,16, + 0,0,5,104,7,109,0,11,0,14,0,33,0,203,64,84,12,17,13,12,27,28,27,14,17,28,27,30,17,28,27,29,17,28,28,27,13,17,33,15, + 33,12,17,14,12,15,15,33,32,17,15,33,31,17,33,15,33,66,12,27,15,13,9,3,193,21,9,30,149,13,9,142,32,28,30,29,28,24,32,31, + 33,13,18,6,14,24,12,6,27,0,86,24,28,15,6,86,18,28,33,34,16,212,196,212,236,50,16,212,238,50,17,57,17,57,17,18,57,17,57,57, + 17,18,57,57,49,0,47,60,230,214,238,16,212,238,17,18,57,57,57,48,75,83,88,7,16,5,237,7,5,237,7,16,8,237,7,16,5,237,7,16, + 5,237,7,5,237,7,5,237,7,16,8,237,89,34,178,32,35,1,1,93,64,32,26,12,115,12,155,12,3,7,15,8,27,80,35,102,13,105,14,117, + 13,123,14,121,28,121,29,118,32,118,33,128,35,12,93,0,93,1,52,38,35,34,6,21,20,22,51,50,54,3,1,33,1,46,1,53,52,54,51,50, + 22,21,20,6,7,1,35,3,33,3,35,3,84,89,63,64,87,88,63,63,89,152,254,240,2,33,254,88,61,62,159,115,114,161,63,60,2,20,210,136, + 253,95,136,213,6,90,63,89,87,65,63,88,88,254,243,253,25,3,78,41,115,73,115,160,161,114,70,118,41,250,139,1,127,254,129,0,0,2,0,8, + 0,0,7,72,5,213,0,15,0,19,0,135,64,57,17,17,14,15,14,16,17,15,15,14,13,17,15,14,12,17,14,15,14,66,5,149,3,11,149,17, + 1,149,16,149,0,129,17,7,149,3,173,13,9,17,16,15,13,12,5,14,10,0,4,8,6,2,28,18,10,14,20,16,212,212,60,236,50,212,196,196, + 17,18,23,57,49,0,47,60,236,236,196,244,236,236,16,238,16,238,48,75,83,88,7,16,5,237,7,5,237,7,16,5,237,7,16,5,237,89,34,178, + 128,21,1,1,93,64,19,103,17,119,16,119,17,134,12,133,16,150,17,144,21,160,21,191,21,9,93,1,21,33,17,33,21,33,17,33,21,33,17,33, + 3,35,1,23,1,33,17,7,53,253,27,2,199,253,57,2,248,252,61,253,240,160,205,2,113,139,254,182,1,203,5,213,170,254,70,170,253,227,170,1, + 127,254,129,5,213,158,252,240,3,16,0,0,255,255,0,115,254,117,5,39,5,240,18,38,0,38,0,0,16,7,0,122,1,45,0,0,255,255,0,201, + 0,0,4,139,7,107,18,38,0,40,0,0,16,7,22,188,4,158,1,117,255,255,0,201,0,0,4,139,7,107,18,38,0,40,0,0,16,7,22,186, + 4,158,1,117,255,255,0,201,0,0,4,139,7,109,18,38,0,40,0,0,17,7,22,189,4,158,1,117,0,7,64,3,64,12,1,93,49,0,0,0, + 255,255,0,201,0,0,4,139,7,78,18,38,0,40,0,0,17,7,22,185,4,158,1,117,0,9,64,5,64,12,64,16,2,93,49,0,255,255,0,59, + 0,0,1,186,7,107,18,38,0,44,0,0,16,7,22,188,3,47,1,117,255,255,0,162,0,0,2,31,7,107,18,38,0,44,0,0,16,7,22,186, + 3,47,1,117,255,255,255,254,0,0,2,96,7,109,18,38,0,44,0,0,17,7,22,189,3,47,1,117,0,8,180,1,6,10,0,7,43,49,0,0, + 255,255,0,6,0,0,2,88,7,78,18,38,0,44,0,0,17,7,22,185,3,47,1,117,0,8,180,0,10,7,1,7,43,49,0,0,0,2,0,10, + 0,0,5,186,5,213,0,12,0,25,0,103,64,32,16,9,169,11,13,149,0,129,18,149,14,11,7,7,1,25,19,4,15,13,22,25,4,50,10,17, + 13,28,8,0,121,26,16,244,60,236,50,196,244,236,16,196,23,57,49,0,47,198,50,238,246,238,16,238,50,48,64,40,32,27,127,27,176,27,3,159, + 9,159,10,159,11,159,12,159,14,159,15,159,16,159,17,191,9,191,10,191,11,191,12,191,14,191,15,191,16,191,17,16,93,1,93,19,33,32,0,17, + 16,0,41,1,17,35,53,51,19,17,33,21,33,17,51,32,0,17,16,0,33,211,1,160,1,177,1,150,254,105,254,80,254,96,201,201,203,1,80,254, + 176,243,1,53,1,31,254,225,254,203,5,213,254,151,254,128,254,126,254,150,2,188,144,1,227,254,29,144,253,234,1,24,1,46,1,44,1,23,0,0, + 255,255,0,201,0,0,5,51,7,94,18,38,0,49,0,0,17,7,22,187,4,254,1,117,0,20,180,0,19,34,4,7,43,64,9,48,19,63,34,16, + 19,31,34,4,93,49,0,0,255,255,0,115,255,227,5,217,7,107,18,38,0,50,0,0,16,7,22,188,5,39,1,117,255,255,0,115,255,227,5,217, + 7,107,18,38,0,50,0,0,16,7,22,186,5,39,1,117,255,255,0,115,255,227,5,217,7,109,18,38,0,50,0,0,17,7,22,189,5,39,1,117, + 0,16,180,15,26,30,21,7,43,64,5,31,26,16,30,2,93,49,0,0,255,255,0,115,255,227,5,217,7,94,18,38,0,50,0,0,17,7,22,187, + 5,39,1,117,0,24,180,3,33,48,9,7,43,64,13,48,33,63,48,32,33,47,48,16,33,31,48,6,93,49,0,0,255,255,0,115,255,227,5,217, + 7,78,18,38,0,50,0,0,17,7,22,185,5,39,1,117,0,20,180,3,31,26,9,7,43,64,9,64,31,79,26,16,31,31,26,4,93,49,0,0, + 0,1,1,25,0,63,5,156,4,197,0,11,0,133,64,77,10,156,11,10,7,8,7,9,156,8,8,7,4,156,3,4,7,7,6,5,156,6,7,6, + 4,156,5,4,1,2,1,3,156,2,2,1,11,156,0,1,0,10,156,9,10,1,1,0,66,10,8,7,6,4,2,1,0,8,5,3,11,9,12,11, + 10,9,7,5,4,3,1,8,2,0,8,6,12,16,212,60,204,50,23,57,49,0,16,212,60,204,50,23,57,48,75,83,88,7,16,8,237,7,16,5, + 237,7,16,5,237,7,16,8,237,7,16,5,237,7,16,8,237,7,16,5,237,7,16,8,237,89,34,9,2,7,9,1,39,9,1,55,9,1,5,156, + 254,55,1,201,119,254,53,254,53,118,1,200,254,56,118,1,203,1,203,4,76,254,53,254,55,121,1,203,254,53,121,1,201,1,203,121,254,53,1,203, + 0,3,0,102,255,186,5,229,6,23,0,9,0,19,0,43,0,158,64,60,29,31,26,13,43,44,19,10,1,0,4,13,41,38,32,20,13,4,42,38, + 30,26,4,149,38,13,149,26,145,38,140,44,43,44,42,20,23,16,32,30,35,19,10,1,0,4,29,41,16,7,31,7,25,35,51,16,25,23,16,44, + 16,252,236,252,236,192,17,18,57,57,23,57,18,57,57,17,18,57,57,17,57,49,0,16,228,244,236,16,238,16,192,16,192,17,18,57,57,18,57,18, + 23,57,18,57,17,18,57,57,48,64,42,87,0,90,21,87,25,85,33,106,21,101,33,123,21,118,28,117,33,9,70,19,89,0,86,19,106,0,100,19, + 100,28,106,40,124,0,115,19,118,28,122,40,11,93,1,93,9,1,30,1,51,50,0,17,52,38,39,46,1,35,34,0,17,20,22,23,7,38,2,53, + 16,0,33,50,22,23,55,23,7,22,18,21,16,0,33,34,38,39,7,39,4,182,253,51,62,161,95,220,1,1,39,121,61,161,95,220,254,253,39,39, + 134,78,79,1,121,1,59,130,221,87,162,102,170,78,80,254,136,254,198,128,221,91,162,103,4,88,252,178,64,67,1,72,1,26,112,184,184,64,67,254, + 184,254,229,112,188,68,158,102,1,8,160,1,98,1,165,77,75,191,89,198,103,254,246,158,254,159,254,91,75,75,191,88,255,255,0,178,255,227,5,41, + 7,107,18,38,0,56,0,0,16,7,22,188,4,238,1,117,255,255,0,178,255,227,5,41,7,107,18,38,0,56,0,0,16,7,22,186,4,238,1,117, + 255,255,0,178,255,227,5,41,7,109,18,38,0,56,0,0,17,7,22,189,4,238,1,117,0,20,180,10,20,24,0,7,43,64,9,47,20,32,24,31, + 20,16,24,4,93,49,0,0,255,255,0,178,255,227,5,41,7,78,18,38,0,56,0,0,17,7,22,185,4,238,1,117,0,28,180,1,25,20,9,7, + 43,64,17,80,25,95,20,64,25,79,20,32,25,47,20,16,25,31,20,8,93,49,0,0,255,255,255,252,0,0,4,231,7,107,18,38,0,60,0,0, + 16,7,22,186,4,115,1,117,0,2,0,201,0,0,4,141,5,213,0,12,0,21,0,61,64,27,14,149,9,13,149,2,246,0,129,11,21,15,9,3, + 4,1,18,25,6,63,13,10,1,28,0,4,22,16,252,236,50,50,252,236,17,23,57,49,0,47,244,252,236,212,236,48,64,9,15,23,31,23,63,23, + 95,23,4,1,93,19,51,17,51,50,4,21,20,4,43,1,17,35,19,17,51,50,54,53,52,38,35,201,202,254,251,1,1,254,255,251,254,202,202,254, + 141,154,153,142,5,213,254,248,225,220,220,226,254,174,4,39,253,209,146,134,134,145,0,0,0,1,0,186,255,227,4,172,6,20,0,47,0,154,64,48, + 45,39,33,12,4,6,13,32,0,4,42,22,134,23,26,185,19,42,185,3,151,19,140,46,12,9,13,29,32,33,39,9,8,36,39,8,6,29,8,36, + 16,22,45,8,16,0,70,48,16,252,196,252,204,16,198,238,212,238,16,238,17,57,57,18,57,18,57,49,0,47,228,254,238,16,254,213,238,18,23,57, + 23,57,48,64,64,15,5,15,6,15,7,15,39,15,40,138,12,138,13,7,10,6,10,7,10,11,10,12,10,13,10,31,13,32,10,33,12,34,4,38, + 25,13,25,31,25,32,58,32,58,33,77,31,77,32,73,33,73,34,106,31,106,32,165,6,165,7,166,32,24,93,1,93,19,52,54,51,50,22,23,14, + 1,21,20,22,31,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,47,1,46,1,53,52,54,55,46,1,35,34,6,21,17,35, + 186,239,218,208,219,3,151,168,58,65,57,166,96,225,211,64,136,73,80,140,65,116,120,59,101,92,96,87,167,151,8,131,113,130,136,187,4,113,200,219, + 232,224,8,115,96,47,81,42,37,106,142,100,172,183,25,24,164,30,29,95,91,63,84,62,55,59,135,91,127,172,29,103,112,139,131,251,147,0,0,0, + 255,255,0,123,255,227,4,45,6,102,18,38,0,68,0,0,17,6,0,67,82,0,0,11,64,7,63,38,47,38,31,38,3,93,49,0,255,255,0,123, + 255,227,4,45,6,102,18,38,0,68,0,0,17,6,0,118,82,0,0,11,64,7,63,38,47,38,31,38,3,93,49,0,255,255,0,123,255,227,4,45, + 6,102,18,38,0,68,0,0,17,6,2,136,82,0,0,8,180,11,40,44,20,7,43,49,255,255,0,123,255,227,4,45,6,55,18,38,0,68,0,0, + 17,6,2,158,82,0,0,20,180,20,46,60,11,7,43,64,9,32,46,47,60,16,46,31,60,4,93,49,255,255,0,123,255,227,4,45,6,16,18,38, + 0,68,0,0,17,6,0,106,82,0,0,32,180,20,45,40,11,7,43,64,21,127,40,111,40,80,45,95,40,64,45,79,40,48,45,63,40,0,45,15, + 40,10,93,49,255,255,0,123,255,227,4,45,7,6,18,38,0,68,0,0,17,6,2,156,82,0,0,37,64,14,38,44,20,44,38,11,7,50,56,20, + 56,50,11,7,43,16,196,43,16,196,49,0,64,9,63,53,63,47,15,53,15,47,4,93,48,0,0,0,0,3,0,123,255,227,7,111,4,123,0,6, + 0,51,0,62,1,3,64,67,39,45,37,61,14,13,0,52,169,37,22,134,21,136,18,0,169,14,58,18,185,28,25,46,134,45,186,42,3,185,14,187, + 7,49,10,184,31,25,140,37,63,52,55,38,6,15,0,37,55,28,7,38,15,21,0,8,13,61,38,8,15,45,55,8,34,69,63,16,252,236,204,212, + 252,60,212,236,196,17,18,57,57,17,57,17,18,57,17,18,57,49,0,16,196,228,50,244,60,196,228,252,60,244,236,16,196,238,50,16,238,16,244,238, + 16,238,17,57,17,57,17,18,57,48,64,129,48,43,48,44,48,45,48,46,48,47,48,48,64,43,64,44,64,45,64,46,64,47,64,48,80,43,80,44, + 80,45,80,46,80,47,80,48,133,43,133,48,128,64,144,64,160,64,176,64,192,64,208,64,224,64,224,64,240,64,29,63,0,63,6,63,13,63,14,63, + 15,5,48,44,48,45,48,46,48,47,64,44,64,45,64,46,64,47,80,44,80,45,80,46,80,47,111,0,111,6,111,13,111,14,111,15,96,44,96,45, + 96,46,96,47,112,44,112,45,112,46,112,47,128,44,128,45,128,46,128,47,29,93,113,1,93,1,46,1,35,34,6,7,3,62,1,51,50,0,29,1, + 33,30,1,51,50,54,55,21,14,1,35,34,38,39,14,1,35,34,38,53,52,54,51,33,53,52,38,35,34,6,7,53,62,1,51,50,22,3,34,6, + 21,20,22,51,50,54,61,1,6,182,1,165,137,153,185,14,68,74,212,132,226,1,8,252,178,12,204,183,104,200,100,100,208,106,167,248,77,73,216,143, + 189,210,253,251,1,2,167,151,96,182,84,101,190,90,142,213,239,223,172,129,111,153,185,2,148,151,180,174,158,1,48,90,94,254,221,250,90,191,200,53, + 53,174,42,44,121,119,120,120,187,168,189,192,18,127,139,46,46,170,39,39,96,254,24,102,123,98,115,217,180,41,0,0,255,255,0,113,254,117,3,231, + 4,123,18,38,0,70,0,0,16,7,0,122,0,143,0,0,255,255,0,113,255,227,4,127,6,102,18,38,0,72,0,0,16,7,0,67,0,139,0,0, + 255,255,0,113,255,227,4,127,6,102,18,38,0,72,0,0,16,7,0,118,0,139,0,0,255,255,0,113,255,227,4,127,6,102,18,38,0,72,0,0, + 17,7,2,136,0,139,0,0,0,8,180,21,30,34,27,7,43,49,0,0,255,255,0,113,255,227,4,127,6,16,18,38,0,72,0,0,17,7,0,106, + 0,139,0,0,0,7,64,3,64,32,1,93,49,0,0,0,255,255,255,199,0,0,1,166,6,102,16,39,0,67,255,29,0,0,18,6,0,243,0,0, + 255,255,0,144,0,0,2,111,6,102,16,39,0,118,255,29,0,0,18,6,0,243,0,0,255,255,255,222,0,0,2,92,6,102,18,38,0,243,0,0, + 17,7,2,136,255,29,0,0,0,8,180,1,7,11,0,7,43,49,0,0,255,255,255,244,0,0,2,70,6,16,18,38,0,243,0,0,17,7,0,106, + 255,29,0,0,0,8,180,0,11,8,1,7,43,49,0,0,0,2,0,113,255,227,4,117,6,20,0,14,0,40,1,39,64,94,37,123,38,37,30,35, + 30,36,123,35,35,30,15,123,35,30,40,123,39,40,30,35,30,38,39,40,39,37,36,37,40,40,39,34,35,34,31,32,31,33,32,32,31,66,40,39, + 38,37,34,33,32,31,8,35,30,3,15,35,3,185,27,9,185,21,140,27,35,177,41,38,39,18,12,33,32,24,40,37,35,34,31,5,30,15,6,12, + 18,18,81,6,18,24,69,41,16,252,236,244,236,17,57,57,23,57,18,57,57,17,18,57,57,49,0,16,236,196,244,236,16,238,18,57,18,57,18,23, + 57,48,75,83,88,7,16,14,201,7,16,8,201,7,16,8,201,7,16,14,201,7,16,8,237,7,14,237,7,16,5,237,7,16,8,237,89,34,178,63, + 42,1,1,93,64,118,22,37,43,31,40,34,47,35,47,36,41,37,45,38,45,39,42,40,54,37,70,37,88,32,88,33,96,32,96,33,102,34,117,32, + 117,33,117,34,19,37,35,37,36,38,38,38,39,39,40,54,36,54,37,70,36,69,37,90,32,90,33,98,32,98,33,127,0,127,1,127,2,122,3,123, + 9,127,10,127,11,127,12,127,13,127,14,127,15,127,16,127,17,127,18,127,19,127,20,123,21,122,27,122,28,127,29,127,30,118,32,118,33,120,34,160, + 42,240,42,39,93,0,93,1,46,1,35,34,6,21,20,22,51,50,54,53,52,38,19,22,18,21,20,0,35,34,0,17,52,0,51,50,22,23,39,5, + 39,37,39,51,23,37,23,5,3,70,50,88,41,167,185,174,146,145,174,54,9,126,114,254,228,230,231,254,229,1,20,221,18,52,42,159,254,193,33,1, + 25,181,228,127,1,77,33,254,217,3,147,17,16,216,195,188,222,222,188,122,188,1,38,143,254,224,173,255,254,201,1,55,0,255,250,1,55,5,5,180, + 107,99,92,204,145,111,97,98,255,255,0,186,0,0,4,100,6,55,18,38,0,81,0,0,16,7,2,158,0,152,0,0,255,255,0,113,255,227,4,117, + 6,102,18,38,0,82,0,0,16,6,0,67,115,0,0,0,255,255,0,113,255,227,4,117,6,102,18,38,0,82,0,0,16,6,0,118,115,0,0,0, + 255,255,0,113,255,227,4,117,6,102,18,38,0,82,0,0,17,6,2,136,115,0,0,8,180,15,26,30,21,7,43,49,255,255,0,113,255,227,4,117, + 6,55,18,38,0,82,0,0,17,6,2,158,115,0,0,20,180,21,32,46,15,7,43,64,9,32,32,47,46,16,32,31,46,4,93,49,255,255,0,113, + 255,227,4,117,6,16,18,38,0,82,0,0,17,6,0,106,115,0,0,20,180,3,31,26,9,7,43,64,9,64,31,79,26,48,31,63,26,4,93,49, + 0,3,0,217,0,150,5,219,4,111,0,3,0,7,0,11,0,41,64,20,0,234,2,6,234,4,2,8,156,4,10,12,9,5,1,114,4,0,8,12, + 16,220,212,60,252,60,196,49,0,16,212,196,252,196,16,238,16,238,48,1,51,21,35,17,51,21,35,1,33,21,33,2,223,246,246,246,246,253,250,5, + 2,250,254,4,111,246,254,18,245,2,65,170,0,3,0,72,255,162,4,156,4,188,0,9,0,19,0,43,0,228,64,60,43,44,38,31,29,26,19,10, + 1,0,4,13,41,38,32,20,13,4,42,38,30,26,4,185,38,13,185,26,184,38,140,44,43,44,42,20,23,16,32,30,35,19,10,1,0,4,16,7, + 31,29,7,18,35,81,41,16,18,23,69,44,16,252,236,50,244,236,50,192,17,18,23,57,18,57,57,17,18,57,57,17,57,49,0,16,228,244,236,16, + 238,16,192,16,192,17,18,57,57,18,57,18,23,57,17,57,57,17,18,57,48,64,112,40,1,63,45,89,20,86,28,85,29,86,32,106,21,102,33,127, + 0,123,4,127,5,127,6,127,7,127,8,127,9,127,10,127,11,127,12,123,13,122,21,123,26,127,27,127,28,127,29,127,30,127,31,127,32,123,33,127, + 34,127,35,127,36,127,37,123,38,155,25,149,37,168,25,160,45,240,45,38,89,0,86,19,85,29,90,40,105,0,102,19,101,28,106,40,122,0,116,19, + 118,28,122,40,137,30,149,24,154,36,162,24,173,36,17,93,1,93,9,1,30,1,51,50,54,53,52,38,39,46,1,35,34,6,21,20,22,23,7,46, + 1,53,16,0,51,50,22,23,55,23,7,30,1,21,16,0,35,34,38,39,7,39,3,137,254,25,41,103,65,147,172,20,92,42,103,62,151,169,19,20, + 125,54,54,1,17,241,93,159,67,139,95,146,53,54,254,238,240,96,161,63,139,96,3,33,253,176,42,40,232,200,79,117,154,41,41,235,211,72,110,46, + 151,77,197,119,1,20,1,56,51,52,168,79,179,77,198,120,254,237,254,199,52,51,168,78,255,255,0,174,255,227,4,88,6,102,18,38,0,88,0,0, + 16,6,0,67,123,0,0,0,255,255,0,174,255,227,4,88,6,102,18,38,0,88,0,0,16,6,0,118,123,0,0,0,255,255,0,174,255,227,4,88, + 6,102,18,38,0,88,0,0,17,6,2,136,123,0,0,8,180,11,23,27,1,7,43,49,255,255,0,174,255,227,4,88,6,16,18,38,0,88,0,0, + 17,6,0,106,123,0,0,24,180,2,27,24,10,7,43,64,13,64,27,79,24,48,27,63,24,0,27,15,24,6,93,49,255,255,0,61,254,86,4,127, + 6,102,18,38,0,92,0,0,16,6,0,118,94,0,0,0,0,2,0,186,254,86,4,164,6,20,0,16,0,28,0,62,64,27,20,185,5,8,26,185, + 0,14,140,8,184,1,189,3,151,29,17,18,11,71,23,4,0,8,2,70,29,16,252,236,50,50,244,236,49,0,16,236,228,228,244,196,236,16,198,238, + 48,64,9,96,30,128,30,160,30,224,30,4,1,93,37,17,35,17,51,17,62,1,51,50,0,17,16,2,35,34,38,1,52,38,35,34,6,21,20,22, + 51,50,54,1,115,185,185,58,177,123,204,0,255,255,204,123,177,2,56,167,146,146,167,167,146,146,167,168,253,174,7,190,253,162,100,97,254,188,254,248, + 254,248,254,188,97,1,235,203,231,231,203,203,231,231,0,0,255,255,0,61,254,86,4,127,6,16,18,38,0,92,0,0,17,6,0,106,94,0,0,22, + 180,24,23,18,25,7,43,64,11,48,23,63,18,32,23,47,18,31,18,5,93,49,0,0,255,255,0,16,0,0,5,104,7,49,16,39,0,113,0,188, + 1,59,19,6,0,36,0,0,0,16,180,14,3,2,9,7,43,64,5,64,3,79,2,2,93,49,0,0,255,255,0,123,255,227,4,45,5,246,16,38, + 0,113,74,0,19,6,0,68,0,0,0,16,180,24,3,2,15,7,43,64,5,111,2,127,3,2,93,49,255,255,0,16,0,0,5,104,7,146,16,39, + 2,154,0,206,1,74,19,6,0,36,0,0,0,18,180,24,0,8,19,7,43,49,0,64,5,111,0,111,8,2,93,48,255,255,0,123,255,227,4,45, + 6,31,16,38,2,154,79,215,19,6,0,68,0,0,0,8,180,34,0,8,25,7,43,49,255,255,0,16,254,117,5,165,5,213,18,38,0,36,0,0, + 16,7,2,157,2,228,0,0,255,255,0,123,254,117,4,128,4,123,18,38,0,68,0,0,16,7,2,157,1,191,0,0,255,255,0,115,255,227,5,39, + 7,107,18,38,0,38,0,0,16,7,22,186,5,45,1,117,255,255,0,113,255,227,3,231,6,102,18,38,0,70,0,0,16,7,0,118,0,137,0,0, + 255,255,0,115,255,227,5,39,7,109,16,39,22,189,5,76,1,117,19,6,0,38,0,0,0,9,178,4,4,30,16,60,61,47,49,0,255,255,0,113, + 255,227,3,231,6,102,18,38,0,70,0,0,16,7,2,136,0,164,0,0,255,255,0,115,255,227,5,39,7,80,16,39,22,193,5,76,1,117,18,6, + 0,38,0,0,255,255,0,113,255,227,3,231,6,20,16,39,2,184,4,164,0,0,18,6,0,70,0,0,255,255,0,115,255,227,5,39,7,109,18,38, + 0,38,0,0,17,7,22,190,5,45,1,117,0,7,64,3,31,29,1,93,49,0,0,0,255,255,0,113,255,227,3,231,6,102,18,38,0,70,0,0, + 16,7,2,137,0,137,0,0,255,255,0,201,0,0,5,176,7,109,16,39,22,190,4,236,1,117,18,6,0,39,0,0,255,255,0,113,255,227,5,219, + 6,20,18,38,0,71,0,0,17,7,22,184,5,20,0,0,0,11,64,7,95,29,63,29,31,29,3,93,49,0,0,0,255,255,0,10,0,0,5,186, + 5,213,16,6,0,146,0,0,0,2,0,113,255,227,4,244,6,20,0,24,0,36,0,74,64,36,7,3,211,9,1,249,34,185,0,22,28,185,13,16, + 140,22,184,5,151,11,2,31,12,4,3,0,8,8,10,6,71,25,18,19,69,37,16,252,236,244,60,196,252,23,60,196,49,0,47,236,228,244,196,236, + 16,196,238,253,60,238,50,48,182,96,38,128,38,160,38,3,1,93,1,17,33,53,33,53,51,21,51,21,35,17,35,53,14,1,35,34,2,17,16,0, + 51,50,22,1,20,22,51,50,54,53,52,38,35,34,6,3,162,254,186,1,70,184,154,154,184,58,177,124,203,255,0,255,203,124,177,253,199,167,146,146, + 168,168,146,146,167,3,182,1,78,125,147,147,125,250,252,168,100,97,1,68,1,8,1,8,1,68,97,254,21,203,231,231,203,203,231,231,255,255,0,201, + 0,0,4,139,7,51,18,38,0,40,0,0,16,7,0,113,0,161,1,61,255,255,0,113,255,227,4,127,5,246,16,39,0,113,0,150,0,0,19,6, + 0,72,0,0,0,7,64,3,112,0,1,93,49,0,0,0,255,255,0,201,0,0,4,139,7,109,16,39,22,192,4,161,1,117,19,6,0,40,0,0, + 0,7,64,3,64,0,1,93,49,0,0,0,255,255,0,113,255,227,4,127,6,72,16,39,2,154,0,150,0,0,19,6,0,72,0,0,0,7,64,3, + 112,0,1,93,49,0,0,0,255,255,0,201,0,0,4,139,7,80,16,39,22,193,4,158,1,117,18,6,0,40,0,0,255,255,0,113,255,227,4,127, + 6,20,16,39,2,184,4,150,0,0,18,6,0,72,0,0,255,255,0,201,254,117,4,141,5,213,18,38,0,40,0,0,16,7,2,157,1,204,0,0, + 255,255,0,113,254,117,4,127,4,123,18,38,0,72,0,0,16,7,2,157,1,120,0,0,255,255,0,201,0,0,4,139,7,103,18,38,0,40,0,0, + 17,7,22,190,4,166,1,111,0,7,64,3,64,12,1,93,49,0,0,0,255,255,0,113,255,227,4,127,6,97,18,38,0,72,0,0,17,7,2,137, + 0,148,255,251,0,16,180,0,33,29,15,7,43,64,5,15,33,0,29,2,93,49,0,0,255,255,0,115,255,227,5,139,7,109,16,39,22,189,5,92, + 1,117,19,6,0,42,0,0,0,9,178,4,4,21,16,60,61,47,49,0,255,255,0,113,254,86,4,90,6,102,16,38,2,136,104,0,19,6,0,74, + 0,0,0,9,178,4,4,10,16,60,61,47,49,0,0,0,255,255,0,115,255,227,5,139,7,109,18,38,0,42,0,0,16,7,22,192,5,27,1,117, + 255,255,0,113,254,86,4,90,6,72,18,38,0,74,0,0,16,7,2,154,0,139,0,0,255,255,0,115,255,227,5,139,7,80,16,39,22,193,5,92, + 1,117,19,6,0,42,0,0,0,8,0,64,3,63,0,1,93,48,0,0,255,255,0,113,254,86,4,90,6,20,16,39,2,184,4,106,0,0,18,6, + 0,74,0,0,255,255,0,115,254,1,5,139,5,240,16,39,2,215,5,94,255,237,18,6,0,42,0,0,255,255,0,113,254,86,4,90,6,52,16,39, + 2,195,3,224,1,12,18,6,0,74,0,0,255,255,0,201,0,0,5,59,7,109,16,39,22,189,5,2,1,117,19,6,0,43,0,0,0,20,180,12, + 2,6,7,7,43,64,9,47,2,32,6,31,2,16,6,4,93,49,0,0,255,255,255,229,0,0,4,100,7,109,16,39,22,189,3,22,1,117,19,6, + 0,75,0,0,0,42,180,20,2,6,19,7,43,49,0,75,176,14,81,88,187,0,20,255,192,0,19,255,192,56,56,89,64,13,144,20,144,19,128,20, + 128,19,64,20,64,19,6,93,0,2,0,201,0,0,6,139,5,213,0,19,0,23,0,58,64,30,6,2,18,149,9,20,17,12,149,21,173,4,0,129, + 14,10,7,12,23,4,28,5,56,18,13,20,1,28,0,24,16,220,236,50,50,204,252,236,50,50,204,49,0,47,60,228,50,252,236,220,50,50,236,50, + 50,48,1,51,21,33,53,51,21,51,21,35,17,35,17,33,17,35,17,35,53,51,23,21,33,53,1,113,202,2,222,202,168,168,202,253,34,202,168,168, + 202,2,222,5,213,224,224,224,164,251,175,2,199,253,57,4,81,164,164,224,224,0,0,0,0,1,0,120,0,0,4,159,6,20,0,27,0,62,64,33, + 3,9,0,3,22,1,14,18,135,13,21,6,135,22,25,184,16,151,10,1,2,8,0,78,19,14,17,21,9,8,16,11,28,16,220,50,236,50,50,204, + 204,244,236,49,0,47,60,236,244,196,236,220,50,236,50,17,18,23,57,48,1,17,35,17,52,38,35,34,6,21,17,35,17,35,53,51,53,51,21,33, + 21,33,17,62,1,51,50,22,4,159,184,124,124,149,172,185,125,125,185,1,96,254,160,66,179,117,193,198,2,164,253,92,2,158,159,158,190,164,253,135, + 4,246,164,122,122,164,254,188,101,100,239,0,255,255,255,228,0,0,2,120,7,94,16,39,22,187,3,46,1,117,19,6,0,44,0,0,0,8,180,30, + 9,24,31,7,43,49,0,0,255,255,255,211,0,0,2,103,6,55,16,39,2,158,255,29,0,0,19,6,0,243,0,0,0,8,180,28,8,22,29,7, + 43,49,0,0,255,255,0,3,0,0,2,89,7,49,16,39,0,113,255,46,1,59,19,6,0,44,0,0,0,8,180,4,3,2,5,7,43,49,0,0, + 255,255,255,242,0,0,2,72,5,245,16,39,0,113,255,29,255,255,19,6,0,243,0,0,0,8,180,4,3,2,5,7,43,49,0,0,255,255,255,245, + 0,0,2,103,7,109,16,39,22,192,3,46,1,117,19,6,0,44,0,0,0,8,180,14,0,8,15,7,43,49,0,0,255,255,255,228,0,0,2,86, + 6,72,16,39,2,154,255,29,0,0,19,6,0,243,0,0,0,8,180,14,0,8,15,7,43,49,0,0,255,255,0,176,254,117,2,37,5,213,16,39, + 2,157,255,100,0,0,18,6,0,44,0,0,255,255,0,150,254,117,2,11,6,20,16,39,2,157,255,74,0,0,18,6,0,76,0,0,255,255,0,201, + 0,0,1,149,7,80,18,38,0,44,0,0,17,7,22,193,3,47,1,117,0,19,179,6,1,7,0,16,60,16,60,49,0,180,63,7,63,6,2,93, + 48,0,0,0,0,2,0,193,0,0,1,121,4,123,0,3,0,4,0,44,64,11,4,184,0,191,2,4,1,8,0,70,5,16,252,236,57,49,0,47, + 236,228,48,64,17,4,4,52,4,68,4,16,6,64,6,80,6,96,6,112,6,8,1,93,19,51,17,35,19,193,184,184,92,4,96,251,160,4,123,0, + 255,255,0,201,254,102,3,239,5,213,16,39,0,45,2,92,0,0,17,6,0,44,0,0,0,8,64,3,17,4,1,16,236,49,0,0,255,255,0,193, + 254,86,3,177,6,20,16,39,0,77,2,56,0,0,17,6,0,76,0,0,0,8,64,3,25,70,1,16,236,49,0,0,255,255,255,150,254,102,2,95, + 7,109,16,39,22,189,3,46,1,117,19,6,0,45,0,0,0,8,180,8,2,6,7,7,43,49,0,0,255,255,255,219,254,86,2,92,6,102,16,39, + 2,136,255,29,0,0,19,6,1,249,0,0,0,8,180,8,2,6,7,7,43,49,0,0,255,255,0,201,254,30,5,106,5,213,16,39,2,215,5,27, + 0,10,18,6,0,46,0,0,255,255,0,186,254,30,4,156,6,20,16,39,2,215,4,172,0,10,18,6,0,78,0,0,0,1,0,186,0,0,4,156, + 4,96,0,10,0,187,64,40,8,17,5,6,5,7,17,6,6,5,3,17,4,5,4,2,17,5,5,4,66,8,5,2,3,3,0,188,9,6,5,1, + 4,6,8,1,8,0,70,11,16,252,236,50,212,196,17,57,49,0,47,60,236,50,23,57,48,75,83,88,7,16,4,237,7,16,5,237,7,16,5,237, + 7,16,4,237,89,34,178,16,12,1,1,93,64,95,4,2,10,8,22,2,39,2,41,5,43,8,86,2,102,2,103,8,115,2,119,5,130,2,137,5, + 142,8,147,2,150,5,151,8,163,2,18,9,5,9,6,2,11,3,10,7,40,3,39,4,40,5,43,6,43,7,64,12,104,3,96,12,137,3,133,4, + 137,5,141,6,143,7,154,3,151,7,170,3,167,5,182,7,197,7,214,7,247,3,240,3,247,4,240,4,26,93,113,0,93,19,51,17,1,51,9,1, + 35,1,17,35,186,185,2,37,235,253,174,2,107,240,253,199,185,4,96,254,27,1,229,253,242,253,174,2,33,253,223,0,255,255,0,201,0,0,4,106, + 7,108,16,39,22,186,3,110,1,118,18,6,0,47,0,0,255,255,0,193,0,0,2,74,7,108,16,39,22,186,3,90,1,118,19,6,0,79,0,0, + 0,30,177,3,4,16,60,49,0,75,176,14,81,88,185,0,0,0,64,56,89,64,7,159,0,143,0,79,0,3,93,48,255,255,0,201,254,30,4,106, + 5,213,16,39,2,215,4,155,0,10,18,6,0,47,0,0,255,255,0,136,254,30,1,173,6,20,16,39,2,215,3,30,0,10,19,6,0,79,0,0, + 0,7,64,3,64,0,1,93,49,0,0,0,255,255,0,201,0,0,4,106,5,213,16,39,22,184,2,159,255,195,18,6,0,47,0,0,255,255,0,193, + 0,0,3,0,6,20,16,39,22,184,2,57,0,2,17,6,0,79,0,0,0,9,64,5,143,0,31,0,2,93,49,0,255,255,0,201,0,0,4,106, + 5,213,16,39,0,121,2,49,0,119,18,6,0,47,0,0,255,255,0,193,0,0,2,132,6,20,16,39,0,121,0,214,0,115,17,6,0,79,0,0, + 0,23,75,176,13,81,75,176,17,83,75,176,24,81,90,91,88,185,0,0,0,64,56,89,49,0,0,0,0,1,255,242,0,0,4,117,5,213,0,13, + 0,63,64,30,12,11,10,4,3,2,6,0,6,149,0,129,8,3,4,1,11,14,0,4,5,1,28,12,7,58,9,0,121,14,16,244,60,236,196,252, + 60,196,17,18,57,17,18,57,49,0,47,228,236,17,23,57,48,180,48,15,80,15,2,1,93,19,51,17,37,23,1,17,33,21,33,17,7,39,55,211, + 203,1,57,80,254,119,2,215,252,94,148,77,225,5,213,253,152,219,111,254,238,253,227,170,2,59,106,110,158,0,0,0,0,1,0,2,0,0,2,72, + 6,20,0,11,0,94,64,26,10,9,8,4,3,2,6,0,151,6,3,4,1,9,10,0,4,122,5,1,8,10,122,7,0,12,16,212,60,228,252,60, + 228,17,18,57,17,18,57,49,0,47,236,23,57,48,1,75,176,16,84,88,189,0,12,0,64,0,1,0,12,0,12,255,192,56,17,55,56,89,64,19, + 16,13,64,13,80,13,96,13,115,4,122,10,112,13,224,13,240,13,9,93,19,51,17,55,23,7,17,35,17,7,39,55,199,184,125,76,201,184,123,74, + 197,6,20,253,166,90,106,141,252,227,2,154,88,106,141,0,255,255,0,201,0,0,5,51,7,108,16,39,22,186,4,197,1,118,19,6,0,49,0,0, + 0,7,64,3,79,0,1,93,49,0,0,0,255,255,0,186,0,0,4,100,6,109,16,38,0,118,66,7,19,6,0,81,0,0,0,9,64,5,63,0, + 79,0,2,93,49,0,0,0,255,255,0,201,254,30,5,51,5,213,16,39,2,215,5,0,0,10,18,6,0,49,0,0,255,255,0,186,254,30,4,100, + 4,123,16,39,2,215,4,144,0,10,18,6,0,81,0,0,255,255,0,201,0,0,5,51,7,95,18,38,0,49,0,0,17,7,22,190,4,245,1,103, + 0,20,180,4,15,11,0,7,43,64,9,47,15,32,11,31,15,16,11,4,93,49,0,0,255,255,0,186,0,0,4,100,6,102,18,38,0,81,0,0, + 17,7,2,137,0,141,0,0,0,16,180,0,25,21,12,7,43,64,5,15,25,0,21,2,93,49,0,0,255,255,0,205,0,0,5,185,5,213,16,39, + 0,81,1,85,0,0,16,6,2,126,27,0,0,1,0,201,254,86,5,25,5,240,0,28,0,59,64,13,25,22,18,24,28,28,18,10,5,28,7,65, + 29,16,252,75,176,16,84,88,185,0,7,255,192,56,89,236,50,212,252,204,17,49,0,64,12,25,149,22,176,7,2,149,14,145,8,129,7,47,228,244, + 236,16,244,236,48,1,16,33,34,6,21,17,35,17,51,21,54,55,54,51,50,18,25,1,20,7,6,43,1,53,51,50,54,53,4,80,254,205,179,215, + 202,202,78,105,106,153,227,233,81,82,181,87,49,102,79,3,127,1,172,255,222,252,178,5,213,241,134,67,67,254,193,254,204,252,111,213,97,96,156,90, + 160,0,0,0,0,1,0,186,254,86,4,100,4,123,0,31,0,59,64,28,13,19,0,3,24,21,7,135,6,16,135,24,28,184,22,188,21,7,13,8, + 0,78,19,23,8,22,70,32,16,252,236,50,244,236,196,49,0,47,228,244,196,236,212,236,17,18,23,57,48,180,96,33,207,33,2,1,93,1,17,20, + 7,6,43,1,53,51,50,55,54,53,17,52,38,35,34,6,21,17,35,17,51,21,54,55,54,51,50,23,22,4,100,82,81,181,254,233,105,38,38,124, + 124,149,172,185,185,66,89,90,117,193,99,99,2,164,253,72,214,96,96,156,48,49,153,2,178,159,158,190,164,253,135,4,96,174,101,50,50,119,120,0, + 255,255,0,115,255,227,5,217,7,49,16,39,0,113,1,39,1,59,19,6,0,50,0,0,0,16,180,13,2,3,7,7,43,64,5,31,2,16,3,2, + 93,49,0,0,255,255,0,113,255,227,4,117,5,245,16,38,0,113,115,255,19,6,0,82,0,0,0,8,180,19,2,3,25,7,43,49,255,255,0,115, + 255,227,5,217,7,109,16,39,22,192,5,39,1,117,19,6,0,50,0,0,0,16,180,17,0,8,23,7,43,64,5,16,0,31,8,2,93,49,0,0, + 255,255,0,113,255,227,4,117,6,72,16,38,2,154,115,0,19,6,0,82,0,0,0,8,180,29,8,0,35,7,43,49,255,255,0,115,255,227,5,217, + 7,107,16,39,22,194,5,39,1,117,18,6,0,50,0,0,255,255,0,113,255,227,4,117,6,102,16,39,2,159,0,160,0,0,18,6,0,82,0,0, + 0,2,0,115,0,0,8,12,5,213,0,16,0,25,0,59,64,31,5,149,3,17,1,149,0,129,24,7,149,3,173,9,24,18,16,10,21,6,2,28, + 17,0,4,8,21,25,13,16,26,16,252,236,212,196,196,212,236,50,18,57,57,57,57,49,0,47,236,236,50,244,236,50,16,238,48,1,21,33,17,33, + 21,33,17,33,21,33,32,0,17,16,0,33,23,35,32,0,17,16,0,33,51,7,250,253,26,2,199,253,57,2,248,251,215,254,79,254,65,1,191,1, + 177,103,129,254,191,254,192,1,64,1,65,129,5,213,170,254,70,170,253,227,170,1,124,1,112,1,109,1,124,170,254,225,254,224,254,223,254,223,0,0, + 0,3,0,113,255,227,7,195,4,123,0,6,0,39,0,51,0,132,64,49,7,8,0,16,134,15,136,12,0,169,8,46,12,185,22,19,40,3,185,8, + 187,34,37,31,184,25,19,140,52,6,0,22,34,49,9,15,0,8,7,75,49,18,9,81,43,18,28,69,52,16,252,236,244,252,244,236,196,17,18,57, + 57,18,57,49,0,16,228,50,244,60,196,228,236,50,16,196,238,50,16,238,16,244,238,17,18,57,48,64,37,63,53,95,53,112,53,159,53,207,53,208, + 53,240,53,7,63,0,63,6,63,7,63,8,63,9,5,111,0,111,6,111,7,111,8,111,9,5,93,113,1,93,1,46,1,35,34,6,7,5,21,33, + 30,1,51,50,54,55,21,14,1,35,34,38,39,14,1,35,34,0,17,16,0,51,50,22,23,62,1,51,50,0,37,34,6,21,20,22,51,50,54,53, + 52,38,7,10,2,164,137,153,185,14,3,72,252,178,12,204,183,106,200,98,100,208,106,160,242,81,71,209,140,241,254,239,1,17,241,140,211,66,78,232, + 143,226,1,8,250,176,148,172,171,149,147,172,172,2,148,152,179,174,158,53,90,190,199,52,52,174,42,44,110,109,110,109,1,57,1,19,1,20,1,56, + 111,108,107,112,254,221,135,231,201,201,231,232,200,199,233,0,255,255,0,201,0,0,5,84,7,108,16,39,22,186,4,149,1,118,18,6,0,53,0,0, + 255,255,0,186,0,0,3,148,6,109,16,38,0,118,66,7,18,6,0,85,0,0,0,0,255,255,0,201,254,30,5,84,5,213,16,39,2,215,5,16, + 0,10,18,6,0,53,0,0,255,255,0,130,254,30,3,74,4,123,16,39,2,215,3,24,0,10,18,6,0,85,0,0,255,255,0,201,0,0,5,84, + 7,95,18,38,0,53,0,0,17,7,22,190,4,125,1,103,0,8,0,64,3,95,29,1,93,48,0,0,255,255,0,186,0,0,3,90,6,102,18,38, + 0,85,0,0,17,6,2,137,27,0,0,16,180,17,23,19,9,7,43,64,5,15,23,0,19,2,93,49,255,255,0,135,255,227,4,162,7,108,16,39, + 22,186,4,149,1,118,18,6,0,54,0,0,255,255,0,111,255,227,3,199,6,109,16,38,0,118,66,7,18,6,0,86,0,0,0,0,255,255,0,135, + 255,227,4,162,7,109,16,39,22,189,4,147,1,117,19,6,0,54,0,0,0,11,180,4,32,21,41,41,16,73,99,58,49,0,0,0,255,255,0,111, + 255,227,3,199,6,102,16,38,2,136,37,0,19,6,0,86,0,0,0,11,180,4,32,21,41,41,16,73,99,58,49,0,255,255,0,135,254,117,4,162, + 5,240,18,38,0,54,0,0,16,7,0,122,0,139,0,0,255,255,0,111,254,117,3,199,4,123,18,38,0,86,0,0,16,6,0,122,23,0,0,0, + 255,255,0,135,255,227,4,162,7,109,18,38,0,54,0,0,17,7,22,190,4,139,1,117,0,11,180,43,32,14,34,34,16,73,99,58,49,0,0,0, + 255,255,0,111,255,227,3,199,6,102,18,38,0,86,0,0,17,7,2,189,4,39,0,0,0,11,180,43,32,14,34,34,16,73,99,58,49,0,0,0, + 255,255,255,250,254,117,4,233,5,213,16,38,0,122,80,0,18,6,0,55,0,0,0,0,255,255,0,55,254,117,2,242,5,158,16,38,0,122,225,0, + 18,6,0,87,0,0,0,0,255,255,255,250,0,0,4,233,7,95,18,38,0,55,0,0,17,7,22,190,4,115,1,103,0,16,180,1,13,9,0,7, + 43,49,0,64,3,95,8,1,93,48,0,0,255,255,0,55,0,0,2,254,6,130,18,38,0,87,0,0,17,7,22,184,2,55,0,112,0,7,64,3, + 143,20,1,93,49,0,0,0,0,1,255,250,0,0,4,233,5,213,0,15,0,70,64,24,7,11,149,4,12,9,3,15,149,0,129,9,5,1,64,7, + 3,28,12,0,64,10,14,16,16,212,60,228,204,252,60,228,204,49,0,47,244,236,50,16,212,60,236,50,48,1,64,19,0,17,31,0,16,1,16,2, + 31,15,16,17,64,17,112,17,159,17,9,93,3,33,21,33,17,33,21,33,17,35,17,33,53,33,17,33,6,4,239,253,238,1,9,254,247,203,254,247, + 1,9,253,238,5,213,170,253,192,170,253,191,2,65,170,2,64,0,0,0,0,1,0,55,0,0,2,242,5,158,0,29,0,67,64,31,8,22,169,5, + 23,4,26,169,0,1,27,188,13,135,16,16,13,14,2,6,8,4,0,8,23,27,21,25,29,70,30,16,252,60,60,196,50,252,60,60,196,196,50,57, + 57,49,0,47,236,244,60,196,252,60,220,60,236,50,48,178,175,31,1,1,93,1,17,33,21,33,21,33,21,33,21,20,23,22,59,1,21,35,34,39, + 38,61,1,35,53,51,53,35,53,51,17,1,119,1,123,254,133,1,123,254,133,37,38,115,189,189,213,81,81,135,135,135,135,5,158,254,194,143,233,142, + 233,137,39,39,154,80,79,210,233,142,233,143,1,62,0,0,255,255,0,178,255,227,5,41,7,94,16,39,22,187,4,238,1,117,19,6,0,56,0,0, + 0,16,180,31,9,24,39,7,43,64,5,16,9,31,24,2,93,49,0,0,255,255,0,174,255,227,4,88,6,55,16,39,2,158,0,131,0,0,19,6, + 0,88,0,0,0,8,180,30,8,22,38,7,43,49,0,0,255,255,0,178,255,227,5,41,7,49,16,39,0,113,0,238,1,59,19,6,0,56,0,0, + 0,20,180,5,3,2,13,7,43,64,9,47,2,32,3,31,2,16,3,4,93,49,0,0,255,255,0,174,255,227,4,88,5,245,16,39,0,113,0,131, + 255,255,19,6,0,88,0,0,0,8,180,6,3,2,14,7,43,49,0,0,255,255,0,178,255,227,5,41,7,109,16,39,22,192,4,238,1,117,19,6, + 0,56,0,0,0,16,180,15,0,8,23,7,43,64,5,16,0,31,8,2,93,49,0,0,255,255,0,174,255,227,4,88,6,72,16,39,2,154,0,131, + 0,0,19,6,0,88,0,0,0,8,180,16,0,8,24,7,43,49,0,0,255,255,0,178,255,227,5,41,7,111,18,38,0,56,0,0,16,7,2,156, + 0,240,0,105,255,255,0,174,255,227,4,88,6,202,18,38,0,88,0,0,17,6,2,156,124,196,0,9,64,5,64,21,64,33,2,93,49,0,0,0, + 255,255,0,178,255,227,5,41,7,107,16,39,22,194,4,238,1,117,18,6,0,56,0,0,255,255,0,174,255,227,4,94,6,102,16,39,2,159,0,176, + 0,0,18,6,0,88,0,0,255,255,0,178,254,117,5,41,5,213,18,38,0,56,0,0,16,7,2,157,0,250,0,0,255,255,0,174,254,117,4,232, + 4,123,18,38,0,88,0,0,16,7,2,157,2,39,0,0,255,255,0,68,0,0,7,166,7,116,16,39,22,189,5,245,1,124,19,6,0,58,0,0, + 0,8,180,21,2,6,20,7,43,49,0,0,255,255,0,86,0,0,6,53,6,109,16,39,2,136,1,69,0,7,19,6,0,90,0,0,0,8,180,21, + 2,6,20,7,43,49,0,0,255,255,255,252,0,0,4,231,7,116,16,39,22,189,4,114,1,124,19,6,0,60,0,0,0,8,180,11,2,6,7,7, + 43,49,0,0,255,255,0,61,254,86,4,127,6,109,16,38,2,136,94,7,19,6,0,92,0,0,0,8,180,24,2,6,23,7,43,49,255,255,255,252, + 0,0,4,231,7,78,18,38,0,60,0,0,17,7,22,185,4,115,1,117,0,8,180,0,16,11,4,7,43,49,0,0,255,255,0,92,0,0,5,31, + 7,108,16,39,22,186,4,149,1,118,18,6,0,61,0,0,255,255,0,88,0,0,3,219,6,109,16,38,0,118,66,7,18,6,0,93,0,0,0,0, + 255,255,0,92,0,0,5,31,7,80,16,39,22,193,4,190,1,117,18,6,0,61,0,0,255,255,0,88,0,0,3,219,6,20,16,39,2,184,4,23, + 0,0,19,6,0,93,0,0,0,14,1,64,9,79,10,95,10,175,10,223,10,4,93,49,255,255,0,92,0,0,5,31,7,109,18,38,0,61,0,0, + 16,7,22,190,4,190,1,117,255,255,0,88,0,0,3,219,6,102,18,38,0,93,0,0,17,6,2,137,27,0,0,16,180,1,15,11,0,7,43,64, + 5,15,15,0,11,2,93,49,0,1,0,47,0,0,2,248,6,20,0,16,0,35,64,18,11,135,10,151,1,2,169,5,188,1,10,16,8,4,6,2, + 76,17,16,252,60,204,252,204,49,0,47,244,236,16,244,236,48,33,35,17,35,53,51,53,52,54,59,1,21,35,34,7,6,21,1,152,185,176,176,174, + 189,174,176,99,39,38,3,209,143,78,187,171,153,40,41,103,0,2,0,32,255,227,4,164,6,20,0,15,0,44,0,68,64,37,4,185,16,20,12,185, + 32,28,140,20,184,34,41,37,169,44,36,39,151,34,46,69,0,18,24,71,42,32,6,44,40,8,37,35,39,70,45,16,252,60,204,236,50,50,50,204, + 244,236,236,49,0,47,244,220,60,236,50,16,228,244,196,236,16,198,238,48,1,52,39,38,35,34,7,6,21,20,23,22,51,50,55,54,1,54,55,54, + 51,50,23,22,17,16,7,6,35,34,39,38,39,21,35,17,35,53,51,53,51,21,33,21,33,3,229,83,84,146,146,84,83,83,84,146,146,84,83,253, + 142,58,89,88,123,204,127,128,128,127,204,123,88,89,58,185,154,154,185,1,69,254,187,2,47,203,116,115,115,116,203,203,116,115,115,116,2,82,100,48, + 49,162,162,254,248,254,248,162,162,49,48,100,168,5,4,125,147,147,125,0,0,3,255,151,0,0,5,80,5,213,0,8,0,17,0,41,0,67,64,35, + 25,0,149,10,9,149,18,129,1,149,10,173,31,17,11,8,2,19,25,31,5,0,14,28,22,5,25,28,46,9,0,28,18,4,42,16,252,236,50,252, + 236,212,236,17,23,57,57,57,49,0,47,236,236,244,236,16,238,57,48,178,15,34,1,1,93,1,17,33,50,54,53,52,38,35,1,17,33,50,54,53, + 52,38,35,37,33,50,22,21,20,6,7,30,1,21,20,4,35,33,17,34,6,29,1,35,53,52,54,1,247,1,68,163,157,157,163,254,188,1,43,148, + 145,145,148,254,11,2,4,231,250,128,124,149,165,254,240,251,253,232,132,118,156,192,2,201,253,221,135,139,140,133,2,102,254,62,111,114,113,112,166,192, + 177,137,162,20,32,203,152,200,218,5,48,95,105,49,70,181,163,0,0,0,255,255,0,201,0,0,4,236,5,213,18,6,3,165,0,0,0,2,0,186, + 255,227,4,164,6,20,0,22,0,38,0,56,64,31,27,185,0,4,35,185,16,12,140,4,184,18,22,169,19,151,18,40,69,20,23,18,8,71,16,31, + 22,8,19,70,39,16,252,236,50,50,244,236,196,236,49,0,47,244,236,16,228,244,196,236,16,198,238,48,1,54,55,54,51,50,23,22,17,16,7,6, + 35,34,39,38,39,21,35,17,33,21,37,1,52,39,38,35,34,7,6,21,20,23,22,51,50,55,54,1,115,58,89,88,123,204,127,128,128,127,204,123, + 88,89,58,185,3,78,253,107,2,114,83,84,146,146,84,83,83,84,146,146,84,83,3,182,100,48,49,162,162,254,248,254,248,162,162,49,48,100,168,6, + 20,166,1,252,192,203,116,115,115,116,203,203,116,115,115,116,0,2,0,0,0,0,4,236,5,213,0,10,0,23,0,51,64,12,23,11,25,0,25,16, + 46,5,11,28,21,22,47,220,236,50,252,236,196,16,204,49,64,9,5,149,12,173,11,129,6,149,20,0,47,236,228,244,236,179,21,21,11,20,17,18, + 57,47,48,1,52,39,38,35,33,17,33,50,55,54,1,17,33,50,4,21,20,4,35,33,17,35,1,4,23,79,78,163,254,188,1,68,163,78,79,253, + 124,1,78,251,1,16,254,240,251,253,232,201,1,56,1,183,139,68,67,253,221,68,67,4,168,253,154,218,222,221,218,4,68,1,145,0,0,2,0,0, + 255,227,4,164,6,21,0,18,0,30,0,62,64,13,17,18,32,19,18,6,71,13,25,18,8,15,16,47,220,236,50,50,244,236,196,16,204,49,64,14, + 0,22,185,3,184,14,12,28,185,9,140,17,151,14,0,47,228,244,236,196,16,244,236,196,179,15,15,17,14,17,18,57,47,48,1,62,1,51,50,0, + 17,16,2,35,34,38,39,21,35,17,35,1,51,1,52,38,35,34,6,21,20,22,51,50,54,1,115,58,177,123,204,0,255,255,204,123,177,58,185,186, + 1,34,81,2,114,167,146,146,167,167,146,146,167,3,182,100,97,254,188,254,248,254,248,254,188,97,100,168,4,68,1,209,252,26,203,231,231,203,203,231, + 231,0,0,0,0,1,0,115,255,227,5,39,5,240,0,25,0,48,64,27,25,134,0,136,22,149,3,145,26,13,134,12,136,16,149,9,140,26,27,16, + 19,25,6,48,13,0,26,16,220,60,244,236,236,49,0,16,244,236,244,236,16,244,236,244,236,48,19,62,1,51,32,0,17,16,0,33,34,38,39,53, + 30,1,51,32,0,17,16,0,33,34,6,7,115,104,237,134,1,83,1,134,254,122,254,173,132,237,106,102,231,130,1,0,1,16,254,240,255,0,130,231, + 102,5,98,71,71,254,97,254,152,254,153,254,97,72,72,211,95,94,1,57,1,39,1,40,1,57,94,95,0,1,0,115,255,227,6,90,7,100,0,36, + 0,68,64,34,33,149,32,37,13,161,14,174,10,149,17,1,161,0,174,4,149,23,145,17,140,37,32,7,25,20,27,17,13,0,48,20,16,37,16,252, + 252,50,236,16,236,196,49,0,16,228,244,236,244,236,16,238,246,238,16,220,236,48,180,15,38,31,38,2,1,93,1,21,46,1,35,32,0,17,16,0, + 33,50,54,55,21,14,1,35,32,0,17,16,0,33,50,23,22,23,54,55,54,59,1,21,35,34,6,5,39,102,231,130,255,0,254,240,1,16,1,0, + 130,231,102,106,237,132,254,173,254,122,1,134,1,83,96,156,13,12,16,83,102,227,77,63,134,110,5,98,213,95,94,254,199,254,216,254,217,254,199,94, + 95,211,72,72,1,159,1,103,1,104,1,159,36,3,4,195,98,122,170,150,0,1,0,113,255,227,4,204,6,20,0,34,0,78,64,36,0,134,1,136, + 4,14,134,13,136,10,185,17,4,185,23,184,17,140,35,1,135,30,151,35,7,18,20,25,8,30,13,0,72,20,69,35,16,252,244,50,204,236,16,236, + 49,0,16,244,236,16,228,244,236,16,254,244,238,16,245,238,48,64,11,15,36,16,36,128,36,144,36,160,36,5,1,93,1,21,46,1,35,34,6,21, + 20,22,51,50,54,55,21,14,1,35,34,0,17,16,0,33,50,23,53,52,54,59,1,21,35,34,6,3,231,78,157,80,179,198,198,179,80,157,78,77, + 165,93,253,254,214,1,45,1,6,71,70,161,181,69,48,105,76,4,126,245,43,43,227,205,205,227,43,43,170,36,36,1,62,1,14,1,18,1,58,12, + 15,214,192,156,97,0,0,0,255,255,0,10,0,0,5,186,5,213,16,6,0,146,0,0,0,2,255,151,0,0,6,20,5,213,0,8,0,26,0,46, + 64,21,0,149,9,129,1,149,16,8,2,16,10,0,5,25,13,50,0,28,9,4,27,16,252,236,244,236,17,57,57,57,57,49,0,47,236,244,236,48, + 178,96,19,1,1,93,1,17,51,32,0,17,16,0,33,37,33,32,0,17,16,0,41,1,17,34,6,29,1,35,53,52,54,1,247,244,1,53,1,31, + 254,225,254,203,254,66,1,159,1,178,1,150,254,104,254,80,254,97,132,118,156,192,5,47,251,119,1,24,1,46,1,44,1,23,166,254,151,254,128,254, + 126,254,150,5,48,95,105,49,70,181,163,0,0,2,0,201,0,0,4,236,5,213,0,7,0,20,0,46,64,12,22,8,4,19,28,10,46,0,25,14, + 16,21,16,252,236,244,236,50,196,196,49,64,12,19,149,9,129,10,4,149,18,173,3,149,10,0,47,236,244,236,16,244,236,48,1,16,41,1,17,33, + 34,6,17,33,17,33,34,36,53,52,36,51,33,17,33,1,158,1,64,1,68,254,188,163,157,3,78,253,232,251,254,240,1,16,251,1,78,253,124,1, + 183,254,239,2,35,135,3,147,250,43,218,222,221,218,1,192,0,2,0,113,255,227,4,90,6,20,0,18,0,30,0,63,64,29,28,185,17,14,22,185, + 5,8,140,14,184,3,18,135,1,151,3,25,4,17,8,2,71,0,19,18,11,69,31,16,252,236,196,244,236,50,50,49,0,47,252,236,16,228,244,196, + 236,16,196,238,48,182,96,32,128,32,160,32,3,1,93,1,53,33,17,35,53,14,1,35,34,2,17,16,0,51,50,22,23,17,1,20,22,51,50,54, + 53,52,38,35,34,6,1,13,3,77,184,58,177,124,203,255,0,255,203,124,177,58,253,141,167,146,146,168,168,146,146,167,5,110,166,249,236,168,100,97, + 1,68,1,8,1,8,1,68,97,100,1,185,252,192,203,231,231,203,203,231,231,0,0,0,0,2,0,113,254,86,4,116,4,99,0,25,0,39,0,84, + 64,20,13,12,11,32,41,69,23,11,18,2,26,18,23,81,6,32,18,17,69,40,16,252,236,196,244,178,127,23,1,93,236,212,236,16,236,17,18,57, + 57,0,64,14,13,12,29,9,6,7,9,185,4,29,185,20,182,40,16,244,236,212,252,212,204,17,18,57,57,64,6,0,37,83,12,13,12,7,14,16, + 236,57,49,48,37,22,21,16,33,34,39,53,22,51,50,53,52,37,38,39,38,17,16,0,51,50,0,3,20,2,3,54,38,35,34,6,21,20,22,23, + 22,23,62,1,3,107,157,254,71,221,120,102,246,246,254,248,208,117,142,1,18,239,240,1,19,1,155,39,1,171,148,148,172,188,126,64,51,99,110,66, + 79,141,254,240,70,153,70,117,92,48,37,112,135,1,15,1,15,1,57,254,199,254,237,156,254,252,1,160,203,229,232,195,194,199,11,6,14,42,220,0, + 0,1,0,131,0,0,4,69,5,213,0,11,0,43,64,9,13,5,9,28,0,11,7,2,12,16,220,196,196,212,236,50,196,49,64,12,10,149,11,129, + 2,6,149,7,173,3,149,2,0,47,236,244,236,16,244,236,48,1,17,33,53,33,17,33,53,33,17,33,53,4,69,252,62,2,248,253,57,2,199,253, + 26,5,213,250,43,170,2,29,170,1,186,170,0,2,0,117,255,227,5,217,5,240,0,19,0,26,0,68,64,38,1,20,0,8,161,7,174,4,0,149, + 20,23,149,17,0,149,20,173,4,149,11,145,17,140,27,1,20,26,26,25,15,51,20,25,7,0,16,27,16,252,196,236,244,236,17,18,57,49,0,16, + 228,244,236,244,228,16,238,16,238,16,244,238,17,18,57,48,19,33,16,0,33,34,6,7,53,54,36,51,32,0,17,16,0,33,32,0,55,22,0,51, + 50,0,55,117,4,143,254,237,254,238,139,252,112,111,1,7,146,1,94,1,139,254,136,254,198,254,183,254,151,220,13,0,255,202,202,0,255,13,3,12, + 1,12,1,50,96,95,215,70,72,254,103,254,146,254,159,254,91,1,183,204,195,254,228,1,28,195,0,0,0,1,0,164,255,227,4,123,5,240,0,40, + 0,64,64,36,10,134,9,136,13,149,6,145,41,0,22,149,19,173,41,31,134,32,136,28,149,35,140,41,42,20,9,31,16,25,3,25,25,38,16,41, + 16,252,236,212,236,212,196,196,204,49,0,16,244,236,244,236,16,244,236,57,16,244,236,244,236,48,1,46,1,53,52,36,51,50,22,23,21,46,1,35, + 34,6,21,20,22,59,1,21,35,34,6,21,20,22,51,50,54,55,21,14,1,35,32,36,53,52,54,1,216,131,142,1,12,230,89,201,115,114,190,83, + 152,163,158,149,182,174,165,185,199,190,109,200,84,106,199,94,254,232,254,208,163,3,37,33,171,124,178,209,32,32,180,38,36,123,115,112,119,166,149,132, + 143,150,50,49,195,37,37,242,221,144,196,0,0,1,255,150,254,102,4,35,5,213,0,17,0,65,64,31,17,8,18,13,149,12,176,18,6,149,4,2, + 149,0,129,4,173,18,17,8,0,7,12,5,1,7,3,28,0,4,18,16,252,236,50,212,196,196,17,18,57,57,49,0,16,236,244,236,16,238,16,244, + 236,16,57,57,48,178,15,11,1,1,93,19,33,21,33,17,33,21,33,17,16,6,43,1,53,51,50,54,53,201,3,90,253,112,2,80,253,176,205,227, + 77,63,134,110,5,213,170,254,72,170,253,159,254,242,244,170,150,194,0,0,0,1,255,127,254,86,2,248,6,20,0,27,0,101,64,35,19,10,15,135, + 13,189,29,5,24,1,20,8,169,6,1,135,0,151,22,6,188,28,2,27,7,0,7,9,5,8,21,23,19,76,28,16,252,75,176,10,84,88,185,0, + 19,0,64,56,89,75,176,22,84,88,185,0,19,255,192,56,89,60,196,252,60,196,196,18,57,57,49,0,16,228,50,252,236,16,238,50,18,57,57,16, + 244,236,57,57,48,1,182,64,29,80,29,160,29,3,93,1,21,35,34,6,29,1,33,21,33,17,20,6,43,1,53,51,50,54,53,17,35,53,51,53, + 52,54,51,2,248,176,99,77,1,47,254,209,174,189,174,176,99,77,176,176,174,189,6,20,153,80,104,99,143,251,235,187,171,153,80,104,4,42,143,78, + 187,171,0,0,0,1,0,115,255,227,6,151,7,100,0,38,0,73,64,16,21,2,0,28,4,17,28,26,52,4,51,33,25,11,70,39,16,252,236,252, + 244,236,16,252,196,196,49,64,24,22,149,21,39,0,5,36,1,149,3,36,149,8,27,161,26,174,30,149,14,145,8,140,39,0,16,228,244,236,244,236, + 16,254,212,238,17,57,57,16,220,236,48,37,17,33,53,33,17,6,4,35,32,0,17,16,0,33,50,22,23,52,54,59,1,21,35,34,6,29,1,46, + 1,35,32,0,17,16,0,33,50,54,4,195,254,182,2,18,117,254,230,160,254,162,254,117,1,139,1,94,91,163,68,201,227,77,63,134,110,112,252,139, + 254,238,254,237,1,19,1,18,107,168,213,1,145,166,253,127,83,85,1,153,1,109,1,110,1,153,25,25,188,234,170,150,194,215,95,96,254,206,254,209, + 254,210,254,206,37,0,0,0,0,2,0,8,254,82,5,118,5,213,0,15,0,37,0,149,64,13,39,80,18,1,18,4,25,23,12,25,31,36,38,16, + 212,212,236,212,236,212,93,196,181,16,8,0,3,4,12,17,18,23,57,49,64,10,0,149,27,189,17,37,18,36,129,38,0,16,228,50,50,50,244,236, + 179,31,23,8,27,17,18,57,57,48,64,12,19,17,17,18,18,8,35,37,17,36,36,8,7,5,16,236,60,7,16,236,60,182,19,17,8,18,8,36, + 8,7,8,16,236,182,35,17,8,36,8,18,8,7,8,16,236,180,16,37,19,17,35,15,64,16,22,21,20,3,23,19,36,8,34,33,32,3,31,35, + 18,8,4,7,17,18,23,57,7,17,18,23,57,1,50,55,54,53,52,39,38,39,6,7,6,21,20,23,22,19,1,51,1,22,23,22,21,20,7,6, + 35,34,39,38,53,52,55,54,55,1,51,2,191,54,44,28,31,51,44,44,51,31,28,44,54,1,217,222,253,186,104,67,46,75,100,155,155,100,75,46, + 67,104,253,186,222,254,253,32,20,66,57,73,121,92,92,121,73,57,66,20,32,3,122,3,94,251,207,200,174,119,66,139,65,87,87,65,139,66,119,174, + 200,4,49,0,0,1,0,186,0,0,7,71,6,20,0,42,0,79,64,17,44,13,18,4,8,17,42,21,8,38,78,31,27,8,29,70,43,16,252,236, + 50,244,236,196,196,204,212,236,57,49,0,64,25,8,135,9,39,20,38,0,135,17,21,27,38,3,32,17,24,135,32,9,35,184,30,151,17,28,47,60, + 236,244,60,196,236,17,18,23,57,16,236,18,57,57,16,236,48,37,50,55,54,53,52,39,38,39,53,22,23,22,17,20,0,43,1,34,38,53,17,52, + 38,35,34,6,21,17,35,17,51,17,62,1,51,50,22,21,17,20,22,51,5,76,149,84,87,74,62,121,224,109,111,254,224,221,70,187,157,124,124,149, + 172,185,185,66,179,117,193,198,76,105,156,98,101,155,222,112,95,33,148,29,143,145,254,236,245,254,230,200,206,1,8,159,158,190,164,253,135,6,20,253, + 158,101,100,239,232,254,242,147,103,0,0,0,0,1,0,201,0,0,2,198,5,213,0,11,0,46,64,16,11,2,0,6,149,0,129,7,5,8,6,1, + 28,0,4,12,16,252,75,176,16,84,88,185,0,0,0,64,56,89,236,196,57,57,49,0,47,228,236,17,57,57,48,1,19,51,17,20,22,59,1,21, + 35,34,38,17,201,202,110,134,63,77,227,205,5,213,252,45,194,150,170,244,1,14,0,0,0,1,0,10,0,0,2,82,5,213,0,11,0,69,64,17, + 2,11,149,5,8,0,175,6,3,5,1,28,10,8,0,4,12,16,252,60,196,75,176,16,84,88,187,0,8,0,64,0,0,0,64,56,56,89,236,50, + 196,49,0,47,236,220,60,244,50,48,1,64,13,48,13,64,13,80,13,96,13,143,13,159,13,6,93,19,51,17,51,21,35,17,35,17,35,53,51,201, + 202,191,191,202,191,191,5,213,253,22,170,253,191,2,65,170,0,1,0,201,0,0,5,247,5,240,0,23,0,102,64,14,0,28,1,7,8,15,7,9, + 11,15,28,14,4,24,16,252,236,50,212,196,17,57,16,212,236,0,49,0,64,37,11,17,8,9,8,10,17,9,9,8,17,17,7,8,7,16,17,8, + 8,7,66,11,8,16,3,14,12,23,2,5,149,19,145,14,175,12,9,47,60,236,244,236,57,57,17,18,23,57,48,75,83,88,7,16,4,237,7,16, + 5,237,7,16,5,237,7,16,4,237,89,34,1,35,53,52,38,35,34,7,9,1,33,1,17,35,17,51,17,1,54,51,50,23,22,21,5,247,170,73, + 38,70,37,253,221,3,26,254,246,253,51,202,202,2,108,85,113,136,85,85,4,72,121,54,80,35,253,249,252,227,2,207,253,49,5,213,253,137,2,67, + 79,92,91,110,0,1,0,185,0,0,4,156,6,20,0,18,0,203,64,11,4,13,9,12,14,16,9,8,0,70,19,16,252,236,50,212,196,17,57,196, + 49,0,64,15,66,16,13,10,3,11,17,6,149,3,151,11,188,17,14,47,60,228,252,228,17,18,23,57,48,75,83,88,64,20,16,17,13,14,13,15, + 17,14,14,13,11,17,12,13,12,10,17,13,13,12,7,16,4,237,7,16,5,237,7,16,5,237,7,16,4,237,89,178,16,20,1,1,93,64,53,11, + 11,10,15,40,11,39,12,40,13,43,14,43,15,64,20,104,11,96,20,137,11,133,12,137,13,141,14,143,15,154,11,151,15,170,11,167,13,182,15,197, + 15,214,15,247,11,240,11,247,12,240,12,26,93,180,9,13,9,14,2,113,0,64,37,4,10,10,16,22,10,39,10,41,13,43,16,86,10,102,10,103, + 16,115,10,119,13,130,10,137,13,142,16,147,10,150,13,151,16,163,10,18,93,19,52,54,59,1,21,35,34,6,21,17,1,51,9,1,35,1,17,35, + 185,163,181,191,168,105,76,2,37,235,253,174,2,107,240,253,199,185,4,126,214,192,156,97,153,253,255,1,227,253,244,253,172,2,35,253,221,0,0,0, + 0,1,0,10,0,0,2,42,6,20,0,11,0,50,64,7,5,1,8,8,0,70,12,16,252,60,236,50,49,0,64,8,2,11,169,5,8,0,151,6, + 47,236,212,60,236,50,48,64,13,16,13,64,13,80,13,96,13,112,13,240,13,6,1,93,19,51,17,51,21,35,17,35,17,35,53,51,193,184,177,177, + 184,183,183,6,20,253,56,144,253,68,2,188,144,0,0,0,0,1,0,61,0,0,4,127,6,20,0,15,0,160,64,19,8,2,11,5,1,14,7,13, + 8,12,6,9,4,6,17,12,6,0,16,16,212,196,178,128,6,1,93,212,196,16,196,204,17,18,23,57,180,16,9,64,9,2,93,49,0,64,15,8, + 2,11,5,1,14,6,6,0,4,9,6,151,13,0,47,60,244,196,196,17,18,23,57,48,64,50,10,3,169,2,169,11,169,5,8,4,12,7,9,4, + 15,17,0,14,17,1,13,6,1,0,5,17,2,17,14,17,15,14,1,17,0,1,13,17,12,7,12,11,17,8,17,7,17,13,6,13,7,5,16,236, + 236,236,7,16,5,236,8,236,8,236,5,236,236,7,8,16,236,5,16,236,7,8,16,60,60,236,236,14,252,60,51,1,39,5,39,37,39,51,23,37, + 23,5,1,35,9,1,61,1,235,71,254,212,33,1,41,75,200,52,1,58,33,254,201,1,237,195,254,198,254,126,4,50,188,101,99,99,197,138,104,97, + 104,250,215,3,60,252,196,0,0,1,0,178,255,227,7,39,5,213,0,39,0,74,64,18,0,18,20,32,29,28,41,31,80,18,28,20,80,10,28,8, + 4,40,16,252,236,252,252,252,204,252,60,17,18,57,49,0,64,22,7,20,10,28,17,0,6,33,8,14,24,149,33,3,36,140,40,18,29,8,129,32, + 47,244,60,60,16,244,60,196,236,50,17,18,23,57,48,57,37,14,1,35,34,39,38,53,17,51,17,20,23,22,51,50,54,53,17,51,17,20,23,22, + 51,50,55,54,53,17,51,17,35,53,14,1,35,34,39,38,3,166,69,192,130,175,95,95,203,39,57,117,143,166,203,57,57,119,123,83,83,203,203,63, + 176,121,122,86,85,213,124,118,123,122,226,4,27,251,239,186,53,78,190,164,3,236,251,239,162,78,77,95,96,163,3,236,250,41,174,103,98,62,62,0, + 0,1,255,150,254,102,5,51,5,213,0,17,0,140,64,41,7,17,1,2,1,2,17,6,7,6,66,8,17,0,13,149,12,176,18,7,2,3,0,175, + 5,6,1,7,2,28,4,54,11,14,12,57,7,28,0,4,18,16,252,236,228,57,57,252,236,17,57,57,49,0,47,236,50,57,57,16,252,236,17,57, + 57,48,75,83,88,7,16,4,237,7,16,4,237,89,34,178,31,11,1,1,93,64,48,54,2,56,7,72,2,71,7,105,2,102,7,128,2,7,6,1, + 9,6,21,1,26,6,70,1,73,6,87,1,88,6,101,1,105,6,121,6,133,1,138,6,149,1,154,6,159,19,16,93,0,93,19,33,1,17,51,17, + 33,1,17,16,6,43,1,53,51,50,54,53,201,1,16,2,150,196,254,240,253,106,205,227,71,63,134,110,5,213,251,31,4,225,250,43,4,225,251,135, + 254,242,244,170,150,194,0,0,255,255,0,186,254,86,4,100,4,123,16,6,3,75,0,0,0,3,0,115,255,227,5,217,5,240,0,11,0,18,0,25, + 0,49,64,11,25,16,25,6,51,15,19,25,0,16,26,16,252,236,50,244,236,50,49,0,64,15,22,149,9,19,149,15,173,26,12,149,3,145,9,140, + 26,16,228,244,236,16,244,236,16,236,48,19,16,0,33,32,0,17,16,0,33,32,0,1,34,0,7,33,38,2,1,26,1,51,50,18,19,115,1,121, + 1,58,1,59,1,120,254,136,254,197,254,198,254,135,2,181,202,255,0,12,3,172,14,254,253,86,8,251,220,220,248,8,2,233,1,98,1,165,254,91, + 254,159,254,158,254,91,1,164,3,197,254,228,195,195,1,28,253,122,254,255,254,194,1,61,1,2,0,0,255,255,0,103,255,227,6,29,6,20,16,38, + 0,50,244,0,16,7,2,204,5,162,1,52,255,255,0,118,255,227,4,211,4,235,16,39,2,204,4,88,0,11,16,6,0,82,5,0,0,2,0,115, + 255,227,6,207,5,240,0,20,0,31,0,51,64,28,4,149,16,175,0,21,149,13,145,0,27,149,7,140,0,33,19,28,0,30,28,16,4,24,25,10, + 16,32,16,252,236,212,60,236,220,236,196,49,0,47,244,236,16,244,236,16,244,236,48,33,17,52,38,35,17,6,33,32,0,17,16,0,33,50,23,33, + 50,22,25,1,1,34,0,17,16,0,51,50,55,17,38,6,5,110,122,188,254,197,254,198,254,135,1,121,1,59,112,97,1,39,227,205,252,88,220,254, + 253,1,3,220,175,128,138,3,211,194,150,251,139,211,1,164,1,98,1,98,1,165,27,244,254,242,252,45,5,76,254,184,254,230,254,229,254,184,103,4, + 24,70,0,0,0,2,0,113,254,86,5,89,4,123,0,22,0,33,0,58,64,32,5,135,17,188,34,23,185,14,184,34,29,185,8,140,22,189,34,17, + 1,5,35,21,8,1,31,8,5,26,18,11,69,34,16,252,236,212,236,220,236,196,17,18,57,49,0,16,228,244,236,16,244,236,16,244,236,48,1,17, + 52,39,38,35,17,6,35,34,0,17,16,0,51,50,23,51,50,23,22,21,17,1,34,6,21,20,22,51,50,55,17,38,4,161,38,38,105,137,240,241, + 254,239,1,17,241,100,82,216,181,82,81,253,26,148,172,171,149,129,64,84,254,86,4,116,153,49,48,252,188,157,1,57,1,19,1,20,1,56,27,96, + 96,214,251,140,5,137,231,201,201,231,58,2,240,54,0,0,0,2,255,151,0,0,4,241,5,213,0,8,0,28,0,58,64,24,1,149,16,0,149,9, + 129,18,16,10,8,2,4,0,5,25,13,63,17,0,28,9,4,29,16,252,236,50,252,236,17,23,57,49,0,47,244,236,212,236,48,64,11,15,21,31, + 21,63,21,95,21,175,21,5,1,93,1,17,51,50,54,53,52,38,35,37,33,50,4,21,20,4,43,1,17,35,17,34,6,29,1,35,53,52,54,1, + 247,254,141,154,154,141,254,56,1,200,251,1,1,254,255,251,254,202,132,118,156,192,5,47,253,207,146,135,134,146,166,227,219,221,226,253,168,5,48,95, + 105,49,70,181,163,0,0,0,0,2,0,185,254,86,4,164,6,20,0,24,0,36,0,79,64,36,35,185,0,23,29,185,14,17,184,23,140,1,189,37, + 3,12,9,169,6,151,37,26,18,20,71,6,9,3,7,32,12,0,8,2,70,37,16,252,236,50,50,204,17,57,57,244,236,49,0,16,244,236,57,57, + 16,228,228,244,196,236,16,196,238,48,64,9,96,38,128,38,160,38,224,38,4,1,93,37,17,35,17,52,54,59,1,21,35,34,6,29,1,62,1,51, + 50,0,17,16,2,35,34,38,1,52,38,35,34,6,21,20,22,51,50,54,1,115,186,163,181,254,231,105,76,58,177,123,204,0,255,255,204,123,177,2, + 56,167,146,146,167,167,146,146,167,168,253,174,6,40,214,192,156,97,153,200,100,97,254,188,254,248,254,248,254,188,97,1,235,203,231,231,203,203,231,231, + 0,2,0,201,254,248,5,84,5,213,0,21,0,29,0,86,64,23,5,6,3,19,0,9,29,24,16,5,10,26,25,4,19,63,14,22,10,18,12,4, + 30,16,252,236,50,50,252,196,236,17,23,57,17,57,57,57,49,0,64,16,0,23,6,3,4,23,149,9,22,149,15,129,4,13,129,11,47,236,220,244, + 236,212,236,18,57,57,18,57,48,1,64,9,32,31,64,31,117,4,124,5,2,93,1,30,1,23,19,35,3,46,1,43,1,17,35,17,51,17,51,32, + 22,21,20,6,1,17,51,50,54,16,38,35,3,141,65,123,62,205,217,191,74,139,120,220,202,202,254,1,0,252,131,253,137,254,141,154,153,142,1,180, + 22,144,126,254,104,1,127,150,98,254,145,5,213,254,248,214,216,141,186,2,79,253,209,146,1,12,145,0,0,1,0,114,255,227,4,141,5,240,0,33, + 0,100,64,17,7,24,25,6,29,10,15,29,25,4,45,0,34,10,25,21,34,16,220,236,228,252,236,196,17,18,57,57,57,57,49,0,64,25,66,25, + 24,7,6,4,14,33,0,14,161,15,148,12,149,17,32,149,0,148,2,145,17,140,34,16,228,244,228,236,16,238,246,238,16,206,17,23,57,48,75,83, + 88,64,10,24,2,7,6,7,25,2,6,6,7,7,16,14,237,7,16,14,237,89,19,54,32,4,16,6,15,1,14,1,20,22,51,50,55,21,4,35, + 32,39,38,53,52,54,63,1,54,55,54,52,39,38,32,7,204,228,1,198,1,23,202,226,123,154,135,188,173,225,248,254,253,214,254,231,146,145,215,226, + 122,166,60,59,89,90,254,161,228,5,164,76,228,254,143,192,45,24,31,124,236,136,139,208,95,112,112,217,182,217,43,25,31,50,51,217,64,64,109,0, + 0,1,0,100,255,227,3,188,4,123,0,39,0,207,64,17,10,30,29,9,13,33,20,33,8,6,13,8,0,82,26,69,40,16,252,228,236,212,236,196, + 17,18,57,57,57,57,49,64,25,30,29,10,9,4,19,0,134,39,137,36,20,134,19,137,16,185,23,36,185,3,184,23,140,40,0,16,228,244,236,16, + 254,245,238,16,245,238,18,23,57,48,64,18,27,28,2,26,29,83,9,10,32,31,2,33,30,83,10,10,9,66,75,83,88,7,16,14,237,17,23,57, + 7,14,237,17,23,57,89,34,178,0,1,1,1,93,64,17,47,41,63,41,95,41,127,41,128,41,144,41,160,41,240,41,8,93,64,37,32,0,32,39, + 36,38,40,30,40,29,42,21,47,20,47,19,42,18,40,10,40,9,41,8,41,7,36,1,134,30,134,29,134,28,134,27,18,0,93,64,23,28,30,28, + 29,28,28,46,31,44,30,44,29,44,28,59,31,59,30,59,29,59,28,11,113,19,62,1,51,50,22,21,20,6,15,1,14,1,21,20,22,51,50,54, + 55,21,14,1,35,34,38,53,52,54,63,1,62,1,53,52,38,35,34,6,7,160,76,180,102,206,224,152,171,64,171,101,140,130,97,198,102,108,195,90, + 216,247,165,196,63,148,98,137,137,90,168,78,4,63,30,30,172,158,130,149,36,15,37,80,75,81,89,53,53,190,35,35,182,156,137,153,42,14,33,73, + 64,84,84,40,40,0,0,0,255,255,0,201,0,0,4,139,5,213,16,6,3,55,0,0,0,2,254,242,254,86,2,215,6,20,0,22,0,31,0,54, + 64,12,29,14,10,21,6,20,1,8,23,10,79,32,16,252,50,252,50,204,204,16,212,204,49,0,64,15,20,31,135,0,11,27,135,16,151,32,4,135, + 6,189,32,16,252,236,16,244,236,212,60,236,50,48,1,17,20,22,59,1,21,35,34,38,53,17,35,32,53,52,33,50,23,22,23,51,21,37,38,39, + 38,35,34,7,6,51,1,119,77,99,176,174,189,174,190,254,242,1,47,181,82,53,18,191,254,134,8,17,33,110,124,3,3,119,4,106,251,61,104,80, + 153,171,187,4,174,210,216,96,64,111,155,154,44,24,48,65,51,0,0,0,0,1,0,55,254,86,2,242,5,158,0,29,0,63,64,14,14,20,8,8, + 2,9,4,0,8,26,28,24,70,30,16,252,60,196,252,60,220,50,57,252,204,49,0,64,18,24,5,8,25,3,169,0,27,1,188,8,135,21,16,135, + 14,189,21,47,252,236,16,236,244,60,204,236,50,17,57,57,48,1,17,33,21,33,17,20,22,59,1,21,20,6,43,1,53,51,50,55,54,61,1,34, + 38,53,17,35,53,51,17,1,119,1,123,254,133,75,115,189,164,180,70,48,106,38,38,213,167,135,135,5,158,254,194,143,253,160,137,78,174,214,192,156, + 48,49,153,20,159,210,2,96,143,1,62,0,0,1,0,24,0,0,4,233,5,213,0,15,0,88,64,21,13,10,12,6,2,149,0,129,4,0,7,1, + 64,3,28,5,11,28,13,5,16,16,212,212,236,16,252,228,57,57,49,0,47,244,236,50,196,57,57,48,1,75,176,10,84,88,189,0,16,0,64,0, + 1,0,16,0,16,255,192,56,17,55,56,89,64,19,0,17,31,0,16,1,16,2,31,7,16,17,64,17,112,17,159,17,9,93,1,33,21,33,17,35, + 17,35,34,6,29,1,35,53,52,54,1,174,3,59,253,238,203,94,132,118,156,192,5,213,170,250,213,5,43,90,105,49,70,181,163,0,0,1,0,55, + 0,0,2,242,6,20,0,27,0,73,64,16,25,22,11,8,4,23,9,2,4,0,8,16,19,14,70,28,16,252,60,196,252,60,196,50,50,23,57,49, + 0,64,19,19,0,25,135,22,151,10,14,5,8,15,3,169,17,1,188,8,135,10,47,236,244,60,236,50,17,57,57,16,244,236,57,57,48,178,175,21, + 1,1,93,1,21,33,21,33,17,20,22,59,1,21,35,34,38,53,17,35,53,51,53,52,54,59,1,21,35,34,6,1,119,1,123,254,133,75,115,189, + 189,213,162,135,135,174,189,174,176,99,77,4,195,99,143,253,160,137,78,154,159,210,2,96,143,78,187,171,153,81,0,0,0,1,255,250,254,102,4,233, + 5,213,0,15,0,84,64,20,7,149,10,189,16,14,2,149,0,129,16,8,1,64,3,28,0,64,13,16,16,212,228,252,228,196,49,0,16,244,236,50, + 16,244,236,48,1,75,176,10,84,88,189,0,16,0,64,0,1,0,16,0,16,255,192,56,17,55,56,89,64,19,0,17,31,0,16,1,16,2,31,15, + 16,17,64,17,112,17,159,17,9,93,3,33,21,33,17,20,22,59,1,21,35,34,38,25,1,33,6,4,239,253,238,110,134,63,78,227,205,253,238,5, + 213,170,251,61,194,150,170,244,1,14,4,195,255,255,0,173,255,247,6,95,6,20,16,38,0,56,251,20,16,7,2,204,5,228,1,52,255,255,0,176, + 255,227,5,105,4,235,16,39,2,204,4,238,0,11,16,6,0,88,2,0,0,1,0,78,255,227,5,207,5,202,0,31,0,58,64,16,29,26,25,33, + 16,0,4,51,10,17,20,25,13,10,16,32,16,252,196,252,196,16,244,196,236,252,196,49,0,64,14,13,17,1,29,149,30,16,129,32,23,149,7,140, + 32,16,244,236,16,252,60,236,50,50,50,48,1,33,22,18,21,16,0,33,32,0,17,52,18,55,33,53,33,21,6,2,21,20,0,51,50,0,53,52, + 2,39,53,33,5,207,254,192,161,142,254,127,254,209,254,207,254,129,145,158,254,193,2,88,178,199,1,9,216,216,1,8,198,177,2,88,5,24,141,254, + 216,194,254,203,254,119,1,138,1,62,184,1,42,139,178,178,97,254,180,202,239,254,221,1,34,240,202,1,76,97,178,0,0,1,0,201,255,225,5,118, + 5,213,0,27,0,45,64,13,16,21,12,7,8,3,25,12,24,28,21,4,28,16,252,236,212,236,47,60,17,18,57,49,0,64,9,8,22,129,28,0, + 149,16,140,28,16,244,236,16,236,196,48,37,50,0,53,52,39,38,39,53,23,22,18,21,16,7,6,33,39,38,39,38,25,1,51,17,20,22,51,2, + 198,216,1,8,99,65,110,179,161,142,192,191,254,207,77,232,97,103,202,110,134,141,1,34,240,202,166,109,87,68,1,141,254,216,194,254,203,197,196,2, + 6,116,122,1,14,3,240,252,16,194,150,0,0,1,255,252,0,0,5,240,5,240,0,23,0,100,64,15,19,28,20,12,4,11,7,0,64,5,28,9, + 64,7,24,16,212,228,252,228,18,57,196,57,47,236,49,0,64,11,18,21,20,0,149,14,145,11,9,175,6,47,236,57,244,236,204,57,57,48,64,25, + 12,17,4,5,4,11,17,10,11,5,5,4,11,17,12,11,8,9,8,10,17,9,9,8,66,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237, + 7,16,5,237,89,34,1,34,7,6,7,1,17,35,17,1,51,9,1,54,51,50,23,22,29,1,35,53,52,38,4,215,57,21,37,17,254,132,203,253, + 240,217,1,158,1,78,90,163,136,85,85,170,73,5,71,14,24,25,253,191,253,57,2,199,3,14,253,154,1,249,136,92,91,110,131,121,54,80,0,0, + 0,1,0,61,254,86,5,216,4,123,0,31,1,106,64,23,18,14,21,27,31,24,8,21,31,14,13,12,10,9,6,3,0,8,31,4,31,11,32,16, + 212,75,176,10,84,75,176,8,84,91,88,185,0,11,0,64,56,89,75,176,20,84,88,185,0,11,255,192,56,89,196,196,17,23,57,16,212,236,17,57, + 17,18,57,49,0,64,58,7,8,2,9,17,0,31,10,17,11,10,0,0,31,14,17,29,0,31,13,17,12,13,0,0,31,13,17,14,13,10,11,10, + 12,17,11,11,10,66,13,11,9,32,0,11,5,135,3,189,32,27,185,18,184,11,188,23,32,16,196,228,244,236,16,244,236,17,57,17,57,18,57,48, + 75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,8,237,7,5,237,23,50,89,34,1,64,141,10,0,10,9,6,11,5, + 12,23,1,21,2,16,4,16,5,23,10,20,11,20,12,39,0,36,1,36,2,32,4,32,5,41,8,40,9,37,10,36,11,36,12,39,13,55,0,53, + 1,53,2,48,4,48,5,56,10,54,11,54,12,56,13,65,0,64,1,64,2,64,3,64,4,64,5,64,6,64,7,64,8,66,9,69,10,71,13,84, + 0,81,1,81,2,85,3,80,4,80,5,86,6,85,7,86,8,87,9,87,10,85,11,85,12,102,1,102,2,104,10,123,8,137,0,138,9,133,11,133, + 12,137,13,153,9,149,11,149,12,164,11,164,12,70,93,0,64,37,6,0,5,8,6,9,3,13,22,10,23,13,16,13,35,13,53,13,73,10,79,10, + 78,13,90,9,90,10,106,10,135,13,128,13,147,13,18,93,5,14,1,43,1,53,51,50,54,63,1,1,51,9,1,54,55,54,51,50,22,29,1,35, + 53,52,38,35,34,7,6,7,2,147,78,148,124,147,108,76,84,51,33,254,59,195,1,94,1,26,21,48,88,135,131,185,178,81,57,57,41,20,10,104, + 200,122,154,72,134,84,4,78,252,148,2,192,52,51,96,191,134,114,114,58,84,42,20,25,0,1,0,92,0,0,5,31,5,213,0,17,0,192,64,53, + 6,3,2,7,2,12,15,16,11,16,7,17,11,16,11,16,17,2,7,2,66,5,13,149,4,14,18,16,149,0,129,7,149,9,12,6,3,15,4,14, + 4,8,14,0,16,7,0,1,66,8,0,10,18,16,220,75,176,9,84,75,176,10,84,91,88,185,0,10,255,192,56,89,196,212,228,17,57,57,16,196, + 16,196,17,23,57,49,0,47,236,244,236,16,212,60,236,50,48,75,83,88,7,16,5,237,7,16,5,237,7,16,5,60,60,7,16,5,60,60,89,34, + 1,64,64,5,2,10,11,24,11,41,2,38,11,56,11,72,2,71,11,72,16,9,5,7,11,16,0,19,22,7,26,16,16,19,47,19,53,7,57,16, + 63,19,71,7,74,16,79,19,85,7,89,17,102,7,105,16,111,19,119,7,120,16,127,19,159,19,22,93,0,93,19,33,21,1,33,21,33,1,33,21, + 33,53,1,33,53,33,1,33,115,4,149,254,112,1,25,254,115,254,84,3,199,251,61,1,185,254,213,1,159,1,131,252,103,5,213,154,254,17,144,253, + 238,170,154,2,34,144,1,223,0,1,0,88,0,0,3,219,4,96,0,17,0,197,64,49,12,15,16,11,16,6,3,2,7,2,16,17,2,7,2,7, + 17,11,16,11,66,16,169,0,188,9,5,13,169,4,14,7,169,9,16,7,15,3,6,12,6,1,0,14,4,8,1,10,18,16,220,75,176,11,84,75, + 176,12,84,91,88,185,0,10,255,192,56,89,75,176,19,84,88,185,0,10,0,64,56,89,196,50,196,196,196,17,23,57,49,0,47,236,212,60,236,50, + 16,244,236,48,75,83,88,7,16,5,237,7,16,5,237,7,16,5,60,60,7,16,5,60,60,89,34,1,64,66,5,2,22,2,38,2,71,2,73,11, + 5,11,16,15,19,24,7,27,16,43,16,32,19,54,7,57,16,48,19,64,1,64,2,69,7,64,8,64,9,67,16,87,7,89,16,95,19,96,1,96, + 2,102,7,96,8,96,9,98,16,127,19,128,19,175,19,27,93,0,93,19,33,21,3,51,21,33,1,33,21,33,53,1,35,53,33,1,33,113,3,106, + 251,194,254,194,254,195,2,180,252,125,1,43,212,1,80,1,13,253,101,4,96,168,254,220,144,254,143,147,168,1,92,144,1,57,0,0,0,1,0,160, + 255,193,4,248,5,213,0,34,0,112,64,14,11,14,13,8,10,4,25,14,16,22,10,13,30,35,16,220,196,196,212,57,196,236,18,57,180,63,14,79, + 14,2,93,17,18,57,49,0,64,19,10,9,149,16,15,11,149,13,129,35,31,161,30,174,0,149,26,140,35,16,244,236,244,236,16,244,236,57,212,236, + 57,48,64,10,16,17,10,11,10,11,17,15,16,15,7,16,5,236,7,16,5,236,64,14,9,10,55,15,2,5,16,11,11,21,16,59,11,4,1,93, + 0,93,37,50,55,54,53,52,39,38,43,1,53,1,33,53,33,21,1,50,23,22,23,22,21,20,7,6,33,34,39,38,39,53,22,23,22,2,168,192, + 99,100,92,93,165,174,1,129,252,252,4,0,254,101,106,128,98,86,81,152,152,254,232,119,125,126,134,106,127,126,107,75,75,143,134,73,74,152,1,234, + 170,154,254,22,56,42,109,104,138,220,122,121,19,18,37,195,49,25,25,0,0,1,0,92,255,193,4,180,5,213,0,34,0,94,64,15,24,22,21,27, + 31,19,13,25,22,5,31,25,21,13,35,16,220,196,180,48,21,64,21,2,93,236,212,196,196,17,57,17,57,17,18,57,49,0,64,19,25,27,149,19, + 20,24,149,22,129,35,4,161,5,174,0,149,9,140,35,16,244,236,244,236,16,244,236,57,212,236,57,48,64,10,19,17,25,24,25,24,17,20,19,20, + 7,16,5,236,7,16,5,236,37,50,55,54,55,21,6,7,6,35,32,39,38,53,52,55,54,55,54,51,1,53,33,21,33,1,21,35,34,7,6,21, + 20,23,22,2,172,137,126,127,106,134,126,125,119,254,232,152,152,81,86,98,128,106,254,101,4,0,252,252,1,129,174,165,93,92,100,99,107,25,25,49, + 195,37,18,19,121,122,220,138,104,109,42,56,1,234,154,170,254,22,152,74,73,134,143,75,75,0,0,0,0,1,0,104,254,76,4,63,4,96,0,32, + 0,163,64,11,0,6,2,12,18,27,19,3,6,2,33,16,220,204,196,196,212,236,17,18,57,49,0,64,26,12,27,0,24,6,66,0,169,7,7,3, + 33,4,169,3,19,134,20,147,16,185,24,189,3,188,33,16,228,252,236,244,236,16,236,17,18,57,47,236,236,17,18,57,57,48,64,8,6,17,0,5, + 17,1,7,2,7,5,16,236,4,16,236,64,27,3,5,5,0,20,5,22,0,35,5,37,0,55,0,52,5,70,0,67,5,91,0,84,5,126,0,13, + 1,93,64,27,4,6,4,1,20,6,20,1,37,6,36,1,53,1,55,6,69,1,70,6,84,1,92,6,127,6,13,0,93,64,9,6,21,7,22,26, + 21,26,18,4,93,9,1,53,33,21,33,1,21,35,34,7,6,21,20,23,22,51,50,54,55,21,6,7,6,35,32,36,53,52,55,54,55,54,2,91, + 254,101,3,106,253,101,1,174,174,165,93,92,100,99,190,109,200,84,106,100,99,94,254,232,254,208,81,86,98,128,1,220,1,220,168,147,254,13,166,74, + 75,132,143,75,75,50,49,195,37,19,18,242,221,138,104,109,42,56,0,0,0,1,0,113,254,86,3,232,4,96,0,32,0,0,1,50,55,54,55,21, + 6,7,6,35,32,17,52,37,36,53,52,35,48,33,1,33,53,33,21,1,32,21,16,5,6,21,20,2,127,84,77,79,81,87,80,86,97,254,32,1, + 150,1,28,235,254,222,1,229,253,101,3,106,254,158,1,111,254,48,226,254,238,21,21,44,179,32,13,14,1,25,238,53,37,98,124,2,56,147,168,254, + 100,229,254,236,49,24,97,139,0,1,0,150,0,0,4,74,5,240,0,36,0,0,37,33,21,33,53,1,55,33,53,33,54,55,54,53,52,39,38,35, + 34,7,6,7,53,62,1,51,50,4,21,20,7,6,7,51,21,35,7,1,137,2,193,252,76,1,58,115,254,167,1,226,95,37,39,83,84,134,95,105, + 106,120,122,212,88,232,1,20,34,31,74,104,236,48,170,170,170,1,64,117,144,109,72,76,73,119,75,75,33,33,67,204,49,50,232,194,92,82,73,96, + 144,49,0,0,0,1,0,93,255,193,4,249,5,213,0,25,0,53,64,14,27,3,8,17,10,11,8,7,0,8,25,7,70,26,16,252,212,236,16,236, + 212,212,236,204,49,0,64,13,22,149,1,0,26,6,149,13,11,149,9,129,26,16,244,236,212,236,16,204,212,236,48,1,16,32,17,52,38,35,33,17, + 33,21,33,17,37,36,23,22,16,15,1,6,7,6,32,36,53,1,38,3,10,185,165,253,247,3,161,253,41,1,115,1,0,162,81,59,28,20,45,152, + 253,196,254,208,1,144,254,219,1,37,134,147,3,44,170,254,37,1,1,208,104,254,224,86,41,29,36,121,242,221,0,0,0,1,0,104,254,76,4,63, + 4,96,0,26,0,51,64,11,28,4,8,18,10,12,8,26,8,70,27,16,252,196,236,212,212,236,204,49,0,64,15,2,135,0,26,24,189,27,7,135, + 14,12,135,10,188,27,16,244,236,212,236,16,252,204,50,236,48,23,22,51,32,17,52,38,35,33,17,33,21,33,17,51,50,30,1,16,15,1,6,7, + 6,33,34,39,104,170,206,1,150,185,165,254,159,3,25,253,159,221,105,228,166,59,28,20,45,152,254,232,187,212,167,99,1,37,134,147,3,44,170,254, + 38,99,212,254,224,86,41,29,36,121,74,0,0,1,0,88,255,227,3,165,5,158,0,36,0,0,1,7,22,23,22,21,20,7,6,33,34,39,38,39, + 53,22,23,22,51,50,55,54,55,52,39,38,43,1,19,35,53,51,17,51,17,51,21,2,33,2,170,112,108,110,137,254,237,85,81,81,76,73,84,78, + 80,179,99,57,1,58,86,192,62,2,229,229,202,231,3,230,125,30,119,115,170,186,125,157,18,17,35,172,40,24,22,114,65,133,98,76,114,1,15,164, + 1,20,254,236,164,0,0,0,0,2,0,186,254,86,4,164,4,123,0,14,0,23,0,64,64,11,25,17,8,13,4,23,0,8,2,70,24,16,252,236, + 50,50,212,236,204,49,0,64,12,66,21,135,5,9,140,3,188,0,1,189,24,16,236,196,244,244,204,236,48,75,83,88,182,23,5,15,135,0,0,14, + 7,4,16,237,0,16,204,89,5,17,35,17,51,21,54,55,54,51,50,23,22,21,16,1,0,53,52,39,38,35,34,7,1,115,185,185,52,135,81,210, + 184,77,78,252,207,2,114,57,56,120,220,173,122,254,208,6,10,170,66,82,49,112,113,153,254,87,254,228,1,144,249,133,66,65,239,0,0,1,0,201, + 254,86,1,147,5,213,0,3,0,38,64,10,0,151,2,189,4,1,8,0,70,4,16,252,236,49,0,16,236,236,48,64,13,16,5,64,5,80,5,96, + 5,112,5,240,5,6,1,93,19,51,17,35,201,202,202,5,213,248,129,0,255,255,0,201,254,86,3,39,5,213,16,39,1,130,1,148,0,0,16,6, + 1,130,0,0,0,1,0,20,254,86,3,156,5,213,0,19,0,58,64,29,12,9,169,15,6,19,2,169,16,5,5,10,0,151,10,189,20,7,3,9, + 5,1,8,18,13,12,16,0,20,16,212,60,60,204,50,252,60,60,204,50,49,0,16,236,236,17,57,47,60,236,50,220,60,236,50,48,1,51,17,33, + 21,33,21,33,21,33,17,35,17,33,53,33,53,33,53,33,1,115,202,1,95,254,161,1,95,254,161,202,254,161,1,95,254,161,1,95,5,213,253,151, + 168,240,170,253,44,2,212,170,240,168,0,0,255,255,0,201,0,0,1,148,5,213,16,6,0,4,148,0,255,255,0,201,0,0,10,208,7,109,16,39, + 1,63,5,177,0,0,16,6,0,39,0,0,255,255,0,201,0,0,9,176,6,102,16,39,1,64,5,213,0,0,16,6,0,39,0,0,255,255,0,113, + 255,227,8,145,6,102,16,39,1,64,4,182,0,0,16,6,0,71,0,0,255,255,0,201,254,102,6,36,5,213,16,39,0,45,4,145,0,0,16,6, + 0,47,0,0,255,255,0,201,254,86,5,222,6,20,16,39,0,77,4,101,0,0,16,6,0,47,0,0,255,255,0,193,254,86,2,239,6,20,16,39, + 0,77,1,118,0,0,16,6,0,79,0,0,255,255,0,201,254,102,6,242,5,213,16,39,0,45,5,95,0,0,16,6,0,49,0,0,255,255,0,201, + 254,86,6,183,6,20,16,39,0,77,5,62,0,0,16,6,0,49,0,0,255,255,0,186,254,86,5,222,6,20,16,39,0,77,4,101,0,0,16,6, + 0,81,0,0,255,255,0,16,0,0,5,104,7,109,18,38,0,36,0,0,17,7,22,190,4,190,1,117,0,6,177,14,0,16,60,49,255,255,0,123, + 255,227,4,45,6,102,18,38,0,68,0,0,17,6,2,137,90,0,0,8,180,11,43,39,20,7,43,49,255,255,255,254,0,0,2,96,7,109,18,38, + 0,44,0,0,17,7,22,190,3,47,1,117,0,11,180,7,32,1,0,0,16,73,99,58,49,0,0,0,255,255,255,224,0,0,2,94,6,102,18,38, + 0,243,0,0,17,7,2,137,255,31,0,0,0,11,180,8,32,1,0,0,16,73,99,58,49,0,0,0,255,255,0,115,255,227,5,217,7,109,18,38, + 0,50,0,0,16,7,22,190,5,39,1,117,255,255,0,113,255,227,4,117,6,102,18,38,0,82,0,0,17,6,2,137,118,0,0,6,177,27,12,16, + 60,49,0,0,255,255,0,178,255,227,5,41,7,109,18,38,0,56,0,0,17,7,22,190,4,246,1,117,0,6,177,21,5,16,60,49,255,255,0,174, + 255,227,4,88,6,102,18,38,0,88,0,0,17,6,2,137,118,0,0,11,180,24,32,11,1,1,16,73,99,58,49,0,255,255,0,178,255,227,5,41, + 8,51,16,38,22,236,48,0,18,6,0,56,0,0,0,0,255,255,0,174,255,227,4,88,7,49,16,39,0,113,0,123,1,59,18,6,0,190,0,0, + 255,255,0,178,255,227,5,41,8,90,18,38,0,56,0,0,16,6,22,239,54,0,0,0,255,255,0,174,255,227,4,88,7,34,18,38,0,88,0,0, + 16,7,22,239,255,190,254,200,255,255,0,178,255,227,5,41,8,90,18,38,0,56,0,0,16,6,22,244,48,0,0,0,255,255,0,174,255,227,4,88, + 7,34,18,38,0,88,0,0,16,7,22,244,255,196,254,200,255,255,0,178,255,227,5,41,8,96,18,38,0,56,0,0,16,6,22,240,48,6,0,0, + 255,255,0,174,255,227,4,88,7,34,18,38,0,88,0,0,16,7,22,240,255,190,254,200,255,255,0,113,255,227,4,127,4,123,18,6,2,27,0,0, + 255,255,0,16,0,0,5,104,8,51,18,38,0,36,0,0,16,6,22,236,0,0,0,0,255,255,0,123,255,227,4,45,7,49,18,38,0,166,0,0, + 16,7,0,113,0,82,1,59,255,255,0,16,0,0,5,104,8,51,18,38,0,36,0,0,16,6,22,238,0,0,0,0,255,255,0,123,255,227,4,45, + 6,244,18,38,0,68,0,0,16,7,22,238,255,147,254,193,255,255,0,8,0,0,7,72,7,52,16,39,0,113,2,215,1,62,18,6,0,136,0,0, + 255,255,0,123,255,227,7,111,5,242,16,39,0,113,1,232,255,252,18,6,0,168,0,0,0,1,0,115,255,227,6,4,5,240,0,37,0,84,64,16, + 33,36,34,30,28,17,52,2,0,4,51,24,25,11,16,38,16,252,236,252,60,204,228,252,196,196,49,0,64,24,4,31,1,34,0,5,27,35,149,37, + 27,149,8,18,161,17,174,21,149,14,145,8,140,38,16,228,244,236,244,236,16,254,212,238,17,57,57,220,176,11,75,84,88,177,34,64,56,89,60,204, + 50,48,1,17,51,21,35,21,6,4,35,32,0,17,16,0,33,50,4,23,21,46,1,35,32,0,17,16,0,33,50,54,55,53,35,53,51,53,33,53, + 5,139,121,121,117,254,230,160,254,162,254,117,1,139,1,94,146,1,7,111,112,252,139,254,238,254,237,1,19,1,18,107,168,67,253,253,254,182,3,12, + 254,214,88,255,83,85,1,153,1,109,1,110,1,153,72,70,215,95,96,254,206,254,209,254,210,254,206,37,39,181,88,132,166,0,0,0,0,2,0,113, + 254,86,4,250,4,123,0,11,0,52,0,88,64,14,15,34,50,37,0,8,12,71,6,18,24,44,69,53,16,252,196,236,244,236,50,50,196,196,49,0, + 64,27,32,17,14,35,37,12,41,9,24,134,25,28,185,21,3,185,50,47,184,51,188,9,185,21,189,38,41,47,196,228,236,228,244,196,236,16,254,213, + 238,17,18,57,57,212,60,204,50,48,182,96,54,128,54,160,54,3,1,93,1,52,38,35,34,6,21,20,22,51,50,54,23,20,7,51,21,35,6,7, + 6,33,34,38,39,53,30,1,51,50,55,54,55,33,53,33,54,61,1,14,1,35,34,2,17,16,18,51,50,22,23,53,51,3,162,165,149,148,165,165, + 148,149,165,184,19,179,198,31,58,127,254,250,97,172,81,81,158,82,181,90,21,17,253,132,2,154,22,57,178,124,206,252,252,206,124,178,57,184,2,61, + 200,220,220,200,199,220,220,235,110,88,70,93,64,140,29,30,179,44,42,95,23,28,69,71,94,91,99,98,1,58,1,3,1,4,1,58,98,99,170,0, + 255,255,0,115,255,227,5,139,7,109,18,38,0,42,0,0,17,7,22,190,5,74,1,117,0,16,177,33,14,16,60,64,7,148,33,84,33,36,33,3, + 93,49,0,0,255,255,0,113,254,86,4,90,6,99,16,38,2,137,74,253,18,6,0,74,0,0,0,0,255,255,0,201,0,0,5,106,7,109,16,39, + 22,190,4,162,1,117,18,6,0,46,0,0,255,255,255,233,0,0,4,156,7,109,18,38,0,78,0,0,17,7,22,190,3,26,1,117,0,42,180,1, + 16,12,0,7,43,49,0,75,176,14,81,88,187,0,1,255,192,0,0,255,192,56,56,89,64,13,144,1,144,0,128,1,128,0,64,1,64,0,6,93, + 255,255,0,115,254,117,5,217,5,240,16,39,2,157,1,52,0,0,18,6,0,50,0,0,255,255,0,113,254,117,4,117,4,123,16,39,2,157,0,128, + 0,0,18,6,0,82,0,0,255,255,0,115,254,117,5,217,7,49,16,39,0,113,1,39,1,59,18,6,1,172,0,0,255,255,0,113,254,117,4,117, + 5,245,16,38,0,113,115,255,18,6,1,173,0,0,0,0,255,255,0,160,255,193,4,248,7,109,16,39,22,190,4,190,1,117,18,6,1,121,0,0, + 255,255,0,88,254,76,4,47,6,102,16,38,2,137,27,0,16,6,2,84,0,0,0,0,255,255,255,219,254,86,2,100,6,102,16,39,2,137,255,37, + 0,0,17,6,1,249,0,0,0,11,180,3,32,8,7,7,16,73,99,58,49,0,0,0,255,255,0,201,0,0,10,208,5,213,16,39,0,61,5,177, + 0,0,16,6,0,39,0,0,255,255,0,201,0,0,9,176,5,213,16,39,0,93,5,213,0,0,16,6,0,39,0,0,255,255,0,113,255,227,8,145, + 6,20,16,39,0,93,4,182,0,0,16,6,0,71,0,0,255,255,0,115,255,227,5,139,7,108,16,39,22,186,5,27,1,118,18,6,0,42,0,0, + 255,255,0,113,254,86,4,90,6,99,18,38,0,74,0,0,16,6,0,118,27,253,0,0,0,1,0,201,255,227,8,45,5,213,0,29,0,53,64,14, + 14,28,17,25,3,28,6,56,27,1,28,0,4,30,16,252,236,50,252,236,50,212,236,49,0,64,14,15,26,149,2,173,4,0,129,28,10,149,21,140, + 28,47,228,236,16,228,50,252,236,196,48,19,51,17,33,17,51,17,20,23,22,23,50,55,54,53,17,51,17,20,7,6,33,32,39,38,53,17,33,17, + 35,201,202,2,222,202,62,61,153,148,66,62,202,100,96,254,230,254,237,103,100,253,34,202,5,213,253,156,2,100,251,236,159,80,78,1,79,75,164,2, + 159,253,90,223,128,120,120,118,233,1,13,253,57,0,0,0,0,2,0,201,254,86,5,2,5,240,0,14,0,23,0,64,64,11,25,17,28,13,4,23, + 0,28,2,4,24,16,252,236,50,50,212,236,204,49,0,64,12,66,21,149,5,9,140,3,129,0,1,189,24,16,236,196,244,244,204,236,48,75,83,88, + 182,23,5,15,135,0,0,14,7,4,16,237,0,16,204,89,37,17,35,17,51,21,54,55,54,51,50,23,22,21,16,1,0,17,52,39,38,35,34,3, + 1,147,202,202,56,145,87,226,198,83,84,252,145,2,161,61,60,129,237,186,156,253,186,7,127,185,72,87,53,120,122,164,254,55,254,206,1,174,1,12, + 143,71,70,254,255,0,0,0,255,255,0,201,0,0,5,51,7,107,16,39,22,188,5,30,1,117,18,6,0,49,0,0,255,255,0,186,0,0,4,100, + 6,100,18,38,0,81,0,0,16,7,0,67,1,24,255,254,255,255,0,16,0,0,5,104,7,115,18,38,0,135,0,0,16,7,22,186,6,92,1,125, + 255,255,0,123,255,227,4,220,7,115,18,38,0,167,0,0,16,7,22,186,5,236,1,125,255,255,0,8,0,0,7,72,7,108,16,39,22,186,6,92, + 1,118,18,6,0,136,0,0,255,255,0,123,255,227,7,111,6,99,18,38,0,168,0,0,16,7,0,118,1,101,255,253,255,255,0,102,255,186,5,229, + 7,108,16,39,22,186,4,254,1,118,18,6,0,154,0,0,255,255,0,72,255,162,4,156,6,99,18,38,0,186,0,0,16,6,0,118,28,253,0,0, + 255,255,0,16,0,0,5,104,7,112,18,38,0,36,0,0,16,7,22,195,4,229,1,122,255,255,0,123,255,227,4,45,6,100,16,39,2,192,4,152, + 255,254,18,6,0,68,0,0,255,255,0,16,0,0,5,104,7,54,18,38,0,36,0,0,16,7,22,191,4,188,1,62,255,255,0,123,255,227,4,45, + 6,72,16,39,2,194,4,101,0,0,18,6,0,68,0,0,255,255,0,201,0,0,4,139,7,112,18,38,0,40,0,0,16,7,22,195,4,165,1,122, + 255,255,0,113,255,227,4,127,6,99,16,39,2,192,4,186,255,253,18,6,0,72,0,0,255,255,0,201,0,0,4,139,7,54,18,38,0,40,0,0, + 16,7,22,191,4,166,1,62,255,255,0,113,255,227,4,127,6,72,16,39,2,194,4,169,0,0,18,6,0,72,0,0,255,255,255,167,0,0,2,115, + 7,112,18,38,0,44,0,0,16,7,22,195,3,89,1,122,255,255,255,195,0,0,2,129,6,99,16,39,2,192,3,102,255,253,18,6,0,243,0,0, + 255,255,0,5,0,0,2,119,7,54,18,38,0,44,0,0,16,7,22,191,3,62,1,62,255,255,255,227,0,0,2,85,6,72,16,39,2,194,3,36, + 0,0,18,6,0,243,0,0,255,255,0,115,255,227,5,217,7,112,18,38,0,50,0,0,16,7,22,195,5,65,1,122,255,255,0,113,255,227,4,117, + 6,100,16,39,2,192,4,159,255,254,18,6,0,82,0,0,255,255,0,115,255,227,5,217,7,54,18,38,0,50,0,0,16,7,22,191,5,28,1,62, + 255,255,0,113,255,227,4,117,6,72,16,39,2,194,4,152,0,0,18,6,0,82,0,0,255,255,0,199,0,0,5,84,7,112,18,38,0,53,0,0, + 16,7,22,195,4,121,1,122,255,255,0,130,0,0,3,74,6,99,16,39,2,192,4,37,255,253,18,6,0,85,0,0,255,255,0,201,0,0,5,84, + 7,54,18,38,0,53,0,0,16,7,22,191,4,128,1,62,255,255,0,186,0,0,3,94,6,72,16,39,2,194,4,45,0,0,18,6,0,85,0,0, + 255,255,0,178,255,227,5,41,7,112,18,38,0,56,0,0,16,7,22,195,5,21,1,122,255,255,0,174,255,227,4,88,6,100,16,39,2,192,4,212, + 255,254,18,6,0,88,0,0,255,255,0,178,255,227,5,41,7,54,18,38,0,56,0,0,16,7,22,191,4,236,1,62,255,255,0,174,255,227,4,88, + 6,72,16,39,2,194,4,171,0,0,18,6,0,88,0,0,255,255,0,135,254,20,4,162,5,240,16,39,2,215,4,118,0,0,18,6,0,54,0,0, + 255,255,0,111,254,20,3,199,4,123,16,39,2,215,4,44,0,0,18,6,0,86,0,0,255,255,255,250,254,20,4,233,5,213,16,39,2,215,4,83, + 0,0,18,6,0,55,0,0,255,255,0,55,254,20,2,242,5,158,16,39,2,215,4,0,0,0,18,6,0,87,0,0,0,1,0,156,254,82,4,115, + 5,240,0,46,0,0,1,4,17,20,14,1,12,1,7,53,54,36,62,1,53,52,38,35,34,15,1,53,55,62,3,53,52,46,3,35,34,7,53,54, + 51,50,30,1,21,20,14,2,3,63,1,52,111,185,255,0,254,234,153,200,1,49,185,92,125,112,95,115,163,248,60,102,104,61,35,55,75,72,38,184, + 243,239,206,131,203,124,23,58,110,2,162,67,254,219,112,206,160,136,96,34,160,55,140,153,157,79,101,132,51,72,171,106,26,65,99,139,82,55,86,51, + 34,12,184,190,164,86,182,128,60,102,113,116,0,1,0,71,254,79,3,188,4,123,0,52,0,0,1,30,3,21,20,14,5,7,53,62,4,53,52,38, + 35,34,15,1,53,55,62,4,53,52,46,3,35,34,6,7,53,36,51,50,30,1,21,20,6,2,167,70,112,62,33,66,108,152,157,179,149,74,162,245, + 158,99,40,118,93,59,63,216,223,34,65,87,63,45,31,49,67,65,35,69,168,147,1,10,134,112,184,116,103,1,205,8,68,90,88,37,75,138,108,97, + 70,61,39,15,130,46,96,91,98,91,51,88,112,25,86,139,85,13,32,60,69,102,57,44,70,42,27,10,59,90,154,133,71,146,97,110,153,0,0,0, + 255,255,0,201,0,0,5,59,7,109,16,39,22,190,5,4,1,117,18,6,0,43,0,0,255,255,255,240,0,0,4,100,7,109,16,39,22,190,3,33, + 1,117,19,6,0,75,0,0,0,42,180,20,5,1,19,7,43,49,0,75,176,14,81,88,187,0,20,255,192,0,19,255,192,56,56,89,64,13,144,20, + 144,19,128,20,128,19,64,20,64,19,6,93,0,1,0,201,254,86,5,25,5,240,0,19,0,46,64,18,3,149,14,145,9,129,18,176,8,19,28,18, + 11,6,28,8,65,20,16,252,75,176,16,84,88,185,0,8,255,192,56,89,236,50,212,252,49,0,47,236,228,244,236,48,1,52,38,35,34,6,21,17, + 35,17,51,21,62,1,23,50,18,25,1,35,4,80,154,153,179,215,202,202,81,204,157,227,233,201,3,127,215,213,255,222,252,178,5,213,241,135,134,1, + 254,193,254,204,250,217,0,0,0,3,0,113,255,112,6,68,6,20,0,7,0,40,0,52,0,0,37,22,51,50,53,52,39,34,7,54,51,50,21,16, + 33,34,39,6,7,35,54,55,38,53,6,7,6,35,34,39,38,16,55,54,51,50,23,22,23,17,51,0,16,23,22,32,55,54,16,39,38,32,7,4, + 182,17,37,160,52,52,202,110,136,244,254,170,73,53,34,24,196,29,67,48,58,88,89,124,203,128,127,127,128,203,124,89,88,58,184,252,213,83,84,1, + 36,84,84,84,84,254,220,84,130,5,175,45,1,32,184,206,254,191,15,72,58,69,147,60,36,100,48,49,162,162,2,16,162,162,49,48,100,2,94,252, + 230,254,106,116,115,115,116,1,150,116,115,115,0,2,0,113,255,227,5,37,5,240,0,12,0,59,0,87,64,28,36,0,20,51,4,24,16,61,69,10, + 28,40,66,29,24,28,33,56,59,16,28,55,66,4,28,47,69,60,16,252,236,244,236,204,178,32,59,1,93,244,236,204,244,236,236,17,18,23,57,49, + 0,64,18,36,51,0,149,20,173,60,13,59,28,29,145,60,7,8,44,140,60,16,244,236,16,244,204,212,204,16,244,236,57,57,48,1,34,7,6,16, + 23,22,32,55,54,53,52,38,3,14,1,21,20,23,22,51,50,55,54,53,52,39,38,39,53,50,23,22,21,20,6,7,22,23,22,21,20,7,6,32, + 39,38,53,52,55,54,55,38,39,38,53,52,55,54,33,2,203,184,106,107,107,106,1,112,107,107,212,244,130,170,95,59,204,168,95,96,76,109,130,228, + 150,139,170,152,172,95,96,156,155,253,186,155,156,96,97,171,171,67,85,130,116,1,1,2,197,77,77,254,242,77,77,77,78,134,135,154,2,39,3,124, + 79,69,72,45,65,65,136,158,43,77,8,100,104,97,186,128,178,32,34,99,99,143,217,116,116,116,116,217,143,99,99,34,31,70,89,88,130,83,74,0, + 0,2,0,113,255,227,4,113,5,15,0,13,0,52,0,67,64,22,54,69,10,8,24,66,14,52,50,8,16,40,41,43,8,38,66,4,8,31,69,53, + 16,252,236,244,236,204,50,212,236,204,50,244,236,236,49,0,64,14,52,41,20,34,0,185,46,173,53,7,185,28,140,53,16,244,236,16,244,236,57,57, + 204,50,48,1,34,7,6,16,23,22,32,55,54,53,52,39,38,19,22,21,20,7,6,7,22,23,22,21,20,7,6,32,39,38,53,52,54,55,38,39, + 38,53,52,55,51,6,20,23,22,51,50,55,54,53,52,39,2,113,144,83,82,82,83,1,32,83,83,83,82,254,58,52,72,130,146,82,81,133,132,254, + 18,132,133,164,146,144,59,52,63,161,43,73,72,131,130,73,74,44,2,197,77,77,254,242,77,77,77,78,134,135,77,77,2,74,64,98,153,64,89,32, + 34,99,99,143,217,116,116,116,116,217,143,198,34,35,86,75,142,89,73,65,232,65,65,65,65,116,119,62,0,1,0,92,254,86,5,31,5,213,0,21, + 0,159,64,12,15,20,17,18,66,11,8,21,6,17,13,22,16,220,75,176,9,84,75,176,10,84,91,88,185,0,13,255,192,56,89,196,196,212,236,228, + 17,57,57,49,0,64,12,66,7,149,5,12,15,149,17,129,20,149,12,47,236,244,236,16,220,236,48,75,83,88,64,10,20,17,14,15,14,15,17,19, + 20,19,7,16,5,237,7,16,5,237,89,1,64,64,5,19,10,14,24,14,41,19,38,14,56,14,72,19,71,14,72,15,9,5,20,11,15,0,23,22, + 20,26,15,16,23,47,23,53,20,57,15,63,23,71,20,74,15,79,23,85,20,89,15,102,20,105,15,111,23,119,20,120,15,127,23,159,23,22,93,0, + 93,5,16,7,6,43,1,53,51,50,55,54,61,1,33,53,1,33,53,33,21,1,33,5,31,158,72,114,254,233,105,38,38,251,245,3,176,252,103,4, + 149,252,80,3,199,20,254,223,80,37,156,48,49,153,20,154,4,145,170,154,251,111,0,0,0,1,0,88,254,86,3,219,4,96,0,21,0,172,64,12, + 11,8,21,13,15,20,18,17,18,6,13,22,16,220,75,176,11,84,75,176,12,84,91,88,185,0,13,255,192,56,89,75,176,19,84,88,185,0,13,0, + 64,56,89,196,196,180,64,18,96,18,2,93,196,17,57,57,16,212,180,64,21,96,21,2,93,236,49,0,64,12,66,7,169,5,12,15,169,17,188,20, + 169,12,47,236,244,236,16,220,236,48,75,83,88,64,10,15,17,19,20,19,20,17,14,15,14,7,16,5,237,7,16,5,237,89,1,64,50,5,19,22, + 19,38,19,71,19,73,14,5,11,15,15,23,24,20,27,15,43,15,32,23,54,20,57,15,48,23,69,20,73,15,87,20,89,15,95,23,102,20,104,15, + 127,23,128,23,175,23,19,93,0,93,5,16,7,6,43,1,53,51,50,55,54,61,1,33,53,1,33,53,33,21,1,33,3,219,158,72,114,254,233,105, + 38,38,253,53,2,180,253,101,3,106,253,76,2,180,20,254,223,80,37,156,48,49,153,20,168,3,37,147,168,252,219,0,255,255,0,16,0,0,5,104, + 7,80,16,39,22,193,4,188,1,117,18,6,0,36,0,0,255,255,0,123,255,227,4,45,6,20,16,39,2,184,4,74,0,0,18,6,0,68,0,0, + 255,255,0,201,254,117,4,139,5,213,18,38,0,40,0,0,16,7,0,122,0,162,0,0,255,255,0,113,254,117,4,127,4,123,18,38,0,72,0,0, + 16,6,0,122,123,0,0,0,255,255,0,115,255,227,5,217,8,51,18,38,0,50,0,0,16,6,22,236,98,0,0,0,255,255,0,113,255,227,4,117, + 7,49,18,38,0,184,0,0,16,7,0,113,0,115,1,59,255,255,0,115,255,227,5,217,8,51,18,38,0,50,0,0,16,6,22,243,105,0,0,0, + 255,255,0,113,255,227,4,117,6,233,18,38,0,82,0,0,16,7,22,243,255,181,254,182,255,255,0,115,255,227,5,217,7,80,16,39,22,193,5,39, + 1,117,18,6,0,50,0,0,255,255,0,113,255,227,4,117,6,20,16,39,2,184,4,115,0,0,18,6,0,82,0,0,255,255,0,115,255,227,5,217, + 8,51,18,38,0,50,0,0,16,6,22,238,106,0,0,0,255,255,0,113,255,227,4,117,7,49,18,38,1,241,0,0,16,7,0,113,0,115,1,59, + 255,255,255,252,0,0,4,231,7,49,16,39,0,113,0,114,1,59,18,6,0,60,0,0,255,255,0,61,254,86,4,127,5,245,16,38,0,113,94,255, + 18,6,0,92,0,0,0,0,0,2,0,138,255,112,3,92,6,14,0,7,0,25,0,0,37,22,51,50,53,52,39,34,7,54,51,50,21,16,33,34, + 39,6,7,35,54,55,38,55,17,51,1,206,17,37,160,52,52,202,110,136,244,254,170,73,53,34,24,196,29,67,49,1,184,130,5,175,45,1,32,184, + 206,254,191,15,72,58,69,147,60,90,5,48,0,2,0,186,255,112,6,78,4,123,0,7,0,43,0,0,37,22,51,50,53,52,39,34,7,54,51,50, + 21,16,33,34,39,6,7,35,54,55,38,55,17,52,38,35,34,6,21,17,35,17,51,21,54,55,54,51,50,23,22,21,4,192,17,37,160,52,52,202, + 110,136,244,254,170,73,53,34,24,196,29,67,49,1,124,124,149,172,185,185,66,89,90,117,193,99,99,130,5,175,45,1,32,184,206,254,191,15,72,58, + 69,147,60,90,1,192,159,158,190,164,253,135,4,96,174,101,50,50,119,120,232,0,0,0,0,2,0,55,255,112,3,97,5,158,0,7,0,33,0,0, + 37,22,51,50,53,52,39,34,7,54,51,50,21,16,33,34,39,6,7,35,54,55,38,53,17,35,53,51,17,51,17,33,21,33,1,211,17,37,160,52, + 52,202,110,136,244,254,170,73,54,33,24,196,29,67,49,135,135,185,1,123,254,133,130,5,175,45,1,32,184,206,254,191,15,72,58,69,147,60,90,2, + 243,143,1,62,254,194,143,0,0,1,255,219,254,86,1,121,4,96,0,11,0,56,64,21,11,2,7,0,7,135,5,189,0,188,12,8,12,5,6,79, + 1,8,0,70,12,16,252,236,228,57,18,57,49,0,16,228,244,236,17,18,57,57,48,64,11,16,13,64,13,80,13,96,13,112,13,5,1,93,19,51, + 17,20,6,43,1,53,51,50,54,53,193,184,163,181,70,49,105,76,4,96,251,140,214,192,156,97,153,0,0,3,0,113,255,227,7,140,6,20,0,9, + 0,35,0,47,0,65,64,19,49,69,37,18,20,71,5,27,13,8,43,24,14,71,1,18,33,69,48,16,252,236,244,60,60,252,60,60,244,236,236,49, + 0,64,16,40,8,185,10,46,4,185,22,29,140,17,10,184,13,151,25,47,236,228,50,244,50,236,50,16,236,50,48,0,16,23,22,32,54,16,38,32, + 7,19,50,23,17,51,17,54,51,50,0,16,2,35,34,39,21,35,53,6,35,34,39,38,16,55,54,0,16,39,38,32,7,6,16,23,22,32,55,1, + 47,83,84,1,36,168,168,254,220,84,185,245,114,185,114,244,204,0,255,255,204,244,114,185,114,245,203,128,127,127,128,5,93,83,84,254,220,84,83,83, + 84,1,36,84,2,250,254,106,116,115,231,1,150,231,115,1,13,197,2,94,253,162,197,254,188,253,240,254,188,197,168,168,197,162,162,2,16,162,162,252, + 233,1,150,116,115,115,116,254,106,116,115,115,0,3,0,113,254,86,7,140,4,123,0,11,0,37,0,47,0,68,64,19,49,69,1,18,36,71,43,17, + 29,18,7,14,30,71,39,18,23,69,48,16,252,236,244,60,60,252,60,60,244,236,236,49,0,64,18,10,42,185,19,4,46,185,33,26,184,12,19,140, + 15,189,29,188,48,16,228,228,228,50,244,60,236,50,16,236,50,48,0,16,39,38,32,7,6,16,23,22,32,55,3,34,39,17,35,17,6,35,34,39, + 38,16,55,54,51,50,23,53,51,21,54,51,50,0,16,2,0,16,23,22,32,54,16,38,32,7,6,205,83,84,254,220,84,83,83,84,1,36,84,185, + 244,114,185,114,245,203,128,127,127,128,203,245,114,185,114,244,204,0,255,255,250,162,83,84,1,36,168,168,254,220,84,1,100,1,150,116,115,115,116,254, + 106,116,115,115,254,243,197,253,174,2,82,197,162,162,2,16,162,162,197,170,170,197,254,188,253,240,254,188,3,23,254,106,116,115,231,1,150,231,115,0, + 0,3,255,253,255,186,5,124,6,23,0,18,0,22,0,25,0,0,1,51,19,1,23,9,1,35,3,33,15,1,35,7,39,35,55,39,55,9,1,51, + 1,3,33,3,2,74,229,134,1,97,102,254,112,1,124,210,136,253,214,205,50,70,59,82,2,1,20,47,2,144,254,238,22,1,111,189,1,93,106,5, + 213,254,161,1,161,89,254,39,252,27,1,127,241,142,70,70,1,17,56,4,196,253,25,1,177,254,79,1,31,0,0,0,0,2,0,12,255,186,5,138, + 6,23,0,34,0,44,0,0,23,39,19,38,17,16,55,54,33,50,23,22,23,55,23,7,21,38,39,1,22,23,22,33,50,55,54,55,21,6,7,6, + 35,32,39,19,1,35,38,35,32,7,6,17,20,114,102,220,117,195,195,1,83,134,118,61,58,101,102,99,46,49,252,244,9,11,136,1,0,130,116,115, + 102,106,119,118,132,254,180,194,57,2,216,1,116,130,255,0,136,136,70,88,1,5,187,1,23,1,104,207,208,36,18,27,120,89,118,187,43,33,252,102, + 13,12,157,47,47,95,211,72,36,36,199,1,21,3,92,47,156,157,254,216,173,0,0,0,0,2,0,9,255,162,4,93,4,188,0,34,0,43,0,0, + 23,39,55,38,53,16,55,54,33,50,23,22,23,55,23,7,21,38,39,1,22,23,22,51,50,55,54,55,21,6,7,6,35,34,39,19,1,38,35,34, + 7,6,21,20,105,96,189,85,151,150,1,6,85,81,46,45,89,95,118,25,24,253,211,7,6,99,179,80,78,79,78,77,82,83,93,240,147,55,1,238, + 71,71,179,99,99,94,78,230,141,204,1,18,157,157,17,10,16,108,79,143,85,14,11,253,94,8,8,113,21,22,43,170,36,18,18,144,1,5,2,86, + 17,113,114,205,103,0,0,0,0,1,0,10,0,0,4,106,5,213,0,13,0,59,64,22,12,5,10,149,2,12,6,149,0,129,8,3,5,1,28,7, + 58,12,10,0,4,14,16,252,60,204,236,252,60,204,49,0,47,228,236,212,60,236,50,48,64,13,48,15,80,15,128,7,128,8,127,4,127,3,6,1, + 93,19,51,17,51,21,35,17,33,21,33,17,35,53,51,201,202,191,191,2,215,252,95,191,191,5,213,253,119,144,253,238,170,2,188,144,0,2,255,178, + 255,186,5,49,6,23,0,15,0,18,0,0,1,21,35,1,17,35,17,1,39,1,17,33,53,33,55,23,9,1,33,4,233,52,254,34,203,254,13,103, + 2,90,253,238,4,153,56,102,253,166,1,44,254,212,5,105,62,253,204,253,9,2,7,253,179,88,2,199,2,82,170,66,89,254,11,1,98,0,0,0, + 0,1,0,111,254,16,4,25,4,123,0,61,0,0,1,52,39,38,47,1,38,39,38,53,52,54,51,50,22,23,21,46,1,35,34,7,6,21,20,23, + 22,31,1,22,23,22,21,20,7,6,7,31,1,22,51,21,35,34,39,38,47,1,38,39,38,39,38,39,53,22,23,22,51,50,55,54,3,10,50,51, + 171,64,171,76,76,224,206,102,180,76,78,168,90,137,68,69,49,49,148,63,198,80,83,123,87,132,159,147,42,76,39,84,114,71,89,237,30,36,16,17, + 97,108,102,99,99,97,130,70,70,1,39,75,40,40,37,15,36,74,75,130,158,172,30,30,174,40,40,42,42,84,64,37,36,33,14,44,75,76,137,156, + 91,64,19,159,126,36,154,61,38,91,243,30,16,3,2,18,35,190,53,26,27,45,44,0,0,1,0,88,254,16,4,51,4,96,0,24,0,0,19,33, + 21,1,22,23,1,23,22,59,1,21,35,34,39,38,47,1,38,43,1,61,1,1,33,113,3,106,253,78,92,49,1,8,147,42,76,108,147,84,114,71, + 89,237,61,90,94,2,180,253,101,4,96,168,252,221,16,49,254,248,126,36,154,61,38,91,243,63,156,12,3,37,0,0,0,1,0,80,0,0,4,141, + 5,213,0,24,0,54,64,17,18,19,12,11,4,15,0,5,1,8,25,22,1,28,4,15,25,16,212,212,236,212,236,17,57,57,17,23,57,49,0,64, + 11,0,149,5,15,149,16,11,149,18,129,2,47,244,236,212,236,212,236,48,1,35,17,35,17,51,50,54,53,52,38,43,1,34,6,7,53,54,59,1, + 50,4,21,20,4,2,145,39,202,241,141,154,154,141,254,69,175,79,152,171,254,244,1,8,254,247,2,90,253,166,3,0,145,135,136,143,42,44,182,70, + 220,225,215,231,0,1,0,80,0,0,3,143,4,123,0,24,0,55,64,16,10,8,6,15,4,12,1,0,4,18,19,22,8,0,12,25,16,212,212,236, + 212,236,18,57,18,23,57,49,0,64,13,22,185,1,23,12,134,13,136,8,185,15,184,23,47,244,236,244,238,16,212,236,48,1,51,50,54,53,52,39, + 38,35,34,7,6,7,53,54,51,50,23,22,21,20,6,35,17,35,1,47,100,141,154,76,85,134,73,86,86,78,152,171,251,125,132,212,194,202,1,166, + 145,135,141,65,72,21,21,43,182,70,110,116,219,213,229,254,252,0,0,0,0,3,0,10,0,0,4,236,5,213,0,12,0,21,0,40,0,92,64,26, + 21,15,12,6,23,29,35,5,0,18,28,26,9,25,32,46,2,4,13,0,28,38,37,22,4,41,16,252,60,204,236,50,50,204,252,236,212,236,17,23, + 57,57,57,49,0,64,21,40,1,149,37,4,4,0,5,29,0,149,14,13,149,22,129,5,149,14,173,35,47,236,236,244,236,16,238,57,17,18,57,47, + 60,236,50,48,178,15,42,1,1,93,1,21,33,21,33,21,33,50,54,53,52,38,35,1,17,33,50,54,53,52,38,35,37,33,50,22,21,20,6,7, + 30,1,21,20,4,35,33,17,35,53,51,1,147,1,91,254,165,1,68,163,157,157,163,254,188,1,43,148,145,145,148,254,11,2,4,231,250,128,124,149, + 165,254,240,251,253,232,191,191,2,201,201,144,202,135,139,140,133,2,102,254,62,111,114,113,112,166,192,177,137,162,20,32,203,152,200,218,1,112,144,0, + 0,2,0,12,255,227,5,206,5,213,0,20,0,29,0,95,64,15,21,3,28,7,9,5,56,22,1,28,19,17,0,65,30,16,252,75,176,16,84,88, + 185,0,0,255,192,56,89,60,204,236,50,252,60,204,236,50,49,0,64,22,29,23,16,10,0,7,20,3,149,17,9,22,22,0,26,149,13,140,4,0, + 129,30,16,228,50,244,236,17,57,47,60,60,236,50,50,17,57,57,57,57,48,1,182,31,31,143,31,159,31,3,93,19,51,17,33,17,51,17,51,21, + 35,21,16,0,33,32,0,17,53,35,53,51,5,33,21,20,22,51,50,54,53,178,203,2,225,203,165,165,254,223,254,230,254,229,254,223,166,166,3,172, + 253,31,174,195,194,174,5,213,253,150,2,106,253,150,164,150,254,220,254,214,1,42,1,36,150,164,164,125,240,211,211,240,255,255,0,16,0,0,5,104, + 5,213,16,6,3,48,0,0,0,3,0,201,255,66,4,139,6,147,0,19,0,23,0,27,0,0,1,51,7,51,21,35,3,33,21,33,3,33,21,33, + 7,35,55,35,17,33,1,19,35,17,1,19,33,17,3,184,170,65,88,146,151,1,10,254,188,185,2,46,253,152,65,170,65,176,2,174,254,60,185,217, + 1,19,151,254,86,6,147,190,170,254,70,170,253,227,170,190,190,5,213,250,213,2,29,253,227,2,199,1,186,254,70,0,0,4,0,113,255,66,4,127, + 5,30,0,5,0,38,0,45,0,49,0,0,1,38,39,38,39,3,5,21,33,3,22,51,50,54,55,21,14,1,35,34,39,7,35,19,38,39,38,17, + 16,0,51,50,23,55,51,7,22,23,22,5,19,38,35,34,6,7,27,1,35,22,3,199,2,83,14,16,111,1,154,254,43,148,74,97,106,199,98,99, + 208,107,123,99,80,170,109,33,28,157,1,41,252,56,49,71,170,92,57,47,131,253,188,135,20,22,154,185,14,90,111,207,11,2,148,151,90,16,13,254, + 242,54,90,254,151,28,52,52,174,42,44,33,194,1,9,23,29,156,1,10,1,19,1,67,9,172,224,34,50,146,197,1,74,2,174,158,254,99,1,14, + 172,0,0,0,0,1,255,150,254,102,2,82,5,213,0,19,0,89,64,31,11,2,7,12,1,12,149,18,15,20,7,149,5,176,16,129,20,0,17,13, + 5,8,6,57,1,17,28,12,16,4,20,16,252,75,176,16,84,88,185,0,16,0,64,56,89,60,236,50,228,57,57,196,16,196,49,0,16,228,252,236, + 16,212,60,236,50,17,18,57,57,48,1,64,13,48,21,64,21,80,21,96,21,143,21,159,21,6,93,1,35,17,16,6,43,1,53,51,50,54,53,17, + 35,53,51,17,51,17,51,2,82,191,205,227,77,63,134,110,191,191,202,191,2,119,253,241,254,242,244,170,150,194,2,15,166,2,184,253,72,0,0,0, + 0,2,255,219,254,86,2,28,6,20,0,19,0,23,0,83,64,36,23,190,20,177,24,15,6,11,0,11,135,9,189,24,2,19,169,5,16,0,188,24, + 12,24,9,10,79,21,5,1,8,20,16,0,70,24,16,252,60,60,236,50,50,228,57,18,57,49,0,16,228,220,60,228,50,16,244,236,17,18,57,57, + 16,244,236,48,64,11,16,25,64,25,80,25,96,25,112,25,5,1,93,19,51,17,51,21,35,17,20,6,43,1,53,51,50,54,53,17,35,53,51,17, + 51,21,35,193,184,163,163,163,181,70,49,105,76,181,181,184,184,4,96,254,8,164,254,40,214,192,156,97,153,1,216,164,3,172,233,0,0,2,0,115, + 254,102,6,176,5,241,0,24,0,36,0,67,64,36,3,12,13,6,149,9,176,37,34,149,0,22,28,149,13,16,140,22,145,1,175,37,9,6,8,2, + 31,13,0,28,2,25,25,19,16,37,16,252,236,212,236,50,50,16,204,57,57,49,0,16,236,228,244,196,236,16,196,238,16,228,236,17,57,57,48,1, + 53,51,17,20,22,59,1,21,35,34,38,17,53,14,1,35,32,0,17,16,0,33,50,22,1,16,18,51,50,18,17,16,2,35,34,2,4,179,196,110, + 134,69,77,227,205,77,236,165,254,242,254,172,1,84,1,14,165,236,252,223,234,204,205,235,235,205,204,234,4,237,232,250,147,194,150,170,244,1,14,127, + 132,128,1,171,1,92,1,92,1,171,128,253,120,254,227,254,187,1,69,1,29,1,29,1,69,254,187,0,0,2,0,113,254,86,5,64,4,123,0,24, + 0,36,0,72,64,34,24,135,0,189,37,34,185,17,14,28,185,5,8,140,14,184,18,188,37,1,23,24,19,31,4,17,8,19,71,25,18,11,69,37, + 16,252,236,244,236,50,50,16,204,57,57,49,0,16,236,228,244,196,236,16,196,238,16,244,236,48,182,96,38,128,38,160,38,3,1,93,1,35,34,38, + 61,1,14,1,35,34,2,17,16,0,51,50,22,23,53,51,17,20,22,59,1,1,20,22,51,50,54,53,52,38,35,34,6,5,64,70,181,163,58,177, + 124,203,255,0,255,203,124,177,58,184,76,105,49,251,239,167,146,146,168,168,146,146,167,254,86,192,214,188,100,97,1,68,1,8,1,8,1,68,97,100, + 170,251,140,153,97,3,61,203,231,231,203,203,231,231,0,0,0,2,0,10,0,0,5,84,5,213,0,23,0,32,0,187,64,24,5,6,3,21,9,0, + 32,26,18,5,10,29,25,4,21,63,24,10,28,14,17,12,4,33,16,252,60,204,236,50,252,196,236,17,23,57,17,57,57,57,49,0,64,33,9,8, + 7,3,10,6,17,3,4,3,5,17,4,4,3,66,6,4,0,25,3,4,16,25,149,13,9,24,149,17,129,11,4,47,60,244,236,212,50,236,50,18, + 57,18,57,18,57,48,75,83,88,7,16,5,237,7,16,5,237,17,23,57,89,34,178,64,34,1,1,93,64,66,122,23,1,5,0,5,1,5,2,6, + 3,7,4,21,0,21,1,20,2,22,3,23,4,37,0,37,1,37,2,38,3,39,6,38,7,38,8,38,9,32,34,54,1,54,2,70,1,70,2,104, + 5,117,4,117,5,119,23,136,6,136,7,152,6,152,7,31,93,0,93,1,30,1,23,19,35,3,46,1,43,1,17,35,17,35,53,51,17,33,32,22, + 21,20,6,1,17,51,50,54,53,52,38,35,3,141,65,123,62,205,217,191,74,139,120,220,202,191,191,1,200,1,0,252,131,253,137,254,146,149,149,146, + 2,188,22,144,126,254,104,1,127,150,98,253,137,2,119,166,2,184,214,216,141,186,2,79,253,238,135,131,131,133,0,0,0,1,0,14,0,0,3,74, + 4,123,0,24,0,61,64,10,10,24,3,8,6,18,8,4,70,25,16,252,60,196,196,252,60,60,49,0,64,16,18,17,11,21,135,14,184,3,8,24, + 169,5,2,9,188,3,47,228,212,60,236,50,16,244,236,196,212,204,48,180,80,26,159,26,2,1,93,1,21,35,17,35,17,35,53,51,17,51,21,62, + 1,51,50,22,31,1,46,1,35,34,6,21,2,30,171,185,172,172,185,58,186,133,19,46,28,1,31,73,44,156,167,2,104,164,254,60,1,196,164,1, + 248,174,102,99,5,5,189,18,17,206,161,0,0,2,255,246,0,0,4,236,5,213,0,17,0,20,0,0,3,51,23,33,55,51,7,51,21,33,1,17, + 35,17,1,33,53,51,5,33,23,4,217,151,2,12,150,217,151,156,254,245,254,246,203,254,246,254,244,157,2,119,254,209,152,5,213,224,224,224,164,254, + 118,253,57,2,199,1,138,164,164,226,0,0,0,2,0,11,254,86,4,181,4,96,0,24,0,27,0,0,5,14,1,43,1,53,51,50,54,63,1,3, + 33,53,51,3,51,19,33,19,51,3,51,21,33,43,1,19,2,147,78,148,124,147,108,76,84,51,33,205,254,214,240,190,195,184,1,76,184,195,185,239, + 254,215,193,218,109,104,200,122,154,72,134,84,1,242,143,1,205,254,51,1,205,254,51,143,254,240,0,0,0,2,0,174,255,227,4,96,4,123,0,10, + 0,37,0,178,64,16,23,0,3,10,39,31,3,8,20,24,10,13,8,12,70,38,16,252,236,50,50,212,236,204,196,17,18,57,57,49,64,21,0,169, + 23,12,14,6,185,17,184,38,32,134,31,186,28,185,35,140,12,188,38,0,16,228,244,236,252,236,16,244,236,196,16,212,228,182,25,31,11,23,9,14, + 0,18,17,57,17,57,18,57,48,64,49,63,30,63,31,63,32,63,33,79,30,79,31,79,32,79,33,95,30,95,31,95,32,95,33,111,30,111,31,111, + 32,111,33,127,30,127,31,127,32,127,33,143,30,143,31,143,32,143,33,24,93,64,37,63,29,63,30,63,31,63,32,63,33,63,34,79,29,79,30,79, + 31,79,32,79,33,79,34,95,29,95,30,95,31,95,32,95,33,95,34,21,1,93,1,50,54,53,52,38,35,34,6,29,1,7,17,51,21,62,1,51, + 50,22,21,20,6,35,33,21,20,22,51,50,54,55,21,14,1,35,34,38,2,29,223,172,129,111,153,185,184,184,63,188,136,172,203,253,251,254,254,167, + 151,96,182,84,101,190,90,243,240,2,43,102,123,98,115,217,180,41,76,2,127,170,102,97,193,162,189,192,18,127,139,46,46,170,39,39,252,0,0,0, + 0,2,0,113,255,227,4,90,4,123,0,16,0,28,0,56,64,25,26,185,0,14,20,185,5,8,140,14,184,1,188,3,23,4,0,8,2,71,17,18, + 11,69,29,16,252,236,244,236,50,50,49,0,47,236,228,244,196,236,16,196,238,48,182,96,30,128,30,160,30,3,1,93,1,53,51,17,35,53,14,1, + 35,34,2,17,16,0,51,50,22,1,20,22,51,50,54,53,52,38,35,34,6,3,162,184,184,58,177,124,203,255,0,255,203,124,177,253,199,167,146,146, + 168,168,146,146,167,3,182,170,251,160,168,100,97,1,68,1,8,1,8,1,68,97,254,21,203,231,231,203,203,231,231,0,0,2,0,186,255,227,4,163, + 4,123,0,11,0,28,0,56,64,25,3,185,12,15,9,185,24,21,140,15,184,27,188,25,0,18,18,71,24,12,6,8,26,70,29,16,252,236,50,50, + 244,236,49,0,47,236,228,244,196,236,16,198,238,48,182,96,30,128,30,160,30,3,1,93,1,52,38,35,34,6,21,20,22,51,50,54,1,62,1,51, + 50,0,17,16,2,35,34,38,39,21,35,17,51,3,229,167,146,146,168,168,146,146,167,253,141,58,177,124,203,0,255,255,203,124,177,58,184,184,2,47, + 203,231,231,203,203,231,231,2,82,100,97,254,188,254,248,254,248,254,188,97,100,170,4,96,0,2,0,186,255,227,4,164,6,20,0,11,0,36,0,67, + 64,31,3,185,12,15,9,185,24,21,140,15,184,25,33,169,30,151,25,0,18,18,71,30,33,31,24,12,6,8,26,70,37,16,252,236,50,50,196,57, + 57,244,236,49,0,47,252,236,16,228,244,196,236,16,198,238,48,182,96,38,128,38,160,38,3,1,93,1,52,38,35,34,6,21,20,22,51,50,54,1, + 62,1,51,50,0,17,16,2,35,34,38,39,21,35,17,52,54,59,1,21,35,34,6,21,3,229,167,146,146,167,167,146,146,167,253,142,58,177,123,204, + 0,255,255,204,123,177,58,185,179,165,254,233,90,91,2,47,203,231,231,203,203,231,231,2,82,100,97,254,188,254,248,254,248,254,188,97,100,168,4,126, + 195,211,156,125,125,0,0,0,0,1,0,127,255,227,3,245,4,123,0,25,0,48,64,27,25,134,0,136,22,185,3,184,26,13,134,12,136,16,185,9, + 140,26,27,69,19,18,6,72,13,0,26,16,220,60,244,236,236,49,0,16,244,236,244,236,16,244,236,244,236,48,19,62,1,51,50,0,17,16,0,33, + 34,38,39,53,30,1,51,50,54,53,52,38,35,34,6,7,127,77,165,93,253,1,42,254,211,254,250,85,162,76,78,157,80,179,198,198,179,80,157,78, + 4,51,36,36,254,194,254,242,254,238,254,198,35,35,172,43,43,227,205,205,227,43,43,0,0,2,0,113,255,115,3,231,4,123,0,39,0,47,0,79, + 64,15,40,11,7,44,44,18,19,7,18,19,0,72,34,69,48,16,252,228,50,236,16,236,17,18,57,57,49,0,64,19,0,134,1,136,4,15,185,46, + 42,185,23,4,185,37,184,27,23,140,48,16,228,204,244,236,16,252,220,236,16,245,238,48,64,11,15,49,16,49,128,49,144,49,160,49,5,1,93,1, + 21,46,1,35,34,6,21,20,23,22,23,54,55,54,51,50,23,22,21,20,7,6,35,34,39,6,21,35,52,55,38,39,38,17,16,0,33,50,22,1, + 22,51,50,53,52,35,34,3,231,78,157,80,179,198,99,7,6,39,62,73,106,163,74,63,95,83,155,80,73,6,153,12,57,47,149,1,45,1,6,85, + 162,254,138,58,77,146,132,101,4,53,172,43,43,227,205,205,114,8,6,81,44,51,72,61,89,125,47,41,17,57,68,104,81,35,51,161,1,12,1,18, + 1,58,35,252,58,19,57,75,0,2,0,113,254,86,5,64,6,20,0,24,0,36,0,75,64,36,4,20,18,5,24,169,0,189,37,34,185,17,14,28, + 185,5,8,140,14,184,18,151,37,24,79,31,4,18,8,19,71,25,18,11,69,37,16,252,236,244,236,50,50,228,49,0,16,236,228,244,196,236,16,196, + 238,16,252,236,17,18,57,57,48,182,96,30,128,30,160,30,3,1,93,1,35,34,38,61,1,14,1,35,34,2,17,16,0,51,50,22,23,17,51,17, + 20,22,59,1,1,20,22,51,50,54,53,52,38,35,34,6,5,64,70,181,163,58,177,124,203,255,0,255,203,124,177,58,184,76,105,49,251,239,167,146, + 146,168,168,146,146,167,254,86,192,214,188,100,97,1,68,1,8,1,8,1,68,97,100,2,94,249,216,153,97,3,61,203,231,231,203,203,231,231,0,0, + 0,2,0,113,255,227,5,185,6,20,0,24,0,36,0,61,64,28,34,185,0,22,28,185,13,16,140,22,184,37,6,169,5,151,37,31,12,0,8,11, + 71,25,18,19,69,37,16,252,236,244,236,50,50,49,0,16,252,228,16,228,244,196,236,16,196,238,48,182,96,30,128,30,160,30,3,1,93,1,53,52, + 54,59,1,21,35,34,6,21,17,35,53,14,1,35,34,2,17,16,0,51,50,22,1,20,22,51,50,54,53,52,38,35,34,6,3,162,163,181,191,170, + 105,76,184,58,177,124,203,255,0,255,203,124,177,253,199,167,146,146,168,168,146,146,167,3,182,200,214,192,156,97,153,251,130,168,100,97,1,68,1,8, + 1,8,1,68,97,254,21,203,231,231,203,203,231,231,0,0,0,2,0,113,255,227,4,127,4,123,0,25,0,34,0,114,64,13,27,24,26,24,18,8, + 75,26,8,16,25,69,35,16,252,196,236,244,236,17,18,57,49,64,23,0,26,25,15,134,16,136,20,26,169,25,20,185,12,25,187,31,185,4,184,12, + 140,35,0,16,228,244,236,228,16,236,16,236,16,244,236,17,18,57,48,64,41,63,36,112,36,160,36,208,36,240,36,5,63,0,63,25,63,24,63,26, + 63,27,5,44,17,47,16,47,15,44,14,111,0,111,25,111,24,111,26,111,27,9,93,113,1,93,19,52,55,54,51,50,23,22,17,16,7,6,33,34, + 38,39,53,22,23,22,51,50,55,54,55,33,55,5,38,39,38,35,34,7,6,113,131,132,226,252,148,149,157,156,254,244,107,208,99,98,100,99,106,183, + 102,103,12,252,178,184,2,144,14,93,92,154,136,82,83,2,94,250,146,145,161,162,254,237,254,246,156,156,44,42,174,52,26,26,99,100,190,144,1,158, + 87,87,90,90,0,2,0,113,255,227,4,127,4,123,0,20,0,27,0,65,64,36,0,21,1,9,134,8,136,5,1,169,21,24,185,18,21,187,5,185, + 12,184,18,140,28,2,21,27,27,8,15,75,21,18,8,1,69,28,16,252,196,236,244,236,17,18,57,49,0,16,228,244,236,228,16,238,16,238,16,244, + 238,17,18,57,48,19,53,33,46,1,35,34,6,7,53,62,1,51,32,0,17,16,0,35,34,0,55,30,1,51,50,54,55,113,3,78,12,205,183,106, + 199,98,99,208,107,1,12,1,57,254,215,252,226,254,249,184,2,165,136,154,185,14,2,0,90,190,199,52,52,174,42,44,254,200,254,246,254,237,254,189, + 1,35,196,151,180,174,158,0,0,2,0,124,255,227,6,132,4,123,0,10,0,52,0,119,64,16,54,46,40,8,39,52,2,18,13,75,5,18,31,21, + 69,53,16,252,196,236,252,236,220,60,252,220,196,182,38,22,11,4,4,2,13,17,18,23,57,49,64,15,47,169,46,39,34,26,185,34,184,53,9,185, + 17,140,53,0,16,244,236,16,244,236,16,212,220,236,180,31,134,30,136,26,16,244,236,64,11,5,21,11,13,2,4,38,22,8,34,17,17,18,23,57, + 48,64,10,52,11,4,5,17,38,22,21,39,21,7,14,16,60,60,252,60,60,4,60,37,54,39,54,39,1,22,23,22,51,50,1,22,21,16,7,6, + 35,34,39,38,39,1,38,39,38,7,6,7,6,7,53,62,1,51,32,23,22,23,55,51,21,20,23,22,59,1,21,35,34,39,38,53,3,78,102,2, + 1,10,253,151,30,32,82,136,168,1,96,31,149,148,252,228,130,92,28,2,254,19,27,76,209,108,97,100,98,99,208,107,1,12,156,36,27,203,184,38, + 38,105,43,64,175,87,82,214,138,207,62,56,254,156,69,35,90,2,144,96,118,254,237,162,161,145,103,156,1,187,39,35,100,1,1,25,26,52,174,42, + 44,156,35,41,117,148,153,49,48,156,96,90,200,0,0,0,255,255,0,133,255,227,3,200,4,124,18,6,3,73,0,0,255,255,0,133,255,227,3,200, + 4,124,18,6,3,203,0,0,0,1,0,133,255,227,6,42,4,124,0,62,0,105,64,16,64,54,48,8,60,47,30,18,46,19,18,3,25,39,11,63, + 16,220,196,196,212,236,212,236,220,60,252,220,196,49,64,22,38,134,39,136,34,185,42,184,63,24,169,25,63,11,134,10,136,15,185,6,140,63,0,16, + 244,236,252,236,16,212,236,16,244,236,252,236,182,61,46,0,42,0,24,25,17,18,57,17,18,57,57,180,55,169,54,48,42,16,212,220,236,48,179,60, + 61,46,47,7,4,16,60,1,30,1,21,20,4,35,34,39,38,39,53,22,23,22,51,50,55,54,53,52,39,38,43,1,53,51,50,55,54,53,52,39, + 38,35,34,7,6,7,53,62,1,51,50,23,22,23,55,51,21,20,23,22,59,1,21,35,34,39,38,53,5,6,2,194,124,138,254,254,238,80,85,84, + 90,71,85,85,93,151,85,84,78,72,137,148,155,116,67,68,70,69,119,71,81,80,97,98,170,76,196,113,95,15,236,184,38,38,105,43,64,175,87,82, + 254,224,64,2,92,24,146,108,173,182,14,14,28,171,37,19,18,56,56,90,88,56,51,152,44,45,70,64,46,46,13,13,29,167,24,24,78,66,106,134, + 148,153,49,48,156,96,90,200,166,70,0,0,0,2,0,113,255,227,4,197,4,124,0,26,0,47,0,59,64,13,23,18,31,49,18,12,18,38,4,18, + 44,69,48,16,252,236,212,236,196,196,212,236,49,64,14,0,185,27,184,48,17,169,18,48,8,185,41,140,48,0,16,244,236,16,212,236,16,244,236,178, + 35,18,17,17,18,57,48,1,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38,43,1,53,51,50,55,54,53,52,39,38,39,50,23,22,21,20, + 7,6,7,30,1,21,20,4,35,32,0,17,16,55,54,2,241,251,96,99,99,104,210,151,85,84,78,72,137,148,155,116,67,68,70,69,104,196,113,114, + 60,60,112,124,138,254,254,238,254,198,254,214,151,151,3,220,110,114,205,208,111,116,56,56,90,88,56,51,152,44,45,70,64,46,46,160,78,79,141,93, + 64,65,24,24,146,108,173,182,1,62,1,14,1,18,157,158,0,1,255,219,254,86,2,28,4,96,0,19,0,75,64,31,15,6,11,0,11,135,9,189, + 20,2,19,169,5,16,0,188,20,12,20,9,10,79,2,5,1,8,19,16,0,70,20,16,252,60,60,236,50,50,228,57,18,57,49,0,16,228,220,60, + 228,50,16,244,236,17,18,57,57,48,64,11,16,21,64,21,80,21,96,21,112,21,5,1,93,19,51,17,51,21,35,17,20,6,43,1,53,51,50,54, + 53,17,35,53,51,193,184,163,163,163,181,70,49,105,76,181,181,4,96,254,8,164,254,40,214,192,156,97,153,1,216,164,0,2,0,113,254,86,5,184, + 6,20,0,11,0,48,0,85,64,41,25,12,29,9,18,134,19,22,185,15,3,185,38,35,184,29,45,169,42,151,9,185,15,189,26,29,42,45,43,38, + 25,0,8,12,71,6,18,18,32,69,49,16,252,196,236,244,236,50,50,196,57,57,49,0,47,196,228,236,244,236,16,244,196,236,16,254,213,238,17,18, + 57,57,48,182,96,50,128,50,160,50,3,1,93,1,52,38,35,34,6,21,20,22,51,50,54,23,16,2,33,34,38,39,53,30,1,51,50,54,61,1, + 14,1,35,34,2,17,16,18,51,50,22,23,53,52,54,59,1,21,35,34,6,21,3,162,165,149,148,165,165,148,149,165,184,254,254,250,97,172,81,81, + 158,82,181,180,57,178,124,206,252,252,206,124,178,57,163,181,190,169,105,76,2,61,200,220,220,200,199,220,220,235,254,226,254,233,29,30,179,44,42,189, + 191,91,99,98,1,58,1,3,1,4,1,58,98,99,200,214,192,156,97,153,0,2,0,113,254,86,4,90,4,96,0,10,0,35,0,67,64,31,24,11, + 28,8,17,134,18,21,185,14,2,185,35,188,8,185,14,189,25,28,24,0,8,11,71,5,18,17,31,69,36,16,252,196,236,244,236,50,49,0,47,196, + 228,236,244,236,16,254,213,238,17,18,57,57,48,182,96,37,128,37,160,37,3,1,93,1,17,33,34,6,21,20,22,51,50,54,23,16,2,33,34,38, + 39,53,30,1,51,50,54,61,1,14,1,35,34,2,17,52,18,51,33,3,162,254,170,135,150,165,148,149,165,184,254,254,250,97,172,81,81,158,82,181, + 180,57,178,124,206,252,252,206,2,31,2,61,1,136,205,187,199,220,220,235,254,226,254,233,29,30,179,44,42,189,191,91,99,98,1,58,1,3,249,1, + 42,0,0,0,0,1,0,113,255,227,4,79,4,123,0,29,0,56,64,31,0,5,27,1,169,3,27,185,8,18,134,17,136,21,185,14,184,8,140,30, + 2,0,8,17,52,4,24,18,11,69,30,16,252,236,220,228,252,196,49,0,16,228,244,236,244,236,16,254,212,238,17,57,57,48,37,17,35,53,33,17, + 14,1,35,34,0,17,16,0,33,50,22,23,21,46,1,35,34,6,21,20,22,51,50,54,3,169,155,1,65,101,215,123,253,254,214,1,45,1,6,104, + 197,93,95,192,99,179,198,198,179,79,124,158,1,17,140,253,240,36,36,1,62,1,14,1,18,1,58,55,55,170,62,62,227,205,205,227,15,0,0,0, + 0,2,0,96,254,82,4,100,4,96,0,19,0,35,0,121,64,10,37,2,24,18,7,32,18,13,18,36,16,212,212,236,212,236,212,196,181,0,28,20, + 3,24,32,17,18,23,57,49,64,10,20,185,10,189,1,19,2,18,188,36,0,16,228,50,50,50,244,236,179,13,7,28,10,17,18,57,57,48,180,19, + 17,18,18,28,7,5,16,236,179,17,18,2,28,8,16,60,180,1,17,2,2,28,7,5,16,236,181,0,1,3,2,18,28,8,16,60,4,16,60,179, + 3,0,19,0,7,14,16,60,179,17,0,1,0,7,14,16,60,9,1,51,1,22,23,22,21,20,6,35,34,38,53,52,55,54,55,1,51,1,50,55, + 54,53,52,39,38,39,6,7,6,21,20,23,22,2,98,1,66,192,254,95,106,38,59,150,150,150,150,59,38,106,254,95,192,1,66,67,31,28,28,40, + 58,58,40,28,28,31,1,232,2,120,252,220,177,83,128,99,129,130,130,129,99,128,83,177,3,36,250,142,27,24,45,69,73,100,99,99,100,73,69,45, + 24,27,0,0,0,2,0,96,255,227,4,100,4,96,0,19,0,35,0,121,64,10,37,2,24,18,7,32,18,13,18,36,16,212,212,236,212,236,212,196, + 181,0,28,20,3,24,32,17,18,23,57,49,64,10,20,185,10,140,1,19,2,18,188,36,0,16,228,50,50,50,244,236,179,13,7,28,10,17,18,57, + 57,48,180,19,17,18,18,28,7,5,16,236,179,17,18,2,28,8,16,60,180,1,17,2,2,28,7,5,16,236,181,0,1,3,2,18,28,8,16,60, + 4,16,60,179,3,0,19,0,7,14,16,60,179,17,0,1,0,7,14,16,60,9,1,51,1,22,23,22,21,20,6,35,34,38,53,52,55,54,55,1, + 51,1,50,55,54,53,52,39,38,39,6,7,6,21,20,23,22,2,98,1,41,217,254,114,71,44,69,150,150,150,150,69,44,71,254,114,217,1,41,67, + 31,28,39,31,56,56,31,39,28,31,2,209,1,143,253,234,98,76,120,62,130,129,129,130,62,120,76,98,2,22,252,31,27,24,45,33,64,50,70,70, + 50,64,33,45,24,27,0,0,0,1,0,174,254,86,4,88,4,96,0,19,0,57,64,27,3,9,0,3,14,1,6,135,14,17,140,10,1,188,12,189, + 20,13,9,8,11,78,2,8,0,70,20,16,252,236,244,236,50,49,0,16,228,228,50,244,196,236,17,18,23,57,48,180,96,21,207,21,2,1,93,19, + 17,51,17,20,22,51,50,54,53,17,51,17,35,17,14,1,35,34,38,174,184,124,124,149,173,184,184,67,177,117,193,200,1,186,2,166,253,97,159,159, + 190,164,2,123,249,246,2,86,102,99,240,0,0,1,0,186,0,0,4,100,6,20,0,27,0,67,64,33,3,9,0,3,22,1,6,135,22,25,184,28, + 12,21,18,169,15,151,10,1,2,8,0,78,15,18,16,21,9,8,11,70,28,16,252,236,50,196,57,57,244,236,49,0,47,60,252,236,57,57,16,244, + 196,236,17,18,23,57,48,178,96,29,1,1,93,1,17,35,17,52,38,35,34,6,21,17,35,17,52,54,59,1,21,35,34,6,29,1,62,1,51,50, + 22,4,100,184,124,124,149,172,185,163,181,254,231,105,77,66,179,117,193,198,2,164,253,92,2,158,159,158,190,164,253,135,4,126,214,192,156,97,153,204, + 101,100,239,0,0,1,0,186,254,86,4,100,6,20,0,33,0,74,64,37,3,9,0,3,29,1,13,135,29,31,184,34,19,28,25,169,22,151,18,7, + 135,4,18,6,10,8,0,78,22,25,23,28,16,8,18,70,34,16,252,236,50,196,57,57,244,236,196,49,0,47,220,236,16,252,236,57,57,16,244,196, + 236,17,18,23,57,48,178,96,35,1,1,93,1,17,20,6,43,1,53,51,50,54,53,17,16,35,34,6,21,17,35,17,52,54,59,1,21,35,34,6, + 29,1,54,51,50,22,4,100,163,181,254,233,105,76,248,149,172,185,163,181,254,231,105,77,131,231,193,198,2,164,253,72,214,192,156,97,153,2,178,1, + 61,190,164,253,135,4,126,214,192,156,97,153,204,201,239,0,0,2,0,14,0,0,2,30,6,20,0,11,0,15,0,62,64,24,14,190,12,177,6,2, + 11,169,5,8,0,188,6,5,2,13,1,8,8,11,12,0,70,16,16,252,60,60,60,236,50,50,50,49,0,47,228,220,60,236,50,16,252,236,48,64, + 11,16,17,64,17,80,17,96,17,112,17,5,1,93,19,51,17,51,21,35,17,35,17,35,53,51,17,51,21,35,194,184,164,164,184,180,180,184,184,4, + 96,254,8,164,254,60,1,196,164,3,172,233,255,255,0,166,0,0,2,110,4,96,16,6,3,77,0,0,0,1,0,116,0,0,2,132,4,96,0,11, + 0,39,64,10,3,6,8,4,8,0,9,8,10,12,16,220,236,50,252,236,50,49,0,64,9,4,11,169,1,188,5,9,169,8,47,236,50,252,236,50, + 48,19,53,33,21,35,17,51,21,33,53,51,17,116,2,16,168,168,253,240,176,3,188,164,164,252,232,164,164,3,24,0,0,1,0,75,0,0,2,223, + 6,20,0,35,0,60,64,13,37,11,86,10,18,1,8,0,19,28,86,29,36,16,220,252,220,60,252,60,220,252,212,49,64,18,20,17,2,35,4,15, + 33,6,195,15,29,11,33,195,24,0,151,19,0,47,228,47,236,50,212,60,236,17,18,23,57,48,1,51,17,22,23,22,51,50,55,54,55,51,6,7, + 6,35,34,39,17,35,17,38,39,38,35,34,7,6,7,35,54,55,54,51,50,23,1,61,184,2,1,17,13,38,18,18,2,125,2,51,51,91,20,19, + 184,6,5,17,13,38,18,18,2,125,2,51,51,91,25,22,6,20,252,237,1,1,9,37,36,82,135,73,74,4,253,133,3,2,4,3,9,37,36,82, + 135,73,74,6,0,2,0,77,0,0,3,84,6,20,0,17,0,24,0,53,64,11,26,4,5,1,8,18,0,7,22,13,25,16,220,220,212,60,50,252, + 60,220,196,49,64,14,17,15,185,20,10,5,169,18,2,2,7,0,151,7,0,47,228,17,57,47,60,236,50,212,236,196,48,1,51,17,51,21,35,17, + 35,17,52,39,35,32,55,54,51,50,23,7,38,35,34,7,20,51,1,162,184,250,250,184,1,61,254,232,1,1,245,53,42,16,23,55,77,1,92,6, + 20,252,254,160,253,142,2,84,15,15,189,246,25,250,132,75,57,0,0,0,0,1,0,193,254,86,2,95,6,20,0,11,0,40,64,7,13,6,0,8, + 11,70,12,16,252,252,212,196,49,0,64,12,10,1,5,0,11,151,12,5,135,6,189,12,16,244,236,16,228,17,18,57,57,48,1,17,20,22,59,1, + 21,35,34,38,53,17,1,121,61,120,49,70,191,153,6,20,249,206,124,116,156,204,202,6,40,0,0,0,0,1,0,193,254,76,5,54,6,20,0,36, + 0,178,64,14,27,35,21,18,38,6,14,35,29,34,8,32,70,37,16,252,252,60,212,196,212,196,236,16,204,178,0,35,27,17,18,57,49,64,24,27, + 66,0,169,26,26,34,31,29,169,34,14,134,13,147,17,185,9,189,34,188,32,151,31,0,47,228,228,252,236,244,236,16,236,17,18,57,47,236,236,179, + 21,6,0,9,17,18,57,57,48,64,8,27,17,0,28,17,36,26,35,7,5,16,236,4,16,236,64,27,12,28,10,0,27,28,25,0,42,28,42,0, + 56,0,59,28,73,0,76,28,84,0,91,28,113,0,13,1,93,64,27,4,27,4,36,20,27,20,36,37,27,36,36,53,36,55,27,69,36,70,27,84, + 36,92,27,127,27,13,0,93,64,9,7,11,6,12,26,12,26,15,4,93,1,50,23,22,23,22,21,20,4,33,34,39,38,39,53,30,1,51,50,55, + 54,53,52,39,38,43,1,53,1,33,17,35,17,51,17,33,21,3,67,105,129,99,85,81,254,208,254,232,94,99,100,106,84,200,109,190,99,100,92,91, + 167,174,1,174,253,106,184,184,3,101,1,220,56,43,108,104,138,221,242,18,19,37,195,49,50,75,75,143,132,75,74,166,1,243,252,51,6,20,254,76, + 168,0,0,0,0,1,0,186,255,230,7,29,4,98,0,38,0,94,64,17,0,18,20,30,27,8,29,80,18,8,20,80,10,8,8,70,39,16,252,236, + 252,252,252,252,60,17,18,57,49,64,22,7,20,10,26,17,0,6,31,8,13,23,135,31,4,35,140,39,27,18,8,188,39,0,16,244,60,60,16,244, + 60,196,236,50,17,18,23,57,48,64,19,48,40,80,40,112,40,144,40,160,40,160,40,191,40,223,40,255,40,9,1,93,37,6,7,6,35,34,38,53, + 17,51,17,20,22,51,50,55,54,53,17,51,17,20,22,51,50,54,53,17,51,17,35,53,6,7,6,35,34,39,38,3,174,67,98,96,130,175,190,185, + 114,117,143,83,83,185,114,119,141,166,185,185,61,90,88,121,122,86,85,216,121,61,60,246,226,2,164,253,98,162,156,96,94,164,2,122,253,98,162,156, + 192,162,2,122,251,158,176,101,51,50,62,62,0,1,0,186,254,86,7,29,4,98,0,38,0,97,64,17,0,18,20,30,27,8,29,80,18,8,20,80, + 10,8,8,70,39,16,252,236,252,252,252,252,60,17,18,57,49,64,24,7,20,10,26,17,0,6,31,8,13,23,135,31,4,35,140,39,27,18,8,188, + 29,189,39,0,16,236,244,60,60,16,244,60,196,236,50,17,18,23,57,48,64,19,48,40,80,40,112,40,144,40,160,40,160,40,191,40,223,40,255,40, + 9,1,93,37,6,7,6,35,34,38,53,17,51,17,20,22,51,50,55,54,53,17,51,17,20,22,51,50,54,53,17,51,17,35,17,6,7,6,35,34, + 39,38,3,174,67,98,96,130,175,190,185,114,117,143,83,83,185,114,119,141,166,185,185,61,90,88,121,122,86,85,216,121,61,60,246,226,2,164,253,98, + 162,156,96,94,164,2,122,253,98,162,156,192,162,2,122,249,244,2,90,101,51,50,62,62,0,1,0,186,254,86,7,29,4,123,0,48,0,99,64,18, + 14,0,17,15,19,8,7,80,28,8,26,80,41,37,8,39,70,49,16,252,236,50,252,252,252,236,17,18,57,204,49,0,64,24,14,135,13,27,7,29, + 20,37,26,0,6,42,27,33,23,135,42,45,3,184,40,188,38,27,47,60,228,244,60,196,236,50,17,18,23,57,16,212,236,48,1,64,19,48,50,80, + 50,112,50,144,50,160,50,160,50,191,50,223,50,255,50,9,93,1,62,1,51,50,23,22,21,17,20,7,6,43,1,53,51,50,55,54,53,3,52,38, + 35,34,6,21,17,35,17,52,39,38,35,34,7,6,21,17,35,17,51,21,62,1,51,50,23,22,4,41,69,192,130,175,95,95,82,81,181,254,233,105, + 38,38,1,114,117,143,166,185,57,57,119,141,83,83,185,185,63,176,121,122,85,86,3,137,124,118,123,122,226,253,72,214,96,96,156,48,49,153,2,178, + 161,156,190,164,253,135,2,158,162,78,77,95,96,163,253,135,4,96,174,103,98,62,62,0,0,1,255,219,254,86,4,107,4,123,0,27,0,81,64,15, + 2,8,0,78,16,28,13,14,79,10,21,8,20,70,28,16,252,236,50,228,57,18,57,244,236,49,0,64,14,3,9,0,3,22,1,6,135,22,25,184, + 20,188,1,47,228,244,196,236,17,18,23,57,64,9,19,10,15,20,15,135,13,189,28,16,244,236,17,18,57,57,48,180,96,29,207,29,2,1,93,1, + 17,35,17,52,38,35,34,6,21,17,20,6,43,1,53,51,50,54,53,17,51,21,62,1,51,50,22,4,107,184,124,124,149,173,163,181,70,49,105,76, + 185,66,179,117,193,198,2,164,253,92,2,158,159,158,190,164,253,115,214,192,156,97,153,4,116,174,101,100,239,0,0,0,0,1,0,186,254,86,5,74, + 4,123,0,29,0,59,64,12,23,26,3,8,21,78,9,13,8,12,70,30,16,252,236,50,244,236,220,196,49,64,13,6,135,14,17,184,12,188,11,26, + 169,27,189,11,0,47,252,236,16,228,244,196,236,181,9,3,20,3,14,10,17,18,23,57,48,1,38,53,17,52,38,35,34,6,21,17,35,17,51,21, + 62,1,51,50,22,21,17,20,23,22,59,1,21,35,34,3,254,82,124,124,149,172,185,185,66,179,117,193,198,38,38,105,49,70,181,254,182,96,214,2, + 178,159,158,190,164,253,135,4,96,174,101,100,239,232,253,72,153,49,48,156,0,1,0,179,0,0,4,100,4,96,0,9,0,121,64,30,7,17,1,2, + 1,2,17,6,7,6,66,7,2,3,0,188,8,5,6,1,7,2,8,4,78,7,8,0,70,10,16,252,236,252,236,17,57,57,49,0,47,60,236,50, + 57,57,48,75,83,88,7,16,4,237,7,16,4,237,89,34,178,31,11,1,1,93,64,48,54,2,56,7,72,2,71,7,105,2,102,7,128,2,7,6, + 1,9,6,21,1,26,6,70,1,73,6,87,1,88,6,101,1,105,6,121,6,133,1,138,6,149,1,154,6,159,11,16,93,0,93,19,33,1,17,51, + 17,33,1,17,35,179,1,16,1,221,196,254,240,254,35,196,4,96,252,121,3,135,251,160,3,108,252,148,0,3,0,113,255,227,4,117,4,123,0,6, + 0,13,0,25,0,44,64,24,4,169,11,7,185,20,0,185,14,184,20,140,26,10,4,18,17,81,11,3,18,23,69,26,16,252,236,50,244,236,50,49, + 0,16,228,244,236,16,238,220,236,48,1,34,6,7,33,46,1,3,50,54,53,33,20,22,19,50,0,17,16,0,35,34,0,17,16,0,2,113,147,149, + 18,2,116,18,149,146,149,168,253,134,168,150,240,1,18,254,238,240,241,254,239,1,17,3,223,193,127,127,193,252,160,232,148,148,232,3,252,254,200,254, + 236,254,237,254,199,1,57,1,19,1,20,1,56,0,0,0,0,2,0,113,0,0,6,36,4,96,0,18,0,29,0,73,64,13,31,4,0,9,6,2, + 8,19,24,18,14,69,30,16,252,236,212,236,50,212,196,196,196,179,10,18,2,19,17,18,57,57,49,64,10,2,19,169,18,188,10,29,7,169,10,0, + 47,252,60,16,244,252,60,64,8,3,169,6,6,14,14,19,10,17,18,57,16,208,47,236,48,1,21,33,17,33,21,33,17,33,21,33,32,39,38,17, + 16,55,54,33,23,35,34,7,6,21,20,23,22,59,1,6,22,253,212,2,21,253,235,2,58,252,225,254,187,167,168,168,167,1,69,42,37,240,120,120, + 120,120,240,37,4,96,154,254,221,155,254,148,156,142,143,1,20,1,18,142,143,130,108,107,216,217,108,109,0,2,0,148,255,220,5,62,4,124,0,19, + 0,36,0,50,64,13,38,69,7,18,25,19,8,0,12,18,20,69,37,16,252,236,212,252,212,236,236,49,0,64,13,0,10,135,23,3,15,135,30,35, + 140,23,184,37,16,228,244,60,236,50,16,236,196,48,1,21,20,22,50,55,54,53,16,2,32,2,17,20,23,22,50,54,61,1,5,16,0,32,0,17, + 20,6,7,6,34,38,39,14,1,34,38,3,72,96,107,38,73,208,254,110,202,73,38,107,96,254,4,1,66,2,34,1,70,58,46,97,215,162,12,18, + 157,214,215,2,148,196,163,181,48,91,157,1,15,1,49,254,208,254,240,157,91,48,181,163,196,200,1,84,1,92,254,164,254,128,108,178,54,112,163,117, + 121,159,237,0,255,255,0,112,254,86,4,209,6,20,18,6,3,105,0,0,0,1,0,0,255,229,2,144,4,96,0,14,0,47,64,9,7,2,4,10, + 14,8,13,4,15,16,47,220,236,50,17,57,57,49,0,64,13,10,0,11,5,4,0,7,135,2,140,12,188,13,47,236,244,236,196,212,204,17,18,57, + 48,37,6,33,34,47,1,22,51,50,54,53,17,51,17,35,1,215,114,254,249,37,56,1,60,88,156,167,185,185,174,201,10,189,35,203,190,2,78,251, + 160,0,0,0,0,1,0,0,255,229,2,144,6,10,0,14,0,47,64,9,7,2,4,10,14,8,13,4,15,16,47,220,236,50,17,57,57,49,0,64, + 13,10,0,11,5,4,0,7,135,2,140,12,151,13,47,236,244,236,196,212,204,17,18,57,48,37,6,33,34,47,1,22,51,50,54,53,17,51,17,35, + 1,215,114,254,249,37,56,1,60,88,159,164,185,185,174,201,10,189,35,206,187,3,248,249,246,0,0,0,0,1,0,0,254,86,3,118,4,96,0,22, + 0,68,64,12,17,79,13,7,2,4,10,22,8,13,4,15,16,47,220,236,50,17,57,57,16,228,49,0,64,22,22,13,11,0,17,169,18,189,23,10, + 0,11,5,4,0,7,135,2,140,12,188,23,16,236,244,236,196,212,204,17,18,57,16,252,236,17,18,57,57,48,37,6,33,34,47,1,22,51,50,54, + 53,17,51,17,20,22,59,1,21,35,34,38,53,1,215,114,254,249,37,56,1,60,88,156,167,185,76,105,49,70,181,163,174,201,10,189,35,203,190,2, + 78,251,140,153,97,156,192,214,0,1,0,186,254,88,3,74,4,123,0,17,0,51,64,22,6,11,7,0,17,11,3,135,14,184,9,188,7,189,18,10, + 6,8,0,8,70,18,16,252,196,236,50,49,0,16,236,228,244,236,196,212,204,17,18,57,48,180,80,19,159,19,2,1,93,1,46,1,35,34,6,21, + 17,35,17,51,21,62,1,51,50,22,23,3,74,31,73,44,156,167,185,185,58,186,133,19,46,28,3,180,18,17,203,190,252,10,6,8,174,102,99,5, + 5,0,0,0,0,1,0,186,254,86,3,74,4,123,0,25,0,58,64,26,6,19,7,11,135,12,189,26,0,25,19,3,135,24,184,17,188,26,11,18, + 6,8,0,16,70,26,16,252,196,236,50,196,49,0,16,228,244,236,196,212,204,16,244,236,17,18,57,48,180,80,27,159,27,2,1,93,1,46,1,35, + 34,6,21,17,20,22,59,1,21,35,34,38,53,17,51,21,62,1,51,50,22,23,3,74,31,73,44,157,167,76,105,233,254,181,163,185,58,186,133,19, + 46,28,3,180,18,17,203,190,253,158,153,97,156,192,214,4,116,174,102,99,5,5,0,0,0,1,0,132,0,0,3,126,4,123,0,15,0,37,64,7, + 2,12,0,8,5,7,16,16,220,204,236,50,204,49,0,64,10,0,7,12,135,11,188,1,6,135,4,47,236,50,252,236,57,57,48,1,17,51,21,33, + 53,51,17,52,54,59,1,21,35,34,6,1,224,164,254,0,164,163,181,254,233,105,76,2,229,253,191,164,164,2,65,214,192,156,97,0,0,1,0,116, + 0,0,3,126,4,123,0,15,0,37,64,7,2,0,8,12,5,7,16,16,220,204,204,252,204,49,0,64,10,0,7,10,135,13,188,1,6,135,4,47, + 236,50,252,236,57,57,48,1,17,51,21,33,53,51,17,52,38,43,1,53,51,50,22,2,202,180,253,240,164,76,105,233,254,181,163,2,229,253,191,164, + 164,2,65,153,97,156,192,0,0,2,0,186,0,0,4,151,4,96,0,19,0,28,0,176,64,52,9,8,7,3,10,6,17,3,4,3,5,17,4,4, + 3,66,6,4,0,21,3,4,21,169,9,20,169,13,188,11,4,5,6,3,17,9,0,28,22,14,5,10,25,18,4,17,20,10,8,12,70,29,16,252, + 236,50,220,196,236,17,23,57,17,57,57,57,49,0,47,60,244,236,212,236,18,57,18,57,18,57,48,75,83,88,7,16,5,237,7,16,5,237,17,23, + 57,89,34,178,64,30,1,1,93,64,66,122,19,1,5,0,5,1,5,2,6,3,7,4,21,0,21,1,20,2,22,3,23,4,37,0,37,1,37,2, + 38,3,39,6,38,7,38,8,38,9,32,30,54,1,54,2,70,1,70,2,104,5,117,4,117,5,119,19,136,6,136,7,152,6,152,7,31,93,0,93, + 1,30,1,23,19,35,3,46,1,43,1,17,35,17,33,50,22,21,20,6,1,17,51,50,54,53,52,38,35,3,20,48,115,50,174,195,162,74,123,81, + 169,185,1,132,218,214,112,253,245,198,119,127,117,129,2,13,10,116,93,254,206,1,31,128,58,254,39,4,96,158,165,105,140,1,157,254,175,86,78,77, + 96,0,0,0,0,2,0,186,0,0,4,151,4,96,0,19,0,28,0,69,64,21,9,7,6,15,3,12,28,22,18,5,2,25,18,8,15,1,20,8, + 0,70,29,16,252,236,50,220,196,236,17,23,57,17,57,57,57,49,0,64,15,6,8,12,20,9,8,3,169,20,21,169,8,0,188,19,47,228,50,236, + 212,236,17,57,17,57,17,57,48,19,51,17,51,50,54,55,19,51,3,14,1,7,30,1,21,20,6,35,33,19,17,51,50,54,53,52,38,35,186,185, + 169,81,123,74,162,195,174,50,115,48,106,112,214,218,254,124,185,198,129,117,127,119,4,96,254,39,58,128,1,31,254,206,93,116,10,27,140,105,165,158, + 1,236,254,175,96,77,78,86,0,1,0,111,254,86,3,199,4,123,0,48,0,128,64,67,13,12,2,14,11,83,40,39,8,9,2,7,10,83,39,40, + 39,66,25,169,26,189,49,10,11,39,40,4,31,0,134,1,137,4,31,137,33,185,17,4,185,46,184,17,140,49,26,21,8,30,39,10,11,40,36,7, + 0,82,36,8,14,7,8,30,43,69,49,16,252,196,236,212,236,228,17,18,57,57,57,57,16,236,204,49,0,16,228,244,236,16,254,245,16,245,238,18, + 23,57,16,252,236,48,75,83,88,7,16,14,237,17,23,57,7,14,237,17,23,57,89,34,178,0,48,1,1,93,1,21,46,1,35,34,6,21,20,22, + 31,1,30,1,21,20,6,35,34,47,1,21,20,22,59,1,21,35,34,38,61,1,22,51,50,54,53,52,38,47,1,46,1,53,52,54,51,50,22,3, + 139,78,168,90,137,137,98,148,63,196,165,247,216,100,88,21,76,105,233,254,181,163,204,193,130,140,101,171,64,171,152,224,206,102,180,4,63,174,40,40, + 84,84,64,73,33,14,42,153,137,156,182,17,4,12,153,97,156,192,214,251,106,89,81,75,80,37,15,36,149,130,158,172,30,0,0,0,0,1,255,217, + 254,86,2,215,6,20,0,19,0,52,64,13,17,20,14,15,79,5,11,10,8,1,0,70,20,16,252,60,236,50,50,228,57,18,57,49,0,64,13,16, + 135,15,189,20,10,1,6,6,135,5,151,20,16,252,236,18,57,57,16,244,236,48,23,17,52,54,59,1,21,35,34,6,21,17,20,6,43,1,53,51, + 50,54,190,174,189,174,176,99,77,163,181,70,49,105,75,20,4,194,187,171,153,80,104,251,41,214,192,156,97,0,0,0,0,1,255,217,254,86,2,215, + 6,20,0,32,0,79,64,18,13,32,28,1,22,33,19,20,79,5,16,10,8,25,30,1,70,33,16,252,60,60,236,50,50,228,57,18,57,16,204,50, + 196,49,0,64,23,30,169,0,188,33,12,28,169,15,27,21,135,20,189,33,10,1,6,6,135,5,151,33,16,252,236,18,57,57,16,244,236,212,60,236, + 50,16,244,236,48,19,53,52,54,59,1,21,35,34,6,21,17,23,51,21,35,17,20,6,43,1,53,51,50,54,53,17,35,53,51,17,35,53,190,174, + 189,174,176,99,77,1,162,163,163,181,70,49,105,75,180,180,175,4,96,78,187,171,153,80,104,253,168,3,164,254,40,214,192,156,97,153,1,216,164,1, + 105,143,0,0,0,1,0,55,254,86,3,53,4,101,0,19,0,34,182,15,79,11,8,1,6,20,16,212,220,252,236,49,0,64,10,14,135,16,189,20, + 4,135,6,188,20,16,244,236,16,244,236,48,5,17,52,38,43,1,53,51,50,22,21,17,20,22,59,1,21,35,34,38,1,151,77,99,176,174,189,174, + 75,105,49,70,181,163,20,3,40,104,80,153,171,187,252,237,153,97,156,192,0,2,254,242,254,86,2,215,6,20,0,22,0,31,0,50,64,12,26,9, + 13,2,17,3,22,8,23,13,79,32,16,252,50,252,50,204,204,16,212,204,49,0,64,12,28,7,3,24,135,0,19,135,17,151,11,0,47,60,244,236, + 16,236,50,212,204,48,33,51,21,35,6,7,6,35,32,53,52,33,51,17,52,54,59,1,21,35,34,6,21,3,35,34,23,22,51,50,55,54,1,119, + 183,191,18,53,82,181,254,209,1,14,190,174,189,174,176,99,77,195,179,119,3,3,124,110,33,17,155,111,64,96,216,210,4,174,187,171,153,80,104,250, + 163,51,65,48,24,0,0,0,0,1,0,55,254,192,2,242,4,94,0,19,0,51,64,9,8,11,14,18,8,5,1,9,2,47,60,212,60,236,50,57, + 57,49,0,64,12,14,5,0,8,169,11,188,15,3,169,18,2,47,60,236,50,244,236,196,57,57,48,1,178,175,21,1,93,1,17,33,53,33,17,52, + 38,43,1,53,51,50,22,21,17,51,21,35,17,1,178,254,133,1,123,75,115,189,189,213,162,135,135,254,192,1,62,143,2,96,137,78,154,159,210,253, + 160,143,254,194,0,1,0,55,254,86,2,246,5,158,0,19,0,61,64,28,14,5,8,15,3,169,0,17,1,188,20,8,135,11,189,20,11,8,9,2, + 4,0,8,16,18,14,70,20,16,252,60,196,252,60,196,50,57,57,49,0,16,252,236,16,244,60,196,236,50,17,57,57,48,178,175,21,1,1,93,1, + 17,33,21,33,17,20,22,59,1,21,35,34,38,53,17,35,53,51,17,1,119,1,123,254,133,76,105,202,224,181,163,135,135,5,158,254,194,143,252,27, + 153,97,156,192,214,3,229,143,1,62,0,0,0,2,0,0,255,227,5,18,4,96,0,22,0,30,0,67,64,31,13,1,28,135,16,0,7,4,169,10, + 20,23,13,16,140,5,1,188,11,23,12,4,8,6,78,24,2,8,0,70,31,16,252,236,50,244,236,50,50,49,0,47,228,50,244,196,220,50,50,236, + 50,50,16,252,17,18,48,180,96,32,207,32,2,1,93,19,17,51,17,33,17,51,17,51,21,35,17,35,53,14,1,35,34,38,61,1,35,53,5,33, + 21,20,22,51,50,54,174,184,2,58,184,186,186,184,67,177,117,193,200,174,3,159,253,199,124,124,143,178,2,104,1,248,254,8,1,248,254,8,164,254, + 60,172,102,99,240,231,10,164,165,2,159,159,186,0,0,0,0,1,0,113,255,226,4,132,4,96,0,31,0,83,64,13,29,26,18,33,0,4,17,20, + 18,14,10,4,32,16,252,196,252,196,212,196,204,252,196,49,0,64,14,17,29,13,1,169,30,16,188,32,23,185,7,140,32,16,244,236,16,252,60,236, + 50,50,50,48,1,64,25,224,17,224,16,239,29,239,30,208,17,208,16,223,29,223,30,64,17,64,16,79,29,79,30,12,93,1,35,30,1,21,20,0, + 35,34,0,53,52,54,55,35,53,33,21,14,1,21,20,22,51,50,54,53,52,38,39,55,33,4,132,236,97,127,254,228,225,225,254,228,127,97,237,1, + 186,102,136,176,144,144,176,136,102,1,1,180,3,188,72,235,152,235,254,220,1,36,235,152,235,72,164,220,66,215,139,159,194,194,159,139,215,66,220,0, + 0,1,0,193,0,0,4,92,4,98,0,30,0,44,64,12,32,0,18,20,25,5,16,12,8,9,70,31,16,252,252,196,196,196,212,236,57,49,0,64, + 10,17,185,4,24,185,25,184,11,188,4,47,236,244,236,16,236,48,1,20,7,6,43,1,34,39,38,53,17,51,17,20,23,22,55,51,50,54,53,52, + 39,38,39,53,22,23,22,23,22,4,92,142,145,222,70,181,82,81,184,38,40,103,51,144,176,74,73,110,104,88,167,51,34,2,15,238,143,146,96,96, + 214,2,202,253,54,153,49,50,2,196,158,232,101,99,30,150,8,48,91,171,115,0,0,0,0,1,0,61,0,0,4,127,4,96,0,6,0,104,64,39, + 4,17,3,3,2,5,17,6,5,2,2,3,5,17,5,4,1,0,1,6,17,0,1,0,66,5,2,1,191,3,6,5,4,2,1,5,3,0,7,16, + 212,75,176,10,84,88,185,0,0,0,64,56,89,75,176,20,84,75,176,21,84,91,88,185,0,0,255,192,56,89,196,23,57,49,0,47,236,50,57,48, + 75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,1,51,1,51,1,35,9,1,61,1,164,250,1,164,195,254,162,254,162, + 4,96,251,160,3,172,252,84,0,1,0,86,0,0,6,53,4,96,0,12,1,239,64,15,8,9,10,11,12,1,2,3,4,5,6,11,0,7,13,16, + 212,75,176,10,84,75,176,17,84,91,75,176,18,84,91,75,176,19,84,91,75,176,11,84,91,88,185,0,7,0,64,56,89,1,75,176,12,84,75,176, + 13,84,91,75,176,16,84,91,88,185,0,7,255,192,56,89,204,23,57,49,64,10,10,5,2,3,12,8,191,7,3,0,0,47,60,60,236,50,23,57, + 48,64,48,2,85,1,2,11,10,11,3,85,10,11,4,85,10,9,10,5,85,6,5,9,9,10,1,17,0,12,0,2,17,3,2,12,12,0,5,17, + 4,5,8,7,8,6,17,7,7,8,66,75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,7,16,8,237,7,16,5,237,7,5, + 237,7,16,8,237,89,34,1,64,255,10,5,25,5,25,2,45,10,58,10,70,5,70,2,73,10,79,10,84,5,84,2,90,10,95,10,97,5,97,2, + 105,10,118,5,112,5,118,2,112,2,136,5,150,5,151,2,155,10,179,5,179,2,193,5,200,4,192,2,29,5,5,9,4,6,3,11,2,10,12,11, + 11,4,9,5,8,21,5,25,4,22,3,26,2,27,12,27,11,20,9,21,8,37,7,37,6,35,5,39,4,33,3,37,2,34,1,34,0,37,12,39, + 11,36,10,33,9,35,8,57,4,54,3,54,12,57,8,48,14,70,5,72,4,70,3,64,3,66,2,64,1,64,0,64,12,68,11,68,10,68,9,64, + 14,64,14,86,7,86,6,86,5,80,3,81,2,82,1,82,0,80,12,83,11,84,10,85,9,99,7,100,6,101,5,106,4,101,3,106,2,106,1,106, + 0,110,11,97,9,103,8,111,14,117,7,117,6,121,5,125,4,120,3,125,2,122,1,127,1,122,0,127,0,120,12,121,11,127,11,123,10,118,9,125, + 8,135,5,136,2,143,14,151,7,151,6,148,5,147,4,156,3,155,2,152,1,152,0,153,12,64,47,150,8,159,14,166,7,166,6,164,5,164,4,171, + 3,171,2,169,1,169,0,171,12,164,8,175,14,181,5,177,4,189,3,187,2,184,11,191,14,196,5,195,4,204,3,202,2,121,93,0,93,33,35,11, + 1,35,11,1,35,1,51,27,1,51,6,53,184,230,229,217,230,229,184,1,37,217,241,242,217,3,106,252,150,3,106,252,150,4,96,252,106,3,150,0, + 0,1,0,61,0,0,4,127,6,20,0,17,0,70,180,19,6,14,0,18,16,212,212,196,196,49,181,7,169,6,151,14,0,0,47,60,244,236,48,183, + 16,13,12,17,17,0,1,0,7,5,16,252,60,60,60,182,8,9,10,11,4,7,12,1,17,18,23,57,64,9,16,17,17,12,15,17,14,14,13,7, + 16,236,8,236,51,1,54,55,54,59,1,21,35,34,7,6,15,1,1,35,9,1,61,1,236,80,72,74,124,147,108,76,42,46,47,33,1,197,195,254, + 161,254,163,4,210,199,62,61,154,36,35,135,94,251,178,3,108,252,148,0,0,1,0,102,0,0,4,107,4,96,0,8,0,56,64,10,2,8,5,10, + 4,5,8,8,0,9,16,212,220,252,212,196,17,18,57,49,179,4,0,188,7,0,47,228,50,48,64,12,3,17,4,5,4,2,17,1,17,0,8,0, + 7,5,16,236,4,236,7,5,16,236,19,51,9,1,51,1,17,35,17,102,217,1,37,1,46,217,254,93,203,4,96,254,56,1,200,253,144,254,16,1, + 240,0,0,0,0,1,0,88,254,86,4,191,4,96,0,19,0,170,64,34,18,17,2,3,2,3,17,17,18,17,66,9,169,10,189,15,18,169,0,188, + 3,169,15,10,79,4,18,3,1,0,4,1,16,20,16,220,75,176,11,84,75,176,12,84,91,88,185,0,16,255,192,56,89,75,176,19,84,88,185,0, + 16,0,64,56,89,196,50,196,17,57,57,16,236,49,0,47,236,244,236,16,252,236,48,75,83,88,7,16,5,237,7,16,5,237,89,34,1,64,66,5, + 2,22,2,38,2,71,2,73,17,5,11,18,15,21,24,3,27,18,43,18,32,21,54,3,57,18,48,21,64,1,64,2,69,3,64,4,64,15,67,18, + 87,3,89,18,95,21,96,1,96,2,102,3,96,4,96,5,98,18,127,21,128,21,175,21,27,93,0,93,19,33,21,1,33,21,20,22,59,1,21,35, + 34,38,61,1,33,53,1,33,113,3,106,253,76,2,180,76,105,47,70,181,163,253,55,2,180,253,101,4,96,168,252,219,167,153,97,156,192,214,20,168, + 3,37,0,0,0,2,0,88,255,145,3,219,4,96,0,26,0,33,0,177,64,17,22,4,18,17,27,30,18,12,25,3,1,0,12,1,1,23,34,16, + 220,75,84,75,176,12,84,91,88,185,0,23,255,192,56,89,75,176,19,84,88,185,0,23,0,64,56,89,196,50,196,17,57,57,16,236,220,60,236,50, + 49,0,64,13,25,169,0,188,19,23,8,185,32,3,27,169,23,47,252,60,220,236,16,204,244,236,48,64,11,25,17,2,3,2,3,17,24,25,24,66, + 75,83,88,7,16,5,237,7,16,5,237,89,34,1,64,58,5,2,22,2,38,2,71,2,73,24,5,11,25,15,35,24,3,27,25,43,25,32,35,54, + 3,57,25,48,35,64,1,64,2,69,3,67,25,87,3,89,25,95,35,96,1,96,2,102,3,98,25,127,35,128,35,175,35,23,93,0,93,19,33,21, + 1,51,54,55,54,51,50,23,22,21,22,7,6,43,1,6,21,35,52,55,33,53,1,33,1,51,50,53,52,7,6,113,3,106,253,76,175,34,84,65, + 96,132,58,38,1,62,82,126,105,3,153,3,254,150,2,180,253,101,1,255,56,138,70,88,4,96,168,252,219,162,71,55,87,57,87,96,47,61,51,60, + 59,52,168,3,37,252,198,54,93,2,2,0,0,1,0,88,254,76,4,47,4,96,0,32,0,169,64,10,27,31,21,18,34,6,30,31,14,33,16,220, + 212,196,212,196,236,16,204,178,0,31,27,17,18,57,49,64,22,27,66,0,169,26,26,30,33,29,169,30,14,134,13,147,17,185,9,189,30,188,33,0, + 16,228,252,236,244,236,16,236,17,18,57,47,236,236,179,21,6,0,9,17,18,57,57,48,64,8,27,17,0,28,17,32,26,31,7,5,16,236,4,16, + 236,64,27,12,28,10,0,27,28,25,0,42,28,42,0,56,0,59,28,73,0,76,28,84,0,91,28,113,0,13,1,93,64,27,4,27,4,32,20,27, + 20,32,37,27,36,32,53,32,55,27,69,32,70,27,84,32,92,27,127,27,13,0,93,64,9,7,11,6,12,26,12,26,15,4,93,1,50,23,22,23, + 22,21,20,4,33,34,39,38,39,53,30,1,51,50,55,54,53,52,39,38,43,1,53,1,33,53,33,21,2,60,106,128,98,86,81,254,208,254,232,94, + 99,100,106,84,200,109,190,99,100,92,93,165,174,1,174,253,101,3,106,1,220,56,42,109,104,138,221,242,18,19,37,195,49,50,75,75,143,132,75,74, + 166,1,243,147,168,0,0,0,0,2,0,109,254,76,4,108,4,96,0,36,0,45,0,0,1,32,55,54,5,22,23,54,53,52,39,38,43,1,53,1, + 33,53,33,21,1,50,23,22,23,22,21,20,7,22,21,35,52,39,48,7,6,55,38,35,34,7,20,51,50,55,1,231,254,177,2,2,1,42,246,158, + 12,92,94,164,174,1,174,253,101,3,106,254,101,105,129,100,84,81,39,100,153,40,20,151,9,125,197,131,1,158,190,99,254,76,189,251,5,4,59,42, + 49,133,74,74,166,1,243,147,168,254,36,56,43,108,103,139,113,85,101,164,82,56,17,121,250,42,75,47,75,0,0,0,0,1,0,88,0,0,3,165, + 6,18,0,28,0,52,64,9,30,5,18,22,26,8,0,13,29,16,220,220,252,220,236,196,49,64,14,13,134,14,12,18,9,185,18,151,27,26,169,0, + 27,0,47,212,228,16,244,236,16,75,80,88,220,27,212,89,236,48,1,51,50,55,54,53,38,39,38,35,34,7,6,7,53,54,55,54,51,32,23,22, + 21,20,7,6,7,17,35,1,84,63,192,86,58,1,57,99,179,80,79,78,78,76,81,81,85,1,19,138,109,108,112,170,202,3,30,114,76,98,133,65, + 114,22,21,43,172,35,17,18,157,125,186,170,115,119,30,253,116,0,0,0,0,1,0,88,0,0,3,165,6,18,0,28,0,53,64,10,30,16,0,8, + 3,24,18,7,69,29,16,252,236,220,252,220,196,49,64,14,16,134,15,12,11,20,185,11,151,2,3,169,0,2,0,47,212,228,16,244,236,16,75,80, + 88,220,27,212,89,236,48,1,17,35,17,38,39,38,53,52,55,54,33,50,23,22,23,21,38,39,38,35,34,7,6,7,20,23,22,51,2,168,202,170, + 112,108,110,137,1,19,85,81,81,76,78,79,78,80,179,99,57,1,58,86,192,3,30,252,226,2,140,30,119,115,170,186,125,157,18,17,35,172,43,21, + 22,114,65,133,98,76,114,0,0,1,0,88,0,0,3,165,6,18,0,28,0,55,64,9,30,24,18,7,3,8,0,16,29,16,220,220,252,220,236,196, + 49,64,16,16,134,15,12,11,20,185,11,140,29,3,169,0,1,151,29,0,16,244,212,228,16,244,236,16,75,80,88,220,27,212,89,236,48,1,19,51, + 17,22,23,22,21,20,7,6,33,34,39,38,39,53,22,23,22,51,50,55,54,55,52,39,38,35,1,84,1,202,170,112,108,109,138,254,237,85,81,81, + 76,78,78,79,80,179,99,57,1,58,86,192,2,244,3,30,253,116,30,119,115,170,186,125,157,18,17,35,172,43,21,22,114,65,133,98,76,114,0,0, + 0,1,0,88,254,76,3,165,6,20,0,35,0,45,182,37,26,8,18,18,0,36,16,220,236,220,50,204,49,0,64,16,9,135,8,13,135,4,151,36, + 26,135,27,22,135,31,189,36,16,252,236,212,236,16,244,236,212,236,48,19,52,55,54,33,50,23,22,23,21,38,39,38,35,34,7,6,21,17,20,23, + 22,51,50,55,54,55,21,6,7,6,35,32,39,38,53,88,110,137,1,19,85,81,81,76,73,84,78,80,176,102,58,58,102,176,80,78,79,78,76,81, + 81,85,254,237,137,110,4,64,186,125,157,18,17,35,172,40,24,22,114,65,133,251,224,133,65,114,22,21,43,172,35,17,18,157,125,186,0,3,0,115, + 255,227,5,217,5,240,0,13,0,23,0,34,0,0,1,52,55,54,51,50,23,22,21,20,6,34,39,38,0,32,0,17,16,0,32,0,17,16,1,32, + 0,17,16,0,33,32,0,16,0,2,181,34,32,48,46,34,32,66,94,32,34,1,78,254,72,254,253,1,3,1,184,1,1,254,35,1,58,1,120,254, + 136,254,198,254,197,254,135,1,121,2,233,46,34,34,34,34,46,47,66,33,33,2,146,254,184,254,229,254,230,254,184,1,72,1,26,1,27,1,236,254, + 91,254,158,254,159,254,91,1,164,2,196,1,165,0,0,0,255,255,0,186,0,0,4,62,4,96,16,6,3,198,0,0,0,2,0,113,255,227,4,197, + 4,124,0,26,0,47,0,61,64,14,49,23,18,31,9,37,4,18,44,15,18,37,69,48,16,252,236,212,236,16,196,212,236,196,49,64,14,0,185,27, + 184,48,10,169,9,48,19,185,34,140,48,0,16,244,236,16,212,236,16,244,236,178,40,10,9,17,18,57,48,1,34,7,6,21,20,23,22,59,1,21, + 35,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38,37,32,23,22,17,16,0,33,34,36,53,52,54,55,38,39,38,53,52,55,54,2,69,119, + 69,70,68,67,116,155,148,137,72,78,84,85,151,210,104,99,99,96,254,246,1,97,151,151,254,214,254,198,238,254,254,138,124,112,60,60,114,113,3,220, + 46,46,64,70,45,44,152,51,56,88,90,56,56,116,111,208,205,114,110,160,158,157,254,238,254,242,254,194,182,173,108,146,24,24,65,64,93,141,79,78, + 0,1,0,113,255,227,5,203,6,20,0,39,0,71,64,39,18,27,17,28,24,169,21,151,40,0,5,37,1,169,3,37,185,8,17,28,136,31,185,14, + 184,8,140,40,2,0,8,27,52,4,34,18,11,69,40,16,252,236,220,228,252,196,49,0,16,228,244,252,236,57,16,254,212,238,17,57,57,16,252,236, + 17,18,57,57,48,37,17,35,53,33,17,14,1,35,34,0,17,16,0,33,50,22,23,53,52,54,59,1,21,35,34,6,21,17,46,1,35,34,6,21, + 20,22,51,50,54,3,169,155,1,65,101,215,123,253,254,214,1,45,1,6,55,105,49,163,181,254,231,105,77,95,192,99,179,198,198,179,79,124,158,1, + 17,140,253,240,36,36,1,62,1,14,1,18,1,58,15,15,33,214,192,156,97,153,254,229,62,62,227,205,205,227,15,0,255,255,0,186,0,0,4,129, + 4,96,16,6,3,209,0,0,0,3,254,242,254,86,2,46,6,20,0,3,0,18,0,27,0,57,64,17,9,19,5,4,22,18,15,4,29,7,1,5, + 8,0,4,70,28,16,252,60,252,60,220,196,16,220,236,17,18,57,57,49,64,11,24,13,189,4,188,0,177,9,19,6,18,0,47,60,204,50,228,228, + 252,196,48,19,51,21,35,21,51,17,51,21,35,6,7,6,35,32,53,52,33,51,7,35,34,23,20,51,50,55,54,193,184,184,184,181,189,18,55,75, + 188,254,209,1,14,193,8,184,117,1,127,95,43,29,6,20,233,203,251,160,139,120,71,96,221,205,139,66,65,48,32,0,0,1,0,186,254,76,4,156, + 4,96,0,10,0,0,1,35,17,1,35,9,1,51,1,17,51,4,156,185,253,219,235,2,82,253,149,240,2,57,185,254,76,3,151,254,29,2,12,2, + 84,253,221,2,35,0,0,0,0,1,0,186,0,0,3,241,4,96,0,5,0,27,64,13,0,191,3,169,6,5,7,3,1,8,0,70,6,16,252,252, + 204,196,49,0,47,16,236,236,48,19,51,17,33,21,33,186,184,2,127,252,201,4,96,252,51,147,0,0,0,2,0,113,254,86,5,248,6,18,0,11, + 0,36,0,67,64,30,3,185,12,15,9,185,24,21,184,15,140,35,189,37,31,135,28,151,37,24,12,6,8,34,71,0,18,18,69,37,16,252,236,244, + 236,50,50,49,0,16,252,236,16,228,228,244,196,236,16,198,238,48,64,9,96,38,128,38,160,38,224,38,4,1,93,1,20,22,51,50,54,53,52,38, + 35,34,6,1,14,1,35,34,2,17,16,0,51,50,22,23,53,52,54,59,1,21,35,34,6,21,17,35,1,47,167,146,146,168,168,146,146,167,2,115, + 58,177,124,203,255,0,255,203,124,177,58,163,181,254,231,105,77,185,2,47,203,231,231,203,203,231,231,253,174,100,97,1,68,1,8,1,8,1,68,97, + 100,198,214,192,156,97,153,249,218,0,0,0,0,1,0,88,0,0,3,165,6,18,0,36,0,76,64,11,38,5,18,22,31,26,8,32,0,14,37,16, + 220,220,60,252,60,220,236,196,179,28,26,35,0,16,204,16,204,49,64,20,13,134,14,12,18,36,27,169,33,30,31,9,185,18,151,31,26,169,0,31, + 0,47,212,228,16,244,236,16,220,60,236,50,16,75,80,88,220,27,212,89,236,48,1,51,50,55,54,53,38,39,38,35,34,7,6,7,53,54,55,54, + 51,32,23,22,21,20,7,6,7,21,51,21,35,17,35,17,35,53,51,1,84,63,192,86,58,1,57,99,179,80,79,78,78,76,81,81,85,1,19,138, + 109,108,112,170,231,231,202,229,228,3,30,114,76,98,133,65,114,22,21,43,172,35,17,18,157,125,186,170,115,119,30,212,164,254,236,1,20,164,0,0, + 0,1,0,88,0,0,3,165,6,18,0,36,0,77,64,12,38,16,34,29,8,35,3,24,18,7,69,37,16,252,236,220,60,252,60,220,196,179,32,34, + 0,35,16,204,16,204,49,64,20,16,134,15,12,11,2,30,169,36,33,35,20,185,11,151,35,3,169,29,35,0,47,212,228,16,244,236,16,220,60,236, + 50,16,75,80,88,220,27,212,89,236,48,19,53,51,53,38,39,38,53,52,55,54,33,50,23,22,23,21,38,39,38,35,34,7,6,7,20,23,22,59, + 1,17,51,21,35,17,35,17,247,231,170,112,108,110,137,1,19,85,81,81,76,78,79,78,80,179,99,57,1,58,86,192,62,229,229,202,1,20,164,212, + 30,119,115,170,186,125,157,18,17,35,172,43,21,22,114,65,133,98,76,114,254,154,164,254,236,1,20,0,0,3,0,113,255,227,7,195,6,20,0,11, + 0,38,0,41,0,0,0,16,23,22,32,55,54,16,39,38,32,7,37,17,51,17,33,21,1,33,21,33,43,1,53,6,7,6,35,34,39,38,16,55, + 54,51,50,23,22,23,17,1,1,47,83,84,1,36,84,84,84,84,254,220,84,2,32,184,3,105,253,76,2,180,252,151,26,158,58,88,89,124,203,128, + 127,127,128,203,124,89,88,242,2,154,2,250,254,106,116,115,115,116,1,150,116,115,115,72,2,94,254,76,168,252,219,147,168,100,48,49,162,162,2,16, + 162,162,49,48,77,252,249,3,7,0,0,0,0,2,0,113,254,76,8,28,6,20,0,52,0,64,0,0,1,17,35,53,6,7,6,35,34,39,38,16, + 55,54,51,50,23,22,23,17,51,17,33,21,1,50,23,22,23,22,21,20,4,33,34,39,38,39,53,30,1,51,50,55,54,53,52,39,38,43,1,53, + 1,4,16,23,22,32,55,54,16,39,38,32,7,4,90,184,58,88,89,124,203,128,127,127,128,203,124,89,88,58,184,3,106,254,101,106,128,98,86,81, + 254,208,254,232,94,99,100,106,84,200,109,190,99,100,92,93,165,174,1,174,250,58,83,84,1,36,84,84,84,84,254,220,84,3,205,252,51,168,100,48, + 49,162,162,2,16,162,162,49,48,100,2,94,254,76,168,254,36,56,42,109,104,138,221,242,18,19,37,195,49,50,75,75,143,132,75,74,166,1,243,211, + 254,106,116,115,115,116,1,150,116,115,115,0,0,4,0,113,255,145,7,194,6,20,0,11,0,14,0,51,0,58,0,0,0,16,23,22,32,55,54,16, + 39,38,32,7,37,17,1,37,33,21,1,51,18,51,50,23,22,33,35,6,21,35,52,55,33,35,53,6,7,6,35,34,39,38,16,55,54,51,50,23, + 22,23,17,51,1,51,50,53,52,35,6,1,47,83,84,1,36,84,84,84,84,254,220,84,2,216,2,153,253,103,3,104,253,76,175,60,219,227,1,1, + 254,178,41,3,153,3,254,150,157,58,88,89,124,203,128,127,127,128,203,124,89,88,58,184,1,253,20,174,70,88,2,250,254,106,116,115,115,116,1,150, + 116,115,115,95,252,250,3,6,147,168,252,219,1,32,246,189,51,60,59,52,168,100,48,49,162,162,2,16,162,162,49,48,100,2,94,250,127,54,91,2, + 0,1,0,55,0,0,6,64,5,158,0,55,0,0,1,17,33,21,33,17,20,23,22,51,33,50,55,54,53,52,38,47,1,46,1,53,52,54,51,50, + 22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,7,6,41,1,34,39,38,53,17,35,53,51,17,1,119,1,123,254,133,37,38,115,2, + 64,130,70,70,94,178,64,171,152,224,206,102,180,76,78,168,90,137,137,98,148,63,198,163,124,76,254,249,253,196,213,81,81,135,135,5,158,254,194,143, + 253,160,137,39,39,45,44,52,73,77,42,15,36,149,130,158,172,30,30,174,40,40,84,84,64,73,33,14,44,151,137,146,101,62,80,79,210,2,96,143, + 1,62,0,0,0,2,0,55,254,86,5,8,6,20,0,38,0,47,0,0,1,17,33,48,53,52,55,54,59,1,21,35,34,7,6,21,19,20,7,6, + 43,1,53,51,50,55,54,61,1,35,34,39,38,53,17,35,53,51,17,1,2,17,33,17,20,23,22,51,1,119,1,120,87,81,195,174,176,99,38,39, + 2,81,82,181,70,49,105,38,38,189,213,81,81,135,135,2,51,2,254,136,37,38,115,5,158,254,194,78,181,91,86,153,40,40,104,251,41,214,96,96, + 156,48,49,153,20,80,79,210,2,96,143,1,62,250,252,1,162,1,149,253,160,137,39,39,0,3,0,55,255,112,5,201,5,158,0,45,0,57,0,68, + 0,0,1,17,33,21,54,33,50,23,22,23,21,38,39,38,35,34,7,6,16,31,1,54,51,32,23,20,7,6,35,34,39,6,21,7,52,55,33,34, + 39,38,53,17,35,53,51,17,1,22,51,50,55,54,39,38,35,34,7,6,5,38,53,16,55,33,17,20,23,22,51,1,119,1,123,149,0,255,85,81, + 81,76,78,79,78,80,179,99,99,99,8,79,206,1,43,1,101,75,157,84,73,2,153,6,254,235,213,81,81,135,135,3,59,66,83,95,21,31,1,1, + 131,114,40,5,254,214,128,139,254,153,37,38,115,5,158,254,194,122,149,17,18,35,172,43,22,21,113,114,254,102,114,9,171,246,118,41,30,18,50,76, + 3,79,65,80,79,210,2,96,143,1,62,250,249,24,7,11,39,75,86,10,9,157,248,1,7,155,253,160,137,39,39,0,0,1,0,47,254,86,6,111, + 6,20,0,53,0,0,1,17,20,7,6,43,1,53,51,50,55,54,53,17,52,38,35,34,6,21,17,35,17,33,17,35,17,35,53,51,53,52,55,54, + 59,1,21,35,34,7,6,29,1,33,59,1,21,54,55,54,51,50,23,22,6,111,82,81,181,254,233,105,38,38,124,124,149,172,185,254,211,185,176,176, + 87,87,189,174,176,99,39,38,1,45,2,183,66,89,90,117,193,99,99,2,164,253,72,214,96,96,156,48,49,153,2,178,159,158,190,164,253,135,3,209, + 252,47,3,209,143,78,187,85,86,153,40,40,104,99,174,101,50,50,119,120,0,1,0,193,0,0,5,65,6,20,0,39,0,0,19,51,17,33,50,55, + 54,53,52,38,47,1,46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,7,6,41,1,193,184,1,253,130,70, + 70,94,178,64,171,152,224,206,102,180,76,78,168,90,137,137,98,148,63,198,163,124,76,254,249,253,79,6,20,250,134,45,44,52,73,77,42,15,36,149, + 130,158,172,30,30,174,40,40,84,84,64,73,33,14,44,151,137,146,101,62,0,2,0,193,0,0,4,226,6,20,0,10,0,13,0,142,64,13,13,5, + 3,11,6,3,9,11,1,8,0,70,14,16,252,252,60,212,196,50,17,18,57,57,49,0,64,10,66,13,169,2,188,5,169,0,151,7,47,236,236,244, + 236,48,75,83,88,64,10,5,17,12,13,12,13,17,4,5,4,7,16,5,237,7,16,5,237,89,1,64,66,5,4,22,4,27,12,38,4,71,4,73, + 12,6,13,13,15,15,24,5,29,13,43,13,48,15,57,13,64,3,64,4,64,6,64,7,64,15,67,13,69,5,87,5,89,13,96,3,96,4,96,6, + 96,7,96,15,98,13,102,5,175,15,191,15,223,15,26,93,0,93,19,51,17,33,21,1,33,21,33,43,1,19,17,1,193,184,3,105,253,76,2,180, + 252,151,26,158,184,2,154,6,20,254,76,168,252,219,147,3,205,252,249,3,7,0,0,0,0,2,0,54,255,226,3,233,5,31,0,12,0,25,0,0, + 19,51,27,1,51,27,1,51,3,35,11,1,35,3,51,27,1,51,27,1,51,3,35,11,1,35,54,116,145,144,137,145,144,116,185,136,152,153,136,185, + 116,145,144,137,145,144,116,185,136,152,153,136,2,85,254,23,1,233,254,23,1,233,253,141,2,2,253,254,5,61,254,23,1,233,254,23,1,233,253,141, + 2,2,253,254,0,2,0,54,0,173,3,233,5,31,0,7,0,15,0,51,64,12,17,12,4,8,9,1,13,5,8,8,0,16,16,220,60,236,50,212, + 60,236,50,196,49,64,12,11,14,13,169,8,16,3,6,5,169,0,16,0,16,212,252,204,50,16,212,252,204,50,48,19,33,17,35,17,33,17,35,17, + 33,17,35,17,33,17,35,54,3,179,143,253,107,143,3,179,143,253,107,143,2,85,254,88,1,5,254,251,4,114,254,88,1,5,254,251,0,1,0,0, + 254,74,4,144,6,20,0,25,0,51,64,12,27,0,22,8,23,78,15,8,5,70,10,26,16,212,252,236,244,236,50,204,49,0,64,15,18,135,0,2, + 140,26,9,135,11,151,22,188,24,189,26,16,236,236,244,236,16,244,204,236,48,37,6,35,34,38,53,17,52,38,43,1,53,51,50,22,21,17,16,51, + 50,54,53,17,51,17,35,3,215,131,231,193,198,76,105,49,70,181,163,248,149,172,185,185,172,201,239,232,2,196,153,97,156,192,214,253,66,254,195,190, + 164,2,121,249,236,0,0,0,0,1,0,0,254,86,5,118,6,20,0,33,0,58,64,13,29,35,0,21,8,23,78,15,8,5,70,10,34,16,212,252, + 236,244,236,50,204,204,49,0,64,18,18,135,0,2,140,34,10,135,11,151,34,28,135,30,189,22,188,34,16,236,252,236,16,244,236,16,244,204,236,48, + 37,6,35,34,38,53,17,52,38,43,1,53,51,50,22,21,17,16,51,50,54,53,17,51,17,6,22,59,1,21,35,34,38,39,3,215,131,231,193,198, + 76,105,49,70,181,163,248,149,172,185,4,80,104,50,70,182,158,5,172,201,239,232,2,196,153,97,156,192,214,253,66,254,195,190,164,2,121,251,142,148, + 102,156,185,221,0,1,0,117,2,156,2,196,6,3,0,19,0,48,64,7,21,0,3,14,10,11,20,16,212,220,60,47,204,204,75,176,13,81,88,177, + 21,64,56,89,49,178,127,21,1,93,0,64,6,6,17,12,2,11,20,16,212,60,196,212,204,48,1,17,35,17,52,38,35,34,6,21,17,35,17,51, + 17,62,1,51,50,22,2,196,116,78,78,94,108,117,117,41,113,74,121,125,4,23,254,133,1,119,89,89,107,92,254,158,3,103,254,171,56,56,134,0, + 0,1,0,117,2,156,2,196,6,3,0,27,0,58,75,176,14,83,88,64,8,29,0,3,16,22,10,11,28,16,212,220,60,204,47,204,204,75,176,13, + 81,88,177,29,64,56,89,49,178,127,29,1,93,0,64,7,6,25,17,15,2,11,28,16,212,60,212,204,212,204,48,89,1,17,35,17,52,38,35,34, + 6,21,17,35,17,52,54,59,1,21,35,34,6,29,1,62,1,51,50,22,2,196,116,78,78,94,108,117,103,114,160,146,66,48,41,113,74,121,125,4, + 23,254,133,1,119,89,89,107,92,254,158,2,132,120,107,87,54,86,114,56,56,134,0,0,0,2,255,233,1,173,0,238,6,3,0,13,0,17,0,35, + 64,7,19,15,1,8,14,0,18,16,220,60,204,220,60,204,49,0,64,7,14,17,0,8,7,0,18,16,212,212,204,16,220,204,48,19,51,17,20,7, + 6,43,1,53,51,50,55,54,53,17,51,21,35,122,116,52,51,114,44,31,66,24,24,116,116,5,15,253,130,120,54,54,88,27,27,86,3,114,130,0, + 0,1,0,117,2,156,2,18,5,30,0,17,0,31,64,5,17,11,7,8,18,16,220,204,0,204,49,0,64,7,0,17,7,3,14,9,8,47,196,212, + 204,16,212,204,48,1,46,1,35,34,6,21,17,35,17,51,21,62,1,51,50,22,23,2,18,19,46,28,98,105,117,117,36,117,84,12,29,18,4,175, + 10,9,113,107,254,182,2,115,97,57,55,2,3,0,0,0,0,1,0,72,2,141,1,228,5,15,0,17,0,27,180,8,6,11,17,18,16,220,220,60, + 204,49,0,181,0,17,3,14,7,9,47,204,212,204,212,204,48,19,30,1,51,50,54,53,17,51,17,35,53,14,1,35,34,38,39,72,19,46,28,98, + 105,116,116,36,117,84,12,29,18,2,252,10,9,113,107,1,74,253,141,97,57,55,2,3,0,1,0,72,1,173,2,117,5,15,0,27,0,39,182,29, + 14,9,6,21,0,28,16,220,220,60,220,220,49,0,64,10,13,15,20,0,27,3,24,8,9,20,47,60,204,212,204,212,204,16,220,204,48,19,30,1, + 51,50,54,53,17,51,17,21,20,22,59,1,21,35,34,38,61,2,14,1,35,34,38,39,72,19,46,28,98,105,116,48,66,31,44,114,103,36,117,84, + 12,29,18,2,252,10,9,113,107,1,74,253,141,11,86,54,88,108,120,11,97,57,55,2,3,0,0,0,0,2,0,32,2,156,2,143,5,15,0,22, + 0,33,0,0,1,30,1,21,20,7,6,43,1,17,51,17,51,50,55,54,63,1,51,7,6,7,6,1,51,50,55,54,53,52,39,38,43,1,1,155, + 67,70,67,68,137,244,116,107,61,37,37,40,102,123,110,33,33,34,254,215,125,75,39,41,41,39,75,125,3,233,15,78,59,91,45,45,2,115,254,247, + 21,20,63,161,171,53,30,30,255,0,23,24,47,46,24,25,0,1,0,54,2,156,3,233,5,15,0,12,0,0,19,51,27,1,51,27,1,51,3,35, + 11,1,35,54,116,145,144,137,145,144,116,185,136,152,153,136,5,15,254,23,1,233,254,23,1,233,253,141,2,2,253,254,0,1,0,38,1,173,2,213, + 5,15,0,17,0,0,1,6,7,6,43,1,53,51,50,55,54,63,1,1,51,27,1,51,1,159,49,47,46,78,93,68,48,26,27,32,21,254,226,123, + 221,220,123,2,98,112,34,35,87,20,20,75,47,2,105,254,22,1,234,0,255,255,0,160,4,116,1,159,6,102,16,6,3,18,0,0,255,255,0,160, + 4,116,3,19,6,102,16,38,3,18,0,0,16,7,3,18,1,116,0,0,255,255,0,174,3,233,1,211,5,213,16,6,10,246,0,0,255,255,0,178, + 3,254,1,215,5,213,16,6,10,247,0,0,0,1,0,196,4,238,1,233,6,218,0,5,0,23,64,10,3,158,0,6,3,2,0,25,5,6,16,220, + 252,212,204,49,0,16,212,236,48,1,21,19,35,3,53,1,151,82,129,164,6,218,172,254,192,1,64,172,0,1,0,117,3,239,1,135,6,20,0,14, + 0,49,180,0,7,4,12,15,16,220,180,63,12,79,12,2,93,204,220,182,0,7,16,7,32,7,3,93,60,49,0,182,1,4,0,7,8,151,15,16, + 244,204,220,178,0,0,1,93,57,204,48,19,53,50,54,53,52,38,35,53,50,23,22,20,7,6,117,64,88,88,64,115,80,79,79,80,3,239,123,88, + 64,63,88,123,80,79,230,80,80,0,0,0,0,1,0,117,3,239,1,135,6,20,0,14,0,49,180,0,8,11,4,15,16,212,204,220,64,13,0,4, + 0,11,16,4,16,11,32,4,32,11,6,93,60,49,0,182,14,11,0,8,7,151,15,16,244,204,212,178,0,0,1,93,57,204,48,1,34,39,38,52, + 55,54,51,21,34,6,21,20,22,51,1,135,115,80,79,79,80,115,64,88,88,64,3,239,80,80,230,79,80,123,88,63,64,88,0,0,0,1,0,117, + 2,156,2,137,6,2,0,28,0,43,64,9,1,5,0,5,22,26,14,0,29,16,212,196,220,220,204,17,18,57,49,0,64,9,26,0,18,13,14,9, + 18,28,29,16,212,212,204,212,204,16,220,204,48,1,51,50,55,54,53,38,39,38,35,34,7,6,7,53,54,55,54,51,50,23,22,21,20,7,6,7, + 17,35,1,20,39,121,55,36,1,35,63,113,50,50,49,49,48,51,51,53,174,87,68,68,70,107,128,4,91,64,42,55,75,36,64,12,12,24,96,20, + 9,10,88,70,104,95,64,67,17,254,147,0,0,1,0,117,2,156,2,137,6,2,0,28,0,45,64,10,28,0,24,15,0,24,7,0,3,29,16,220, + 204,220,204,16,196,17,18,57,49,0,64,9,3,0,11,16,15,20,11,2,29,16,212,212,204,212,204,16,220,204,48,1,17,35,17,38,39,38,53,52, + 55,54,51,50,23,22,23,21,38,39,38,35,34,7,6,7,20,23,22,51,1,234,127,107,71,68,69,87,173,53,51,51,48,49,50,49,50,113,62,36, + 1,37,54,121,4,91,254,65,1,109,17,67,64,95,104,70,88,10,9,20,96,24,12,12,64,36,75,55,42,64,0,0,0,1,1,11,4,50,2,245, + 6,176,0,6,0,0,1,37,21,13,1,21,37,1,11,1,234,254,153,1,103,254,22,5,187,245,139,180,180,139,245,0,0,1,1,11,4,50,2,245, + 6,176,0,6,0,0,1,5,53,45,1,53,5,2,245,254,22,1,103,254,153,1,234,5,39,245,139,180,180,139,245,0,0,1,0,193,4,124,3,63, + 6,102,0,6,0,61,180,4,2,117,6,7,16,220,236,57,49,0,181,4,5,2,0,179,7,16,244,204,50,180,16,2,16,5,2,93,57,48,0,75, + 176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,1,51,19,35,11,1,35,1,182,148,245,139,180, + 180,139,6,102,254,22,1,103,254,153,0,0,0,1,0,193,4,124,3,63,6,102,0,6,0,76,180,3,5,117,1,7,16,220,236,57,49,0,181,3, + 0,4,1,179,7,16,244,60,212,178,16,0,1,93,57,48,0,75,176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7,0,7,0,64, + 56,17,55,56,89,64,12,53,0,58,6,53,2,58,4,4,51,3,1,93,1,93,1,3,51,27,1,51,3,1,182,245,139,180,180,139,245,4,124,1, + 234,254,153,1,103,254,22,0,0,1,0,193,4,238,3,63,6,102,0,6,0,55,64,12,4,5,2,180,0,179,7,4,2,117,6,7,16,220,236,57, + 49,0,16,244,236,50,57,48,0,75,176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,1,51,19, + 35,39,7,35,1,182,148,245,139,180,180,139,6,102,254,136,245,245,0,0,0,1,0,193,4,238,3,63,6,102,0,6,0,55,64,12,3,0,180,4, + 1,179,7,3,5,117,1,7,16,220,236,57,49,0,16,244,60,236,57,48,0,75,176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7, + 0,7,0,64,56,17,55,56,89,1,3,51,23,55,51,3,1,182,245,139,180,180,139,245,4,238,1,120,245,245,254,136,0,1,0,214,3,231,1,94, + 6,18,0,3,0,19,64,4,5,0,3,4,16,220,220,204,49,0,64,2,3,2,47,196,48,1,17,35,17,1,94,136,6,18,253,213,2,43,0,0, + 255,255,0,213,5,98,3,43,5,246,16,6,0,113,0,0,0,1,1,115,4,238,3,82,6,102,0,3,0,0,1,51,1,35,2,139,199,254,186,153, + 6,102,254,136,0,1,0,170,4,240,2,137,6,102,0,3,0,0,9,1,35,1,1,111,1,26,153,254,186,6,102,254,138,1,118,0,0,1,0,214, + 254,209,1,94,0,252,0,3,0,19,64,4,5,0,3,4,16,220,220,204,49,0,64,2,3,2,47,196,48,37,17,35,17,1,94,136,252,253,213,2, + 43,0,0,0,255,255,0,213,254,192,3,43,255,84,16,7,0,113,0,0,249,94,0,0,0,1,0,170,254,28,2,137,255,146,0,3,0,0,5,1, + 35,1,1,111,1,26,153,254,186,110,254,138,1,118,0,0,0,1,1,115,254,28,3,82,255,148,0,3,0,0,5,51,1,35,2,139,199,254,186,153, + 108,254,136,0,0,2,0,111,0,0,1,212,4,35,0,2,0,5,0,69,64,11,0,1,3,5,3,0,4,2,5,1,6,16,212,60,196,75,176,16, + 80,88,179,7,64,2,64,56,56,89,50,57,57,49,0,47,196,212,196,48,64,9,15,3,0,0,96,0,111,3,4,93,1,64,13,80,7,96,7,96, + 4,96,2,100,3,100,0,6,93,1,3,33,3,19,33,1,33,178,1,101,179,179,254,155,2,217,1,74,253,39,254,182,0,1,0,111,2,217,1,212, + 4,35,0,2,0,52,182,0,1,3,0,2,1,3,16,212,196,75,176,16,80,88,179,4,64,2,64,56,56,89,57,49,0,16,212,196,48,64,5,0, + 0,96,0,2,93,1,64,9,80,4,96,4,96,2,100,0,4,93,1,3,33,1,33,178,1,101,2,217,1,74,0,0,255,255,0,117,1,254,1,135, + 4,35,16,7,2,128,0,0,254,15,0,0,255,255,0,117,1,254,1,135,4,35,16,7,2,129,0,0,254,15,0,0,0,1,1,31,1,212,2,225, + 3,150,0,7,0,0,1,21,33,53,51,17,51,17,2,225,254,62,150,150,2,106,150,150,1,44,254,212,0,1,1,31,1,212,2,225,3,150,0,7, + 0,0,1,53,33,21,35,17,35,17,1,31,1,194,150,150,3,0,150,150,254,212,1,44,0,1,0,100,0,255,2,186,3,85,0,11,0,0,1,53, + 51,21,51,21,35,21,35,53,35,53,1,68,150,224,224,150,224,2,117,224,224,150,224,224,150,0,0,0,0,1,0,100,1,223,2,38,2,117,0,3, + 0,0,1,33,53,33,2,38,254,62,1,194,1,223,150,0,0,1,0,199,5,41,3,57,6,72,0,13,0,87,64,14,11,240,4,7,0,179,14,7, + 86,8,1,86,0,14,16,220,236,212,236,49,0,16,244,60,212,236,48,0,75,176,9,84,88,189,0,14,255,192,0,1,0,14,0,14,0,64,56,17, + 55,56,89,0,75,176,15,84,75,176,16,84,91,75,176,17,84,91,88,189,0,14,0,64,0,1,0,14,0,14,255,192,56,17,55,56,89,19,51,30, + 1,51,50,54,55,51,14,1,35,34,38,199,118,11,97,87,86,96,13,118,10,158,145,145,158,6,72,75,75,74,76,143,144,144,0,0,0,1,1,154, + 5,68,2,102,6,16,0,3,0,78,64,9,2,206,0,205,4,1,100,0,4,16,212,236,49,0,16,252,236,48,0,75,176,10,84,75,176,13,84,91, + 88,189,0,4,0,64,0,1,0,4,0,4,255,192,56,17,55,56,89,1,176,13,75,84,176,14,75,84,91,88,189,0,4,0,64,0,1,0,4,0, + 4,255,192,56,17,55,56,89,1,51,21,35,1,154,204,204,6,16,204,0,0,2,0,238,4,225,3,18,7,6,0,11,0,23,0,32,64,17,3,193, + 21,242,9,193,15,241,24,0,86,12,120,6,86,18,24,16,212,236,244,236,49,0,16,244,236,244,236,48,1,52,38,35,34,6,21,20,22,51,50,54, + 55,20,6,35,34,38,53,52,54,51,50,22,2,152,88,64,65,87,87,65,64,88,122,159,115,115,159,159,115,115,159,5,244,63,88,87,64,65,87,88, + 64,115,160,160,115,115,159,159,0,1,1,76,254,117,2,193,0,0,0,19,0,32,64,15,11,14,10,7,243,14,244,0,1,0,10,4,39,17,20,16, + 212,236,196,212,204,49,0,47,252,252,196,18,57,48,33,51,14,1,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,1,184,119,45,43,55, + 54,32,62,31,38,68,30,122,115,53,61,88,31,46,46,15,15,133,10,10,87,93,48,105,0,1,0,182,5,29,3,74,6,55,0,27,0,99,64,36, + 0,18,7,14,11,4,1,18,7,15,11,4,18,195,25,7,4,195,21,11,237,28,15,1,14,0,7,21,86,22,119,7,86,8,118,28,16,244,236,252, + 236,17,57,57,57,57,49,0,16,252,60,252,212,60,236,17,18,57,17,18,57,17,18,57,17,18,57,48,0,75,176,9,84,75,176,12,84,91,88,189, + 0,28,255,192,0,1,0,28,0,28,0,64,56,17,55,56,89,1,39,46,1,35,34,6,7,35,62,1,51,50,22,31,1,30,1,51,50,54,55,51, + 14,1,35,34,38,1,252,57,22,33,13,38,36,2,125,2,102,91,38,64,37,57,22,33,13,38,36,2,125,2,102,91,38,64,5,90,55,20,19,73, + 82,135,147,28,33,55,20,19,73,82,135,147,28,0,0,0,0,2,0,240,4,238,3,174,6,102,0,3,0,7,0,66,64,17,6,2,180,4,0,179, + 8,4,7,3,0,5,1,3,5,7,8,16,212,220,212,204,17,57,17,18,57,49,0,16,244,60,236,50,48,0,75,176,9,84,75,176,14,84,91,88, + 189,0,8,255,192,0,1,0,8,0,8,0,64,56,17,55,56,89,1,51,3,35,3,51,3,35,2,252,178,248,135,129,170,223,137,6,102,254,136,1, + 120,254,136,0,0,1,255,255,1,222,2,173,4,8,0,15,0,0,3,37,51,21,20,23,22,59,1,21,35,34,39,38,53,5,1,1,22,184,38,38, + 105,43,64,175,87,82,254,235,3,100,164,148,153,49,48,156,96,90,200,162,0,1,0,239,4,238,3,16,6,102,0,11,0,0,1,39,7,35,55,39, + 51,23,55,51,7,23,2,92,92,93,180,181,181,180,93,92,180,182,182,4,238,97,97,187,189,96,96,189,187,0,0,0,0,2,0,117,1,171,2,253, + 5,15,0,13,0,21,0,0,1,22,21,20,35,32,53,52,55,3,51,23,55,51,1,6,21,20,51,50,53,52,2,5,178,242,254,245,181,250,137,191, + 183,137,254,188,137,136,129,3,220,249,180,132,132,191,242,1,47,224,224,254,138,174,152,77,77,137,0,0,0,1,0,122,2,156,0,238,6,3,0,3, + 0,13,177,2,3,47,204,49,0,177,0,3,47,196,48,19,51,17,35,122,116,116,6,3,252,153,0,0,0,1,0,117,2,156,2,144,5,47,0,50, + 0,0,1,21,38,39,38,35,34,7,6,21,20,23,22,31,1,22,23,22,21,20,7,6,35,34,39,38,39,53,22,23,22,51,50,54,53,52,39,38, + 47,1,38,39,38,53,52,55,54,51,50,23,22,2,106,49,53,52,57,87,43,43,31,31,93,40,125,50,52,78,77,136,57,62,61,68,64,63,62,61, + 82,88,32,28,111,40,108,48,48,71,70,130,64,57,57,5,13,97,22,11,11,23,24,47,36,20,21,18,8,24,42,43,77,87,51,51,10,10,19,107, + 30,15,15,50,45,42,23,20,23,8,21,41,42,73,88,48,49,9,8,0,0,1,0,117,2,156,3,33,5,15,0,11,0,0,1,3,1,35,39,7, + 35,1,3,51,23,55,3,20,255,1,12,137,205,205,137,1,18,251,137,187,187,5,15,254,207,254,190,246,246,1,72,1,43,223,223,0,255,255,0,117, + 2,156,2,137,6,2,16,6,2,131,0,0,0,1,0,214,0,0,3,29,5,88,0,5,0,21,64,9,1,169,3,0,0,8,4,2,6,16,196,212, + 236,49,0,47,212,236,48,33,17,33,53,33,17,2,149,254,65,2,71,4,208,136,250,168,0,1,0,214,0,0,3,29,5,88,0,7,0,39,64,24, + 63,4,63,1,47,4,47,1,31,4,31,1,6,1,169,4,5,0,0,4,8,6,2,8,16,196,212,236,50,49,0,47,212,220,236,93,48,33,17,33, + 53,33,17,51,17,2,149,254,65,1,191,136,3,156,136,1,52,250,168,0,0,1,0,214,0,0,3,29,5,88,0,7,0,25,64,11,1,169,4,5, + 0,0,4,8,6,2,8,16,196,212,236,50,49,0,47,212,220,236,48,33,17,33,53,33,17,51,17,2,149,254,65,1,191,136,2,104,136,2,104,250, + 168,0,0,0,0,1,0,214,0,0,3,29,5,88,0,7,0,39,64,24,112,4,112,1,48,4,48,1,16,4,16,1,6,4,169,1,5,0,0,4, + 8,6,2,8,16,196,212,236,50,49,0,47,212,220,236,93,48,33,17,33,53,33,17,51,17,2,149,254,65,1,191,136,1,52,136,3,156,250,168,0, + 0,1,0,214,0,0,3,29,5,88,0,5,0,21,64,9,1,0,169,4,0,8,2,4,6,16,196,212,236,49,0,47,236,196,48,37,17,51,17,33, + 53,2,149,136,253,185,136,4,208,250,168,136,255,255,0,193,253,236,3,63,255,214,16,7,2,135,0,0,249,112,0,0,255,255,0,213,4,226,3,43, + 6,118,18,39,0,113,0,0,0,128,18,6,0,113,0,128,255,255,0,174,3,233,3,109,5,213,18,6,10,251,0,0,255,255,0,238,254,20,3,18, + 0,57,16,7,2,156,0,0,249,51,0,0,0,1,0,182,254,118,3,74,255,144,0,33,0,95,64,14,18,1,17,0,9,26,86,27,119,9,86,10, + 118,34,16,244,236,252,236,17,57,57,57,57,49,0,64,21,0,22,9,17,14,5,1,22,9,18,14,5,22,195,31,9,5,195,26,14,34,16,212,60, + 252,212,60,236,17,18,57,17,18,57,17,18,57,17,18,57,48,0,75,176,9,84,88,189,0,28,255,192,0,1,0,28,0,28,0,64,56,17,55,56, + 89,1,39,38,39,38,35,34,7,6,7,35,54,55,54,51,50,22,31,1,22,23,22,51,50,55,54,55,51,6,7,6,35,34,38,1,252,57,22,17, + 16,13,38,18,18,2,125,2,51,51,91,38,64,37,57,22,17,16,13,38,18,18,2,125,2,51,51,91,38,64,254,179,55,20,10,9,37,36,82,135, + 73,74,28,33,55,20,10,9,37,36,82,135,73,74,28,0,0,2,252,168,4,123,254,135,6,102,0,3,0,4,0,54,64,12,1,180,0,179,4,184, + 5,4,3,68,1,5,16,220,236,57,49,0,16,228,244,236,48,0,75,176,9,84,75,176,14,84,91,88,189,0,4,255,192,0,1,0,4,0,4,0, + 64,56,17,55,56,89,9,1,35,9,1,253,109,1,26,153,254,186,1,88,6,102,254,138,1,118,254,21,0,2,253,113,4,123,255,80,6,102,0,3, + 0,4,0,54,64,12,2,180,0,179,4,184,5,4,3,68,1,5,16,212,236,57,49,0,16,228,244,236,48,0,75,176,9,84,75,176,14,84,91,88, + 189,0,4,255,192,0,1,0,4,0,4,0,64,56,17,55,56,89,1,51,1,35,23,254,137,199,254,186,153,143,6,102,254,136,115,0,0,2,252,193, + 4,123,255,63,6,102,0,6,0,7,0,60,64,15,4,5,2,180,0,179,7,184,8,7,4,2,117,6,8,16,220,236,57,57,49,0,16,228,244,236, + 50,57,48,0,75,176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,1,51,19,35,39,7,35,5, + 253,182,148,245,139,180,180,139,1,63,6,102,254,136,245,245,115,0,0,0,255,255,252,180,5,29,255,72,6,55,16,7,2,158,251,254,0,0,0,0, + 255,255,252,217,5,98,255,47,5,246,16,7,0,113,252,4,0,0,0,0,255,255,251,236,5,124,0,20,6,11,16,7,11,28,252,0,0,0,0,0, + 255,255,252,191,5,41,255,49,6,72,16,7,2,154,251,248,0,0,0,0,0,2,253,162,4,123,254,90,6,20,0,3,0,4,0,37,64,12,2,190, + 0,177,4,184,5,4,1,8,0,5,16,212,236,57,49,0,16,228,252,236,48,0,1,64,7,4,4,52,4,68,4,3,93,1,51,21,35,23,253,162, + 184,184,94,6,20,233,176,0,0,3,252,215,4,123,255,41,6,16,0,3,0,7,0,8,0,73,64,17,6,2,206,4,0,205,8,184,9,1,100,8, + 0,5,100,4,9,16,220,252,212,57,236,49,0,16,228,252,60,236,50,48,1,64,35,4,8,52,8,68,8,96,1,96,2,96,3,96,0,96,1,96, + 2,96,5,96,6,96,8,112,1,112,2,112,5,112,6,112,8,17,93,1,51,21,35,37,51,21,35,5,254,94,203,203,254,121,203,203,1,41,6,16, + 202,202,202,203,0,1,253,55,4,242,254,247,6,123,0,25,0,34,64,9,20,86,64,5,128,12,86,25,13,47,204,236,26,220,26,236,49,0,64,6, + 23,193,64,2,192,13,47,26,220,26,236,48,1,54,51,50,22,21,20,15,1,6,7,6,21,35,53,52,54,63,1,54,53,52,38,35,34,7,253,55, + 112,105,104,127,88,44,35,4,7,119,30,51,45,46,62,71,90,100,6,72,51,85,67,61,65,32,26,9,16,32,12,40,54,37,34,34,40,21,36,52, + 255,255,252,236,4,225,255,16,7,6,16,7,2,156,251,254,0,0,0,0,255,255,252,244,4,238,255,178,6,102,16,7,2,159,252,4,0,0,0,0, + 0,2,252,197,4,123,255,67,6,102,0,6,0,7,0,60,64,15,3,0,180,4,1,179,7,184,8,7,3,5,117,1,8,16,220,236,57,57,49,0, + 16,228,244,60,236,57,48,0,75,176,9,84,75,176,14,84,91,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,1,3,51,23, + 55,51,3,7,253,186,245,139,180,180,139,245,78,4,238,1,120,245,245,254,136,115,0,0,0,1,253,188,4,236,254,68,6,168,0,3,0,14,178,2, + 27,0,47,236,49,0,177,3,1,47,204,48,1,17,35,17,254,68,136,6,168,254,68,1,188,0,0,0,255,255,252,240,4,236,255,16,6,168,16,39, + 2,190,255,52,0,0,16,7,2,190,0,204,0,0,0,0,0,2,252,93,4,238,255,27,6,102,0,3,0,7,0,66,64,17,6,2,180,4,0,179, + 8,4,5,1,0,7,3,1,7,5,8,16,212,220,212,204,17,57,17,18,57,49,0,16,244,60,236,50,48,0,75,176,9,84,75,176,14,84,91,88, + 189,0,8,255,192,0,1,0,8,0,8,0,64,56,17,55,56,89,1,19,35,3,33,19,35,3,253,15,205,135,248,2,0,190,137,223,6,102,254,136, + 1,120,254,136,1,120,0,0,255,255,252,191,5,41,255,49,7,86,16,39,2,184,0,0,1,66,16,7,2,154,251,248,0,0,0,0,0,1,252,191, + 5,41,255,49,6,72,0,12,0,24,181,7,86,8,1,86,0,47,236,212,236,49,0,180,10,240,4,0,7,47,60,220,236,48,3,35,46,1,35,34, + 6,7,35,62,1,32,22,207,118,11,97,87,86,96,13,118,10,158,1,34,158,5,41,75,75,74,76,143,144,144,0,0,0,1,254,31,3,233,255,68, + 5,40,0,3,0,10,64,3,2,1,4,0,16,212,204,48,1,35,19,51,254,242,211,164,129,3,233,1,63,0,0,0,0,1,253,144,4,194,254,130, + 6,193,0,8,0,0,1,16,35,53,22,53,35,53,51,254,130,242,112,112,242,5,195,254,255,123,3,137,254,0,0,0,0,1,253,144,4,194,254,130, + 6,193,0,8,0,0,1,53,51,21,35,20,55,21,34,253,144,241,111,112,242,5,195,254,254,137,3,123,0,1,255,121,4,154,0,135,6,18,0,3, + 0,0,3,51,3,35,64,199,117,153,6,18,254,136,0,0,255,255,252,168,253,223,254,135,255,85,16,7,0,67,251,254,248,239,0,0,255,255,253,113, + 253,221,255,80,255,85,16,7,0,118,251,254,248,239,0,0,0,1,253,36,254,20,254,60,255,206,0,7,0,0,1,35,53,51,53,51,17,35,253,196, + 160,160,120,120,254,181,120,161,254,70,0,0,0,1,253,196,254,20,254,220,255,206,0,7,0,0,5,51,21,51,21,35,21,35,253,196,120,160,160,120, + 50,161,120,161,0,1,254,85,5,134,0,63,7,112,0,5,0,0,3,33,53,33,17,35,73,254,158,1,234,136,6,232,136,254,22,0,0,1,254,240, + 3,107,0,123,4,224,0,19,0,49,64,6,7,86,14,4,17,0,47,75,176,12,84,75,176,13,84,91,75,176,14,84,91,88,185,0,0,0,64,56, + 89,220,50,220,236,49,0,64,5,10,4,193,0,17,47,196,252,204,48,1,53,30,1,51,50,54,53,52,38,39,51,30,1,21,20,6,35,34,38,254, + 240,61,88,31,46,46,15,15,133,10,10,87,93,48,105,3,215,119,45,43,55,54,32,62,31,38,68,30,122,115,53,0,0,1,253,128,254,18,254,86, + 255,190,0,13,0,28,64,6,13,6,10,86,3,14,16,212,252,204,50,49,0,64,6,6,193,7,13,193,0,47,252,220,236,48,1,34,38,53,52,54, + 51,21,34,6,21,20,22,51,254,86,90,124,124,90,40,53,53,40,254,18,125,90,89,124,120,53,39,40,53,0,0,0,0,1,253,11,254,20,254,245, + 255,77,0,7,0,0,1,51,21,33,53,51,53,51,254,68,177,254,22,177,136,254,156,136,136,177,0,0,0,1,253,11,254,20,254,245,255,77,0,7, + 0,0,1,35,53,33,21,35,21,35,253,188,177,1,234,177,136,254,197,136,136,177,0,0,0,1,253,36,254,20,254,220,255,206,0,11,0,0,1,35, + 53,51,53,51,21,51,21,35,21,35,253,196,160,160,120,160,160,120,254,181,120,161,161,120,161,0,0,0,0,1,253,11,254,136,254,245,255,16,0,3, + 0,0,1,53,33,21,253,11,1,234,254,136,136,136,0,0,0,1,253,122,254,86,255,208,0,128,0,13,0,0,39,21,20,7,6,43,1,53,51,50, + 55,54,61,1,48,82,81,181,254,233,105,38,38,128,148,214,96,96,156,48,49,153,148,0,0,1,253,119,254,86,255,205,0,128,0,13,0,0,37,51, + 21,20,23,22,59,1,21,35,34,39,38,53,253,119,184,38,38,105,233,254,181,81,82,128,148,153,49,48,156,96,96,214,0,1,253,162,254,137,254,90, + 255,115,0,3,0,0,5,51,21,35,253,162,184,184,141,234,255,255,252,213,254,137,255,39,255,83,16,7,0,106,251,254,249,67,0,0,0,2,253,40, + 254,18,254,212,255,190,0,11,0,23,0,30,64,8,0,86,12,120,6,86,18,24,16,212,236,244,236,49,0,64,6,21,193,3,9,193,15,47,252,220, + 236,48,1,52,38,35,34,6,21,20,22,51,50,54,55,20,6,35,34,38,53,52,54,51,50,22,254,91,54,39,40,53,53,40,39,54,121,124,90,90, + 124,124,90,90,124,254,234,38,54,53,39,40,53,54,38,90,125,125,90,89,124,124,0,0,0,1,253,106,254,20,254,143,255,84,0,3,0,10,64,3, + 3,0,4,0,16,212,204,48,5,51,3,35,253,188,211,164,129,172,254,192,255,255,253,35,254,117,254,193,0,0,16,7,0,122,252,0,0,0,0,0, + 255,255,253,76,254,117,254,193,0,0,16,7,2,157,252,0,0,0,0,0,0,1,253,188,254,20,254,68,255,160,0,3,0,14,178,2,27,0,47,236, + 49,0,177,1,3,47,204,48,5,17,35,17,254,68,136,96,254,116,1,140,0,1,252,240,254,80,255,23,255,154,0,7,0,0,7,17,35,53,33,21, + 35,17,233,137,254,235,137,102,254,182,194,194,1,74,0,0,0,1,252,99,254,57,255,152,255,88,0,20,0,0,1,6,35,34,3,52,53,51,22,51, + 50,55,51,22,23,50,55,51,2,7,34,253,254,60,116,218,17,117,14,104,101,15,118,12,105,102,15,118,15,220,116,254,139,82,1,26,2,3,150,150, + 149,1,150,254,226,1,0,0,255,255,252,197,254,20,255,67,255,140,17,7,2,137,252,4,249,38,0,39,0,75,176,9,84,75,176,14,84,75,176,11, + 84,75,176,12,84,91,91,91,88,189,0,7,0,64,0,1,0,7,0,7,255,192,56,17,55,56,89,0,255,255,252,191,254,20,255,61,255,140,17,7, + 2,136,251,254,249,38,0,39,0,75,176,9,84,75,176,14,84,75,176,11,84,75,176,12,84,91,91,91,88,189,0,7,0,64,0,1,0,7,0,7, + 255,192,56,17,55,56,89,0,255,255,252,191,254,57,255,49,255,88,16,7,2,154,251,248,249,16,0,0,0,1,252,191,254,54,255,49,255,85,0,12, + 0,0,3,35,46,1,35,34,6,7,35,62,1,32,22,207,118,11,97,87,86,96,13,118,10,158,1,34,158,254,54,75,75,74,76,143,144,144,0,0, + 255,255,252,180,254,57,255,72,255,83,16,7,2,158,251,254,249,28,0,0,255,255,252,217,254,192,255,47,255,84,16,7,2,143,252,4,0,0,0,0, + 255,255,251,236,254,29,0,20,254,172,16,7,0,66,252,0,0,0,0,0,255,255,251,236,254,29,0,20,255,238,16,7,10,245,252,0,0,0,0,0, + 0,1,251,140,1,236,255,173,3,12,0,27,0,0,3,21,14,1,35,34,39,38,39,46,1,35,34,6,7,53,62,1,51,50,22,23,22,23,22,51, + 50,54,83,75,143,79,90,113,22,11,77,103,51,79,141,73,78,146,83,53,100,74,12,21,116,93,70,137,3,12,174,59,55,51,10,4,33,24,59,63, + 174,60,54,22,31,5,10,55,61,0,0,0,0,1,253,120,1,196,255,136,2,104,0,3,0,0,3,21,33,53,120,253,240,2,104,164,164,0,0,0, + 0,1,250,237,1,196,255,255,2,104,0,3,0,0,1,53,33,21,250,237,5,18,1,196,164,164,0,0,0,1,251,104,255,162,255,188,4,188,0,3, + 0,0,5,39,1,23,251,200,96,3,245,95,94,78,4,204,79,0,0,0,0,1,250,18,255,186,255,145,6,23,0,3,0,0,5,39,1,23,250,121, + 103,5,25,102,70,88,6,5,89,0,0,0,0,1,253,172,254,18,254,130,255,190,0,13,0,28,64,6,13,6,10,86,3,14,16,212,252,204,50,49, + 0,64,6,0,193,13,7,193,6,47,252,220,236,48,5,50,22,21,20,6,35,53,50,54,53,52,38,35,253,172,90,124,124,90,40,53,53,40,66,125, + 90,89,124,120,53,39,40,53,0,1,252,241,254,91,255,24,255,165,0,7,0,0,1,17,51,21,33,53,51,17,252,241,137,1,21,137,254,91,1,74, + 194,194,254,182,0,2,253,33,254,20,254,227,255,214,0,3,0,7,0,0,5,17,33,17,1,53,35,21,254,227,254,62,1,74,210,42,254,62,1,194, + 254,182,210,210,0,1,252,99,254,57,255,152,255,88,0,20,0,0,5,54,51,50,19,20,21,35,38,35,34,7,35,38,39,34,7,35,18,55,50,253, + 254,59,116,218,17,118,13,103,102,16,118,11,105,102,15,118,15,220,116,250,82,254,230,2,3,150,150,149,1,150,1,30,1,0,0,0,0,1,253,43, + 4,243,254,229,6,173,0,11,0,0,1,7,39,55,39,55,23,55,23,7,23,7,254,8,125,96,125,125,96,125,125,96,125,125,96,5,112,125,96,125, + 125,96,125,125,96,125,125,96,0,1,254,6,4,194,255,32,6,210,0,29,0,0,1,46,1,53,52,54,55,21,14,1,21,20,23,22,31,1,30,1, + 21,20,6,7,53,62,1,53,52,39,38,39,254,67,33,28,147,135,82,73,9,12,18,55,33,28,147,135,82,73,9,12,18,5,199,28,48,28,80,81, + 2,110,2,27,28,10,12,15,14,43,28,48,28,80,81,2,110,2,27,28,10,12,15,14,255,255,251,236,4,58,0,20,6,11,16,39,11,28,252,0, + 0,0,16,7,11,28,252,0,254,190,0,0,255,255,252,168,4,240,254,135,6,102,16,7,0,67,251,254,0,0,0,0,255,255,253,113,4,238,255,80, + 6,102,16,7,0,118,251,254,0,0,0,0,255,255,252,180,5,29,255,72,6,55,16,7,2,158,251,254,0,0,0,0,255,255,253,144,4,194,254,130, + 6,193,16,6,2,196,0,0,255,255,252,231,5,70,255,98,7,210,16,7,3,28,252,16,0,0,0,0,255,255,253,198,254,86,254,162,255,164,16,7, + 3,22,252,16,0,0,0,0,0,1,252,213,5,29,255,43,6,73,0,7,0,0,3,35,53,33,21,35,17,33,213,150,254,214,150,2,86,5,29,150, + 150,1,44,0,0,2,253,31,254,50,254,225,255,184,0,3,0,7,0,0,1,33,53,33,53,33,53,33,254,225,254,62,1,194,254,62,1,194,254,50, + 120,150,120,0,0,2,253,21,254,20,254,235,255,160,0,3,0,7,0,0,5,51,17,35,1,51,17,35,253,21,150,150,1,64,150,150,96,254,116,1, + 140,254,116,0,0,1,253,31,254,20,254,225,255,214,0,5,0,0,5,33,17,35,17,33,253,31,1,194,150,254,212,42,254,62,1,44,0,1,252,182, + 4,238,255,74,6,102,0,39,0,0,1,55,51,7,22,23,22,51,50,55,54,55,51,6,7,6,35,34,39,38,39,7,35,55,38,39,38,35,34,7, + 6,7,35,54,55,54,51,50,23,22,253,255,66,109,107,11,22,16,13,38,18,18,2,125,2,51,51,91,38,32,30,33,66,110,107,13,20,16,13,38, + 18,18,2,125,2,51,51,91,38,32,30,5,255,103,169,9,14,10,36,37,82,135,74,73,14,13,29,103,168,11,13,10,36,37,82,135,74,73,14,13, + 0,3,252,182,4,137,255,74,6,204,0,29,0,33,0,37,0,0,1,39,46,1,35,34,6,29,1,35,52,54,51,50,22,31,1,30,1,51,50,54, + 61,1,51,14,1,35,34,38,7,51,21,35,19,51,21,35,253,252,57,25,31,12,36,40,125,103,86,36,61,48,57,23,34,15,32,40,125,2,103,84, + 34,59,232,150,150,210,150,150,5,104,33,14,11,50,45,6,101,118,16,27,30,13,12,51,41,6,100,119,16,46,150,2,67,150,0,0,255,255,252,182, + 4,197,255,74,6,144,16,34,22,187,0,183,16,3,22,187,0,0,0,167,0,1,252,99,254,40,255,157,255,194,0,13,0,0,1,55,33,23,35,39, + 55,51,7,33,39,51,23,7,254,112,132,254,25,132,127,175,175,127,132,1,231,132,126,175,175,254,40,155,155,205,205,155,155,205,205,0,0,1,253,51, + 254,20,254,205,255,164,0,8,0,0,1,35,53,7,53,55,23,21,39,254,50,100,155,205,205,155,254,20,231,132,126,175,175,126,132,0,0,1,253,120, + 4,225,254,136,7,6,0,16,0,0,1,6,7,6,21,20,23,22,23,21,38,39,38,52,55,54,55,254,136,64,42,44,44,42,64,114,78,80,80,78, + 114,6,139,1,42,44,64,65,43,43,1,123,1,79,80,230,80,78,1,0,255,255,252,191,4,96,255,49,6,216,16,39,2,194,0,0,0,144,16,6, + 2,184,0,229,255,255,253,43,254,20,254,229,255,206,16,7,2,238,0,0,249,33,0,0,0,1,253,120,4,225,254,136,7,6,0,18,0,0,1,48, + 53,22,23,22,20,7,6,7,48,53,54,55,54,53,52,39,38,253,120,114,78,80,80,78,114,64,42,44,44,42,6,139,123,1,78,80,230,80,79,1, + 123,1,43,43,65,64,44,42,255,255,255,46,5,68,255,250,6,16,16,7,2,155,253,148,0,0,0,0,0,3,252,144,254,18,255,111,255,191,0,7, + 0,21,0,29,0,0,0,22,50,62,1,38,34,6,55,54,50,22,20,6,34,39,6,34,38,52,54,50,18,54,52,38,34,6,20,22,253,9,53,79, + 53,2,55,79,53,247,62,181,124,124,182,61,62,182,124,124,182,254,54,54,79,53,53,254,195,53,53,77,55,53,109,63,124,179,125,65,64,125,179,124, + 254,206,54,77,54,53,79,53,255,255,252,112,254,27,3,144,255,133,16,7,11,29,252,201,0,0,0,0,255,255,252,112,6,107,3,144,7,213,16,7, + 11,29,252,201,8,80,0,0,0,1,252,112,6,215,3,144,7,107,0,3,0,0,1,33,21,33,252,112,7,32,248,224,7,107,148,0,0,1,252,112, + 254,192,3,144,255,84,0,3,0,0,5,33,21,33,252,112,7,32,248,224,172,148,0,0,0,1,253,42,6,13,2,214,7,39,0,35,0,0,3,39, + 38,39,38,35,34,7,6,7,35,54,55,54,51,50,23,22,31,1,22,23,22,51,50,55,54,55,51,6,7,6,35,34,39,38,4,144,28,79,44,36, + 101,53,70,5,162,4,113,112,200,91,63,57,90,144,28,79,44,36,97,57,71,4,162,4,113,112,200,91,63,57,6,74,55,11,18,10,36,48,71,135, + 74,73,14,13,34,55,11,18,10,36,44,75,135,74,73,14,13,0,0,0,255,255,252,112,6,4,3,144,7,110,16,7,11,30,252,201,0,0,0,0, + 0,1,252,119,254,40,3,147,255,194,0,8,0,0,1,53,33,39,51,23,7,35,55,252,119,6,115,132,126,175,175,126,132,254,195,100,155,205,205,155, + 255,255,0,201,0,0,4,113,5,213,16,6,17,233,0,0,255,255,0,193,0,0,3,208,4,96,16,6,17,234,0,0,0,1,0,201,0,0,6,28, + 5,213,0,11,0,0,19,33,17,35,17,33,17,35,17,33,17,35,201,5,83,202,254,134,203,254,134,202,5,213,252,244,2,98,250,213,5,43,253,158, + 0,1,0,201,0,0,4,101,5,213,0,11,0,0,19,33,17,35,17,35,17,35,17,35,17,35,201,3,156,184,185,185,185,185,5,213,252,244,2,98, + 250,213,5,43,253,158,0,0,0,1,0,160,4,116,1,159,6,102,0,3,0,17,64,6,1,0,4,2,0,4,16,212,204,49,0,16,212,204,48,27, + 1,51,3,160,65,190,110,4,116,1,242,254,14,0,0,0,0,1,0,160,254,86,1,159,0,72,0,3,0,17,64,6,2,3,4,0,2,4,16,212, + 204,49,0,16,212,204,48,37,3,35,19,1,159,65,190,110,72,254,14,1,242,0,0,0,255,255,0,201,0,0,5,51,5,213,16,6,3,172,0,0, + 255,255,0,186,0,0,4,121,4,96,16,6,3,204,0,0,0,1,1,182,254,86,2,146,255,164,0,13,0,0,1,35,34,39,38,61,1,51,21,20, + 23,22,59,1,2,146,148,26,26,20,149,10,12,14,35,254,86,33,26,46,229,229,14,12,13,0,0,0,255,255,0,127,255,227,3,245,4,123,16,6, + 2,22,0,0,255,255,0,113,255,227,3,231,4,123,16,39,0,121,1,79,255,132,16,6,0,70,0,0,255,255,0,127,255,227,3,245,4,123,16,39, + 0,121,0,142,255,132,16,6,2,22,0,0,255,255,0,158,255,18,1,195,4,35,18,6,0,30,0,0,0,1,1,115,4,238,3,82,6,102,0,3, + 0,49,64,9,2,180,0,179,4,3,68,1,4,16,212,236,49,0,16,244,236,48,0,75,176,9,84,75,176,14,84,91,88,189,0,4,255,192,0,1, + 0,4,0,4,0,64,56,17,55,56,89,1,51,1,35,2,139,199,254,186,153,6,102,254,136,0,0,0,255,255,0,215,5,70,3,82,7,210,18,38, + 0,106,0,0,17,7,3,27,0,0,1,108,0,20,0,64,7,175,8,159,8,95,8,3,93,64,5,95,8,15,8,2,113,48,0,0,255,255,0,16, + 0,0,5,104,6,102,16,39,3,27,254,218,0,0,16,6,3,38,0,0,255,255,0,219,2,72,1,174,3,70,18,6,0,121,0,0,255,255,255,231, + 0,0,5,117,6,102,16,39,3,27,254,116,0,0,16,7,3,42,0,234,0,0,0,0,255,255,255,243,0,0,6,31,6,102,16,39,3,27,254,128, + 0,0,16,7,3,44,0,228,0,0,0,0,255,255,255,237,0,0,2,125,6,102,16,39,3,27,254,122,0,0,16,7,3,46,0,234,0,0,0,0, + 255,255,255,242,255,227,6,1,6,102,16,39,3,27,254,127,0,0,16,6,3,52,40,0,255,255,255,225,0,0,6,145,6,102,16,39,3,27,254,110, + 0,0,16,7,3,57,1,170,0,0,0,0,255,255,255,219,0,0,6,5,6,102,16,39,3,27,254,104,0,0,16,6,3,61,54,0,255,255,0,5, + 0,0,2,128,7,210,16,39,3,28,255,46,0,0,18,6,3,77,15,0,255,255,0,16,0,0,5,104,5,213,18,6,0,36,0,0,255,255,0,201, + 0,0,4,236,5,213,18,6,0,37,0,0,0,1,0,201,0,0,4,106,5,213,0,5,0,25,64,12,4,149,1,129,0,7,2,4,28,1,4,6, + 16,252,252,204,196,49,0,47,244,236,48,51,17,33,21,33,17,201,3,161,253,41,5,213,170,250,213,0,0,2,0,16,0,0,5,104,5,213,0,2, + 0,6,0,61,64,12,66,0,149,4,129,1,149,3,8,6,3,7,16,212,196,196,49,0,47,236,244,236,48,75,83,88,64,18,0,17,5,4,3,2, + 17,6,6,5,0,17,4,1,17,3,3,4,5,7,16,236,16,236,7,16,236,8,16,236,89,9,1,33,5,1,51,1,2,188,254,102,3,53,251,185, + 2,58,229,2,57,5,14,251,154,168,5,213,250,43,0,0,255,255,0,201,0,0,4,139,5,213,18,6,0,40,0,0,255,255,0,92,0,0,5,31, + 5,213,18,6,0,61,0,0,255,255,0,201,0,0,5,59,5,213,18,6,0,43,0,0,0,3,0,115,255,227,5,217,5,240,0,3,0,18,0,33, + 0,50,64,28,4,149,19,145,34,3,149,0,173,34,11,149,26,140,34,35,16,1,15,25,22,51,0,8,25,30,16,34,16,252,236,196,244,236,196,236, + 49,0,16,244,236,16,244,236,16,244,236,48,1,33,21,33,1,34,7,6,17,16,0,51,50,55,54,17,16,39,38,39,32,0,17,16,7,6,33,32, + 39,38,17,16,55,54,1,197,2,194,253,62,1,98,220,129,130,1,3,220,220,129,128,128,129,220,1,58,1,120,188,188,254,198,254,197,188,189,189,188, + 3,112,170,2,134,164,164,254,229,254,230,254,184,164,164,1,26,1,27,164,164,164,254,91,254,158,254,159,210,211,210,210,1,98,1,98,211,210,0,0, + 255,255,0,201,0,0,1,147,5,213,18,6,0,44,0,0,255,255,0,201,0,0,5,106,5,213,18,6,0,46,0,0,0,1,0,16,0,0,5,104, + 5,213,0,6,0,60,64,11,66,6,149,2,129,5,1,8,4,1,7,16,212,196,196,49,0,47,60,244,236,48,75,83,88,64,18,6,17,3,2,1, + 5,17,4,4,3,6,17,2,0,17,1,1,2,5,7,16,236,16,236,7,16,236,8,16,236,89,51,35,1,51,1,35,1,229,213,2,58,229,2,57, + 210,254,38,5,213,250,43,5,14,0,0,0,255,255,0,201,0,0,6,31,5,213,18,6,0,48,0,0,255,255,0,201,0,0,5,51,5,213,18,6, + 0,49,0,0,0,3,0,201,0,0,4,98,5,213,0,3,0,7,0,11,0,42,64,22,7,149,4,129,11,3,149,0,173,8,149,11,13,4,1,9, + 5,0,8,4,4,12,16,252,60,196,212,60,196,236,49,0,47,236,244,236,16,244,236,48,1,33,21,33,3,33,21,33,17,33,21,33,1,50,2,199, + 253,57,105,3,153,252,103,3,153,252,103,3,113,170,3,14,170,251,127,170,255,255,0,115,255,227,5,217,5,240,18,6,0,50,0,0,255,255,0,201, + 0,0,5,59,5,213,18,6,3,179,0,0,255,255,0,201,0,0,4,141,5,213,18,6,0,51,0,0,0,1,0,201,0,0,4,139,5,213,0,11, + 0,70,64,17,66,10,6,149,7,129,0,4,149,3,13,1,8,4,7,4,12,16,252,60,212,60,204,49,0,47,236,50,244,236,50,48,75,83,88,64, + 18,11,17,5,5,4,10,17,6,6,5,11,17,5,0,17,4,5,4,5,7,16,236,16,236,7,16,236,8,16,236,89,37,33,21,33,53,9,1,53, + 33,21,33,1,1,177,2,218,252,62,1,223,254,33,3,176,253,56,1,223,170,170,170,2,112,2,17,170,170,253,243,0,255,255,255,250,0,0,4,233, + 5,213,18,6,0,55,0,0,255,255,255,252,0,0,4,231,5,213,18,6,0,60,0,0,0,3,0,115,0,0,5,217,5,213,0,8,0,17,0,39, + 0,60,64,16,41,13,25,33,18,26,0,28,37,29,17,4,25,22,16,40,16,252,236,212,60,60,252,60,60,212,236,196,49,0,64,14,17,0,149,29, + 26,27,129,39,9,8,149,37,18,39,47,212,60,252,60,16,244,212,60,252,60,48,1,6,7,6,21,20,23,22,23,51,54,55,54,53,52,39,38,39, + 3,38,39,38,17,16,55,54,55,53,51,21,22,23,22,17,16,7,6,7,21,35,2,194,150,98,130,130,98,150,202,150,98,128,128,98,150,202,244,158, + 189,189,157,245,202,244,157,188,188,157,244,202,4,142,21,87,115,198,197,115,87,21,21,87,115,197,198,115,87,21,252,16,22,134,160,1,15,1,15,161, + 135,22,159,159,23,134,161,254,241,254,242,161,134,23,157,0,255,255,0,61,0,0,5,59,5,213,18,6,0,59,0,0,0,1,0,115,0,0,5,219, + 5,213,0,29,0,46,64,23,16,13,149,27,2,21,14,7,129,0,31,21,28,22,2,14,28,27,15,8,28,7,30,16,220,236,212,60,252,60,212,236, + 204,49,0,47,228,50,50,220,60,236,50,48,33,54,39,34,39,38,3,17,51,17,16,23,22,23,17,51,17,54,55,54,25,1,51,17,2,7,6,35, + 6,23,2,194,1,1,214,188,184,5,213,130,110,138,202,138,110,130,213,5,184,188,214,1,1,134,176,210,204,1,104,1,153,254,103,254,230,164,140,14, + 3,241,252,15,14,140,164,1,26,1,153,254,103,254,152,204,210,72,238,0,0,1,0,78,0,0,5,207,5,231,0,38,0,51,64,27,11,149,30,145, + 38,3,18,21,149,2,20,3,7,25,40,16,0,34,51,26,18,14,25,21,26,16,39,16,252,196,252,196,16,244,196,236,252,196,49,0,47,60,236,50, + 50,50,244,236,48,37,21,33,53,54,55,54,53,52,39,38,35,34,0,21,20,23,22,23,21,33,53,33,38,39,38,53,16,55,54,33,32,23,22,17, + 20,7,6,7,5,207,253,168,177,99,99,132,132,216,216,254,247,99,100,178,253,168,1,63,158,73,72,192,191,1,49,1,47,193,192,71,71,161,178,178, + 178,97,166,166,202,240,145,145,254,221,239,202,166,166,97,178,178,139,149,149,184,1,62,197,197,197,196,254,203,194,148,148,141,0,0,0,255,255,0,6, + 0,0,2,88,7,78,16,39,22,185,3,47,1,117,19,6,3,46,0,0,0,8,180,9,3,6,8,7,43,49,0,0,255,255,255,252,0,0,4,231, + 7,78,16,39,22,185,4,113,1,117,19,6,3,57,0,0,0,8,180,12,2,7,8,7,43,49,0,0,255,255,0,113,255,231,4,228,6,102,18,38, + 3,69,0,0,16,6,3,27,110,0,0,0,255,255,0,133,255,227,3,200,6,102,16,38,3,27,80,0,18,6,3,73,0,0,0,0,255,255,0,186, + 254,86,4,100,6,102,16,39,3,27,0,198,0,0,18,6,3,75,0,0,255,255,0,166,0,0,2,152,6,102,18,38,3,77,0,0,16,7,3,27, + 255,70,0,0,255,255,0,149,255,227,4,42,7,210,18,38,3,89,0,0,16,6,3,28,27,0,0,0,0,2,0,113,255,231,4,228,4,121,0,13, + 0,42,0,200,64,11,18,17,7,44,16,23,7,18,37,69,43,16,252,236,212,196,196,18,57,57,64,10,63,16,47,16,31,16,3,143,16,1,93,113, + 0,64,17,18,17,11,3,185,41,184,25,11,185,33,140,15,188,22,135,25,47,236,228,244,236,16,244,236,17,57,57,5,64,20,29,17,0,17,14,17, + 18,17,17,16,15,17,14,17,0,17,29,17,17,16,7,16,60,236,236,236,8,7,16,60,236,236,49,48,1,64,11,132,18,134,17,136,1,137,13,128, + 16,5,93,64,19,73,19,73,18,73,28,74,29,78,13,76,0,78,1,73,14,75,17,9,93,64,17,58,14,57,18,58,17,56,29,56,17,63,13,60, + 0,62,1,8,93,64,11,43,13,43,1,42,0,41,14,41,17,5,93,64,13,25,15,24,14,27,13,27,1,26,0,25,17,6,93,0,64,5,43,30, + 43,31,2,93,1,39,38,35,34,7,6,21,20,23,22,51,50,55,27,1,51,3,23,22,23,22,59,1,21,35,34,39,38,39,6,7,6,35,34,39, + 38,17,16,55,54,51,32,3,78,44,45,178,134,61,77,75,76,121,134,72,164,99,164,205,40,9,35,41,32,88,110,94,84,41,17,46,94,44,143,235, + 114,117,127,141,198,1,55,2,9,231,237,110,138,182,220,105,107,213,1,231,1,37,253,161,219,49,41,48,156,84,42,88,111,87,41,152,157,1,19,1, + 38,138,154,0,0,2,0,192,254,86,4,136,6,33,0,14,0,28,0,55,64,15,24,18,7,30,69,19,18,11,22,0,28,8,3,70,29,16,252,236, + 50,196,212,236,228,212,236,49,0,64,14,26,185,5,9,21,185,22,17,185,13,140,2,189,29,16,236,244,236,212,252,57,212,236,48,37,17,35,17,16, + 33,32,17,16,7,4,17,16,33,34,3,22,51,32,17,16,5,53,32,17,52,35,32,17,1,121,185,1,170,1,178,172,1,24,254,30,212,89,111,197, + 1,32,254,48,1,107,234,254,251,69,254,17,6,3,1,200,254,127,254,238,100,90,254,245,254,38,1,74,173,1,58,1,26,22,170,1,64,219,254,200, + 0,1,0,32,254,86,4,127,4,96,0,14,0,64,64,7,16,3,7,8,4,12,15,16,212,212,252,212,196,49,0,64,7,2,12,191,6,189,4,7, + 47,60,236,228,50,48,5,64,18,1,17,8,7,2,17,3,4,3,14,13,1,17,0,17,7,8,7,7,16,236,236,57,57,7,16,236,8,236,1,19, + 1,51,1,17,35,17,1,38,43,1,53,51,50,1,105,245,1,94,195,254,59,184,254,218,44,95,49,70,197,3,176,253,76,3,100,251,160,254,86,1, + 170,3,68,126,158,0,0,0,0,2,0,113,255,227,4,117,5,240,0,28,0,45,0,84,64,20,6,5,40,4,47,69,28,40,18,10,81,18,4,18, + 24,33,18,18,69,46,16,252,236,212,236,16,244,178,127,10,1,93,236,196,236,17,18,57,57,0,64,14,6,5,37,2,28,0,2,185,26,37,185,14, + 140,46,16,244,236,212,252,212,204,17,18,57,57,64,6,22,29,83,5,6,5,7,14,16,236,57,49,48,1,38,35,34,21,20,5,22,23,22,17,16, + 7,6,35,34,39,38,17,52,55,54,55,38,53,16,33,50,23,1,6,7,6,21,20,23,22,51,50,54,53,52,39,38,39,38,3,236,102,239,253,1, + 8,208,117,142,137,137,240,239,138,137,137,53,75,156,1,185,221,120,254,24,68,55,86,85,86,149,147,172,91,97,126,64,5,17,70,117,92,48,37,112, + 135,254,235,254,247,156,157,157,156,1,19,204,165,64,36,79,141,1,16,70,254,40,29,73,113,204,203,114,115,232,190,199,96,103,11,6,0,1,0,133, + 255,227,3,200,4,124,0,50,0,61,64,34,12,134,11,136,16,185,8,184,51,27,169,24,51,39,134,40,136,35,185,44,140,51,52,25,11,39,20,8, + 4,31,8,48,69,51,16,252,236,212,236,212,196,196,196,49,0,16,244,236,244,236,16,212,236,16,244,236,244,236,48,1,38,39,38,53,52,55,54,51, + 50,22,23,21,38,39,38,35,34,7,6,21,20,23,22,59,1,21,35,34,7,6,21,20,23,22,51,50,55,54,55,21,6,7,6,35,34,39,38,53, + 52,54,1,139,112,60,60,114,113,196,76,170,98,97,80,81,71,119,69,70,68,67,116,155,148,137,72,78,84,85,151,93,85,85,71,90,84,85,80,238, + 129,129,138,2,92,24,65,64,93,141,79,78,24,24,167,29,13,13,46,46,64,70,45,44,152,51,56,88,90,56,56,18,19,37,171,28,14,14,91,91, + 173,108,146,0,0,1,0,107,254,82,3,248,6,20,0,29,0,62,64,11,10,14,18,31,4,25,24,28,18,20,30,16,212,236,212,212,212,196,252,204, + 75,176,16,81,88,185,0,22,0,64,56,89,49,0,64,14,8,185,10,0,185,18,140,30,26,23,135,24,151,30,16,244,236,50,16,244,236,220,236,48, + 37,22,23,22,21,20,7,6,35,52,53,22,55,54,53,52,39,38,35,32,3,16,1,33,53,33,21,0,17,16,2,202,132,79,84,74,80,163,69,42, + 32,32,31,58,253,162,1,2,59,253,236,3,102,253,44,127,1,75,79,120,115,80,87,75,76,5,44,35,37,53,44,42,2,51,1,236,1,89,185,185, + 254,148,254,39,254,105,0,0,0,1,0,186,254,86,4,100,4,123,0,21,0,49,64,22,6,135,14,18,184,12,188,2,189,11,23,70,3,8,0,78, + 9,13,8,12,70,22,16,252,236,50,244,236,236,49,0,47,236,228,244,196,236,48,64,5,160,23,128,23,2,1,93,1,17,35,17,52,38,35,34,6, + 21,17,35,17,51,21,54,55,54,51,50,23,22,4,100,184,124,124,149,172,185,185,66,89,90,117,193,99,99,2,164,251,178,4,72,159,158,190,164,253, + 135,4,96,174,101,50,50,119,120,0,0,0,0,3,0,113,255,233,4,117,6,36,0,8,0,17,0,33,0,79,64,27,13,185,18,151,34,1,149,17, + 34,5,185,26,140,34,35,69,0,9,18,22,81,1,17,18,30,69,34,16,252,236,50,244,178,127,22,1,93,236,50,236,49,0,16,244,236,16,212,64, + 7,63,17,31,17,15,17,3,93,236,16,244,236,48,64,11,25,6,22,4,119,4,160,35,128,35,5,1,93,1,33,18,23,22,51,50,55,54,19,2, + 39,38,35,34,7,6,3,1,50,23,22,17,16,7,6,35,34,39,38,17,16,55,54,3,177,253,131,15,69,86,149,150,83,73,9,28,54,86,147,153, + 81,64,19,1,61,240,137,137,137,137,240,241,136,137,137,136,2,198,254,213,127,156,157,138,1,201,1,28,100,158,156,126,254,252,2,180,212,211,254,138, + 254,139,212,213,213,212,1,117,1,118,211,212,0,1,0,166,0,0,2,110,4,96,0,13,0,27,64,7,15,6,0,8,13,70,14,16,252,252,212,196, + 49,0,64,5,13,188,5,135,8,47,236,228,48,1,17,20,23,22,59,1,21,35,34,39,38,53,3,1,99,34,36,108,89,111,180,82,82,1,4,96, + 253,43,145,46,48,156,96,98,212,2,202,0,0,1,0,191,0,0,4,133,4,96,0,11,0,73,64,9,13,6,4,9,1,8,11,70,12,16,252,236, + 50,196,212,196,49,0,64,5,3,0,188,7,11,47,60,228,50,48,64,22,8,17,9,4,5,7,17,6,6,5,8,5,9,4,3,17,4,2,17,9, + 9,4,7,16,4,236,16,5,236,9,60,60,7,16,5,236,16,8,236,19,51,17,1,51,9,1,35,1,7,17,35,191,190,1,227,224,254,71,1,254, + 225,254,98,137,190,4,96,254,47,1,209,254,90,253,70,2,66,129,254,63,0,1,0,61,0,0,4,127,6,20,0,13,0,70,64,5,15,1,11,5, + 14,16,212,196,212,196,49,0,64,6,10,135,11,151,2,5,47,60,244,236,48,64,24,3,17,1,0,6,4,17,5,6,5,7,17,6,17,3,17,1, + 0,0,2,17,0,1,0,7,16,5,236,16,9,236,236,5,236,7,16,5,236,16,8,236,9,1,35,9,1,35,1,39,38,43,1,53,23,22,2,122, + 2,5,195,254,198,254,126,195,1,235,74,47,107,96,117,226,5,101,250,155,3,60,252,196,4,50,198,126,158,2,3,0,255,255,0,174,254,86,4,229, + 4,96,16,6,0,119,0,0,0,1,0,74,0,0,4,24,4,96,0,21,0,66,64,7,23,7,18,17,0,1,22,16,212,196,212,236,196,49,64,4, + 11,1,188,0,0,47,228,50,48,64,22,20,19,18,3,17,21,17,6,5,4,3,7,3,17,1,0,0,2,17,1,1,0,7,16,5,236,16,9,236, + 18,23,57,5,236,18,23,57,33,1,51,1,54,55,54,55,54,39,38,39,51,49,22,23,22,21,20,7,6,7,1,160,254,170,198,1,33,120,100,76, + 4,2,24,28,106,186,69,46,42,136,177,123,4,96,252,84,124,172,129,112,53,100,119,131,89,124,114,78,196,175,228,116,0,1,0,107,254,82,4,1, + 6,20,0,38,0,64,64,15,10,14,18,40,4,34,29,28,32,18,24,37,18,20,39,16,212,236,212,236,212,212,196,212,196,252,204,49,64,18,8,185, + 10,0,185,18,140,39,22,35,135,34,30,27,135,28,151,39,0,16,244,252,60,212,236,57,16,244,236,220,236,48,37,22,23,22,21,20,7,6,35,52, + 53,22,55,54,53,52,39,38,35,32,17,16,37,36,17,52,55,35,53,33,21,32,17,20,5,21,36,19,18,2,218,132,79,84,74,80,163,69,42,32, + 32,31,58,253,145,1,77,254,232,220,208,3,21,253,139,2,16,253,198,2,1,127,1,75,79,120,115,80,87,75,76,5,44,35,37,53,44,42,1,181, + 1,44,88,36,1,4,197,82,185,185,254,221,191,9,170,22,254,188,254,241,255,255,0,113,255,227,4,117,4,123,18,6,0,82,0,0,0,1,0,74, + 255,217,4,152,4,96,0,23,0,47,64,11,25,10,1,18,8,3,19,8,0,22,24,16,220,196,236,212,236,196,196,204,49,64,12,7,135,14,140,21, + 3,19,23,135,0,188,21,0,47,244,236,50,50,16,244,236,48,19,33,21,35,17,20,22,51,50,54,55,21,14,1,35,34,38,53,17,33,17,35,17, + 35,74,4,49,141,49,55,15,44,7,35,74,37,120,92,254,99,188,143,4,96,184,253,80,72,63,5,1,133,13,12,131,176,2,156,252,88,3,168,0, + 0,2,0,186,254,86,4,164,4,123,0,17,0,29,0,49,64,25,21,185,4,184,30,27,185,10,140,15,189,30,31,69,18,18,7,81,13,8,24,18, + 16,70,30,16,252,236,236,244,178,127,7,1,93,236,236,49,0,16,236,244,236,16,244,236,48,1,54,55,54,51,50,0,17,16,2,35,34,38,39,17, + 35,17,52,5,52,38,35,34,6,21,20,22,51,50,54,1,20,61,151,59,182,204,0,255,255,204,123,177,58,185,3,43,167,146,146,167,167,146,146,167, + 3,152,102,90,35,254,188,254,248,254,248,254,188,97,100,253,174,3,207,231,221,203,231,231,203,203,231,231,0,1,0,113,254,82,3,231,4,123,0,36, + 0,54,64,12,29,33,18,23,38,9,72,16,18,3,69,37,16,252,236,244,204,212,252,196,49,64,17,27,185,29,19,185,0,140,37,9,134,10,136,13, + 185,6,184,37,0,16,244,252,244,236,16,244,236,220,236,48,5,32,0,17,16,0,33,50,22,23,21,46,1,35,34,6,21,20,22,51,50,23,22,21, + 20,7,6,35,52,53,22,55,54,53,52,39,38,2,168,254,243,254,214,1,45,1,6,85,162,76,78,157,80,179,198,198,175,131,80,84,74,80,163,69, + 42,32,32,31,29,1,62,1,14,1,18,1,58,35,35,172,43,43,227,205,205,227,76,79,120,115,80,87,75,76,5,44,35,37,53,44,42,0,0,0, + 0,2,0,113,255,227,4,214,4,96,0,13,0,30,0,49,64,11,32,15,10,18,19,81,4,18,27,69,31,16,252,236,244,178,127,19,1,93,236,212, + 196,49,64,12,7,185,23,140,31,17,135,0,185,14,188,31,0,16,244,236,236,16,244,236,48,1,34,7,6,21,20,22,51,50,54,53,52,39,38,39, + 33,21,35,22,21,16,7,6,35,34,39,38,17,16,55,54,2,115,152,82,86,171,149,147,172,86,79,154,2,99,206,109,137,137,240,241,136,137,137,113, + 3,206,110,115,190,201,231,232,200,183,122,110,146,184,156,221,254,237,156,157,157,156,1,19,1,21,155,129,0,1,0,100,0,0,4,109,4,96,0,17, + 0,35,64,8,19,13,3,15,8,12,10,18,16,212,196,252,196,196,196,49,0,64,8,15,11,135,12,188,2,185,5,47,236,244,236,50,48,37,22,59, + 1,21,35,34,39,38,53,17,33,53,33,21,33,17,20,2,230,36,108,89,111,180,82,82,254,92,4,9,254,87,204,48,156,96,98,212,2,18,184,184, + 253,227,145,0,0,1,0,149,255,227,4,42,4,96,0,28,0,43,64,10,30,69,9,18,19,0,8,28,70,29,16,252,236,212,236,228,64,7,63,30, + 63,9,63,19,3,93,49,0,64,6,13,28,188,5,185,23,47,236,244,60,48,1,17,20,23,22,51,50,55,54,55,54,39,38,39,51,49,22,23,22, + 21,20,7,6,39,34,39,38,53,3,1,82,50,55,107,150,105,59,15,8,30,28,106,186,70,45,42,128,156,254,179,101,98,1,4,96,253,43,135,64, + 69,208,118,187,102,128,119,131,90,123,115,154,253,187,228,1,120,118,197,2,202,0,0,0,0,2,0,112,254,86,4,209,4,104,0,10,0,41,0,61, + 64,16,43,69,7,18,15,19,2,8,30,22,40,35,18,26,69,42,16,252,236,212,60,204,252,60,212,236,236,49,0,64,16,0,31,185,11,30,184,42, + 3,39,135,19,22,140,21,189,42,16,236,244,60,236,50,16,244,60,236,50,48,1,34,21,17,50,55,54,53,52,39,38,39,50,23,22,17,16,7,6, + 35,17,35,17,34,39,38,17,16,55,54,55,21,6,7,6,21,20,23,22,51,17,16,3,61,65,95,95,85,86,70,54,140,127,137,137,129,203,183,199, + 134,136,136,102,166,66,58,86,86,77,112,3,203,145,253,82,104,93,223,208,112,91,157,132,141,254,217,254,241,161,152,254,110,1,145,153,156,1,19,1, + 30,146,109,28,163,23,78,115,190,202,115,103,2,175,1,46,0,1,0,59,254,85,4,100,4,97,0,23,0,174,64,12,4,16,1,13,4,9,15,20, + 15,3,9,24,16,212,60,212,60,17,18,23,57,177,25,15,16,196,49,64,19,4,16,1,13,4,21,15,8,169,15,9,188,24,20,169,21,2,189,24, + 0,16,252,60,236,16,252,60,236,17,18,23,57,48,176,37,75,83,88,64,18,0,17,17,12,17,5,3,14,0,5,14,17,15,2,17,3,3,14,7, + 5,16,236,16,236,7,8,16,236,16,236,180,13,12,17,14,3,15,180,4,5,0,14,3,15,180,16,12,17,2,15,15,180,1,15,2,0,5,15,180, + 6,7,5,5,4,7,5,17,18,57,180,23,22,17,5,4,7,5,17,18,57,180,11,10,12,17,12,7,5,17,18,57,180,18,19,17,17,12,7,5, + 17,18,57,89,5,3,1,35,1,3,38,43,1,53,23,4,23,19,1,51,1,19,22,59,1,21,39,36,2,220,149,254,205,217,1,178,182,49,154,49, + 70,1,2,65,148,1,51,217,254,78,182,49,154,49,70,254,254,250,1,127,253,208,3,24,1,215,126,158,2,7,167,254,129,2,48,252,232,254,41,126, + 158,2,7,0,0,1,0,112,254,86,4,209,4,96,0,27,0,54,64,13,29,19,8,20,25,13,8,0,12,6,8,5,28,16,220,236,212,60,252,60, + 212,236,204,49,0,64,14,19,12,5,188,28,14,11,135,25,0,140,27,189,28,16,236,244,60,236,50,16,244,60,60,48,5,38,39,38,53,17,51,17, + 20,23,22,23,17,51,17,54,55,54,53,17,51,17,20,7,6,7,17,35,2,69,231,107,131,186,85,74,124,183,131,67,85,186,131,118,220,183,25,37, + 97,119,243,2,137,253,126,183,76,66,14,3,213,252,44,14,66,84,175,2,129,253,120,252,110,99,35,254,110,0,0,0,0,1,0,135,255,227,6,39, + 4,96,0,26,0,56,64,20,18,18,19,28,69,16,18,21,11,8,12,7,18,2,5,18,4,2,69,27,16,252,220,236,16,236,212,252,212,236,236,220, + 236,49,0,64,9,11,18,4,188,14,9,135,23,0,47,60,236,50,244,60,196,48,5,32,17,52,19,51,2,21,16,51,50,17,51,16,51,50,17,52, + 3,51,18,21,16,33,32,3,2,2,38,254,97,155,198,143,222,203,170,203,222,143,198,155,254,97,254,240,33,41,29,2,82,235,1,64,254,192,240,254, + 79,2,26,253,230,1,177,240,1,64,254,192,235,253,174,1,43,254,213,0,255,255,0,5,0,0,2,125,6,16,18,38,3,77,15,0,16,7,0,106, + 255,46,0,0,255,255,0,149,255,227,4,42,6,16,16,38,0,106,29,0,18,6,3,89,0,0,0,0,255,255,0,113,255,227,4,117,6,102,16,38, + 3,27,125,0,18,6,3,83,0,0,0,0,255,255,0,149,255,227,4,42,6,102,16,38,3,27,34,0,18,6,3,89,0,0,0,0,255,255,0,135, + 255,227,6,39,6,102,18,38,3,93,0,0,16,7,3,27,1,89,0,0,0,1,0,201,254,86,5,106,5,213,0,12,0,0,19,51,17,1,33,9, + 2,35,9,1,17,35,201,202,2,158,1,4,253,27,3,26,254,146,134,1,16,253,13,202,5,213,253,137,2,119,253,72,252,227,254,86,1,132,2,245, + 253,49,0,0,0,3,0,167,255,233,4,77,6,36,0,10,0,27,0,39,0,71,64,14,5,28,26,41,69,38,28,13,0,30,28,20,70,40,16,252, + 236,50,212,236,236,212,178,63,26,1,93,236,49,0,64,16,28,11,0,185,30,40,34,185,17,140,40,7,185,23,151,40,16,244,236,16,244,236,16,212, + 182,63,30,31,30,15,30,3,93,236,57,57,48,1,50,54,55,54,53,54,35,34,7,6,1,22,21,20,7,6,32,39,38,2,55,54,23,30,1,18, + 6,7,6,35,16,23,22,51,50,55,62,1,38,1,105,80,203,68,121,1,204,122,93,54,1,238,246,59,126,254,14,139,111,2,120,134,210,164,218,2, + 93,251,89,223,58,80,174,143,87,24,1,173,3,112,4,61,108,147,222,186,108,254,199,167,233,130,95,213,213,168,3,44,190,213,1,1,226,254,229,182, + 150,20,254,234,128,176,156,45,209,158,0,0,0,2,0,113,255,233,4,117,6,36,0,10,0,31,0,55,64,15,11,0,8,33,69,21,7,8,15,21, + 26,8,25,69,32,16,252,236,204,220,236,16,236,252,60,49,0,64,14,4,135,18,151,32,0,135,11,29,135,22,140,26,32,16,204,244,236,220,236,16, + 244,236,48,1,52,39,38,35,34,6,21,20,23,22,5,32,39,38,17,52,54,51,50,18,16,0,32,0,17,23,21,16,18,32,18,3,174,49,66,149, + 83,120,121,74,1,19,254,204,131,211,208,175,218,245,254,228,254,35,254,245,188,176,1,47,165,3,112,246,126,170,137,90,170,90,55,170,65,105,1,54, + 160,222,254,100,252,252,254,101,1,182,1,210,1,160,254,243,254,189,1,66,0,1,0,87,0,0,5,81,5,223,0,32,0,73,64,9,34,0,27,20, + 4,28,15,7,33,16,220,204,252,57,220,196,180,63,0,64,27,2,93,204,49,0,64,17,7,4,20,5,14,149,15,31,0,149,13,149,20,24,17,145, + 5,47,244,60,204,236,236,204,212,236,17,18,57,57,64,9,111,31,127,31,143,31,207,31,4,93,48,1,6,3,6,21,17,35,17,52,39,2,39,38, + 34,7,53,54,50,23,4,19,18,37,54,50,23,22,21,20,7,6,35,34,4,70,160,82,42,203,42,82,160,77,119,40,31,111,85,1,67,72,107,1, + 31,38,95,42,83,17,25,75,133,5,17,72,254,243,141,165,253,118,2,138,165,141,1,13,72,35,9,170,10,13,48,254,114,1,123,67,9,32,64,91, + 41,47,66,0,255,255,255,225,0,0,6,161,6,102,16,39,3,27,254,110,0,0,16,7,3,102,1,80,0,0,0,0,255,255,0,87,0,0,5,81, + 7,78,16,39,22,185,4,197,1,117,18,6,3,102,0,0,0,3,0,112,254,86,4,209,6,20,0,21,0,30,0,39,0,65,64,16,41,26,18,6, + 9,1,30,8,12,20,32,36,18,16,69,40,16,252,236,212,60,60,252,60,60,212,236,196,49,64,18,30,32,135,1,20,184,40,22,31,135,9,12,140, + 21,151,11,189,40,0,16,236,228,244,60,252,60,16,244,60,252,60,48,1,17,50,23,22,17,16,7,6,35,17,35,17,34,39,38,17,16,55,54,51, + 17,19,50,55,54,55,54,39,38,35,3,17,34,7,6,23,22,23,22,2,252,199,133,137,137,133,199,183,199,134,136,136,134,199,183,113,77,84,1,1, + 86,77,113,183,113,76,87,1,1,85,76,6,20,254,99,153,156,254,237,254,237,156,153,254,111,1,145,153,156,1,19,1,19,156,153,1,157,250,119,103, + 115,202,200,117,103,252,184,3,72,103,117,200,202,115,103,0,0,2,0,65,255,227,6,109,4,96,0,16,0,30,0,69,64,22,4,17,18,16,4,6, + 14,32,69,3,29,18,6,24,8,25,20,18,1,14,69,31,16,252,196,236,212,252,212,236,196,236,17,18,23,57,49,0,64,15,24,16,17,3,135,1, + 188,31,27,22,135,8,12,140,31,16,244,60,236,50,16,244,236,50,50,204,48,19,53,33,21,35,22,21,16,37,36,3,2,33,32,17,52,55,41,1, + 6,21,16,51,50,3,51,2,55,54,17,52,65,6,44,147,77,254,97,254,241,34,41,254,248,254,97,77,4,58,252,146,71,222,207,4,170,4,207,222, + 3,168,184,184,207,164,253,173,1,1,1,42,254,213,2,82,164,207,209,167,254,79,2,26,253,227,3,3,1,174,167,0,0,1,0,112,254,91,4,205, + 4,103,0,57,0,0,5,38,39,38,52,55,7,2,7,6,35,34,53,52,1,54,53,52,39,38,35,34,7,53,54,51,50,23,4,17,20,7,55,18, + 55,54,51,50,21,20,1,6,21,20,23,22,51,50,55,2,7,6,34,39,53,22,51,50,3,249,246,33,10,13,189,96,200,55,34,55,1,36,62,14, + 26,142,57,91,64,91,26,27,1,29,29,189,96,200,55,34,55,254,220,62,14,26,142,57,91,38,205,70,162,93,95,73,164,10,32,240,73,129,53,108, + 254,247,124,34,79,154,1,9,138,122,58,54,104,108,224,48,4,39,254,195,91,77,108,1,9,124,34,79,154,254,247,138,122,58,54,104,108,253,224,102, + 36,49,160,49,0,2,0,115,254,88,5,217,5,240,0,17,0,31,0,68,64,14,33,16,29,25,14,10,0,28,3,22,25,7,16,32,16,252,236,220, + 182,0,3,16,3,48,3,3,93,252,57,220,182,0,14,16,14,48,14,3,93,236,236,49,0,64,12,19,149,10,145,32,26,149,0,3,1,189,32,16, + 236,212,60,236,16,244,236,48,5,17,35,17,38,39,38,16,55,54,33,32,23,22,17,16,7,6,2,32,7,6,17,16,23,22,32,55,54,17,16,39, + 3,132,184,252,160,189,189,188,1,59,1,58,188,188,188,159,123,254,72,129,130,130,129,1,184,129,128,128,24,254,112,1,144,26,179,210,2,196,211,210, + 210,211,254,158,254,159,210,179,5,73,164,164,254,229,254,230,164,164,164,164,1,26,1,27,164,0,0,0,0,2,0,113,254,86,4,117,4,123,0,13, + 0,31,0,60,64,16,33,69,10,18,28,0,25,7,14,18,17,4,18,21,69,32,16,252,236,220,178,48,17,1,93,252,57,57,57,220,236,236,49,0, + 64,13,0,185,25,184,32,7,185,14,17,140,15,189,32,16,236,244,60,236,16,244,236,48,1,34,7,6,16,23,22,51,50,54,53,52,39,38,3,17, + 35,17,38,39,38,17,16,55,54,51,50,0,17,16,7,6,2,115,148,86,86,85,86,149,147,172,86,86,57,170,190,107,137,137,136,241,240,1,18,137, + 106,3,223,115,116,254,110,116,115,232,200,199,116,117,252,9,254,110,1,146,27,125,156,1,19,1,20,156,156,254,200,254,236,254,237,156,123,0,0,0, + 0,1,0,139,254,82,4,171,5,213,0,36,0,46,64,10,18,22,18,38,12,35,4,28,30,37,16,220,236,204,212,204,252,196,49,0,64,13,16,149, + 18,8,149,26,140,37,0,149,34,129,37,16,244,236,16,244,236,220,236,48,1,32,7,6,17,16,23,22,51,50,23,22,21,20,7,6,35,52,53,22, + 55,54,53,52,39,38,35,32,39,38,17,16,55,54,41,1,21,3,70,254,243,96,123,91,109,200,122,89,84,74,80,163,69,42,32,32,31,58,254,192, + 142,149,185,138,1,120,1,101,5,43,119,152,254,205,254,181,127,152,84,79,120,115,80,87,75,76,5,44,35,37,53,44,42,203,214,1,101,1,78,237, + 177,170,0,0,0,1,0,113,254,82,4,81,4,96,0,32,0,52,64,11,25,29,18,34,19,7,12,18,3,69,33,16,252,236,204,212,204,252,196,178, + 15,7,1,93,49,0,64,13,23,185,25,15,185,0,140,33,9,185,6,184,33,16,244,236,16,244,236,220,236,48,5,34,0,17,16,0,41,1,21,33, + 34,6,21,20,22,51,50,23,22,21,20,7,6,35,52,53,22,55,54,53,52,39,38,2,103,204,254,214,1,45,1,6,1,173,254,91,179,198,197,111, + 131,80,84,74,80,163,69,42,32,32,32,29,1,62,1,14,1,18,1,31,156,199,206,205,227,76,79,120,115,80,87,75,76,5,44,35,37,53,44,42, + 255,255,0,201,0,0,4,35,5,213,18,6,0,41,0,0,0,1,255,64,254,86,3,70,6,20,0,39,0,54,183,9,20,22,19,18,32,0,40,16, + 220,204,252,60,204,204,49,0,64,20,22,135,19,10,135,9,19,14,135,5,151,40,32,135,31,36,135,27,189,40,16,252,236,212,236,16,244,236,204,212, + 236,16,236,48,51,17,52,55,54,51,50,23,22,23,21,38,39,38,35,34,7,6,21,17,33,21,33,17,20,7,6,35,34,39,38,39,53,22,23,22, + 51,50,55,54,238,136,96,169,49,50,49,51,36,41,41,44,120,58,75,1,65,254,191,139,98,173,57,51,51,46,49,50,50,48,87,64,82,4,130,160, + 142,100,9,9,18,164,28,14,15,62,81,111,254,201,143,253,63,146,165,115,10,11,22,164,31,16,17,75,95,0,0,0,0,1,0,179,255,252,4,212, + 5,213,0,23,0,0,1,3,1,3,6,23,22,55,21,34,39,38,55,19,1,19,54,39,38,7,53,50,23,22,2,54,110,3,12,234,39,27,66,131, + 230,81,95,19,154,253,6,172,39,27,66,131,230,81,95,4,135,254,91,1,126,253,44,96,42,108,35,189,70,82,182,1,218,254,145,2,144,96,42,108, + 35,189,70,82,0,1,0,191,0,0,4,136,6,19,0,7,0,66,64,10,1,2,6,5,3,7,6,0,4,8,16,220,204,23,57,49,0,182,66,3, + 169,7,5,151,1,47,228,212,236,48,75,83,88,64,16,3,17,0,2,17,1,0,1,7,17,4,6,17,5,4,5,7,5,16,236,16,236,7,5,16, + 236,16,236,89,9,1,35,19,33,1,51,3,4,136,254,231,184,226,253,38,1,25,184,226,3,112,252,144,2,198,3,77,253,93,0,0,0,1,0,114, + 254,86,6,96,5,240,0,33,0,0,1,17,35,17,6,7,53,54,33,32,19,18,17,16,3,35,0,17,16,39,6,7,6,21,17,35,54,17,52,63, + 1,2,33,34,2,81,170,205,104,208,1,130,1,217,237,214,246,225,1,4,82,82,95,64,205,2,182,187,208,254,164,48,5,58,253,140,2,73,75,105, + 198,207,254,206,254,236,253,194,254,88,254,146,1,76,1,202,1,209,125,47,77,52,208,253,198,33,2,20,247,143,141,1,4,0,0,0,0,1,0,119, + 254,144,4,150,4,120,0,22,0,0,1,3,35,1,38,39,1,35,1,38,39,38,35,53,32,23,22,19,18,17,35,16,39,3,110,239,185,1,100,14, + 50,254,70,185,2,31,98,46,188,211,1,45,242,224,172,116,168,96,1,52,254,204,1,192,35,77,253,208,2,176,127,33,132,164,216,200,254,80,254,223, + 254,137,1,94,246,0,0,0,0,1,0,115,254,75,7,5,5,213,0,61,0,87,64,28,60,13,1,16,8,0,57,18,58,63,16,53,28,13,0,17, + 43,28,44,34,28,25,30,18,29,25,16,62,16,252,220,236,16,236,212,252,57,212,57,236,236,220,236,16,220,75,83,88,176,9,60,89,93,49,0,64, + 15,9,8,62,43,57,29,129,62,13,38,49,149,21,140,62,16,244,236,50,57,16,244,60,204,16,204,57,48,1,16,7,6,7,6,5,6,7,39,54, + 55,54,55,38,39,38,39,6,7,6,35,34,39,38,17,52,19,54,55,51,6,3,6,21,16,23,22,51,50,55,54,61,1,51,21,20,23,22,51,50, + 55,54,17,52,39,2,39,51,22,23,18,7,5,61,68,219,180,254,236,118,140,97,138,121,205,164,103,68,100,39,39,100,101,146,211,121,123,100,59,93, + 249,84,135,67,72,73,125,114,72,71,199,70,70,116,134,65,71,67,135,84,250,95,56,100,2,224,254,239,203,230,166,136,100,42,23,133,24,48,81,128, + 23,65,94,173,173,94,94,177,180,1,152,201,1,14,159,127,70,254,191,159,183,254,205,107,109,105,104,198,241,241,198,104,105,109,119,1,39,183,159,1, + 65,70,130,156,254,235,0,0,0,1,0,135,254,85,6,39,4,96,0,37,0,83,64,25,16,33,25,22,18,23,39,69,20,18,0,25,2,15,8,16, + 11,18,6,9,18,8,6,69,38,16,252,220,236,16,236,212,252,57,212,57,236,236,220,236,16,220,75,83,88,176,34,60,89,49,0,64,15,34,33,38, + 15,22,8,188,38,0,18,13,135,4,140,38,16,244,236,50,57,16,244,60,196,16,204,57,48,33,36,3,2,33,32,17,52,19,51,2,21,2,23,22, + 3,51,2,55,54,17,52,3,51,18,21,22,7,6,7,6,7,6,7,39,54,55,54,4,136,254,237,30,35,254,242,254,97,135,218,143,1,223,208,5, + 170,3,206,222,143,218,135,1,57,105,197,154,210,107,112,91,81,139,199,1,1,13,254,237,2,58,235,1,64,254,192,240,254,151,1,1,1,212,254,43, + 2,2,1,104,240,1,64,254,192,235,209,132,244,158,123,73,37,16,108,11,43,63,0,0,0,1,0,115,254,86,5,72,5,240,0,29,0,46,64,10, + 15,28,17,12,0,4,28,25,69,30,16,252,236,220,220,60,236,49,0,64,14,0,149,29,140,14,129,30,8,149,21,140,15,189,30,16,236,244,236,16, + 252,244,236,48,1,6,7,6,17,20,23,22,51,50,55,54,25,1,51,17,35,17,6,7,6,35,32,39,38,17,16,19,54,37,2,236,180,96,133,110, + 98,195,196,98,99,217,217,68,104,104,170,255,0,156,162,186,151,1,40,5,74,18,132,185,254,238,249,171,152,152,153,1,11,2,236,248,129,2,144,132, + 64,63,213,221,1,71,1,54,1,8,213,1,0,1,0,113,254,86,4,140,4,123,0,28,0,46,64,10,14,8,16,11,28,4,8,24,69,29,16,252, + 236,220,220,60,236,49,0,64,14,0,135,28,140,13,188,29,7,160,20,140,14,189,29,16,236,244,236,16,252,244,236,48,1,6,7,6,21,20,23,22, + 32,55,54,53,17,51,17,35,17,6,7,6,35,34,39,38,53,52,55,54,51,2,139,154,80,114,94,83,1,76,84,84,184,184,58,88,89,144,218,133, + 137,158,127,253,3,253,14,99,141,208,189,129,116,115,116,203,2,49,249,246,2,82,100,48,49,162,168,248,236,200,162,0,0,1,0,201,254,75,5,226, + 5,213,0,37,0,57,64,14,16,13,12,21,28,39,69,4,29,33,28,32,4,38,16,252,236,50,212,236,236,220,196,75,83,88,177,13,12,16,60,89, + 49,0,64,11,25,149,0,184,30,13,12,189,32,129,30,47,228,252,204,16,244,236,48,1,32,23,22,17,20,7,6,7,6,7,6,7,39,54,55,54, + 55,54,55,54,53,52,39,38,35,34,7,6,21,17,35,17,51,17,54,55,54,3,76,1,39,177,190,60,67,170,195,241,185,73,97,134,125,217,152,136, + 44,54,126,115,205,203,115,113,202,202,78,105,105,4,123,179,194,254,253,204,161,178,128,147,69,53,12,133,22,50,87,122,109,104,127,192,157,150,134,129, + 126,222,254,39,5,213,253,154,135,66,67,0,0,2,0,45,255,227,4,146,4,154,0,23,0,77,0,0,1,38,35,34,7,6,7,6,7,6,21,20, + 23,22,23,22,23,22,51,50,55,54,55,54,37,22,21,20,7,6,33,34,39,38,35,34,7,39,54,51,50,23,22,51,50,55,54,53,52,39,6,7, + 6,7,6,39,38,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,50,23,54,55,23,6,3,44,127,141,31,55,29,37,29,16,14,12,15,24, + 26,35,32,30,25,71,59,73,36,1,11,108,127,111,254,247,141,99,75,53,65,81,84,135,95,130,82,63,91,157,79,75,49,27,31,70,117,102,71,41, + 72,50,64,48,41,30,29,31,46,62,80,101,94,210,144,56,42,136,55,3,68,152,22,11,33,26,32,27,33,32,21,28,17,20,6,5,25,20,49,24, + 50,192,212,176,156,136,46,35,65,147,76,46,35,94,89,127,140,113,25,23,52,43,38,2,1,10,7,34,26,72,52,66,59,59,61,47,63,34,43,159, + 86,104,80,146,0,1,0,79,254,86,5,11,5,246,0,33,0,0,5,4,33,32,1,0,55,54,53,52,39,38,35,34,7,6,7,35,54,55,54,33, + 32,23,22,21,20,7,0,1,22,51,32,55,4,250,255,0,254,237,254,175,254,185,2,186,179,108,108,99,164,180,94,35,24,240,44,86,163,1,24,1, + 19,161,162,162,254,247,254,24,156,213,1,41,232,236,190,1,163,1,241,219,132,156,141,101,93,146,54,63,161,102,194,144,145,241,216,182,254,242,254,133, + 181,179,0,0,0,1,0,100,254,86,4,106,4,123,0,32,0,0,1,6,35,32,1,0,55,54,53,52,39,38,35,34,7,6,7,35,54,55,54,51, + 50,4,21,20,7,6,1,22,51,50,55,4,92,218,234,254,238,254,222,2,66,167,92,92,84,139,153,80,30,20,204,37,73,139,238,232,1,20,138,175, + 254,47,145,169,253,197,254,239,153,1,121,1,89,194,107,125,111,83,75,117,44,50,129,82,156,232,194,164,156,197,254,224,186,144,0,0,0,2,0,115, + 0,0,5,182,5,239,0,2,0,53,0,0,37,33,9,3,38,39,38,35,34,15,1,53,54,55,54,51,50,23,22,23,9,1,54,55,54,51,50,23, + 22,23,21,39,38,35,34,7,6,7,9,1,22,23,22,59,1,21,33,53,51,50,55,54,1,218,2,110,254,205,254,20,1,128,254,220,19,26,34,63, + 25,22,69,33,32,31,28,114,75,44,47,1,2,1,9,52,39,75,114,29,30,32,33,68,23,24,60,38,19,26,254,210,1,116,6,7,29,69,71,250, + 195,71,72,26,12,170,1,202,254,104,2,61,1,187,29,26,34,4,10,187,11,5,5,67,40,70,254,129,1,127,75,35,67,5,5,11,187,10,4,34, + 17,38,254,69,253,195,9,8,33,170,170,33,15,0,0,0,0,2,0,54,0,0,4,203,4,123,0,2,0,53,0,0,37,33,3,9,1,3,38,39, + 38,35,34,15,1,53,54,55,54,51,50,23,22,23,27,1,54,55,54,51,50,23,22,23,21,39,38,35,34,7,6,7,3,1,22,23,22,59,1,21, + 33,53,51,50,55,54,1,154,1,204,228,254,91,1,57,239,21,17,29,54,21,19,58,28,27,26,24,131,64,37,40,197,197,40,37,64,131,24,26,27, + 28,58,19,21,54,29,17,21,246,1,45,6,5,25,58,73,251,107,73,58,25,5,158,1,56,254,238,1,164,1,61,28,14,25,3,7,141,8,4,4, + 51,30,53,254,250,1,6,53,30,51,4,4,8,141,7,3,25,14,28,254,184,254,103,8,5,25,158,158,25,5,0,0,0,2,0,115,255,227,5,37, + 6,16,0,29,0,43,0,0,1,36,7,6,7,54,55,54,51,50,0,16,0,33,32,39,38,17,16,55,54,33,50,55,54,55,21,6,7,6,18,16, + 38,35,34,7,6,21,20,23,22,51,50,55,3,42,254,214,87,56,22,81,85,123,130,245,1,50,254,206,254,249,254,206,164,163,139,124,1,176,115,149, + 160,75,94,151,108,142,200,186,188,104,105,105,101,191,188,98,5,45,2,115,74,160,86,34,49,254,188,253,240,254,188,156,155,1,80,1,222,210,187,10, + 10,39,177,36,8,6,252,65,1,130,230,115,116,192,189,120,115,115,0,0,0,2,0,113,255,227,4,91,6,16,0,31,0,47,0,0,1,38,7,6, + 7,54,55,54,51,50,23,22,16,7,6,35,34,39,38,17,16,55,54,33,50,55,54,55,21,6,7,6,19,52,39,38,35,34,7,6,21,20,23,22, + 51,50,55,54,2,155,227,73,44,20,41,101,91,120,204,127,128,128,127,219,255,137,136,116,103,1,79,95,92,83,71,93,69,90,168,83,84,146,149,86, + 88,88,84,151,148,82,83,5,55,2,120,74,169,70,54,49,162,162,253,240,162,162,156,155,1,80,1,222,210,187,10,10,39,167,39,5,6,252,248,205, + 114,115,115,116,203,199,120,115,115,116,0,0,0,1,0,44,254,86,4,183,5,213,0,15,0,52,64,13,3,18,0,15,4,28,7,8,18,11,12,7, + 16,16,220,60,220,236,16,252,60,220,236,49,0,64,13,2,9,4,7,149,15,12,188,13,129,5,189,16,16,236,236,244,60,236,50,204,50,48,1,17, + 35,53,33,17,35,17,33,21,35,17,33,17,51,17,4,183,203,254,235,203,254,235,203,1,224,203,4,96,254,242,100,250,160,5,96,100,1,14,1,117, + 254,139,0,0,0,1,0,55,254,85,4,20,5,207,0,15,0,51,64,13,3,8,0,15,4,8,7,8,8,11,12,7,16,16,220,60,220,236,16,252, + 60,220,236,49,0,64,12,2,9,4,7,135,15,12,188,13,5,189,16,16,236,204,244,60,236,50,204,50,48,1,17,35,53,35,17,35,17,35,21,35, + 17,33,17,51,17,4,20,173,229,185,229,173,1,146,185,4,95,255,0,112,250,134,5,122,112,1,0,1,112,254,144,0,0,1,0,112,255,242,4,205, + 4,103,0,51,0,0,1,2,7,6,35,34,53,52,1,54,53,52,39,38,35,34,7,53,54,51,50,23,4,17,20,7,55,18,55,54,51,50,21,20, + 1,6,21,20,23,22,51,50,55,21,6,35,34,39,36,17,52,55,2,40,96,200,55,34,55,1,36,62,14,26,142,57,91,64,91,26,27,1,29,29, + 189,96,200,55,34,55,254,220,62,14,26,142,57,91,64,91,26,27,254,227,29,1,153,254,247,124,34,79,154,1,9,138,122,58,54,104,108,224,48,4, + 37,254,193,91,77,108,1,9,124,34,79,154,254,247,138,122,58,54,104,108,224,48,4,37,1,63,91,77,0,2,0,186,254,86,4,164,4,123,0,24, + 0,36,0,58,64,14,20,38,69,26,18,10,81,17,8,31,18,0,70,37,16,252,236,236,244,178,127,10,1,93,236,236,196,49,0,64,15,19,185,22, + 28,185,6,184,37,34,185,13,140,22,189,37,16,236,244,236,16,244,236,16,236,48,19,52,55,54,55,54,51,50,23,22,16,7,6,35,34,39,38,39, + 18,41,1,21,33,32,17,36,16,39,38,32,7,6,16,23,22,32,55,186,90,54,158,59,182,204,127,128,128,127,204,120,91,89,58,5,1,32,1,244, + 254,28,254,18,3,43,83,84,254,220,84,83,83,84,1,36,84,2,37,208,163,98,94,35,162,162,253,240,162,162,49,48,100,254,88,170,2,218,52,1, + 150,116,115,115,116,254,106,116,115,115,0,0,255,255,0,113,255,227,3,231,4,123,18,6,0,70,0,0,255,255,255,219,254,86,1,121,6,20,18,6, + 0,77,0,0,255,255,0,115,255,227,5,217,5,240,18,6,1,97,0,0,0,1,0,113,255,227,3,216,4,123,0,33,0,0,1,38,39,38,35,34, + 7,6,7,33,21,33,22,23,22,51,50,63,1,21,7,6,35,32,39,38,16,55,54,33,50,23,22,23,3,216,37,37,99,106,183,102,95,18,2,165, + 253,91,18,95,102,183,128,77,74,79,104,107,254,244,156,157,157,156,1,12,101,110,40,39,3,174,13,10,26,99,92,169,144,169,92,99,26,25,167,18, + 22,156,156,2,40,156,156,22,8,12,0,0,0,1,0,196,255,227,4,43,4,123,0,33,0,0,19,53,54,55,54,51,32,23,22,16,7,6,33,34, + 47,1,53,23,22,51,50,55,54,55,33,53,33,38,39,38,35,34,7,6,196,39,40,110,101,1,12,156,157,157,156,254,244,107,104,79,74,77,128,183, + 102,95,18,253,91,2,165,18,95,102,183,106,99,37,3,174,163,12,8,22,156,156,253,216,156,156,22,18,167,25,26,99,92,169,144,169,92,99,26,10, + 255,255,0,201,0,0,4,141,5,213,18,6,0,160,0,0,255,255,0,186,254,86,4,164,6,20,18,6,0,192,0,0,255,255,0,115,255,227,5,39, + 5,240,18,6,0,38,0,0,0,1,0,201,0,0,6,31,5,213,0,12,0,148,64,16,9,8,3,2,1,5,10,6,28,4,62,10,28,0,4,13, + 16,252,236,252,236,17,23,57,49,0,64,12,66,10,7,2,3,8,3,0,175,8,11,5,47,60,196,236,50,17,23,57,48,75,83,88,64,24,3,17, + 7,8,7,2,17,1,2,8,8,7,2,17,3,2,9,10,9,1,17,10,10,9,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,178, + 112,14,1,1,93,64,17,4,2,6,7,6,10,54,2,73,7,73,10,89,7,89,10,8,64,21,2,1,13,3,22,8,25,9,38,1,41,3,53,1, + 58,3,69,8,74,9,10,93,0,93,19,33,9,1,33,17,35,17,1,35,1,17,35,201,1,45,1,125,1,127,1,45,197,254,127,203,254,127,196,5, + 213,254,33,1,223,250,43,5,31,254,25,1,231,250,225,0,0,1,0,127,254,86,4,179,4,96,0,12,0,79,64,9,14,70,7,8,4,10,8,0, + 13,16,220,236,220,236,236,49,0,64,13,66,10,7,2,3,9,3,0,188,9,12,189,6,47,236,196,236,50,17,23,57,48,75,83,88,64,18,2,17, + 8,10,9,3,17,7,8,7,2,17,9,1,17,10,10,9,5,7,16,237,16,237,7,16,237,8,16,237,89,19,33,19,1,33,17,35,17,1,35,1, + 17,35,127,1,27,254,1,0,1,27,185,254,236,153,254,235,185,4,96,254,123,1,133,251,160,3,178,254,96,1,160,250,164,0,0,0,0,2,0,85, + 254,86,4,164,4,123,0,27,0,39,0,0,23,17,52,55,54,55,54,51,50,23,22,16,7,6,35,34,39,38,39,17,33,21,33,21,35,53,35,53, + 0,16,39,38,32,7,6,16,23,22,32,55,186,90,61,151,59,182,204,127,128,128,127,204,123,88,89,58,1,229,254,27,185,101,3,144,83,84,254,220, + 84,83,83,84,1,36,84,144,2,181,231,140,102,90,35,162,162,253,240,162,162,49,48,100,254,200,170,112,112,170,1,244,1,150,116,115,115,116,254,106, + 116,115,115,0,255,255,0,115,255,227,5,39,5,240,18,6,1,72,0,0,255,255,0,115,255,227,5,39,5,240,18,38,3,141,0,0,16,7,0,121, + 2,51,0,0,255,255,0,115,255,227,5,39,5,240,16,39,0,121,0,228,0,0,18,6,3,145,0,0,255,255,0,201,0,0,4,139,7,107,18,38, + 3,169,0,0,16,7,22,188,4,238,1,117,255,255,0,201,0,0,4,139,7,78,18,38,3,169,0,0,17,7,22,185,4,157,1,117,0,133,177,146, + 151,66,176,147,176,152,66,177,128,4,66,177,129,0,66,124,176,0,176,1,35,73,176,19,176,14,35,73,97,176,128,98,104,176,19,70,97,176,0,70, + 96,176,146,67,176,1,96,35,66,176,146,67,176,1,96,67,176,0,85,88,176,14,176,146,67,176,1,96,67,56,176,14,17,176,1,53,89,177,128,0, + 66,177,129,0,66,24,176,0,16,176,19,176,14,176,1,35,73,104,59,176,19,17,176,2,53,0,176,0,176,19,35,73,176,64,80,88,176,19,176,64, + 56,176,19,17,176,2,53,176,1,53,89,0,0,1,255,250,254,102,5,172,5,213,0,27,0,52,64,11,5,10,28,27,20,14,22,28,19,17,28,16, + 212,204,252,60,204,220,252,204,49,0,64,15,5,149,4,176,16,14,149,23,16,22,17,149,19,129,16,47,244,236,50,16,212,236,16,244,236,48,37,16, + 6,43,1,53,51,50,54,53,17,52,38,35,33,17,35,17,33,53,33,21,33,17,33,50,22,21,5,172,204,228,76,62,134,111,124,124,254,136,203,254, + 82,4,139,253,238,1,161,186,222,104,254,242,244,170,150,194,1,34,159,158,253,57,5,43,170,170,254,70,233,238,0,0,255,255,0,201,0,0,4,106, + 7,107,18,38,3,167,0,0,16,7,22,186,4,174,1,117,0,1,0,115,255,227,5,39,5,240,0,24,0,78,64,9,26,18,11,0,17,20,25,6, + 25,16,220,236,50,212,60,204,204,49,0,64,23,19,149,18,173,25,12,161,11,174,14,149,9,145,25,0,161,1,174,23,149,3,140,25,16,244,236,244, + 236,16,244,236,244,236,16,244,236,177,18,14,73,177,23,19,73,80,88,179,18,19,64,2,23,56,89,48,1,21,6,33,32,0,17,16,0,33,32,23, + 21,38,33,32,2,7,33,21,33,22,18,33,32,5,39,212,254,245,254,177,254,122,1,134,1,79,1,15,208,211,255,0,254,248,238,22,3,30,252,226, + 22,238,1,8,1,0,1,70,211,144,1,159,1,104,1,103,1,159,142,213,189,254,227,239,170,239,254,228,255,255,0,135,255,227,4,162,5,240,18,6, + 0,54,0,0,255,255,0,201,0,0,1,147,5,213,18,6,0,44,0,0,255,255,0,6,0,0,2,88,7,78,16,6,0,145,0,0,255,255,255,150, + 254,102,1,147,5,213,18,6,0,45,0,0,0,2,0,84,0,0,8,47,5,213,0,20,0,28,0,51,64,12,23,25,16,0,28,27,11,1,28,10, + 6,29,16,212,212,236,212,60,236,220,236,49,0,64,14,27,149,12,173,20,1,149,10,129,28,6,149,5,20,47,60,236,50,244,236,16,252,236,48,1, + 33,21,16,2,5,53,54,18,17,53,33,17,51,50,4,21,20,4,35,33,37,32,17,52,38,43,1,17,4,112,254,27,200,254,145,217,149,3,120,234, + 251,1,16,254,240,251,254,76,1,170,1,64,157,163,224,5,43,184,253,202,253,251,56,170,47,1,166,2,88,254,253,154,218,221,222,218,166,1,17,139, + 135,253,221,0,0,2,0,201,0,0,7,204,5,213,0,18,0,27,0,53,64,14,19,25,15,8,0,28,23,10,7,2,28,5,4,28,16,252,236,50, + 220,60,236,50,220,236,49,0,64,13,23,1,149,11,7,173,9,5,129,24,149,0,4,47,60,236,228,50,252,60,236,50,48,33,17,33,17,35,17,51, + 17,33,17,51,17,51,50,4,21,20,4,35,1,52,38,43,1,17,51,50,54,4,13,253,134,202,202,2,122,202,234,251,1,16,254,240,251,1,54,157, + 163,224,224,161,159,2,199,253,57,5,213,253,156,2,100,253,154,218,222,221,218,1,183,139,135,253,221,135,0,1,255,250,0,0,5,172,5,213,0,19, + 0,44,64,10,6,28,3,16,10,18,28,14,13,20,16,212,204,252,60,204,220,236,49,0,64,11,10,149,19,12,18,13,149,15,129,5,12,47,60,244, + 236,50,16,212,236,48,1,50,22,21,17,35,17,52,38,35,33,17,35,17,33,53,33,21,33,17,4,20,186,222,201,124,124,254,136,203,254,82,4,139, + 253,238,3,113,233,238,254,102,1,138,159,158,253,57,5,43,170,170,254,70,255,255,0,201,0,0,5,134,7,107,18,38,3,174,0,0,16,7,22,186, + 4,238,1,117,255,255,0,201,0,0,5,51,7,107,18,38,3,172,0,0,16,7,22,188,4,229,1,117,255,255,0,35,0,0,4,189,7,109,16,39, + 22,192,4,114,1,117,18,6,3,183,0,0,0,1,0,201,254,191,5,59,5,213,0,11,0,41,64,13,13,4,6,28,7,11,149,9,3,28,2,4, + 12,16,252,236,212,252,212,236,236,49,0,183,11,4,149,6,2,129,9,1,47,60,228,50,236,204,48,41,1,17,51,17,33,17,51,17,33,17,35,2, + 173,254,28,202,2,222,202,254,28,170,5,213,250,213,5,43,250,43,254,191,255,255,0,16,0,0,5,104,5,213,18,6,0,36,0,0,0,2,0,201, + 0,0,4,236,5,213,0,8,0,21,0,46,64,12,23,9,0,25,16,46,4,11,28,21,4,22,16,252,236,50,244,236,196,204,49,0,64,12,11,149, + 21,129,20,4,149,12,173,5,149,20,47,236,244,236,16,244,236,48,1,52,38,35,33,17,33,50,54,19,21,33,17,33,50,4,21,20,4,41,1,17, + 4,23,157,163,254,188,1,68,163,157,108,253,16,1,78,251,1,16,254,249,254,252,253,232,1,183,139,135,253,221,135,4,168,166,254,64,218,222,221,218, + 5,213,0,0,255,255,0,201,0,0,4,236,5,213,18,6,0,37,0,0,0,1,0,201,0,0,4,106,5,213,0,5,0,25,64,12,4,149,1,129, + 0,7,2,4,28,1,4,6,16,252,252,204,196,49,0,47,244,236,48,51,17,33,21,33,17,201,3,161,253,41,5,213,170,250,213,0,0,2,0,101, + 254,191,5,219,5,213,0,7,0,23,0,52,64,15,2,28,14,19,149,25,16,23,3,28,13,20,149,23,24,16,220,236,212,236,16,212,204,252,60,236, + 49,0,64,11,3,149,13,129,18,22,15,0,23,149,20,47,236,50,50,204,50,244,236,48,37,33,17,33,21,16,3,6,5,54,55,18,25,1,33,17, + 51,17,35,17,33,17,35,17,1,211,2,148,254,27,112,23,254,177,134,38,97,3,120,170,170,251,222,170,170,4,129,212,254,13,254,181,68,43,63,120, + 1,52,2,38,1,26,250,213,254,21,1,65,254,191,1,235,255,255,0,201,0,0,4,139,5,213,18,6,0,40,0,0,0,1,0,40,0,0,8,118, + 5,213,0,19,0,152,64,11,8,5,1,4,6,9,1,28,12,0,20,16,220,60,236,50,212,196,17,57,57,49,0,64,17,66,13,12,16,19,8,9, + 5,2,8,18,3,0,175,15,10,6,47,60,60,236,50,50,23,57,48,75,83,88,64,22,7,17,6,8,17,5,9,4,6,5,3,17,4,2,17,5, + 8,9,9,4,9,4,9,7,16,60,60,4,237,16,5,237,7,8,16,237,5,16,237,89,1,64,19,13,1,8,14,1,7,15,1,6,16,1,5,17, + 1,4,18,1,3,0,16,73,58,73,58,73,58,73,58,73,58,73,58,0,64,8,19,2,16,5,13,8,12,9,16,60,16,60,16,60,16,60,1,51, + 17,1,51,9,1,35,9,1,17,35,17,9,1,35,9,1,51,1,3,234,202,2,170,245,253,223,2,68,211,254,19,254,254,202,254,254,254,19,211,2, + 68,253,223,245,2,170,5,213,253,30,2,226,253,179,252,120,3,1,254,233,254,22,1,234,1,23,252,255,3,136,2,77,253,30,0,0,0,1,0,135, + 255,227,4,154,5,240,0,40,0,63,64,12,27,31,25,3,42,22,25,9,37,16,6,41,16,252,50,212,236,204,212,252,204,49,0,64,22,26,149,27, + 12,16,161,15,174,19,149,12,37,161,38,174,34,149,0,145,12,140,41,16,228,244,236,244,236,16,236,244,236,16,212,236,48,1,50,4,21,20,6,7, + 30,1,21,20,4,35,34,36,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,2,73,246,1,56,142, + 131,145,163,254,157,238,122,254,228,44,153,169,124,188,208,185,195,204,212,179,158,163,198,134,92,205,113,236,5,240,209,178,124,171,33,31,196,144,230,233, + 66,28,208,89,43,144,149,132,149,166,119,112,115,123,24,77,197,40,34,0,0,1,0,201,0,0,5,51,5,213,0,9,0,121,64,30,3,17,9,9, + 8,8,17,4,4,3,66,8,3,9,6,175,2,5,9,4,7,3,28,0,54,7,28,6,4,10,16,252,236,252,236,17,57,57,49,0,47,60,236,50, + 57,57,48,75,83,88,7,16,4,237,7,16,4,237,89,34,178,31,11,1,1,93,64,48,54,8,56,3,72,8,71,3,105,8,102,3,128,8,7,6, + 4,9,9,21,4,26,9,70,4,73,9,87,4,88,9,101,4,105,9,121,9,133,4,138,9,149,4,154,9,159,11,16,93,0,93,1,17,35,17,1, + 33,17,51,17,1,5,51,196,253,106,254,240,196,2,150,5,213,250,43,4,225,251,31,5,213,251,31,4,225,0,0,0,255,255,0,201,0,0,5,51, + 7,109,18,38,3,172,0,0,17,7,22,192,4,245,1,117,0,35,180,6,10,18,0,7,43,176,10,75,84,176,11,75,84,91,176,16,75,84,91,88, + 187,0,18,0,64,0,10,255,192,56,56,89,49,0,0,0,0,1,0,201,0,0,5,134,5,213,0,11,0,89,64,11,8,5,1,4,6,9,1,28, + 0,4,12,16,252,236,50,212,196,17,57,57,49,0,64,11,66,8,9,5,2,4,3,0,175,10,6,47,60,236,50,23,57,48,75,83,88,64,22,7, + 17,6,8,17,5,9,4,6,5,3,17,4,2,17,5,8,9,9,4,9,4,9,7,16,60,60,4,237,16,5,237,7,8,16,237,5,16,237,89,19, + 51,17,1,33,9,1,35,9,1,17,35,201,202,2,210,1,3,253,191,2,95,220,253,250,254,239,202,5,213,253,30,2,226,253,178,252,121,3,1,254, + 233,254,22,0,0,1,0,84,0,0,5,58,5,213,0,15,0,37,64,10,17,4,10,28,7,11,28,6,1,16,16,212,212,236,212,236,236,49,0,64, + 8,11,149,6,129,1,149,0,9,47,60,236,244,236,48,51,53,54,55,18,17,53,33,17,35,17,33,21,16,3,6,84,217,62,87,3,120,202,254,27, + 102,98,170,47,164,1,2,2,88,254,250,43,5,43,184,253,202,254,248,253,255,255,0,201,0,0,6,31,5,213,18,6,0,48,0,0,255,255,0,201, + 0,0,5,59,5,213,18,6,0,43,0,0,255,255,0,115,255,227,5,217,5,240,18,6,0,50,0,0,0,1,0,201,0,0,5,59,5,213,0,7, + 0,31,64,16,4,149,7,129,2,6,9,4,3,28,0,4,28,7,4,8,16,252,236,212,236,236,49,0,47,60,244,236,48,1,17,35,17,33,17,35, + 17,5,59,202,253,34,202,5,213,250,43,5,43,250,213,5,213,0,0,0,255,255,0,201,0,0,4,141,5,213,18,6,0,51,0,0,255,255,0,115, + 255,227,5,39,5,240,18,6,0,38,0,0,255,255,255,250,0,0,4,233,5,213,18,6,0,55,0,0,0,1,0,35,0,0,4,189,5,213,0,17, + 0,62,180,19,17,6,13,18,16,212,196,212,196,49,0,182,66,16,13,129,6,149,5,47,236,236,50,48,75,83,88,64,18,15,17,0,13,12,16,17, + 17,17,0,15,17,12,14,17,13,13,12,5,7,16,236,16,236,7,16,236,8,16,236,89,37,6,7,6,43,1,53,51,50,55,54,63,1,1,51,9, + 1,51,2,143,21,32,79,251,77,63,119,46,28,18,45,254,33,217,1,115,1,117,217,181,50,38,93,170,27,17,42,106,4,107,252,148,3,108,0,0, + 0,3,0,121,0,0,6,106,5,213,0,6,0,13,0,31,0,61,64,17,33,16,10,25,26,14,0,21,28,29,13,22,3,25,17,16,32,16,252,236, + 212,60,60,252,60,60,212,236,236,49,0,64,14,13,0,149,23,20,21,129,31,7,5,149,29,14,31,47,220,60,236,50,16,244,220,60,236,50,48,1, + 14,1,21,20,22,23,51,62,1,53,52,38,39,3,36,0,17,16,0,37,53,51,21,4,0,17,16,0,5,21,35,3,13,217,230,230,217,203,217,228, + 228,217,203,254,195,254,169,1,87,1,61,203,1,61,1,85,254,171,254,195,203,4,162,20,204,197,197,203,20,20,203,197,197,204,20,252,16,23,1,43, + 1,9,1,9,1,45,23,139,139,23,254,213,254,245,254,247,254,213,23,178,255,255,0,61,0,0,5,59,5,213,18,6,0,59,0,0,0,1,0,201, + 254,191,5,229,5,213,0,11,0,41,64,12,13,9,149,0,6,28,7,3,28,2,4,12,16,252,236,212,236,60,252,204,49,0,64,8,6,2,129,11, + 8,4,149,1,47,236,50,204,244,60,48,41,1,17,51,17,33,17,51,17,51,17,35,5,59,251,142,202,2,222,202,170,170,5,213,250,213,5,43,250, + 213,254,21,0,0,1,0,175,0,0,4,179,5,213,0,15,0,36,64,10,17,4,1,13,28,14,7,28,6,16,16,220,236,212,236,50,236,49,0,183, + 2,149,11,173,13,6,129,0,47,228,50,244,236,48,33,17,33,34,38,53,17,51,17,20,22,51,33,17,51,17,3,232,254,95,186,222,201,124,124,1, + 120,203,2,100,233,238,1,154,254,118,159,158,2,199,250,43,0,1,0,201,0,0,7,197,5,213,0,11,0,42,64,13,13,4,2,28,3,10,28,11, + 7,28,6,4,12,16,252,236,212,252,212,236,236,49,0,64,8,10,2,6,129,0,8,149,5,47,236,50,244,60,60,48,37,33,17,51,17,33,17,51, + 17,33,17,51,4,172,2,79,202,249,4,202,2,79,202,170,5,43,250,43,5,213,250,213,5,43,0,0,0,1,0,201,254,191,8,111,5,213,0,15, + 0,50,64,15,17,13,149,0,10,28,11,6,28,7,3,28,2,4,16,16,252,236,212,252,212,236,60,252,204,49,0,64,10,6,10,2,129,15,12,8, + 4,149,1,47,236,50,50,204,244,60,60,48,41,1,17,51,17,33,17,51,17,33,17,51,17,51,17,35,7,197,249,4,202,2,79,202,2,79,202,170, + 170,5,213,250,213,5,43,250,213,5,43,250,213,254,21,0,0,2,0,60,0,0,6,24,5,213,0,12,0,23,0,42,64,22,2,149,3,129,0,18, + 149,5,173,19,149,0,16,13,25,9,18,4,28,1,3,24,16,204,220,236,50,212,236,204,49,0,47,236,244,236,16,244,236,48,33,17,33,53,33,17, + 33,50,4,21,20,4,35,1,52,39,38,35,33,17,33,50,55,54,1,245,254,71,2,131,1,78,251,1,16,254,240,251,1,54,79,78,163,254,188,1, + 68,161,80,79,5,43,170,253,154,218,222,221,218,1,183,139,68,67,253,221,68,67,0,0,255,255,0,201,0,0,6,70,5,213,16,38,3,192,0,0, + 16,7,0,44,4,179,0,0,0,2,0,201,0,0,4,236,5,213,0,10,0,21,0,36,64,19,5,149,13,173,11,129,6,149,21,23,0,25,17,5, + 12,28,11,4,22,16,252,236,50,212,236,204,49,0,47,236,228,244,236,48,1,52,39,38,35,33,17,33,50,55,54,1,51,17,33,50,4,21,20,4, + 35,33,4,23,79,78,163,254,188,1,68,163,78,79,252,178,202,1,78,251,1,16,254,240,251,253,232,1,183,139,68,67,253,221,68,67,4,168,253,154, + 218,222,221,218,0,1,0,111,255,227,5,35,5,240,0,24,0,78,64,9,26,5,8,25,19,7,0,14,25,16,220,60,204,212,236,50,204,49,0,64, + 23,6,149,7,173,25,13,161,14,174,11,149,16,145,25,0,161,24,174,2,149,22,140,25,16,244,236,244,236,16,244,236,244,236,16,244,236,177,7,11, + 73,177,2,6,73,80,88,179,7,6,64,2,23,56,89,48,19,22,33,32,18,55,33,53,33,38,2,33,32,7,53,54,33,32,0,17,16,0,33,32, + 39,111,211,1,0,1,8,238,22,252,226,3,30,22,238,254,248,255,0,211,208,1,15,1,79,1,134,254,122,254,177,254,245,212,1,70,189,1,28,239, + 170,239,1,29,189,213,142,254,97,254,153,254,152,254,97,144,0,2,0,211,255,227,8,48,5,240,0,15,0,38,0,56,64,31,0,149,20,145,39,8, + 149,28,140,39,33,149,38,173,36,129,35,40,12,25,24,4,25,32,16,33,37,28,36,4,39,16,252,236,50,212,60,236,212,236,204,49,0,47,228,244, + 236,16,244,236,16,244,236,48,1,34,7,6,17,16,23,22,51,50,55,54,17,16,39,38,1,18,55,54,33,32,23,22,17,16,7,6,33,32,39,38, + 3,33,17,35,17,51,17,5,126,220,130,129,129,130,220,220,128,129,129,128,252,115,14,180,180,1,59,1,58,188,188,188,188,254,198,254,197,180,180,14, + 254,208,202,202,5,76,164,164,254,229,254,230,164,164,164,164,1,26,1,27,164,164,253,243,1,24,205,204,210,211,254,158,254,159,210,211,205,205,1,24, + 253,107,5,213,253,106,0,0,0,2,0,136,0,0,4,198,5,213,0,8,0,22,0,64,64,11,24,4,20,5,28,17,0,25,9,13,23,16,212,196, + 236,212,236,50,236,49,0,64,12,66,6,149,16,129,9,21,149,3,173,19,9,47,60,244,236,16,244,236,48,75,83,88,183,21,17,10,22,17,9,10, + 9,5,7,16,236,16,236,89,1,20,22,51,33,17,33,34,6,9,1,38,36,53,52,36,41,1,17,35,17,33,1,1,155,149,146,1,58,254,198,146, + 149,254,237,1,152,100,255,0,1,4,1,2,2,4,202,254,242,254,118,4,39,131,135,2,18,133,251,86,2,141,26,169,215,206,224,250,43,2,119,253, + 137,0,0,0,255,255,0,123,255,227,4,45,4,123,18,6,0,68,0,0,0,2,0,112,255,227,4,127,6,55,0,29,0,41,0,58,64,14,19,20, + 43,69,39,18,3,81,28,33,18,9,69,42,16,252,236,50,244,236,236,212,196,49,0,64,17,22,169,17,151,42,36,185,6,30,185,9,28,0,184,6, + 140,42,16,228,244,57,57,236,16,238,16,244,236,48,1,50,0,17,16,0,35,34,0,3,39,38,53,52,55,54,36,37,54,55,23,6,15,1,6,7, + 6,15,1,54,23,34,6,21,20,22,51,50,54,53,52,38,2,125,240,1,18,254,238,240,241,254,246,7,6,5,58,91,1,59,1,8,122,54,51,49, + 45,250,126,76,199,19,7,130,211,148,172,171,149,147,172,172,4,123,254,200,254,236,254,237,254,199,1,48,1,28,229,119,41,160,118,185,160,2,1,17, + 146,20,1,17,9,44,117,153,56,119,156,231,201,201,231,232,200,199,233,0,0,3,0,186,0,0,4,62,4,96,0,8,0,17,0,32,0,47,64,13, + 14,18,22,34,5,18,28,0,9,8,18,70,33,16,252,236,50,212,236,204,212,236,49,0,64,11,0,169,10,32,9,169,18,188,1,169,32,47,236,244, + 236,16,212,236,48,1,17,33,50,54,53,52,38,35,1,17,51,50,54,53,52,38,35,37,33,50,22,21,20,6,7,30,1,21,20,6,35,33,1,114, + 1,6,126,132,132,126,254,250,242,104,132,132,104,254,86,1,182,197,212,108,106,127,140,231,214,254,57,2,4,254,143,95,90,90,94,1,201,254,202,83, + 74,74,79,147,144,133,103,121,15,24,152,114,150,164,0,0,0,1,0,186,0,0,3,208,4,96,0,5,0,25,182,7,2,4,8,1,70,6,16,252, + 252,220,204,49,0,180,4,169,1,188,0,47,244,236,48,51,17,33,21,33,17,186,3,22,253,163,4,96,147,252,51,0,0,2,0,107,254,229,5,29, + 4,96,0,6,0,22,0,52,64,15,2,8,13,18,169,24,15,22,3,8,12,19,169,22,23,16,220,236,212,236,16,212,196,252,60,236,49,0,64,11, + 3,169,12,188,17,21,14,0,22,169,19,47,236,50,50,204,50,244,236,48,37,33,17,33,21,16,7,5,54,55,54,17,53,33,17,51,17,35,17,33, + 17,35,17,1,187,2,22,254,125,118,254,216,91,40,98,2,245,147,147,252,116,147,147,3,58,140,254,100,220,54,40,85,211,1,169,212,252,51,254,82, + 1,27,254,229,1,174,0,0,255,255,0,113,255,227,4,127,4,123,18,6,0,72,0,0,0,1,0,70,0,0,6,239,4,96,0,19,0,152,64,11, + 8,5,1,4,6,9,1,8,12,0,20,16,220,60,236,50,212,196,17,57,57,49,0,64,17,66,13,12,16,19,8,9,5,2,8,18,3,0,188,15, + 10,6,47,60,60,236,50,50,23,57,48,75,83,88,64,22,7,17,6,8,17,5,9,4,6,5,3,17,4,2,17,5,8,9,9,4,9,4,9,7, + 16,60,60,4,237,16,5,237,7,8,16,237,5,16,237,89,1,64,19,13,1,8,14,1,7,15,1,6,16,1,5,17,1,4,18,1,3,0,16,73, + 58,73,58,73,58,73,58,73,58,73,58,0,64,8,19,2,16,5,13,8,12,9,16,60,16,60,16,60,16,60,1,51,17,1,51,9,1,35,1,7, + 17,35,17,39,1,35,9,1,51,1,3,63,183,1,233,214,254,110,1,204,197,254,135,187,183,187,254,135,197,1,204,254,110,214,1,233,4,96,253,242, + 2,14,254,81,253,79,2,54,201,254,147,1,109,201,253,202,2,177,1,175,253,242,0,0,0,1,0,133,255,227,3,200,4,124,0,40,0,78,64,11, + 25,18,38,42,16,18,3,21,32,10,41,16,220,196,196,212,236,204,212,236,49,0,64,22,32,134,31,136,28,185,35,184,41,20,169,21,41,9,134,10, + 136,13,185,6,140,41,16,244,252,176,12,75,81,88,252,27,244,89,236,16,212,236,16,244,252,176,12,75,81,88,252,27,244,89,236,48,1,30,1,21, + 20,4,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,2,194,124, + 138,254,254,238,80,169,90,71,170,93,151,169,150,137,148,155,116,135,139,119,71,161,97,98,170,76,196,227,120,2,92,24,146,108,173,182,28,28,171,37, + 37,112,90,88,107,152,89,70,64,92,26,29,167,24,24,157,141,93,129,0,0,1,0,186,0,0,4,121,4,96,0,9,0,63,64,21,66,8,3,9, + 6,188,2,5,11,70,9,4,7,3,8,0,7,8,6,70,10,16,252,236,212,236,17,57,57,236,49,0,47,60,228,50,57,57,48,75,83,88,64,10, + 3,17,9,9,8,8,17,4,4,3,7,16,236,7,16,236,89,1,17,35,17,1,35,17,51,17,1,4,121,183,253,228,236,183,2,27,4,96,251,160, + 3,131,252,125,4,96,252,127,3,129,0,0,255,255,0,186,0,0,4,121,6,20,18,38,3,204,0,0,17,7,2,154,0,154,255,204,0,35,180,7, + 10,18,3,7,43,176,14,75,84,176,16,75,84,91,176,21,75,84,91,88,187,0,18,0,64,0,10,255,192,56,56,89,49,0,0,0,0,1,0,186, + 0,0,4,145,4,96,0,11,0,89,64,11,8,5,1,4,6,9,1,8,0,70,12,16,252,236,50,212,196,17,57,57,49,0,64,11,66,8,9,5, + 2,4,3,0,188,10,6,47,60,236,50,23,57,48,75,83,88,64,22,7,17,6,8,17,5,9,4,6,5,3,17,4,2,17,5,8,9,9,4,9, + 4,9,7,16,60,60,4,237,16,5,237,7,8,16,237,5,16,237,89,19,51,17,1,51,9,1,35,1,7,17,35,186,183,2,7,226,254,84,1,227, + 206,254,115,197,183,4,96,253,242,2,14,254,79,253,81,2,53,200,254,147,0,1,0,76,0,0,4,115,4,96,0,15,0,36,64,10,17,70,10,8, + 7,11,8,6,1,16,16,212,212,236,212,236,236,49,0,183,11,169,6,188,1,169,0,9,47,60,236,244,236,48,51,53,54,55,54,17,53,33,17,35, + 17,33,21,16,7,6,76,182,56,68,2,245,184,254,123,88,94,153,28,126,177,1,197,183,251,160,3,205,111,254,80,194,207,0,0,0,0,1,0,186, + 0,0,5,79,4,96,0,12,0,77,64,22,66,10,7,2,3,8,3,0,188,9,6,12,14,70,7,8,4,10,8,0,70,13,16,252,236,220,236,236, + 49,0,47,60,196,236,50,17,23,57,48,75,83,88,64,18,2,17,8,10,9,3,17,7,8,7,2,17,9,1,17,10,10,9,5,7,16,237,16,237, + 7,16,237,8,16,237,89,19,33,9,1,33,17,35,17,1,35,1,17,35,186,1,13,1,62,1,63,1,11,185,254,203,184,254,202,185,4,96,253,18, + 2,238,251,160,3,176,253,39,2,217,252,80,0,1,0,186,0,0,4,129,4,96,0,11,0,39,64,20,9,169,2,4,0,188,7,11,13,70,8,4, + 8,5,9,1,8,0,70,12,16,252,236,50,220,236,50,236,49,0,47,60,228,50,220,236,48,19,51,17,33,17,51,17,35,17,33,17,35,186,185,2, + 85,185,185,253,171,185,4,96,254,55,1,201,251,160,2,4,253,252,0,0,255,255,0,113,255,227,4,117,4,123,18,6,0,82,0,0,0,1,0,186, + 0,0,4,129,4,96,0,7,0,31,64,16,4,169,7,188,2,6,3,8,9,70,0,4,8,7,70,8,16,252,236,212,236,236,49,0,47,60,244,236, + 48,1,17,35,17,33,17,35,17,4,129,185,253,171,185,4,96,251,160,3,205,252,51,4,96,0,0,0,255,255,0,186,254,86,4,164,4,123,18,6, + 0,83,0,0,255,255,0,113,255,227,3,231,4,123,18,6,0,70,0,0,0,1,0,60,0,0,4,109,4,96,0,7,0,28,182,9,1,3,8,6, + 0,8,16,220,212,252,220,204,49,0,181,3,7,169,0,188,5,47,244,236,50,48,19,33,21,33,17,35,17,33,60,4,49,254,66,181,254,66,4,96, + 147,252,51,3,205,0,0,0,255,255,0,61,254,86,4,127,4,96,18,6,0,92,0,0,0,3,0,112,254,86,6,103,5,213,0,10,0,40,0,51, + 0,66,64,17,53,69,41,18,33,12,6,25,8,39,46,26,0,18,18,69,52,16,252,236,212,60,60,252,60,60,212,236,236,49,0,64,18,44,8,185, + 30,21,184,25,151,52,49,3,185,36,15,140,11,189,52,16,236,244,60,236,50,16,228,244,60,236,50,48,1,20,22,51,50,55,17,38,35,34,6,1, + 17,14,1,35,34,2,17,16,18,51,50,22,23,17,51,17,62,1,51,50,18,17,16,2,35,34,38,39,17,1,52,38,35,34,7,17,22,51,50,54, + 1,47,145,123,98,114,114,98,123,145,1,224,57,131,83,167,233,233,167,83,131,57,185,57,131,83,167,233,233,167,83,131,57,1,224,145,123,98,114,114, + 98,123,145,2,47,235,199,168,2,20,168,199,251,60,2,57,94,78,1,53,1,19,1,19,1,61,76,94,2,4,253,252,94,76,254,195,254,237,254,237, + 254,203,78,94,253,199,3,217,235,199,168,253,236,168,199,0,255,255,0,59,0,0,4,121,4,96,18,6,0,91,0,0,0,1,0,186,254,229,5,20, + 4,96,0,11,0,40,64,12,13,9,169,6,8,0,7,3,8,2,70,12,16,252,236,212,60,236,252,204,49,0,183,6,2,188,11,8,4,169,1,47, + 236,50,204,244,60,48,41,1,17,51,17,33,17,51,17,51,17,35,4,129,252,57,185,2,85,185,147,147,4,96,252,51,3,205,252,51,254,82,0,0, + 0,1,0,150,0,0,4,0,4,96,0,17,0,59,64,17,2,169,13,15,7,188,0,19,70,1,15,8,16,8,8,7,18,16,220,236,212,236,50,236, + 49,0,47,228,50,212,236,176,0,176,2,35,73,176,13,176,15,35,73,82,88,177,2,13,184,255,192,176,2,23,56,89,48,33,17,33,34,39,38,53, + 17,51,17,20,23,22,51,33,17,51,17,3,72,254,169,153,102,92,184,52,53,104,1,41,184,1,215,95,86,184,1,28,254,245,117,59,59,1,246,251, + 160,0,0,0,0,1,0,186,0,0,6,152,4,96,0,11,0,41,64,13,13,70,2,8,3,10,8,11,7,8,6,70,12,16,252,236,212,252,212,236, + 236,49,0,183,10,2,6,188,0,8,169,5,47,236,50,244,60,60,48,37,33,17,51,17,33,17,51,17,33,17,51,4,5,1,218,185,250,34,185,1, + 217,185,147,3,205,251,160,4,96,252,51,3,205,0,0,0,0,1,0,186,254,229,7,43,4,96,0,15,0,50,64,15,17,13,169,10,8,0,11,6, + 8,7,3,8,2,70,16,16,252,236,212,252,212,60,236,252,204,49,0,64,10,6,10,2,188,15,12,8,4,169,1,47,236,50,50,204,244,60,60,48, + 41,1,17,51,17,33,17,51,17,33,17,51,17,51,17,35,6,152,250,34,185,1,217,185,1,218,185,147,147,4,96,252,51,3,205,252,51,3,205,252, + 51,254,82,0,0,2,0,62,0,0,5,46,4,96,0,12,0,21,0,44,64,11,23,69,19,18,3,14,11,8,8,10,22,16,196,220,236,50,212,236, + 236,49,0,64,11,8,169,11,188,7,14,169,12,15,169,7,47,236,212,236,16,244,236,48,1,50,22,21,20,6,35,33,17,33,53,33,17,5,33,17, + 33,50,54,53,52,38,3,113,214,231,231,214,254,56,254,149,2,36,1,7,254,249,1,7,126,131,131,2,151,163,168,168,164,3,205,147,254,55,147,254, + 143,95,90,90,94,0,0,0,255,255,0,186,0,0,5,155,4,123,16,39,0,243,4,34,0,0,16,6,3,224,0,0,0,2,0,186,0,0,4,62, + 4,96,0,8,0,19,0,37,64,11,21,69,0,18,15,5,11,8,9,70,20,16,252,236,50,212,236,236,49,0,183,4,169,11,9,188,5,169,19,47, + 236,228,212,236,48,1,52,38,35,33,17,33,50,54,1,51,17,33,50,22,21,20,6,35,33,3,122,131,126,254,250,1,6,126,131,253,64,185,1,14, + 214,231,231,214,254,57,1,76,90,94,254,143,95,3,110,254,55,163,168,168,164,0,0,0,0,1,0,113,255,227,3,231,4,123,0,24,0,77,64,9, + 5,8,18,19,72,7,14,0,25,16,220,60,204,244,236,50,49,0,64,23,14,134,13,136,11,24,134,0,136,2,185,22,7,169,6,187,11,185,16,184, + 22,140,25,16,228,244,236,244,238,16,254,244,238,16,245,238,177,7,11,73,177,2,6,73,80,88,179,7,6,64,2,23,56,89,48,55,22,51,50,54, + 55,33,53,33,46,1,35,34,7,53,54,51,32,0,17,16,0,33,34,39,113,158,157,147,210,19,253,200,2,50,12,159,199,154,161,157,166,1,6,1, + 45,254,219,254,255,189,147,213,86,171,218,147,105,223,86,172,70,254,195,254,241,254,242,254,194,72,0,0,0,2,0,193,255,227,6,76,4,123,0,11, + 0,30,0,58,64,15,32,69,9,18,18,3,18,24,12,25,29,8,28,70,31,16,252,236,50,212,60,236,212,236,236,49,0,64,16,0,185,15,184,27, + 6,185,21,140,27,25,169,30,28,188,27,47,228,212,236,16,244,236,16,244,236,48,1,34,6,21,20,22,51,50,54,53,52,38,1,54,18,51,50,0, + 17,16,0,35,34,0,39,35,17,35,17,51,17,4,74,148,172,171,149,147,172,172,253,113,19,249,240,240,1,18,254,238,240,241,254,249,9,208,184,184, + 3,223,231,201,201,231,232,200,199,233,254,194,190,1,28,254,200,254,236,254,237,254,199,1,46,248,253,247,4,96,254,65,0,2,0,116,0,0,4,34, + 4,96,0,8,0,22,0,60,64,9,20,5,8,17,0,18,9,13,23,16,212,196,236,212,236,50,49,0,64,11,66,6,169,16,188,9,21,169,3,19, + 9,47,60,212,236,16,244,236,48,75,83,88,183,21,17,10,22,17,9,10,9,5,7,16,236,16,236,89,1,20,22,59,1,17,35,34,6,9,1,46, + 1,53,52,54,51,33,17,35,17,35,1,1,122,128,119,248,248,119,128,254,250,1,86,116,154,215,217,1,182,185,229,254,182,3,29,83,94,1,97,92, + 252,143,1,235,26,137,143,162,161,251,160,1,217,254,39,0,255,255,0,113,255,227,4,127,6,107,18,38,3,201,0,0,16,6,0,67,90,5,0,0, + 255,255,0,113,255,227,4,127,6,16,18,38,3,201,0,0,17,7,0,106,0,150,0,0,0,133,177,146,151,66,176,147,176,152,66,177,128,4,66,177, + 129,0,66,124,176,15,176,1,35,73,176,35,176,30,35,73,97,176,128,98,104,176,35,70,97,176,15,70,96,176,146,67,176,1,96,35,66,176,146,67, + 176,1,96,67,176,0,85,88,176,30,176,146,67,176,1,96,67,56,176,30,17,176,2,53,89,177,128,0,66,177,129,0,66,24,176,15,16,176,35,176, + 30,176,1,35,73,104,59,176,35,17,176,3,53,0,176,18,176,35,35,73,176,64,80,88,176,35,176,64,56,176,35,17,176,3,53,176,2,53,89,0, + 0,1,0,47,254,86,4,144,6,20,0,31,0,63,64,15,20,23,8,16,78,8,29,9,5,8,1,3,0,70,32,16,252,60,204,236,50,50,204,244, + 252,204,49,0,64,17,20,169,19,31,8,1,169,7,2,4,26,135,10,13,4,151,30,47,236,212,196,236,16,220,60,236,50,16,212,236,48,19,35,53, + 51,17,51,17,33,21,33,17,62,1,51,50,22,17,20,0,7,53,54,18,53,52,38,35,34,6,21,17,35,223,176,176,185,2,29,253,227,66,178,118, + 182,216,254,169,215,122,245,124,124,154,167,185,3,209,143,1,180,254,76,143,254,109,101,100,233,254,234,226,254,89,41,140,22,1,46,210,208,159,196,158, + 254,251,0,0,255,255,0,186,0,0,3,216,6,109,18,38,3,199,0,0,16,7,0,118,0,134,0,7,0,1,0,113,255,227,3,231,4,123,0,24, + 0,78,64,10,10,11,8,18,16,2,72,22,69,25,16,252,228,50,252,50,204,49,0,64,23,2,134,3,136,5,17,134,16,136,14,185,19,9,169,10, + 187,5,185,0,184,19,140,25,16,228,244,236,244,238,16,254,244,238,16,245,238,177,9,5,73,177,14,10,73,80,88,179,9,10,64,2,23,56,89,48, + 1,50,23,21,38,35,34,6,7,33,21,33,30,1,51,50,55,21,6,35,32,0,17,16,0,2,164,166,157,161,154,199,159,12,2,50,253,200,19,210, + 147,157,158,147,189,254,255,254,219,1,45,4,123,70,172,86,223,105,147,218,171,86,170,72,1,62,1,14,1,15,1,61,255,255,0,111,255,227,3,199, + 4,123,18,6,0,86,0,0,255,255,0,193,0,0,1,121,6,20,18,6,0,76,0,0,255,255,255,244,0,0,2,70,6,16,16,6,0,177,0,0, + 255,255,255,219,254,86,1,121,6,20,18,6,0,77,0,0,0,2,0,76,0,0,6,191,4,96,0,22,0,31,0,54,64,14,33,69,26,18,12,17, + 8,30,7,18,8,6,1,32,16,212,212,236,212,60,236,212,236,236,49,0,64,14,30,169,9,31,169,16,18,169,6,188,1,169,0,16,47,60,236,244, + 236,16,236,212,236,48,51,53,54,55,54,17,53,33,17,51,50,22,21,20,6,35,33,17,33,21,16,7,6,37,50,54,53,52,38,43,1,17,76,182, + 56,68,2,216,171,214,232,231,214,254,155,254,154,88,94,3,120,126,132,132,126,163,153,28,126,177,1,197,183,254,55,163,168,168,164,3,205,111,254,80, + 194,207,118,95,90,90,94,254,143,0,0,0,0,2,0,186,0,0,6,183,4,96,0,18,0,27,0,56,64,16,29,69,22,18,5,10,18,8,26,0, + 11,15,8,13,70,28,16,252,236,50,220,60,236,50,212,236,49,0,64,13,19,169,9,26,11,169,1,16,18,14,188,9,13,47,60,228,50,220,60,236, + 50,16,236,48,1,17,51,50,22,21,20,6,35,33,17,33,17,35,17,51,17,33,17,1,50,54,53,52,38,43,1,17,4,78,171,214,232,231,214,254, + 155,253,222,185,185,2,34,1,92,126,132,132,126,163,4,96,254,55,163,168,168,164,2,4,253,252,4,96,254,55,1,201,252,51,95,90,90,94,254,143, + 0,1,0,47,0,0,4,137,6,20,0,27,0,58,64,15,8,25,19,8,16,78,25,9,5,8,1,3,0,70,28,16,252,60,204,236,50,50,244,236, + 16,204,49,0,64,14,8,1,169,7,2,4,22,135,10,13,4,151,18,26,47,60,236,212,196,236,16,220,60,236,50,48,19,35,53,51,17,51,17,33, + 21,33,17,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21,17,35,223,176,176,185,2,29,253,227,66,179,117,189,202,184,124,124,152,169,185,3, + 209,143,1,180,254,76,143,254,109,101,100,234,237,254,208,1,42,159,158,193,161,254,251,0,255,255,0,186,0,0,4,145,6,109,18,38,3,206,0,0, + 16,6,0,118,111,7,0,0,255,255,0,186,0,0,4,121,6,107,18,38,3,204,0,0,16,6,0,67,93,5,0,0,255,255,0,61,254,86,4,127, + 6,20,18,38,3,215,0,0,16,6,2,154,94,204,0,0,0,1,0,186,254,229,4,129,4,96,0,11,0,41,64,13,13,70,6,8,7,11,169,9, + 3,8,2,70,12,16,252,236,212,252,212,236,236,49,0,183,11,4,169,6,2,188,9,1,47,60,228,50,236,204,48,41,1,17,51,17,33,17,51,17, + 33,17,35,2,84,254,102,185,2,85,185,254,102,147,4,96,252,51,3,205,251,160,254,229,0,1,0,115,255,227,7,5,5,213,0,52,0,56,64,20, + 36,18,37,54,16,32,28,41,22,28,23,13,28,4,9,18,8,4,16,53,16,252,220,236,16,236,212,252,212,236,236,220,236,49,0,64,9,22,36,8, + 129,17,28,149,45,0,47,60,236,50,244,60,204,48,5,34,39,38,17,52,19,54,55,51,6,3,6,21,16,23,22,51,50,55,54,61,1,51,21,20, + 23,22,51,50,55,54,17,52,39,2,39,51,22,23,18,21,16,7,6,35,34,39,38,39,6,7,6,2,58,211,121,123,100,59,93,249,84,135,67,72, + 73,125,114,72,71,199,70,70,116,134,65,71,67,135,84,250,95,56,100,123,123,209,146,101,100,39,39,100,101,29,177,180,1,152,201,1,14,159,127,70, + 254,191,159,183,254,205,107,109,105,104,198,241,241,198,104,105,109,119,1,39,183,159,1,65,70,130,156,254,231,190,254,102,178,177,94,94,173,173,94,94, + 255,255,0,135,255,227,6,39,4,96,16,6,3,93,0,0,0,2,0,30,0,0,5,177,5,213,0,18,0,29,0,58,64,14,31,19,25,5,13,17, + 25,15,0,28,11,9,13,30,16,220,60,204,252,60,60,204,16,212,236,204,49,0,64,15,10,18,149,12,16,14,129,9,24,149,1,173,25,149,9,47, + 236,244,236,16,244,212,60,236,50,48,1,21,33,50,4,21,20,4,35,33,17,33,53,33,53,51,21,33,21,1,52,39,38,35,33,17,33,50,55,54, + 2,88,1,78,251,1,16,254,240,251,253,232,254,144,1,112,202,1,113,1,19,79,78,163,254,188,1,68,163,78,79,4,81,226,218,222,221,218,4,81, + 164,224,224,164,253,102,139,68,67,253,221,68,67,0,0,0,0,2,0,30,0,0,4,231,6,20,0,7,0,25,0,58,64,15,27,69,0,18,23,9, + 17,5,19,15,28,11,9,13,26,16,220,60,204,252,60,60,204,16,212,236,236,49,0,64,14,9,17,169,11,15,13,4,169,19,13,151,5,169,8,47, + 236,228,212,236,16,212,60,236,50,48,36,52,38,35,33,17,33,50,5,17,33,53,33,17,51,17,33,21,33,17,33,50,22,16,6,35,4,35,131,126, + 254,250,1,6,126,253,195,254,187,1,69,185,1,169,254,87,1,14,214,231,231,214,242,180,94,254,143,147,3,205,147,1,180,254,76,147,254,202,163,254, + 176,164,0,0,0,1,0,211,255,227,7,27,5,240,0,43,0,0,1,17,35,17,51,17,51,18,55,54,33,50,23,22,23,21,38,39,38,35,32,7, + 6,7,33,21,33,18,23,22,33,50,55,54,55,21,6,7,6,35,32,39,38,3,1,157,202,202,210,30,157,195,1,83,134,118,119,104,102,115,116,130, + 255,0,136,103,25,2,178,253,70,7,129,137,0,255,130,116,115,102,106,119,118,132,254,173,195,186,9,2,199,253,57,5,213,253,156,1,8,167,208,36, + 35,71,213,95,47,47,156,119,198,170,254,243,148,157,47,47,95,211,72,36,36,207,198,1,79,0,0,0,0,1,0,193,255,227,5,129,4,123,0,35, + 0,0,1,50,23,21,38,35,34,7,6,7,33,21,33,22,23,22,51,50,55,21,6,35,32,39,38,39,35,17,35,17,51,17,51,54,55,54,4,62, + 166,157,161,154,230,92,34,12,1,204,254,44,13,158,85,120,157,158,147,188,254,243,148,123,10,147,184,184,152,23,122,151,4,123,70,172,86,180,65,87, + 143,244,94,51,86,170,72,173,144,228,253,252,4,96,254,51,202,128,158,0,0,2,0,16,0,0,6,248,5,213,0,11,0,14,0,0,33,35,1,33, + 17,35,17,33,1,35,1,51,19,9,1,6,248,225,254,234,254,233,202,254,231,254,234,225,3,2,229,177,254,220,254,220,2,27,253,229,2,27,253,229, + 5,213,252,243,2,55,253,201,0,2,0,51,0,0,6,17,4,96,0,11,0,14,0,0,33,35,3,35,17,35,17,35,3,35,1,51,19,11,1,6, + 17,195,236,227,184,229,236,195,2,142,195,145,243,243,1,149,254,107,1,149,254,107,4,96,253,185,1,161,254,95,0,0,0,2,0,201,0,0,9,20, + 5,213,0,19,0,22,0,0,33,35,1,33,17,35,17,33,1,35,1,33,17,35,17,51,17,33,1,51,19,9,1,9,20,225,254,234,254,233,202,254, + 231,254,234,225,1,111,253,248,202,202,2,95,1,60,229,177,254,220,254,220,2,27,253,229,2,27,253,229,2,199,253,57,5,213,253,156,2,100,252,243, + 2,55,253,201,0,2,0,193,0,0,7,208,4,96,0,19,0,22,0,0,33,35,3,35,17,35,17,35,3,35,1,33,17,35,17,51,17,33,1,51, + 19,11,1,7,208,195,236,227,184,229,236,195,1,28,254,107,184,184,1,233,1,30,195,145,243,243,1,149,254,107,1,149,254,107,1,231,254,25,4,96, + 254,23,1,233,253,185,1,161,254,95,0,0,0,2,0,115,0,0,5,217,5,213,0,23,0,26,0,130,64,20,25,26,14,13,20,28,15,19,14,0, + 7,28,12,8,13,24,0,28,3,27,16,220,236,57,204,220,180,15,8,79,8,2,93,57,236,16,204,220,182,0,19,64,14,64,19,3,93,57,236,17, + 18,57,57,49,0,64,14,66,12,15,17,0,3,25,149,24,13,129,20,8,2,47,60,60,244,57,236,212,60,236,50,48,75,83,88,64,20,24,17,15, + 26,24,25,17,14,15,14,24,17,12,25,24,26,17,13,12,13,7,5,16,237,8,16,237,7,5,16,237,8,16,237,89,178,64,28,1,1,93,1,17, + 35,17,6,7,6,17,35,16,55,54,55,1,33,1,22,23,22,17,35,16,39,38,39,1,33,3,139,202,147,100,130,213,189,120,170,254,81,5,18,254, + 80,164,116,188,213,128,96,248,1,62,253,131,2,89,253,167,2,89,28,126,164,254,229,1,98,210,134,49,2,234,253,19,50,130,210,254,158,1,30,161, + 122,202,2,40,0,2,0,107,0,0,4,123,4,96,0,2,0,26,0,126,64,20,0,1,3,26,9,28,4,8,3,13,20,28,25,21,26,2,13,28, + 16,27,16,220,236,57,204,220,178,128,21,1,93,57,236,16,204,220,178,48,3,1,93,57,236,17,18,57,57,49,0,64,14,66,25,4,17,13,16,0, + 149,2,26,188,9,21,15,47,60,60,244,57,236,212,60,236,50,48,75,83,88,64,20,2,17,4,1,2,0,17,3,4,3,2,17,25,0,2,1,17, + 26,25,26,7,5,16,237,8,16,237,7,5,16,237,8,16,237,89,180,112,28,143,28,2,1,93,1,33,19,9,1,22,23,22,17,35,52,39,38,39, + 17,35,17,6,7,6,21,35,16,55,54,55,1,3,69,254,93,209,2,8,254,187,107,75,137,195,86,58,86,184,83,56,86,194,137,74,108,254,187,3, + 182,254,150,2,20,253,204,38,86,156,254,236,199,116,79,26,254,92,1,162,26,75,116,201,1,20,156,85,39,2,52,0,0,2,0,201,0,0,7,196, + 5,213,0,30,0,33,0,0,9,1,33,1,22,23,22,17,35,16,39,38,39,17,35,17,6,7,6,17,35,16,55,54,55,33,17,35,17,51,17,5, + 1,33,3,239,254,159,5,18,254,80,164,116,188,213,128,96,153,202,147,100,130,213,189,85,110,253,181,202,202,3,132,1,62,253,131,3,113,2,100,253, + 19,50,130,210,254,158,1,30,161,122,32,253,167,2,89,28,126,164,254,229,1,98,210,95,52,253,57,5,213,253,156,110,2,40,0,0,0,2,0,193, + 0,0,6,46,4,96,0,30,0,33,0,0,9,1,33,1,22,23,22,17,35,52,39,38,39,17,35,17,6,7,6,21,35,16,55,54,55,33,17,35, + 17,51,17,1,33,19,3,55,254,231,4,16,254,187,107,75,137,195,86,58,86,184,83,56,86,194,137,27,31,254,146,184,184,3,127,254,93,209,2,119, + 1,233,253,204,38,86,156,254,236,199,116,79,26,254,92,1,162,26,75,116,201,1,20,156,31,24,254,25,4,96,254,23,1,63,254,150,0,1,0,115, + 254,86,4,115,7,122,0,83,0,0,1,20,7,6,35,34,38,35,34,21,20,51,50,55,54,23,22,23,21,38,35,34,6,35,34,39,38,53,52,55, + 54,51,33,50,55,54,53,52,39,38,35,53,50,22,51,50,55,54,53,52,33,34,7,53,54,55,3,51,19,55,54,55,54,55,54,51,50,23,21,39, + 38,35,34,15,1,22,23,22,21,16,5,22,23,22,4,115,115,152,198,68,186,35,96,220,65,128,116,32,98,84,68,116,59,252,60,125,74,163,53,63, + 117,1,95,104,70,65,187,88,249,18,86,23,163,82,117,254,197,165,222,160,129,159,115,160,106,30,15,23,23,35,66,26,35,39,11,15,34,50,90,166, + 98,114,254,239,141,82,85,1,190,207,103,136,8,130,114,12,11,2,7,37,167,39,27,44,97,146,122,81,94,88,82,106,189,55,25,166,2,38,54,141, + 238,74,180,45,13,1,131,254,131,222,64,24,39,18,27,10,87,5,2,111,202,24,87,100,167,254,253,69,30,92,96,0,0,1,0,91,254,116,3,200, + 6,6,0,79,0,0,1,20,7,6,35,34,38,35,34,21,20,23,22,51,50,54,51,50,23,21,38,35,34,6,35,34,39,38,53,16,51,33,50,54, + 53,52,39,38,39,34,35,53,50,23,50,51,32,53,52,39,38,35,34,7,53,54,55,3,51,19,55,54,55,54,51,50,23,21,38,35,34,15,1,4, + 21,20,7,22,23,22,3,200,118,109,162,68,168,25,80,98,33,39,44,178,45,99,88,59,98,49,210,50,105,63,137,196,1,44,90,110,78,60,114,5, + 178,11,33,32,21,1,53,94,72,92,145,184,126,102,159,115,160,106,47,21,43,81,26,35,50,15,34,50,91,1,48,232,111,71,80,1,82,158,94,86, + 8,129,97,27,9,36,39,139,34,23,37,82,151,1,12,96,89,76,56,43,8,152,1,160,81,42,33,55,167,31,11,1,131,254,131,222,99,23,50,10, + 87,7,111,202,47,242,196,50,22,64,73,0,0,1,0,16,0,0,6,193,5,213,0,28,0,0,1,39,38,35,34,7,6,7,1,35,17,35,17,35, + 1,51,1,51,17,51,17,51,19,54,55,54,51,50,23,6,193,58,25,32,37,29,66,60,254,228,250,202,250,254,92,195,1,94,125,202,125,232,78,104, + 66,129,51,56,5,20,7,3,25,56,161,253,10,254,202,1,54,4,96,252,84,3,235,252,19,2,114,212,80,51,16,0,0,1,0,50,254,86,6,208, + 6,30,0,28,0,0,1,39,38,35,34,7,6,7,1,35,17,35,17,35,1,51,1,51,17,51,17,51,19,54,55,54,51,50,23,6,208,58,25,32, + 37,29,66,60,254,228,250,183,250,254,92,195,1,94,125,183,125,232,78,104,66,129,51,56,3,222,7,3,25,56,161,253,10,254,86,1,170,4,96,252, + 84,5,106,250,148,2,114,212,80,51,16,0,255,255,0,115,255,227,5,217,5,240,18,6,1,97,0,0,255,255,0,113,255,227,4,117,4,123,18,6, + 2,55,0,0,0,1,0,16,0,0,6,39,5,240,0,18,0,0,1,50,23,21,39,38,35,34,7,6,7,1,35,1,51,9,1,18,54,5,169,63, + 63,68,22,25,73,34,71,84,254,129,229,253,198,211,1,217,1,56,115,174,5,240,21,187,10,4,34,67,221,252,20,5,213,251,23,3,61,1,50,149, + 0,1,0,50,0,0,5,31,4,123,0,19,0,0,1,50,23,21,39,38,35,34,7,6,7,1,35,1,51,1,19,54,55,54,4,180,51,56,58,19, + 38,37,29,65,61,254,228,250,254,92,195,1,94,232,80,102,66,4,123,16,141,7,3,25,55,162,253,10,4,96,252,84,2,112,213,79,51,0,0,0, + 255,255,0,16,0,0,6,39,7,112,16,39,22,195,4,228,1,122,18,6,4,8,0,0,255,255,0,50,0,0,5,31,6,102,16,39,2,192,4,194, + 0,0,18,6,4,9,0,0,0,3,0,115,254,86,7,179,5,240,0,17,0,30,0,44,0,0,9,1,6,7,6,43,1,53,51,50,55,54,55,19, + 1,51,27,1,1,16,7,2,32,3,38,16,55,18,32,19,22,3,16,39,38,32,7,6,17,16,23,22,32,55,54,7,179,254,20,82,70,74,124,147, + 108,76,42,38,55,124,254,162,195,253,253,253,63,95,126,254,0,127,96,96,127,2,0,126,95,213,28,56,254,152,58,28,29,57,1,104,57,27,4,96, + 251,56,203,58,61,154,36,33,137,1,55,3,107,253,138,2,118,254,138,254,221,208,254,236,1,19,209,2,68,209,1,20,254,237,209,254,222,1,6,114, + 234,234,116,254,251,254,252,116,234,234,114,0,0,3,0,113,254,86,6,255,4,123,0,17,0,31,0,37,0,0,9,1,6,7,6,43,1,53,51,50, + 55,54,55,19,1,51,27,1,0,16,7,6,35,34,39,38,16,55,54,51,50,23,2,16,35,34,16,51,6,255,254,20,82,70,74,124,147,108,76,42, + 38,55,124,254,162,195,253,253,253,117,95,115,204,206,116,96,96,116,206,204,115,100,219,224,224,4,96,251,56,203,58,61,154,36,33,137,1,55,3,107, + 253,138,2,118,254,171,254,72,167,201,200,166,1,188,166,200,201,252,205,3,96,252,160,0,0,2,0,115,255,227,7,45,5,240,0,41,0,82,0,0, + 37,51,50,55,54,53,52,39,38,43,1,6,7,6,7,6,34,39,38,39,38,39,35,34,7,6,21,20,23,22,59,1,54,55,54,55,54,50,23,22, + 23,22,7,35,32,39,38,16,55,54,33,51,54,55,54,55,54,50,23,22,23,22,23,51,32,23,22,17,16,7,6,33,35,6,7,6,7,6,34,39, + 38,39,38,4,93,30,235,114,128,128,114,235,30,11,15,22,27,26,62,26,27,22,16,10,46,235,114,130,130,114,235,46,10,16,22,27,26,62,26,27, + 22,16,254,46,254,161,152,189,189,152,1,95,45,11,16,22,27,26,62,26,31,18,16,11,29,1,94,152,188,188,152,254,162,29,10,17,22,27,26,62, + 26,31,18,16,194,145,164,242,243,164,145,20,14,21,12,11,11,12,21,16,18,145,164,243,242,164,145,18,16,21,12,11,11,12,21,16,161,170,210,2, + 116,211,170,21,15,21,12,11,11,14,19,17,19,170,211,254,198,254,199,210,171,19,17,21,12,11,11,14,19,17,0,0,0,2,0,113,255,227,5,161, + 4,123,0,38,0,80,0,0,37,51,50,55,54,53,52,39,38,43,1,6,7,14,1,34,38,39,38,39,35,34,7,6,21,20,23,22,59,1,54,55, + 62,1,50,23,22,23,22,7,35,32,39,38,53,52,55,54,33,51,54,55,54,55,54,50,23,22,23,22,23,51,32,23,22,21,20,7,6,33,35,6, + 7,6,7,6,34,39,38,39,38,3,114,45,161,72,86,86,63,170,45,7,10,18,44,52,44,18,10,7,45,163,71,86,85,72,163,45,7,10,18,44, + 52,22,27,13,9,201,46,254,255,120,137,137,116,1,5,46,7,9,13,27,22,52,22,27,13,9,7,46,1,2,119,137,137,116,254,251,46,7,9,13, + 27,22,52,22,27,13,9,164,96,116,183,167,131,97,11,10,17,20,20,17,10,11,95,116,184,188,112,95,11,10,17,20,10,12,15,10,147,137,156,238, + 233,162,136,10,10,15,12,10,10,12,15,10,10,136,156,239,232,162,137,10,10,15,12,10,10,12,15,10,255,255,0,118,255,227,8,250,7,116,16,38, + 18,203,0,0,16,39,4,26,6,151,0,0,16,7,4,24,6,48,1,39,255,255,0,152,255,227,7,161,6,16,16,38,18,204,0,0,16,39,4,26, + 5,252,254,156,16,7,4,24,5,149,255,195,255,255,0,115,255,227,7,5,7,51,16,39,23,131,0,99,1,83,16,6,3,244,0,0,255,255,0,135, + 255,227,6,39,5,224,16,38,23,131,0,0,16,6,3,245,0,0,0,0,0,1,0,115,254,86,5,39,5,240,0,29,0,57,64,10,0,28,27,13, + 48,22,25,5,16,30,16,252,236,252,212,180,47,27,63,27,2,93,236,49,0,64,12,14,161,13,174,18,149,9,145,28,26,149,0,47,236,204,244,236, + 244,236,48,180,15,31,31,31,2,1,93,33,35,32,39,38,17,16,55,54,33,50,23,22,23,21,38,39,38,35,32,7,6,17,16,23,22,51,33,17, + 35,3,250,174,254,165,187,195,195,195,1,83,134,118,119,104,102,115,116,130,255,0,136,136,136,152,240,1,107,201,198,208,1,83,1,104,207,208,36,35, + 71,213,95,47,47,156,157,254,216,254,211,130,148,253,176,0,0,1,0,113,254,86,3,231,4,123,0,29,0,57,64,10,29,18,26,12,72,21,18,4, + 69,30,16,252,236,244,212,236,49,0,64,12,12,134,13,136,17,185,8,184,28,25,169,0,47,236,204,244,252,245,238,48,64,11,15,31,16,31,128,31, + 144,31,160,31,5,1,93,33,32,39,38,53,16,55,54,33,50,23,22,23,21,38,39,38,35,34,7,6,21,20,23,22,59,1,17,35,17,2,152,254, + 251,141,149,151,150,1,6,85,81,81,76,78,79,78,80,179,99,99,99,99,179,245,201,150,159,250,1,18,157,157,17,18,35,172,43,22,21,113,114,205, + 185,114,113,253,195,1,170,0,0,1,0,59,255,165,3,202,3,167,0,19,0,0,1,7,39,7,23,7,39,7,39,55,39,55,23,55,39,55,23,55, + 23,7,3,202,100,216,105,216,100,216,125,174,125,216,100,216,105,216,100,216,105,174,105,2,17,174,125,181,125,174,125,216,100,216,125,174,125,181,125,174, + 125,181,100,181,0,1,251,218,4,222,255,66,6,122,0,47,0,0,1,33,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54, + 55,54,51,33,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,254,185,254,51,10,11,19,20,25,24,56,24,25,20, + 19,11,10,10,11,19,20,25,24,28,1,205,10,11,19,20,25,24,56,24,25,20,20,10,10,10,11,19,20,25,24,5,103,27,25,27,18,19,11,10, + 10,11,19,18,27,25,27,28,25,27,18,19,11,10,27,25,27,18,19,11,10,10,11,19,21,24,25,28,27,25,27,18,19,11,10,0,0,1,253,7, + 5,41,0,9,6,77,0,13,0,0,19,35,38,35,34,7,6,7,53,54,55,54,51,32,9,118,23,162,93,91,147,136,139,74,119,125,1,36,5,41, + 155,47,75,23,134,39,42,67,0,1,253,179,4,194,254,165,6,97,0,8,0,0,1,34,17,53,51,21,35,20,55,254,165,242,241,133,134,4,194,1, + 11,148,158,157,3,0,0,0,0,1,253,179,4,194,254,165,6,97,0,8,0,0,1,16,35,53,22,53,35,53,51,254,165,242,134,133,241,5,205,254, + 245,103,3,157,158,0,0,0,0,1,249,202,4,217,0,9,6,77,0,13,0,0,1,18,33,50,5,4,37,21,36,39,36,39,38,7,249,202,135,1, + 175,114,1,69,1,50,1,32,254,95,239,254,217,102,221,152,5,1,1,76,123,116,1,134,23,92,113,7,12,207,0,0,0,8,247,214,254,144,3,70, + 7,96,0,12,0,25,0,38,0,51,0,64,0,77,0,90,0,103,0,0,1,35,46,1,35,34,6,7,35,62,1,32,22,1,35,46,1,35,34,6, + 7,35,62,1,32,22,5,35,46,1,35,34,6,7,35,62,1,32,22,1,35,46,1,35,34,6,7,35,62,1,32,22,5,35,46,1,35,34,6,7, + 35,62,1,32,22,1,35,46,1,35,34,6,7,35,62,1,32,22,5,35,46,1,35,34,6,7,35,62,1,32,22,1,35,46,1,35,34,6,7,35, + 62,1,32,22,254,199,118,11,97,87,86,96,13,118,10,158,1,34,158,3,56,118,11,97,87,86,96,13,118,10,158,1,34,158,249,174,118,11,97,87, + 86,96,13,118,10,158,1,34,158,6,102,118,11,97,87,86,96,13,118,10,158,1,34,158,249,174,118,11,97,87,86,96,13,118,10,158,1,34,158,7, + 183,118,11,97,87,86,96,13,118,10,158,1,34,158,247,12,118,11,97,87,86,96,13,118,10,158,1,34,158,4,137,118,11,97,87,86,96,13,118,10, + 158,1,34,158,6,65,75,75,74,76,143,144,144,254,81,75,75,74,76,143,144,144,143,75,75,74,76,143,144,144,250,1,75,75,74,76,143,144,144,143, + 75,75,74,76,143,144,144,2,41,75,75,74,76,143,144,144,143,75,75,74,76,143,144,144,251,152,75,75,74,76,143,144,144,0,0,0,0,8,248,88, + 253,195,2,194,8,45,0,5,0,11,0,17,0,23,0,29,0,35,0,41,0,47,0,0,39,55,23,19,7,3,1,7,39,3,55,19,1,39,55,37, + 23,5,1,23,7,5,39,37,1,53,51,5,21,45,1,21,35,37,53,5,1,35,53,19,51,11,1,51,21,3,35,19,107,150,121,111,92,169,251,119, + 150,121,111,92,169,5,31,150,122,1,86,92,254,227,250,76,149,121,254,169,91,1,28,6,96,172,1,64,254,192,248,194,172,254,192,1,64,4,95,211, + 164,129,82,211,211,164,129,82,90,150,121,254,169,92,1,29,5,181,150,121,1,87,92,254,227,254,241,149,122,110,91,169,251,119,150,121,111,92,168,2, + 24,212,164,130,82,212,212,164,130,82,2,223,172,1,64,254,192,248,194,172,254,192,1,64,255,255,0,201,254,86,5,252,7,109,16,38,23,132,0,0, + 16,7,22,192,4,245,1,117,255,255,0,193,254,86,5,56,6,20,16,38,23,133,0,0,16,7,2,154,0,160,255,204,0,2,0,33,0,0,4,236, + 5,213,0,18,0,29,0,58,64,14,31,19,25,5,13,17,25,15,0,28,11,9,13,30,16,220,60,204,252,60,60,204,16,212,236,204,49,0,64,15, + 10,18,149,12,16,14,129,9,24,149,1,173,25,149,9,47,236,244,236,16,244,212,60,236,50,48,1,21,33,50,4,21,20,4,35,33,17,35,53,51, + 53,51,21,51,21,1,52,39,38,35,33,17,33,50,55,54,1,147,1,78,251,1,16,254,240,251,253,232,168,168,202,168,1,220,79,78,163,254,188,1, + 68,163,78,79,4,81,226,218,222,221,218,4,81,164,224,224,164,253,102,139,68,67,253,221,68,67,0,0,0,2,0,38,0,0,4,69,5,158,0,10, + 0,30,0,57,64,15,32,69,0,18,17,22,30,6,12,28,28,24,22,26,31,16,220,60,204,252,60,60,204,16,212,236,236,49,0,64,13,22,30,169, + 24,28,26,5,169,12,26,6,169,21,47,236,196,212,236,16,212,60,236,50,48,1,52,39,38,35,33,17,33,50,55,54,1,17,33,50,23,22,16,7, + 6,35,33,17,35,53,51,17,51,17,51,21,3,129,62,67,128,254,249,1,7,129,66,62,253,248,1,15,208,121,116,116,115,214,254,57,155,155,184,157, + 1,76,94,42,46,254,151,46,43,2,223,254,202,85,82,254,176,82,82,3,209,143,1,62,254,194,143,0,0,2,0,201,0,0,4,225,5,213,0,15, + 0,28,0,0,1,23,7,39,6,43,1,17,35,17,33,50,23,22,21,20,39,54,55,52,38,43,1,17,51,50,55,39,55,4,85,140,106,146,126,214, + 254,202,1,200,251,128,129,226,12,1,154,141,254,254,114,71,215,106,3,35,117,126,123,83,253,168,5,213,113,114,219,146,45,44,57,134,146,253,207,47, + 180,126,0,0,0,2,0,186,254,86,4,164,4,123,0,16,0,41,0,0,37,39,55,23,54,53,52,39,38,32,7,6,16,23,22,51,50,5,23,7, + 39,6,35,34,39,38,39,17,35,17,51,21,54,55,54,51,50,23,22,16,7,6,3,42,140,110,138,79,83,84,254,220,84,83,83,84,146,70,1,27, + 147,111,149,87,108,123,88,89,58,185,185,58,89,88,123,204,127,128,128,12,152,167,93,165,115,197,203,116,115,116,115,254,106,116,115,20,174,93,179,46, + 48,49,100,253,174,6,10,170,100,48,49,162,162,253,240,162,15,0,0,0,0,1,0,201,0,0,4,106,7,7,0,7,0,27,64,13,3,6,149,1, + 129,0,3,4,6,28,1,4,8,16,252,252,220,204,49,0,47,244,236,204,48,51,17,33,17,51,17,33,17,201,2,247,170,253,41,5,213,1,50,254, + 36,250,213,0,0,1,0,186,0,0,3,208,5,154,0,7,0,29,183,9,3,4,6,8,1,70,8,16,252,252,220,204,204,49,0,181,3,6,169,1, + 188,0,47,244,236,204,48,51,17,33,17,51,17,33,17,186,2,131,147,253,162,4,96,1,58,254,51,252,51,0,0,0,0,1,0,71,0,0,4,239, + 5,213,0,13,0,41,64,20,1,12,149,9,4,8,149,5,129,0,15,6,10,12,9,28,2,4,1,14,16,220,60,204,252,60,204,204,196,49,0,47, + 244,252,220,60,236,50,48,33,17,33,53,33,17,33,21,33,17,33,21,33,17,1,78,254,249,1,7,3,161,253,41,2,35,253,221,2,148,170,2,151, + 170,254,19,170,253,108,0,0,0,1,0,56,0,0,4,85,4,96,0,13,0,43,64,10,15,6,10,12,9,8,2,4,1,14,16,220,60,204,252,60, + 204,220,204,49,0,64,10,1,12,169,9,4,8,169,5,188,0,47,244,252,220,60,236,50,48,33,17,33,53,33,17,33,21,33,17,33,21,33,17,1, + 63,254,249,1,7,3,22,253,162,1,160,254,96,1,244,170,1,194,157,254,219,170,254,12,0,1,0,201,254,102,4,204,5,213,0,27,0,51,64,12, + 18,24,28,4,29,12,0,6,28,3,4,28,16,252,252,60,220,204,196,252,204,49,0,64,14,18,149,17,176,2,0,149,7,2,6,149,3,129,2,47, + 244,236,16,212,236,16,244,236,48,1,17,35,17,33,21,33,17,33,50,23,22,21,17,16,6,43,1,53,51,50,55,54,53,17,52,38,35,1,147,202, + 3,161,253,41,1,161,186,113,109,204,228,76,62,134,56,55,124,124,2,199,253,57,5,213,170,254,70,119,114,238,254,206,254,242,244,170,75,75,194,1, + 34,159,158,0,0,1,0,186,254,86,4,11,4,96,0,29,0,51,64,12,19,25,8,4,31,12,0,6,8,3,70,30,16,252,252,60,220,204,196,252, + 204,49,0,64,14,19,169,18,189,1,0,169,7,1,6,169,3,188,1,47,244,236,16,212,236,16,252,236,48,1,17,35,17,33,21,33,17,51,32,23, + 22,21,17,20,7,6,43,1,53,51,50,55,54,53,17,52,39,38,35,1,114,184,3,22,253,162,250,1,7,70,82,82,81,181,193,172,110,33,38,38, + 49,134,1,231,254,25,4,96,170,254,193,71,81,229,254,242,214,96,96,156,48,55,147,1,8,170,32,41,0,1,0,40,254,191,8,145,5,213,0,23, + 0,0,1,51,17,1,51,9,1,51,17,35,17,35,9,1,17,35,17,9,1,35,9,1,51,1,3,234,202,2,170,245,253,223,1,215,136,197,41,254, + 19,254,254,202,254,254,254,19,211,2,68,253,223,245,2,170,5,213,253,30,2,226,253,179,253,34,254,21,1,65,3,1,254,233,254,22,1,234,1,23, + 252,255,3,136,2,77,253,30,0,1,0,70,254,229,7,3,4,96,0,23,0,0,1,51,17,1,51,9,1,51,17,35,17,35,1,7,17,35,17,39, + 1,35,9,1,51,1,3,63,183,1,233,214,254,110,1,102,122,184,33,254,135,187,183,187,254,135,197,1,204,254,110,214,1,233,4,96,253,242,2,14, + 254,81,253,232,254,76,1,27,2,54,201,254,147,1,109,201,253,202,2,177,1,175,253,242,255,255,0,135,254,117,4,154,5,240,16,38,0,122,57,0, + 18,6,3,171,0,0,0,0,255,255,0,133,254,117,3,200,4,124,16,38,0,122,206,0,18,6,3,203,0,0,0,0,0,1,0,201,254,191,5,180, + 5,213,0,15,0,0,19,51,17,1,33,9,1,51,17,35,17,35,9,1,17,35,201,202,2,210,1,3,253,191,1,237,160,197,69,253,250,254,239,202, + 5,213,253,30,2,226,253,178,253,35,254,21,1,65,3,1,254,233,254,22,0,1,0,186,254,229,4,179,4,96,0,15,0,0,19,51,17,1,51,9, + 1,51,17,35,17,35,1,7,17,35,186,183,2,7,226,254,84,1,119,142,184,56,254,115,197,183,4,96,253,242,2,14,254,79,253,234,254,76,1,27, + 2,53,200,254,147,0,0,0,0,1,0,201,0,0,5,134,5,213,0,18,0,0,19,51,17,55,17,51,21,1,33,9,1,35,1,17,35,17,7,17, + 35,201,202,173,100,1,193,1,3,253,191,2,95,220,253,250,100,173,202,5,213,253,30,177,1,84,238,1,203,253,178,252,121,3,1,254,37,1,117,177, + 254,22,0,0,0,1,0,186,0,0,4,145,4,96,0,18,0,0,19,51,17,55,53,51,21,1,51,9,1,35,1,17,35,53,7,17,35,186,183,96, + 101,1,66,226,254,84,1,227,206,254,115,101,96,183,4,96,253,242,97,221,118,1,70,254,79,253,81,2,53,254,197,212,97,254,147,0,0,1,0,33, + 0,0,5,134,5,213,0,19,0,0,19,51,21,51,21,35,17,1,33,9,1,35,9,1,17,35,17,35,53,51,201,202,168,168,2,210,1,3,253,191, + 2,95,220,253,250,254,239,202,168,168,5,213,224,144,254,142,2,226,253,178,252,121,3,1,254,233,254,22,4,101,144,0,0,1,0,61,0,0,4,145, + 6,20,0,19,0,0,19,51,21,33,21,33,17,1,51,9,1,35,1,7,17,35,17,35,53,51,186,183,1,100,254,156,2,7,226,254,84,1,227,206, + 254,115,197,183,125,125,6,20,122,125,253,53,2,14,254,79,253,81,2,53,200,254,147,5,29,125,0,0,0,1,0,50,0,0,6,178,5,213,0,13, + 0,95,64,11,8,5,1,4,6,9,1,28,12,0,14,16,212,220,236,50,212,196,17,57,57,49,0,64,14,66,13,160,0,8,9,5,2,4,3,0, + 175,10,6,47,60,236,50,23,57,16,236,48,75,83,88,64,22,7,17,6,8,17,5,9,4,6,5,3,17,4,2,17,5,8,9,9,4,9,4,9, + 7,16,60,60,4,237,16,5,237,7,8,16,237,5,16,237,89,19,33,17,1,33,9,1,35,9,1,17,35,17,33,50,2,141,2,210,1,3,253,191, + 2,95,220,253,250,254,239,202,254,61,5,213,253,30,2,226,253,178,252,121,3,1,254,233,254,22,5,43,0,1,0,42,0,0,5,130,4,96,0,13, + 0,95,64,11,8,5,1,4,6,9,1,8,11,0,14,16,212,220,236,50,212,196,17,57,57,49,0,64,14,66,13,160,0,8,9,5,2,4,3,0, + 188,10,6,47,60,236,50,23,57,16,236,48,75,83,88,64,22,7,17,6,8,17,5,9,4,6,5,3,17,4,2,17,5,8,9,9,4,9,4,9, + 7,16,60,60,4,237,16,5,237,7,8,16,237,5,16,237,89,19,33,17,1,51,9,1,35,1,7,17,35,17,33,42,2,56,2,7,226,254,84,1, + 227,206,254,115,197,183,254,127,4,96,253,242,2,14,254,79,253,81,2,53,200,254,147,3,198,0,0,0,0,1,0,201,254,191,6,4,5,213,0,15, + 0,54,64,26,12,149,2,173,4,0,129,6,149,9,14,10,7,149,10,11,3,28,5,56,13,1,28,0,4,16,16,252,236,50,252,236,50,60,236,49, + 0,47,60,204,236,228,50,252,236,48,178,80,17,1,1,93,19,51,17,33,17,51,17,51,17,35,17,35,17,33,17,35,201,202,2,222,202,201,201,202, + 253,34,202,5,213,253,156,2,100,250,213,254,21,1,65,2,199,253,57,0,0,1,0,193,254,229,5,64,4,96,0,15,0,49,64,26,13,169,2,4, + 0,188,6,169,9,11,15,17,70,12,4,8,7,169,10,5,13,1,8,0,70,16,16,252,236,50,220,60,236,236,50,236,49,0,47,60,204,236,228,50, + 220,236,48,19,51,17,33,17,51,17,51,17,35,17,35,17,33,17,35,193,184,2,87,184,184,184,184,253,169,184,4,96,254,51,1,205,252,57,254,76, + 1,27,2,4,253,252,0,0,0,1,0,201,0,0,8,18,5,213,0,13,0,45,64,24,6,149,4,10,149,2,173,4,0,129,12,8,5,9,3,28, + 7,56,11,1,28,0,4,14,16,252,236,50,252,236,50,196,49,0,47,60,228,50,252,236,16,236,48,19,51,17,33,17,33,21,33,17,35,17,33,17, + 35,201,202,2,222,3,161,253,41,202,253,34,202,5,213,253,156,2,100,170,250,213,2,199,253,57,0,0,0,1,0,193,0,0,6,230,4,96,0,13, + 0,43,64,22,6,169,4,11,169,2,4,0,188,9,13,5,10,4,8,7,11,1,8,0,70,14,16,252,236,50,220,236,50,196,49,0,47,60,228,50, + 220,236,16,236,48,19,51,17,33,17,33,21,33,17,35,17,33,17,35,193,184,2,87,3,22,253,162,184,253,169,184,4,96,254,51,1,205,170,252,74, + 2,4,253,252,0,1,0,201,254,102,8,116,5,213,0,29,0,56,64,14,31,15,28,19,26,3,28,0,8,4,28,7,4,30,16,252,236,212,60,236, + 220,204,252,204,49,0,64,15,29,149,10,173,2,3,149,7,129,6,19,149,20,6,2,47,60,220,236,16,244,236,16,244,236,48,1,17,35,17,33,17, + 35,17,33,17,33,50,23,22,21,17,16,6,43,1,53,51,50,55,54,53,17,52,38,35,5,59,202,253,34,202,4,114,1,161,186,113,109,204,228,76, + 62,134,56,55,124,124,2,199,253,57,5,43,250,213,5,213,253,156,119,114,238,254,206,254,242,244,170,75,75,194,1,34,159,158,0,0,0,1,0,193, + 254,86,7,33,4,96,0,31,0,51,64,14,33,15,8,20,27,3,8,0,8,4,8,7,70,32,16,252,236,212,60,236,220,204,252,204,49,0,64,11, + 31,9,3,169,7,188,2,19,21,2,6,47,60,220,204,16,244,236,220,204,48,1,17,35,17,33,17,35,17,33,17,51,32,23,22,21,17,20,7,6, + 43,1,53,51,50,55,54,53,17,52,39,38,7,4,136,184,253,169,184,3,199,250,1,7,70,82,82,81,181,193,172,110,33,38,38,49,134,1,231,254, + 25,3,198,252,58,4,96,254,23,71,81,229,254,242,214,96,96,156,48,55,147,1,8,164,38,46,5,0,0,2,0,115,255,227,6,247,5,241,0,65, + 0,89,0,0,37,46,3,53,52,62,4,51,50,30,4,21,20,14,2,7,30,1,51,50,54,55,21,14,1,35,34,46,2,39,14,1,35,34,36,38, + 2,53,52,18,62,1,55,21,14,3,21,20,30,2,51,50,54,55,62,3,53,52,46,4,35,34,14,4,21,20,30,2,4,43,57,108,82,50,19,42, + 68,97,129,83,78,125,97,70,45,21,26,63,106,81,38,104,59,62,101,51,46,120,61,38,81,85,87,43,66,195,121,170,254,244,188,99,91,172,247,157, + 115,171,112,56,60,123,190,129,82,128,177,63,83,48,20,11,23,36,48,62,38,49,72,51,33,18,7,40,66,84,174,49,137,170,196,107,66,138,131,116, + 87,50,50,84,112,123,127,58,83,180,178,170,74,26,21,19,26,168,23,18,8,20,35,27,38,52,116,207,1,29,168,160,1,16,203,125,14,167,22,102, + 154,205,124,125,222,167,98,25,109,58,134,142,145,69,47,102,99,89,67,40,43,71,91,96,95,38,98,171,142,110,0,0,0,2,0,113,255,227,5,120, + 4,122,0,63,0,80,0,0,19,52,62,2,55,21,14,3,21,20,30,2,51,50,54,55,46,3,53,52,62,2,51,50,30,2,21,20,6,7,30,1, + 51,50,62,2,55,21,14,3,35,34,38,39,14,3,35,34,46,2,5,62,3,53,52,46,2,35,34,14,2,21,20,113,75,143,209,134,93,138,91,45, + 50,96,138,88,39,86,28,36,63,47,27,40,80,116,77,66,112,80,45,92,95,35,68,30,27,45,41,42,24,17,37,45,56,37,55,130,67,30,70,73, + 71,31,135,212,145,76,3,86,34,45,26,11,22,33,40,18,26,44,33,19,2,40,131,216,156,88,3,155,6,70,114,152,88,98,160,114,62,11,17,37, + 103,120,130,64,93,159,115,65,57,104,146,89,155,241,94,19,10,4,10,19,15,157,10,17,12,7,28,44,18,27,18,9,84,153,214,184,38,94,100,99, + 43,75,105,66,31,38,72,105,67,247,0,0,255,255,0,115,254,117,5,39,5,240,16,39,0,122,1,45,0,0,18,6,3,181,0,0,255,255,0,113, + 254,117,3,231,4,123,16,39,0,122,0,143,0,0,18,6,3,213,0,0,0,1,255,250,254,191,4,233,5,213,0,11,0,44,64,13,13,10,64,1, + 28,4,11,28,8,64,5,8,12,16,196,220,236,252,60,236,252,196,49,0,64,9,10,6,149,9,129,1,149,3,5,47,204,236,244,236,50,48,37,51, + 17,35,17,35,17,33,53,33,21,33,2,215,201,201,203,253,238,4,239,253,238,170,254,21,1,65,5,43,170,170,0,0,0,1,0,60,254,229,4,109, + 4,96,0,11,0,40,64,10,13,9,1,8,4,11,8,6,8,12,16,220,220,252,60,236,220,204,49,0,64,9,11,7,169,8,188,0,169,3,5,47, + 204,236,244,236,50,48,37,51,17,35,17,35,17,33,53,33,21,33,2,175,184,184,181,254,66,4,49,254,66,153,254,76,1,27,3,182,170,170,0,0, + 255,255,255,252,0,0,4,231,5,213,18,6,0,60,0,0,0,1,0,61,254,86,4,127,4,96,0,8,0,111,64,16,4,8,188,2,9,6,3,0, + 8,3,4,0,8,3,4,9,16,212,75,176,10,84,75,176,8,84,91,88,185,0,11,0,64,56,89,75,176,20,84,88,185,0,11,255,192,56,89,212, + 252,73,58,17,18,57,49,0,16,204,228,50,48,64,25,7,17,8,0,8,6,17,5,6,0,8,0,6,17,6,7,3,3,4,5,17,4,4,3,66, + 75,83,88,7,16,5,237,7,16,8,237,7,16,8,237,7,16,5,237,89,34,37,17,35,17,1,51,9,1,51,2,197,195,254,59,195,1,94,1,94, + 195,18,254,68,1,188,4,78,252,148,3,108,0,1,255,252,0,0,4,231,5,213,0,16,0,0,1,33,17,35,17,33,53,33,53,1,51,9,1,51, + 1,21,33,3,223,254,248,203,254,249,1,7,253,240,217,1,158,1,155,217,253,240,1,8,1,115,254,141,1,115,170,170,3,14,253,154,2,102,252,242, + 170,0,0,0,0,1,0,61,254,86,4,127,4,96,0,16,0,0,9,1,21,33,21,33,21,35,53,33,53,33,53,1,51,9,1,4,127,254,70,1, + 6,254,250,195,254,239,1,17,254,59,195,1,94,1,94,4,96,251,178,88,170,186,186,170,88,4,78,252,148,3,108,0,0,1,0,61,254,191,5,59, + 5,213,0,15,0,0,37,51,17,35,17,35,9,1,35,9,1,51,9,1,51,1,4,203,112,197,20,254,92,254,89,218,2,21,254,47,217,1,115,1, + 117,217,254,32,170,254,21,1,65,2,123,253,133,3,29,2,184,253,213,2,43,253,51,0,0,1,0,59,254,229,4,121,4,96,0,15,0,0,37,51, + 17,35,17,35,9,1,35,9,1,51,9,1,51,1,4,8,113,184,33,254,186,254,186,217,1,179,254,114,217,1,41,1,41,217,254,107,153,254,76,1, + 27,1,184,254,72,2,74,2,22,254,113,1,143,253,223,0,0,1,255,250,254,191,7,71,5,213,0,15,0,53,64,16,17,5,149,8,2,28,3,10, + 13,64,15,28,12,64,10,16,16,212,228,252,228,16,212,236,60,252,204,49,0,64,11,15,10,149,2,12,129,7,4,0,149,9,47,236,50,204,244,60, + 236,50,48,37,33,17,51,17,51,17,35,17,33,17,33,53,33,21,33,2,214,2,222,202,201,201,251,142,253,238,4,239,253,238,170,5,43,250,213,254, + 21,1,65,5,43,170,170,0,0,1,0,5,254,229,6,66,4,96,0,15,0,51,64,14,17,5,169,2,8,8,3,10,13,15,8,12,10,16,16,220, + 196,252,196,16,212,60,236,252,204,49,0,64,11,15,11,169,2,12,188,7,4,0,169,9,47,236,50,204,244,60,236,50,48,37,33,17,51,17,51,17, + 35,17,33,17,33,53,33,21,33,2,120,2,90,184,184,184,252,57,254,66,4,49,254,66,153,3,199,252,57,254,76,1,27,3,182,170,170,0,0,0, + 0,1,0,175,254,191,5,124,5,213,0,20,0,46,64,12,1,22,4,6,19,28,4,20,13,28,12,21,16,220,236,212,60,236,50,236,50,49,0,64, + 11,7,149,17,173,19,12,129,0,149,3,5,47,204,236,228,50,244,236,48,37,51,17,35,17,35,17,33,34,39,38,53,17,51,17,20,22,51,33,17, + 51,4,179,201,201,203,254,95,186,113,109,201,124,124,1,120,203,170,254,21,1,65,2,199,119,114,238,1,55,254,217,159,158,2,100,0,0,1,0,150, + 254,229,4,184,4,96,0,21,0,70,64,12,1,23,70,6,20,8,4,21,13,8,12,22,16,220,236,212,60,236,50,236,50,49,0,64,10,7,169,18, + 20,12,188,0,169,3,5,47,204,236,228,50,212,236,176,5,176,7,35,73,176,18,176,20,35,73,82,88,177,7,18,184,255,192,176,2,23,56,89,48, + 37,51,17,35,17,35,17,33,34,39,38,61,1,51,21,20,23,22,51,33,17,51,4,0,184,184,184,254,169,153,102,92,184,52,53,104,1,41,184,153, + 254,76,1,27,2,9,95,86,184,234,211,117,59,59,1,190,0,1,0,175,0,0,4,179,5,213,0,24,0,0,1,35,34,39,38,53,17,51,17,20, + 22,59,1,17,51,17,51,17,51,17,35,17,35,17,35,2,130,59,186,113,109,201,124,124,18,144,214,203,203,214,144,2,199,119,114,238,1,55,254,217, + 159,158,1,57,254,199,2,100,250,43,2,199,254,207,0,0,0,1,0,150,0,0,4,0,4,96,0,24,0,0,1,53,51,21,51,17,51,17,35,17, + 35,21,35,53,35,34,39,38,61,1,51,21,20,23,22,1,249,160,175,184,184,175,160,8,153,102,92,184,52,43,2,164,194,196,1,190,251,160,2,9, + 196,196,95,86,184,234,211,117,59,48,0,0,0,1,0,175,0,0,4,179,5,213,0,15,0,36,64,10,17,8,28,6,12,0,28,15,4,16,16,252, + 236,50,212,236,204,49,0,183,2,149,11,173,15,129,7,14,47,60,244,244,236,48,1,17,33,50,22,21,17,35,17,52,38,35,33,17,35,17,1,122, + 1,161,186,222,201,124,124,254,136,203,5,213,253,156,233,238,254,102,1,138,159,158,253,57,5,213,0,0,255,255,0,186,0,0,4,100,6,20,18,6, + 0,75,0,0,0,2,0,20,255,227,7,20,5,240,0,34,0,42,0,73,64,17,35,36,9,15,36,25,8,51,9,25,24,30,18,29,0,24,43,16, + 220,50,220,236,16,236,244,236,196,17,18,57,49,0,64,22,16,161,15,174,12,30,24,8,149,0,36,173,12,149,20,40,149,4,145,20,140,43,16,228, + 244,236,16,236,244,60,236,50,204,16,244,236,48,1,18,55,54,33,32,23,22,19,33,16,0,33,50,54,55,21,6,7,6,35,32,39,38,3,6,39, + 38,61,1,51,21,20,23,22,37,33,38,39,38,32,7,6,1,178,34,150,188,1,58,1,67,181,187,1,251,112,1,18,1,18,139,252,112,111,131,132, + 146,254,162,197,188,10,170,118,122,170,75,66,1,64,3,173,24,98,130,254,72,128,97,3,109,1,10,167,210,210,219,254,132,254,244,254,206,96,95,215, + 70,36,36,205,194,1,85,1,103,107,223,76,62,160,65,57,2,191,124,164,164,124,0,0,0,2,0,15,255,227,5,102,4,123,0,37,0,46,0,105, + 64,17,46,38,21,29,38,8,19,75,0,6,18,5,21,18,11,0,47,16,220,50,236,220,64,11,0,5,112,48,127,5,176,48,207,48,5,93,236,16, + 244,236,196,17,18,57,49,0,64,26,19,38,20,30,134,29,136,25,6,11,38,169,20,25,185,34,0,20,187,42,185,15,184,34,140,47,16,228,244,236, + 228,178,111,20,1,93,50,16,236,16,252,60,204,16,244,178,47,29,1,93,236,17,18,57,48,1,34,39,38,61,1,51,21,20,23,22,51,54,55,54, + 33,50,23,22,29,1,33,22,23,22,51,50,55,54,55,21,6,7,6,35,32,39,38,1,38,39,38,35,34,7,6,7,1,88,144,89,96,156,48,57, + 74,26,116,146,0,255,226,131,132,252,178,12,102,103,183,106,100,99,98,104,99,110,101,254,243,156,148,3,78,2,82,83,136,154,93,92,14,2,4,82, + 90,172,70,49,151,33,38,197,130,161,145,146,250,90,190,100,99,26,26,52,174,44,20,22,156,148,1,129,151,90,90,87,87,158,0,0,0,2,0,20, + 254,135,7,20,5,240,0,7,0,45,0,0,1,33,38,39,38,32,7,6,7,18,55,54,33,32,23,22,19,33,16,0,33,50,54,55,21,6,7,6, + 7,17,35,17,36,39,38,3,6,39,38,61,1,51,21,20,23,22,2,139,3,173,24,98,130,254,72,128,97,241,34,150,188,1,58,1,67,181,187,1, + 251,112,1,18,1,18,139,252,112,111,131,109,119,178,254,253,160,188,10,170,118,122,170,75,66,3,109,191,124,164,164,124,191,1,10,167,210,210,219,254, + 132,254,244,254,206,96,95,215,70,36,30,5,254,163,1,99,32,166,195,1,84,1,103,107,223,76,62,160,65,57,0,0,0,2,0,15,254,183,5,102, + 4,123,0,8,0,49,0,0,1,38,39,38,35,34,7,6,15,1,34,39,38,61,1,51,21,20,23,22,51,54,55,54,33,50,23,22,29,1,33,22, + 23,22,51,50,55,54,55,21,6,7,6,7,17,35,17,38,39,38,4,174,2,82,83,136,154,93,92,14,198,144,89,96,156,48,57,74,26,116,146,0, + 255,226,131,132,252,178,12,102,103,183,106,100,99,98,104,99,79,74,166,194,123,148,2,148,151,90,90,87,87,158,143,82,90,172,70,49,151,33,38,197, + 130,161,145,146,250,90,190,100,99,26,26,52,174,44,20,16,4,254,210,1,51,26,123,148,255,255,0,201,0,0,1,147,5,213,18,6,0,44,0,0, + 255,255,0,40,0,0,8,118,7,109,16,39,22,192,6,91,1,117,18,6,3,170,0,0,255,255,0,70,0,0,6,239,6,72,16,39,2,154,1,168, + 0,0,18,6,3,202,0,0,0,1,0,201,254,102,5,53,5,213,0,28,0,0,1,51,50,23,22,21,17,16,6,43,1,53,51,50,55,54,53,17, + 52,38,35,33,17,35,17,51,17,1,33,2,169,139,186,113,109,204,228,76,62,134,56,55,124,124,254,136,202,202,2,158,1,4,3,113,119,114,238,254, + 206,254,242,244,170,75,75,194,1,34,159,158,253,57,5,213,253,137,2,119,0,1,0,191,254,86,4,136,4,96,0,30,0,0,1,51,32,23,22,21, + 17,20,7,6,43,1,53,51,50,55,54,53,17,52,39,38,35,33,17,35,17,51,17,1,51,2,94,20,1,5,72,82,82,81,181,193,172,110,33,38, + 38,44,139,254,252,185,185,2,37,235,2,119,71,81,229,254,242,214,96,96,156,48,55,147,1,8,166,36,41,254,25,4,96,254,29,1,227,0,0,0, + 0,1,0,54,254,86,6,3,5,213,0,20,0,0,33,35,17,33,21,16,3,6,5,53,54,55,18,25,1,33,17,51,21,1,35,5,58,202,254,27, + 132,98,254,145,212,67,117,3,120,201,254,146,134,5,43,212,254,24,254,170,253,56,167,46,168,1,37,2,53,1,26,250,213,170,254,86,0,1,0,46, + 254,86,5,43,4,96,0,20,0,0,37,51,21,1,35,19,35,17,33,21,16,3,6,5,53,54,55,54,17,53,33,4,115,184,254,222,123,229,184,254, + 123,118,94,254,204,179,59,98,2,245,153,153,254,86,1,170,3,199,134,254,146,254,252,207,29,153,27,127,207,1,167,212,0,1,0,201,254,102,5,59, + 5,213,0,20,0,49,64,14,15,8,0,28,22,4,10,56,7,3,28,5,4,21,16,252,236,50,252,236,252,60,204,49,0,64,11,14,16,4,2,149, + 8,173,9,6,129,4,47,228,50,252,236,16,220,204,48,37,17,33,17,35,17,51,17,33,17,51,17,16,6,43,1,53,51,50,55,54,4,113,253,34, + 202,202,2,222,202,206,227,76,62,134,56,55,104,2,95,253,57,5,213,253,156,2,100,250,147,254,242,244,170,75,75,0,0,1,0,193,254,86,4,136, + 4,96,0,21,0,47,64,13,16,8,0,8,23,70,10,7,3,8,5,70,22,16,252,236,50,220,236,252,60,204,49,0,64,10,15,17,4,2,169,8, + 9,6,188,4,47,244,60,220,236,16,220,204,48,5,17,33,17,35,17,51,17,33,17,51,17,20,7,6,43,1,53,51,50,55,54,3,208,253,169,184, + 184,2,87,184,82,81,181,193,172,110,33,38,20,2,24,253,252,4,96,254,51,1,205,251,140,214,96,96,156,48,55,0,0,1,0,201,254,86,6,4, + 5,213,0,16,0,0,33,35,17,33,17,35,17,51,17,33,17,51,17,51,21,1,35,5,59,202,253,34,202,202,2,222,202,201,254,146,134,2,199,253, + 57,5,213,253,156,2,100,250,213,170,254,86,0,1,0,193,254,86,5,64,4,96,0,16,0,0,33,35,17,33,17,35,17,51,17,33,17,51,17,51, + 21,1,35,4,136,184,253,169,184,184,2,87,184,184,254,222,123,2,4,253,252,4,96,254,51,1,205,252,57,153,254,86,0,1,0,175,254,191,4,179, + 5,213,0,20,0,47,64,13,20,28,17,1,14,28,22,4,15,8,28,7,21,16,220,236,212,236,252,50,50,236,49,0,64,11,2,149,12,173,14,7, + 129,0,149,19,17,47,204,236,228,50,244,236,48,37,17,33,34,39,38,53,17,51,17,20,22,51,33,17,51,17,35,17,35,17,3,232,254,95,186,113, + 109,201,124,124,1,120,203,203,201,170,2,29,119,114,238,1,55,254,217,159,158,2,100,250,43,254,191,1,235,0,0,0,0,1,0,150,254,229,4,0, + 4,96,0,21,0,71,64,13,21,8,18,1,15,8,23,70,16,8,8,7,22,16,220,236,212,236,252,50,50,236,49,0,64,10,2,169,13,15,7,188, + 0,169,20,18,47,204,236,228,50,212,236,176,18,176,2,35,73,176,13,176,15,35,73,82,88,177,2,13,184,255,192,176,2,23,56,89,48,37,17,33, + 34,39,38,61,1,51,21,20,23,22,51,33,17,51,17,35,17,35,17,3,72,254,169,153,102,92,184,52,53,104,1,41,184,184,184,153,1,112,95,86, + 184,234,211,117,59,59,1,190,251,160,254,229,1,180,0,0,0,1,0,201,254,86,6,232,5,213,0,17,0,0,37,51,21,1,35,1,35,17,1,35, + 1,17,35,17,33,9,1,33,6,31,201,254,146,134,1,43,197,254,127,203,254,127,196,1,45,1,125,1,127,1,45,170,170,254,86,1,170,5,31,252, + 0,4,0,250,225,5,213,252,8,3,248,0,0,1,0,193,254,86,6,0,4,96,0,17,0,0,37,51,21,1,35,19,35,17,1,35,1,17,35,17, + 33,9,1,33,5,72,184,254,222,123,229,178,254,203,184,254,202,178,1,6,1,62,1,63,1,4,153,153,254,86,1,170,3,176,253,39,2,217,252,80, + 4,96,253,18,2,238,0,0,255,255,0,193,0,0,1,121,6,20,18,6,0,79,0,0,255,255,0,16,0,0,5,104,7,146,16,39,2,154,0,206, + 1,74,19,6,3,164,0,0,0,18,180,24,0,8,19,7,43,49,0,64,5,111,0,111,8,2,93,48,255,255,0,123,255,227,4,45,6,31,16,38, + 2,154,79,215,19,6,3,196,0,0,0,8,180,34,0,8,25,7,43,49,255,255,0,16,0,0,5,104,7,78,18,38,3,164,0,0,17,7,22,185, + 4,188,1,117,0,20,180,10,18,13,5,7,43,64,9,48,18,63,13,0,18,15,13,4,93,49,0,0,255,255,0,123,255,227,4,45,6,16,18,38, + 3,196,0,0,17,6,0,106,82,0,0,32,180,20,45,40,11,7,43,64,21,127,40,111,40,80,45,95,40,64,45,79,40,48,45,63,40,0,45,15, + 40,10,93,49,255,255,0,8,0,0,7,72,5,213,18,6,0,136,0,0,255,255,0,123,255,227,7,111,4,123,18,6,0,168,0,0,255,255,0,201, + 0,0,4,139,7,109,16,39,22,192,4,161,1,117,19,6,3,169,0,0,0,7,64,3,64,0,1,93,49,0,0,0,255,255,0,113,255,227,4,127, + 6,72,16,39,2,154,0,150,0,0,19,6,3,201,0,0,0,7,64,3,112,0,1,93,49,0,0,0,255,255,0,117,255,227,5,217,5,240,18,6, + 1,81,0,0,255,255,0,113,255,227,4,127,4,123,18,6,2,27,0,0,255,255,0,117,255,227,5,217,7,78,16,39,22,185,5,32,1,117,18,6, + 4,108,0,0,255,255,0,113,255,227,4,127,6,16,16,38,0,106,84,0,18,6,4,109,0,0,0,0,255,255,0,40,0,0,8,118,7,78,16,39, + 22,185,6,81,1,117,18,6,3,170,0,0,255,255,0,70,0,0,6,239,6,16,16,39,0,106,1,158,0,0,18,6,3,202,0,0,255,255,0,135, + 255,227,4,154,7,78,16,39,22,185,4,135,1,117,18,6,3,171,0,0,255,255,0,133,255,227,3,200,6,16,16,38,0,106,58,0,18,6,3,203, + 0,0,0,0,255,255,0,160,255,193,4,248,5,213,18,6,1,121,0,0,255,255,0,88,254,76,4,47,4,96,18,6,2,84,0,0,255,255,0,201, + 0,0,5,51,7,49,16,39,0,113,0,245,1,59,18,6,3,172,0,0,255,255,0,186,0,0,4,121,5,245,16,39,0,113,0,146,255,255,18,6, + 3,204,0,0,255,255,0,201,0,0,5,51,7,78,16,39,22,185,4,245,1,117,18,6,3,172,0,0,255,255,0,186,0,0,4,121,6,16,16,39, + 0,106,0,146,0,0,18,6,3,204,0,0,255,255,0,115,255,227,5,217,7,78,18,38,3,178,0,0,17,7,22,185,5,39,1,117,0,20,180,3, + 31,26,9,7,43,64,9,64,31,79,26,16,31,31,26,4,93,49,0,0,255,255,0,113,255,227,4,117,6,16,18,38,3,210,0,0,17,6,0,106, + 115,0,0,20,180,3,31,26,9,7,43,64,9,64,31,79,26,48,31,63,26,4,93,49,255,255,0,115,255,227,5,217,5,240,18,6,1,97,0,0, + 255,255,0,113,255,227,4,117,4,123,18,6,2,55,0,0,255,255,0,115,255,227,5,217,7,78,18,38,4,124,0,0,16,7,22,185,5,39,1,117, + 255,255,0,113,255,227,4,117,6,16,18,38,4,125,0,0,16,6,0,106,115,0,0,0,255,255,0,111,255,227,5,35,7,78,16,39,22,185,4,103, + 1,117,18,6,3,193,0,0,255,255,0,113,255,227,3,231,6,16,16,38,0,106,226,0,18,6,3,225,0,0,0,0,255,255,0,35,0,0,4,189, + 7,49,16,39,0,113,0,114,1,59,18,6,3,183,0,0,255,255,0,61,254,86,4,127,5,245,16,38,0,113,94,255,18,6,3,215,0,0,0,0, + 255,255,0,35,0,0,4,189,7,78,16,39,22,185,4,114,1,117,18,6,3,183,0,0,255,255,0,61,254,86,4,127,6,16,16,38,0,106,94,0, + 18,6,3,215,0,0,0,0,255,255,0,35,0,0,4,189,7,107,16,39,22,194,4,114,1,117,18,6,3,183,0,0,255,255,0,61,254,86,4,127, + 6,102,16,38,2,159,94,0,18,6,3,215,0,0,0,0,255,255,0,175,0,0,4,179,7,78,16,39,22,185,4,204,1,117,18,6,3,187,0,0, + 255,255,0,150,0,0,4,0,6,16,16,38,0,106,94,0,18,6,3,219,0,0,0,0,0,1,0,201,254,191,4,106,5,213,0,9,0,35,64,10, + 11,2,6,149,9,4,28,1,4,10,16,252,252,60,236,204,196,49,0,182,4,149,1,129,6,8,0,47,204,204,244,236,48,51,17,33,21,33,17,51, + 17,35,17,201,3,161,253,41,201,201,5,213,170,251,127,254,21,1,65,0,0,1,0,186,254,229,3,208,4,96,0,9,0,35,64,10,11,2,6,169, + 9,4,8,1,70,10,16,252,252,60,236,220,204,49,0,182,4,169,1,188,6,8,0,47,204,204,244,236,48,51,17,33,21,33,17,51,17,35,17,186, + 3,22,253,162,184,184,4,96,170,252,227,254,76,1,27,0,255,255,0,201,0,0,6,70,7,78,18,38,3,191,0,0,16,7,22,185,5,183,1,117, + 255,255,0,186,0,0,5,155,6,16,18,38,3,223,0,0,16,7,0,106,1,8,0,0,0,1,0,71,254,86,4,239,5,213,0,25,0,57,64,13, + 25,14,27,6,10,12,9,28,2,21,4,1,26,16,220,60,60,204,252,60,204,204,196,220,204,49,0,64,14,20,21,14,0,1,12,149,9,4,8,149, + 5,129,0,47,244,252,220,60,236,50,16,204,220,204,48,33,17,33,53,33,17,33,21,33,17,33,21,33,17,33,21,20,7,6,43,1,53,51,50,54, + 53,1,78,254,249,1,7,3,161,253,41,2,35,253,221,1,105,71,82,191,254,233,105,76,2,148,170,2,151,170,254,19,170,253,236,148,200,96,110,156, + 97,173,0,0,0,1,0,56,254,86,4,85,4,96,0,25,0,59,64,14,27,6,9,25,14,10,12,9,8,2,21,4,1,26,16,220,60,196,204,252, + 60,204,220,204,16,220,204,49,0,64,14,20,21,14,0,1,12,169,9,4,8,169,5,188,0,47,244,236,220,60,252,60,16,204,220,204,48,33,17,33, + 53,33,17,33,21,33,17,33,21,33,17,33,21,20,7,6,43,1,53,51,50,54,53,1,63,254,249,1,7,3,22,253,162,1,160,254,96,1,110,70, + 82,192,254,233,106,75,1,244,170,1,194,157,254,219,170,254,140,148,200,96,110,156,97,173,0,1,0,61,254,102,5,42,5,213,0,23,0,0,37,22, + 7,6,7,6,43,1,53,51,50,55,54,55,9,1,35,9,1,51,9,1,51,1,5,42,1,2,15,83,102,228,76,62,135,55,40,11,254,94,254,89, + 218,2,21,254,47,217,1,115,1,117,217,254,32,26,2,24,190,98,122,170,75,53,115,2,120,253,133,3,29,2,184,253,213,2,43,253,51,0,0,0, + 0,1,0,59,254,86,4,100,4,96,0,23,0,0,9,2,22,21,20,7,6,43,1,53,50,55,62,1,53,9,1,35,9,1,51,9,1,4,100,254, + 107,1,107,27,67,81,196,193,196,25,79,53,254,189,254,186,217,1,179,254,114,217,1,41,1,41,4,96,253,223,254,23,38,57,205,97,115,156,3,10, + 109,152,1,180,254,72,2,74,2,22,254,113,1,143,0,0,0,1,0,61,0,0,5,59,5,213,0,17,0,0,19,51,9,1,51,1,33,21,33,1, + 35,9,1,35,1,33,53,33,129,217,1,115,1,117,217,254,78,1,116,254,144,1,206,217,254,92,254,89,218,1,212,254,140,1,150,5,213,253,213,2, + 43,253,119,144,253,68,2,123,253,133,2,188,144,0,0,0,0,1,0,59,0,0,4,121,4,96,0,17,0,0,9,1,51,9,1,51,1,33,21,33, + 1,35,9,1,35,1,33,53,1,183,254,169,217,1,41,1,41,217,254,170,1,13,254,224,1,126,217,254,186,254,186,217,1,127,254,223,2,148,1,204, + 254,113,1,143,254,52,144,253,252,1,184,254,72,2,4,144,0,2,0,145,0,0,4,180,5,213,0,10,0,21,0,38,64,10,23,4,5,20,28,11, + 0,25,16,22,16,220,236,212,236,50,236,49,0,64,9,6,149,20,173,11,129,5,149,12,47,236,228,244,236,48,1,20,23,22,51,33,17,33,34,7, + 6,1,17,33,34,36,53,52,36,51,33,17,1,102,79,78,163,1,68,254,188,163,78,79,3,78,253,232,251,254,240,1,16,251,1,78,1,183,138,67, + 68,2,35,67,68,3,147,250,43,218,221,222,218,2,102,0,0,2,0,113,0,0,3,245,4,96,0,10,0,22,0,37,64,11,24,70,5,21,8,11, + 0,18,17,69,23,16,252,236,212,236,50,236,49,0,183,6,169,21,11,188,5,169,12,47,236,228,212,236,48,1,20,23,22,51,33,17,33,34,7,6, + 1,17,33,34,39,38,16,55,54,51,33,17,1,53,62,66,129,1,7,254,249,128,67,62,2,192,254,57,214,115,116,116,121,208,1,15,1,76,90,43, + 46,1,105,46,42,2,182,251,160,82,82,1,80,82,85,1,197,0,0,0,0,2,0,145,255,227,7,67,5,213,0,12,0,48,0,57,64,14,50,4, + 38,28,41,13,27,12,28,29,5,25,23,49,16,220,236,212,236,50,57,212,236,236,49,0,64,16,34,8,149,19,1,149,26,173,45,19,140,40,188,29, + 129,49,16,236,236,228,50,244,236,16,236,50,48,1,33,34,7,6,16,23,22,51,50,55,54,53,19,6,7,6,7,6,35,34,39,38,53,52,36,51, + 33,17,51,17,20,23,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,3,234,254,188,163,78,79,79,95,129,180,75,86,33,12,14,51,106, + 94,110,238,129,136,1,16,251,1,78,201,63,52,112,105,59,63,202,110,104,215,217,102,49,2,201,67,68,254,234,80,95,109,125,159,254,221,29,28,96, + 54,49,129,137,202,222,218,2,102,251,236,143,91,74,74,79,155,2,159,253,90,224,127,120,120,57,0,0,0,2,0,113,255,227,6,115,4,96,0,13, + 0,48,0,56,64,15,50,70,38,8,41,14,13,27,8,30,5,18,22,69,49,16,252,236,212,236,50,57,212,236,236,49,0,64,14,34,9,169,49,1, + 169,26,45,18,140,40,29,188,49,16,236,204,228,50,212,236,16,236,50,48,1,33,34,7,6,21,20,23,22,51,50,55,54,53,19,6,7,6,35,34, + 39,38,53,52,55,54,51,33,17,51,17,20,23,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,3,61,254,249,128,67,62,65,64,106,148, + 92,45,49,67,93,94,136,172,102,101,116,121,208,1,15,184,62,60,106,104,60,62,184,100,104,206,211,100,31,2,2,46,42,94,92,58,57,109,52,156, + 254,246,108,48,49,97,96,166,170,82,85,1,197,253,97,159,80,79,79,82,157,1,65,254,184,236,115,120,120,37,0,0,0,1,0,201,255,227,7,3, + 5,240,0,55,0,64,64,15,57,46,28,44,6,11,25,27,44,0,25,35,18,6,56,16,252,212,236,204,212,252,204,16,236,204,49,0,64,19,31,5, + 149,6,39,149,50,18,161,19,174,15,149,23,145,45,50,140,56,16,228,204,244,236,244,236,16,236,212,236,57,48,1,52,39,38,43,1,53,51,50,55, + 54,53,52,39,38,35,34,6,7,53,54,55,54,51,50,23,22,21,20,7,6,7,22,23,22,21,20,23,22,51,50,55,54,53,17,51,17,20,7,6, + 35,34,39,38,39,38,3,170,92,93,165,174,182,149,79,79,81,82,152,83,190,114,115,100,101,89,230,134,134,71,71,131,145,82,81,63,52,112,105,59, + 63,202,110,104,215,217,102,48,28,33,1,178,132,74,75,166,59,60,112,115,61,62,36,38,180,32,16,16,104,105,178,124,85,86,33,31,98,98,144,128, + 91,74,74,79,155,2,159,253,90,224,127,120,120,56,80,97,0,1,0,171,255,227,6,70,4,124,0,53,0,71,64,14,55,46,18,44,11,18,27,44, + 0,18,35,6,20,54,16,220,196,212,236,204,212,236,16,236,204,49,0,64,19,20,134,19,136,15,185,23,184,54,5,169,6,54,39,185,50,140,44,54, + 16,204,244,236,16,212,236,16,244,252,176,12,75,81,88,252,27,244,89,236,48,1,52,39,38,43,1,53,51,50,55,54,53,52,39,38,35,34,7,6, + 7,53,62,1,51,50,23,22,21,20,7,6,7,22,23,22,21,20,23,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,3,19,78,72,137, + 148,155,116,67,68,70,69,119,71,81,80,97,98,170,76,196,113,114,60,60,112,129,64,69,62,61,105,104,60,62,184,100,104,206,199,112,98,1,56,102, + 56,51,152,44,45,70,64,46,46,13,13,29,167,24,24,78,79,141,93,64,65,24,25,72,79,72,88,68,69,79,82,157,1,65,254,184,236,115,120,117, + 101,0,0,0,0,1,0,201,254,86,5,60,5,240,0,41,0,58,64,13,8,13,25,29,39,28,43,2,25,37,20,6,42,16,252,212,236,204,236,212, + 252,204,49,0,64,18,33,7,149,8,0,20,161,21,174,17,149,25,145,39,149,40,189,0,47,236,236,244,236,244,236,16,212,236,57,48,33,35,17,52, + 39,38,43,1,53,51,50,55,54,53,52,39,38,35,34,6,7,53,54,55,54,51,50,23,22,21,20,7,6,7,22,23,22,21,17,51,17,35,4,115, + 201,92,93,165,174,182,149,79,79,81,82,152,83,190,114,115,100,101,89,230,134,134,71,71,131,145,82,81,201,201,1,177,133,74,75,166,59,60,112,115, + 61,62,36,38,180,32,16,16,104,105,178,124,85,86,33,31,98,97,146,254,249,253,172,0,0,1,0,171,254,86,4,131,4,124,0,41,0,63,64,12, + 17,18,33,1,18,43,6,18,41,12,26,42,16,220,196,212,236,204,236,212,236,49,0,64,17,26,134,25,136,21,185,29,184,4,11,169,12,0,169,2, + 189,4,47,236,236,212,236,16,244,252,176,12,75,81,88,252,27,244,89,236,48,37,51,17,35,17,35,17,52,39,38,43,1,53,51,50,55,54,53,52, + 39,38,35,34,7,6,7,53,62,1,51,50,23,22,21,20,7,6,7,22,23,22,21,3,200,187,184,184,78,72,137,148,155,116,67,68,70,69,119,71, + 81,80,97,98,170,76,196,113,114,60,60,112,126,67,69,153,253,189,1,170,1,70,88,56,51,152,44,45,70,64,46,46,13,13,29,167,24,24,78,79, + 141,93,64,65,24,24,73,75,106,0,0,0,0,1,0,54,255,227,7,202,5,213,0,33,0,52,64,13,35,4,11,28,10,21,28,0,22,28,33,28, + 34,16,212,212,236,212,236,212,252,236,49,0,64,14,22,149,33,129,34,5,149,16,140,28,149,27,10,34,16,204,60,236,244,236,16,244,236,48,1,17, + 20,23,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,53,17,33,21,16,3,6,5,53,54,55,18,25,1,5,58,63,52,112,105,59,63, + 202,110,104,215,214,105,110,254,27,132,98,254,145,212,67,117,5,213,251,236,143,91,74,74,79,155,2,159,253,90,224,127,120,120,125,226,3,113,212,254, + 24,254,170,253,56,167,46,168,1,37,2,53,1,26,0,0,0,1,0,46,255,227,6,238,4,96,0,32,0,52,64,13,34,70,10,8,9,20,8,0, + 21,8,32,27,33,16,212,212,236,212,236,212,252,236,49,0,64,14,21,169,32,188,33,4,169,15,140,27,169,26,9,33,16,204,60,236,244,236,16,244, + 236,48,1,17,20,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,53,17,33,21,16,3,6,5,53,54,55,54,17,53,4,115,122,103,104, + 60,62,184,100,104,206,199,112,98,254,123,118,94,254,204,179,59,98,4,96,253,4,87,138,79,82,157,1,65,254,184,236,115,120,117,101,123,2,143,134, + 254,146,254,252,207,29,153,27,127,207,1,167,212,0,0,0,255,255,0,201,255,227,8,45,5,213,18,6,1,184,0,0,0,1,0,193,255,227,7,3, + 4,96,0,28,0,54,64,15,30,70,10,8,9,20,28,8,0,21,25,8,24,70,29,16,252,236,50,220,236,50,212,252,236,49,0,64,13,21,169,26, + 28,24,188,23,4,169,15,140,9,23,47,204,244,236,16,228,50,220,236,48,1,17,20,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,61, + 1,33,17,35,17,51,17,33,17,4,136,122,103,104,60,62,184,100,104,206,199,112,98,253,169,184,184,2,87,4,96,253,4,87,138,79,82,157,1,65, + 254,184,236,115,120,117,101,123,204,253,252,4,96,254,51,1,205,0,0,0,0,1,0,115,255,227,5,137,5,240,0,27,0,48,64,11,29,4,16,25, + 28,27,20,28,10,16,28,16,252,236,220,236,196,236,49,0,64,14,22,149,6,26,16,149,15,18,149,13,145,6,140,28,16,228,244,236,212,252,204,16, + 236,48,1,20,7,6,7,6,35,32,39,38,16,55,54,33,32,23,21,38,33,32,17,16,33,50,54,53,17,51,5,137,100,45,137,124,151,254,155,196, + 192,191,197,1,101,1,39,225,225,254,234,253,219,2,37,215,123,202,1,186,224,127,57,33,30,210,204,2,208,205,210,142,215,191,253,159,253,160,148,164, + 1,240,0,0,0,1,0,113,255,227,4,70,4,123,0,27,0,48,64,11,29,69,6,18,18,20,13,18,0,69,28,16,252,236,212,236,196,236,49,0, + 64,14,16,185,24,19,7,185,6,9,185,4,184,24,140,28,16,228,244,236,212,252,204,16,236,48,19,16,55,54,33,50,23,21,38,35,34,7,6,16, + 23,22,51,50,17,53,51,21,20,6,35,32,39,38,113,146,150,1,11,208,186,190,196,189,98,90,90,98,189,226,184,201,229,254,252,149,142,2,47,1, + 14,157,161,110,170,124,124,114,254,124,114,124,1,62,190,197,236,231,166,158,0,1,255,250,255,227,5,102,5,213,0,25,0,47,64,12,9,28,11,27, + 24,64,0,28,23,64,20,26,16,212,228,252,228,204,220,236,49,0,64,12,5,149,16,21,0,149,23,129,16,140,10,26,16,204,228,244,236,50,16,236, + 48,1,17,20,23,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,53,17,33,53,33,21,2,215,63,52,111,105,59,63,202,110,104,215,214, + 105,110,253,238,4,239,5,43,252,150,143,91,74,74,79,155,2,159,253,90,224,127,120,120,125,226,3,113,170,170,0,0,0,1,0,5,255,227,4,246, + 4,96,0,25,0,50,64,10,10,8,11,27,24,0,8,21,23,26,16,212,220,252,204,204,220,236,49,0,64,12,5,169,16,140,26,0,22,169,23,188, + 10,26,16,204,244,236,50,16,244,236,178,16,10,1,93,48,1,17,20,23,22,51,50,55,54,53,17,51,17,20,7,6,35,34,39,38,53,17,33,53, + 33,21,2,120,62,61,105,104,60,62,184,100,104,206,199,112,98,254,66,4,49,3,182,253,174,86,70,69,79,82,157,1,65,254,184,236,115,120,117,101, + 123,2,126,170,170,0,0,0,255,255,0,164,255,227,4,123,5,240,18,6,1,82,0,0,255,255,0,133,255,227,3,200,4,124,18,6,3,73,0,0, + 0,1,0,84,254,102,5,58,5,213,0,24,0,47,64,11,13,26,4,19,28,7,20,28,6,1,25,16,212,212,236,212,236,236,204,49,0,64,13,13, + 149,12,189,25,20,149,6,129,1,149,0,25,16,50,236,244,236,16,244,236,48,51,53,54,55,54,17,53,33,17,16,6,43,1,53,51,50,55,54,53, + 17,33,21,16,3,6,84,221,58,87,3,120,205,227,77,63,134,55,55,254,27,102,98,170,48,163,246,2,100,254,250,147,254,242,244,170,75,76,193,4, + 195,184,253,202,254,248,253,0,0,1,0,76,254,86,4,115,4,96,0,24,0,47,64,11,13,26,70,19,8,7,20,8,6,1,25,16,212,212,236,212, + 236,236,204,49,0,64,13,13,169,12,189,25,20,169,6,188,1,169,0,25,16,50,236,244,236,16,244,236,48,51,53,54,55,54,17,53,33,17,20,6, + 43,1,53,51,50,55,54,53,17,33,21,16,7,6,76,187,51,68,2,245,163,181,70,49,97,46,38,254,123,88,94,153,29,125,166,1,208,183,251,140, + 214,192,156,48,41,161,3,225,111,254,80,194,207,0,0,0,0,1,0,84,0,0,9,28,5,213,0,23,0,0,51,53,54,55,18,17,53,33,9,1, + 51,9,1,35,9,1,35,9,1,33,21,16,3,6,84,217,62,87,3,121,1,115,1,117,217,254,32,2,0,217,254,92,254,89,218,2,21,254,160,253, + 184,102,98,170,47,164,1,2,2,88,254,253,213,2,43,253,51,252,248,2,123,253,133,3,29,2,14,184,253,202,254,248,253,0,0,0,0,1,0,76, + 0,0,7,178,4,96,0,24,0,0,9,2,35,9,1,35,9,1,33,21,16,7,6,5,53,54,55,54,17,53,33,23,9,1,7,157,254,107,1,170, + 217,254,186,254,186,217,1,179,254,223,254,48,88,94,254,204,182,56,68,2,245,1,1,39,1,41,4,96,253,223,253,193,1,184,254,72,2,74,1,131, + 111,254,80,194,207,29,153,28,126,177,1,197,183,3,254,116,1,143,0,0,0,2,0,201,0,0,6,232,5,213,0,8,0,26,0,0,1,17,51,50, + 54,53,52,38,35,1,6,33,35,17,35,17,33,50,4,21,20,7,1,51,9,1,35,1,147,254,141,154,154,141,1,149,127,254,234,254,202,1,200,251, + 1,1,6,1,104,217,254,32,2,0,217,5,47,253,207,146,135,134,146,253,179,138,253,168,5,213,227,219,48,42,2,24,253,51,252,248,0,2,0,186, + 254,86,6,168,4,123,0,24,0,32,0,0,9,2,35,1,6,7,6,35,34,38,39,17,35,17,51,21,62,1,51,50,23,22,23,1,0,16,38,32, + 6,16,22,32,6,147,254,107,1,170,217,254,203,26,92,127,204,123,177,58,185,185,58,177,123,204,127,84,29,1,37,254,43,167,254,220,167,167,1,36, + 4,96,253,223,253,193,1,161,168,116,162,97,100,253,174,6,10,170,100,97,162,107,151,1,137,253,4,1,150,231,231,254,106,231,0,0,0,2,0,136, + 0,0,7,188,5,213,0,21,0,29,0,0,51,1,38,36,53,52,36,41,1,21,33,17,33,21,33,17,33,21,33,17,33,1,18,16,22,51,33,17, + 33,34,136,1,152,100,255,0,1,4,1,2,4,232,253,28,2,197,253,59,2,246,252,62,254,244,254,118,55,149,146,1,56,254,200,146,2,141,26,169, + 215,206,224,170,254,70,170,253,227,170,2,119,253,137,4,170,254,250,135,2,18,0,0,0,0,3,0,116,255,227,7,119,4,123,0,31,0,38,0,47, + 0,0,1,21,33,30,1,51,50,54,55,21,14,1,35,32,39,38,39,35,1,35,1,46,1,53,52,54,51,33,54,51,50,0,7,46,1,35,34,6, + 7,37,20,22,59,1,17,35,34,6,7,119,252,178,12,205,183,106,199,98,99,208,107,254,244,157,152,4,229,254,182,198,1,86,116,154,215,217,2,101, + 86,103,226,1,7,184,2,165,136,154,185,14,253,75,128,119,248,248,119,128,2,94,90,190,199,52,52,174,42,44,156,152,194,254,39,1,235,26,137,143, + 162,161,27,254,221,196,151,180,174,158,138,83,94,1,97,92,255,255,0,115,254,248,5,217,5,240,16,6,0,52,0,0,255,255,0,113,254,86,4,90, + 4,123,16,6,0,84,0,0,255,255,0,68,0,0,7,166,5,213,16,6,0,58,0,0,255,255,0,86,0,0,6,53,4,96,16,6,0,90,0,0, + 0,1,0,201,0,0,5,134,5,213,0,20,0,0,1,51,23,55,33,1,23,35,39,7,1,35,9,1,17,35,17,51,17,1,39,2,106,135,151,221, + 1,3,254,163,200,142,128,158,2,95,220,253,250,254,239,202,202,1,175,219,5,138,151,226,254,155,200,128,161,252,121,3,1,254,233,254,22,5,213,253, + 30,1,184,220,0,1,0,186,0,0,4,145,4,96,0,19,0,0,1,51,23,55,51,7,23,35,39,7,1,35,1,7,17,35,17,51,17,1,2,53, + 140,65,118,226,230,147,142,76,127,1,227,206,254,115,197,183,183,1,75,4,41,64,119,233,147,76,129,253,81,2,53,200,254,147,4,96,253,242,1,80, + 0,1,0,84,254,102,8,115,5,213,0,37,0,57,64,14,14,28,39,19,25,32,28,29,7,33,28,6,1,38,16,212,212,236,212,60,236,220,196,204, + 236,49,0,64,15,19,149,18,29,149,8,33,149,6,129,18,189,8,0,31,47,60,204,236,244,236,16,236,16,236,48,51,53,54,55,18,17,53,33,17, + 33,50,23,22,21,17,16,6,43,1,53,51,50,55,54,53,17,52,38,35,33,17,35,17,33,21,16,3,6,84,217,62,87,3,120,1,161,186,113,109, + 204,228,76,62,134,56,55,124,124,254,136,202,254,27,102,98,170,47,164,1,2,2,88,254,253,156,119,114,238,254,206,254,242,244,170,75,75,194,1,34, + 159,158,253,57,5,43,184,253,202,254,248,253,0,1,0,76,254,86,7,12,4,96,0,39,0,57,64,14,14,8,41,20,26,34,8,31,7,35,8,6, + 1,40,16,212,212,236,212,60,236,220,196,204,236,49,0,64,15,20,169,19,31,169,8,35,169,6,188,19,189,8,0,33,47,60,204,236,244,236,16,236, + 16,236,48,51,53,54,55,54,17,53,33,17,51,32,23,22,21,17,20,7,6,43,1,53,51,50,55,54,53,17,52,39,38,35,33,17,35,17,33,21, + 16,7,6,76,182,56,68,2,245,250,1,7,70,82,82,81,181,193,172,110,33,38,38,44,139,254,252,184,254,123,88,94,153,28,126,177,1,197,183,254, + 23,71,81,229,254,242,213,97,96,156,48,55,147,1,8,166,36,41,254,25,3,205,111,254,80,194,207,0,0,1,0,201,254,102,8,116,5,213,0,33, + 0,63,64,17,16,12,28,35,23,29,3,28,27,5,56,31,1,28,0,4,34,16,252,236,50,252,60,236,50,212,204,236,204,49,0,64,16,18,149,16, + 189,28,27,30,149,6,2,173,4,0,129,32,28,47,60,228,50,252,60,236,50,16,252,236,48,19,51,17,33,17,51,17,33,50,23,22,21,17,16,6, + 43,1,53,51,50,55,54,53,17,52,38,35,33,17,35,17,33,17,35,201,202,2,222,202,1,161,186,113,109,204,228,76,62,134,56,55,124,124,254,136, + 202,253,34,202,5,213,253,156,2,100,253,156,119,114,238,254,206,254,242,244,170,75,75,194,1,34,159,158,253,57,2,199,253,57,0,0,0,1,0,186, + 254,86,7,26,4,96,0,35,0,64,64,16,12,8,37,18,24,32,4,8,29,5,33,1,8,0,70,36,16,252,236,50,220,60,236,50,220,196,204,236, + 49,0,64,17,18,169,17,29,169,6,33,169,2,4,0,188,31,17,189,6,35,47,204,236,60,228,50,220,236,16,236,16,236,48,19,51,17,33,17,51, + 17,51,32,23,22,21,17,20,7,6,43,1,53,51,50,55,54,53,17,52,39,38,35,33,17,35,17,33,17,35,186,185,2,85,185,250,1,7,70,82, + 82,81,181,193,172,110,33,38,38,44,139,254,252,185,253,171,185,4,96,254,55,1,201,254,23,71,81,229,254,242,213,97,96,156,48,55,147,1,8,166, + 36,41,254,25,2,4,253,252,0,1,0,201,254,191,6,4,5,213,0,11,0,0,33,17,33,17,35,17,33,17,51,17,35,17,4,113,253,34,202,4, + 114,201,201,5,43,250,213,5,213,250,213,254,21,1,65,0,0,1,0,186,254,229,5,57,4,96,0,11,0,0,1,17,51,17,35,17,35,17,33,17, + 35,17,4,129,184,184,185,253,171,185,4,96,252,57,254,76,1,27,3,205,252,51,4,96,0,1,0,178,255,196,5,112,5,213,0,35,0,0,1,30, + 1,23,54,53,17,51,17,20,7,22,23,7,38,39,14,1,35,32,0,25,1,51,17,20,30,2,51,50,54,55,46,1,39,3,136,39,85,46,44,203, + 97,79,89,70,113,108,69,175,107,254,235,254,217,203,42,89,140,98,63,102,41,54,94,38,1,227,52,90,41,101,185,3,139,252,92,229,144,51,39,158, + 52,72,46,47,1,41,1,37,3,164,252,117,120,171,109,51,18,20,45,96,52,0,0,0,0,1,0,178,0,0,5,51,5,242,0,25,0,0,51,17, + 16,0,33,32,0,17,21,35,53,52,46,2,35,34,14,2,21,17,33,21,33,17,178,1,34,1,24,1,25,1,36,203,43,90,139,96,98,139,90,42, + 3,182,252,74,3,164,1,37,1,41,254,217,254,217,57,32,121,171,109,50,50,109,171,121,254,231,175,254,61,0,0,0,0,2,0,93,0,0,5,213, + 5,242,0,19,0,35,0,0,1,51,21,35,17,35,17,33,34,46,2,52,62,2,51,32,0,17,3,17,52,46,2,35,34,14,2,20,30,2,51,4, + 219,250,250,203,254,145,139,216,148,77,77,148,216,140,1,23,1,34,203,42,90,138,96,105,143,86,37,44,91,139,95,2,114,175,254,61,1,195,80,142, + 196,232,197,143,81,254,214,254,220,254,206,1,25,121,171,109,50,58,100,136,158,132,95,53,0,1,0,90,0,0,5,203,5,242,0,25,0,0,33,17, + 52,46,2,35,34,14,2,29,1,35,53,16,0,33,32,0,25,1,51,21,35,17,4,6,42,90,140,97,96,139,90,43,203,1,36,1,25,1,24,1, + 34,250,250,3,139,121,171,109,50,50,109,171,121,32,57,1,39,1,39,254,215,254,219,254,206,175,254,61,0,1,0,178,255,227,5,51,5,213,0,25, + 0,0,1,17,33,21,33,17,20,30,2,51,50,62,2,61,1,51,21,16,0,33,32,0,25,1,1,125,3,182,252,74,42,90,139,98,96,139,90,43, + 203,254,220,254,231,254,232,254,222,5,213,254,139,175,254,153,121,171,109,50,50,109,171,121,32,57,254,217,254,217,1,41,1,37,3,164,0,1,0,178, + 0,0,5,138,5,243,0,41,0,0,1,20,14,4,7,33,21,33,17,51,21,51,50,62,4,53,52,46,2,34,14,2,29,1,35,53,52,62,2,32, + 30,2,5,138,51,84,109,113,110,44,1,228,251,100,203,86,61,153,157,151,117,71,48,102,158,220,156,99,46,203,76,153,229,1,50,235,159,82,3,129, + 103,180,153,124,93,61,13,170,1,76,162,43,83,123,162,199,117,103,171,121,67,64,112,151,86,71,75,121,210,154,88,90,165,231,0,0,0,1,0,188, + 0,0,4,237,5,213,0,9,0,0,37,33,21,33,17,51,17,33,21,33,1,135,2,219,252,90,203,3,102,252,154,175,175,5,213,254,139,175,0,0, + 0,1,0,178,0,0,5,51,5,242,0,23,0,0,51,17,16,0,33,32,0,17,21,35,53,52,46,2,35,34,14,2,21,17,33,21,178,1,34,1, + 24,1,25,1,36,203,43,90,139,96,98,139,90,42,3,182,3,164,1,37,1,41,254,217,254,217,57,32,121,171,109,50,50,109,171,121,253,36,175,0, + 0,2,0,178,255,227,6,174,5,242,0,41,0,56,0,0,0,34,14,2,21,17,35,17,52,62,2,32,30,2,29,1,51,21,35,17,20,14,2,35, + 34,46,2,52,62,2,59,1,53,52,46,1,0,20,30,2,50,62,2,53,17,35,34,14,1,3,195,240,175,113,54,203,91,171,246,1,54,246,171,91, + 206,206,66,116,161,94,95,159,116,65,68,117,159,91,234,53,111,254,200,37,65,88,104,86,62,34,234,57,90,62,5,78,50,109,171,121,252,117,3,164, + 147,221,148,74,74,148,221,147,52,175,254,215,107,163,110,57,58,115,175,234,168,108,51,24,122,173,109,252,225,168,112,66,28,27,65,107,80,1,35,25, + 63,0,0,0,0,2,0,93,255,227,5,213,5,213,0,21,0,35,0,0,1,20,14,2,35,34,46,2,52,62,2,51,33,17,51,17,51,21,35,33, + 34,14,2,20,30,2,51,50,54,53,17,4,219,73,144,213,139,140,216,148,77,77,148,216,139,1,111,203,250,250,253,197,95,139,91,44,37,86,143,105, + 192,174,2,87,146,233,162,87,93,157,209,232,208,158,92,1,117,254,139,175,66,110,144,158,148,115,69,247,242,1,65,0,0,1,0,188,0,0,5,51, + 5,213,0,24,0,0,19,51,17,62,1,51,50,30,2,29,1,35,53,52,46,2,34,14,2,21,17,35,188,203,63,188,118,138,212,146,75,203,43,90, + 139,192,139,91,43,203,5,213,254,9,77,73,72,147,221,150,75,50,121,171,109,50,50,108,172,121,253,243,0,1,0,188,0,0,4,68,5,213,0,5, + 0,0,1,17,33,21,33,17,1,135,2,189,252,120,5,213,250,218,175,5,213,0,0,0,0,1,0,188,255,227,6,203,5,213,0,29,0,0,1,17, + 20,30,2,50,62,2,53,17,51,17,20,14,2,34,46,2,53,17,33,17,35,17,51,17,3,202,54,84,102,96,98,81,51,203,72,128,176,210,179,132, + 75,254,136,203,203,4,96,253,49,75,102,62,27,27,62,102,75,2,207,253,73,119,171,111,53,53,111,171,119,2,8,252,79,5,213,254,139,0,0,0, + 0,2,1,8,255,230,6,26,5,240,0,43,0,62,0,0,1,51,21,51,62,3,51,50,30,2,23,21,46,3,35,34,6,7,22,4,30,1,21,20, + 14,4,35,34,46,2,53,52,54,55,35,19,20,30,2,51,50,62,2,53,52,46,1,36,43,1,14,1,1,12,203,78,66,153,163,168,82,60,100,88, + 84,45,53,106,101,92,39,97,179,79,155,1,17,204,118,39,76,111,147,180,106,159,239,161,80,76,67,139,203,42,101,166,125,124,172,106,47,66,159,254, + 246,200,29,76,87,5,213,245,63,101,71,37,9,18,27,18,215,35,47,28,11,57,52,9,89,161,232,153,83,157,139,117,84,47,99,174,237,137,128,231, + 101,254,52,95,175,133,80,76,127,168,92,96,174,132,78,97,235,0,0,0,0,1,0,178,0,0,5,41,5,213,0,24,0,0,33,35,17,14,1,35, + 34,46,2,53,17,51,17,20,30,2,50,62,2,61,1,51,5,41,203,69,182,118,138,212,146,75,203,43,90,139,192,139,91,43,203,1,227,63,67,72, + 147,221,150,2,38,253,243,121,171,109,50,50,108,171,122,152,0,1,0,70,255,202,5,26,5,213,0,25,0,0,37,21,1,46,3,62,1,55,54,36, + 55,3,51,1,14,3,7,14,2,22,23,5,26,252,22,62,103,63,11,59,139,119,155,1,56,164,207,238,1,3,113,203,193,187,96,103,95,13,56,47, + 152,206,1,64,19,57,76,96,117,138,80,104,166,71,1,47,254,137,43,88,97,109,64,69,92,62,38,15,0,2,0,168,255,208,5,128,5,243,0,53, + 0,67,0,0,19,52,62,2,51,50,22,23,62,3,53,52,46,2,34,14,2,29,1,35,53,52,62,2,32,30,2,21,20,14,2,7,30,1,23,7, + 46,1,39,14,1,35,34,46,2,37,34,14,2,21,20,22,51,50,54,55,46,1,183,59,101,132,72,120,237,118,40,65,47,26,47,100,159,224,157,98, + 44,203,78,154,229,1,44,235,160,84,34,63,87,54,56,109,56,136,54,111,56,110,249,126,71,132,102,61,1,108,33,63,49,29,88,88,86,176,81,94, + 175,1,9,73,114,78,40,96,80,50,115,124,134,70,103,174,125,70,64,112,151,86,71,75,121,210,154,88,88,163,231,144,86,165,156,142,63,45,95,51, + 142,52,101,48,89,100,36,75,113,220,19,36,51,32,65,79,72,64,66,80,0,1,0,100,0,0,5,213,5,242,0,23,0,0,37,51,21,33,17,52, + 46,2,35,34,14,2,29,1,35,53,16,0,33,32,0,17,4,219,250,254,59,43,90,140,97,98,139,89,41,203,1,32,1,28,1,26,1,33,175,175, + 3,139,121,171,109,50,52,109,171,119,32,57,1,39,1,39,254,214,254,220,0,2,0,105,0,0,5,185,5,226,0,26,0,36,0,0,1,34,14,2, + 7,1,21,33,34,46,2,62,1,55,62,1,55,1,51,19,62,3,51,1,14,1,30,1,51,33,1,14,1,5,38,45,112,124,133,67,2,116,251,196, + 66,110,75,35,20,81,77,67,161,89,254,228,243,188,80,159,150,136,56,252,145,80,68,14,89,77,2,244,253,234,71,129,5,41,35,64,91,57,252,114, + 164,32,69,108,153,200,126,109,201,88,1,151,254,238,66,107,74,40,252,126,133,169,96,35,2,251,74,166,0,1,0,178,255,227,6,35,5,213,0,23, + 0,0,1,17,16,0,33,32,0,25,1,51,17,20,30,2,51,50,62,2,53,17,33,21,5,41,254,223,254,230,254,228,254,224,203,42,89,140,98,97, + 140,89,42,1,197,5,38,253,11,254,221,254,213,1,39,1,39,3,164,252,117,120,171,109,51,51,109,171,120,3,139,175,0,1,0,146,255,227,5,89, + 5,241,0,55,0,0,1,20,14,2,32,46,2,53,51,20,30,2,51,50,62,2,53,52,38,35,33,53,33,50,62,2,53,52,38,32,6,21,35,52, + 62,2,50,30,2,21,20,14,2,7,30,3,5,89,77,153,230,254,206,229,152,76,203,43,96,155,113,112,155,94,42,202,201,253,176,2,80,81,119,77, + 37,159,254,202,160,203,74,136,191,234,192,137,76,37,64,84,46,68,117,87,50,1,188,103,173,126,71,74,130,175,101,65,114,87,50,50,86,112,62,128, + 127,175,39,67,92,53,118,113,114,123,95,149,103,54,53,102,147,93,59,104,83,60,15,17,63,91,118,0,0,1,0,0,255,227,5,113,5,213,0,23, + 0,0,1,17,20,30,2,51,50,62,2,61,1,51,21,16,0,33,32,0,25,1,35,53,1,197,41,90,140,99,98,139,89,41,203,254,223,254,229,254, + 230,254,223,250,5,213,252,117,120,171,109,51,51,110,170,120,32,57,254,220,254,214,1,45,1,33,2,244,176,0,0,0,0,1,0,160,255,226,5,121, + 5,213,0,46,0,0,1,46,1,43,1,53,51,50,22,23,1,21,37,46,1,35,34,14,2,21,20,22,51,50,62,2,61,1,51,21,20,14,2,35, + 34,46,2,53,52,62,2,55,2,100,56,138,85,141,219,106,162,71,2,107,254,150,26,64,42,111,186,135,75,208,211,105,155,101,50,203,82,156,228,145, + 146,233,163,88,78,138,189,111,5,0,25,18,170,24,30,254,254,212,148,11,13,72,134,192,121,240,248,60,109,152,92,71,75,128,211,151,83,86,165,242, + 156,126,215,165,107,19,0,0,0,1,0,178,0,0,5,41,5,242,0,21,0,0,51,17,16,0,33,32,0,25,1,35,17,52,46,2,35,34,14,2, + 21,17,178,1,32,1,28,1,26,1,33,203,43,90,139,96,98,139,90,42,3,164,1,39,1,39,254,214,254,220,252,92,3,139,121,171,109,50,50,109, + 171,121,252,117,0,1,0,120,255,198,5,80,5,243,0,37,0,0,37,23,21,1,53,23,30,1,51,50,62,2,53,52,38,35,34,14,2,29,1,35, + 53,52,62,2,32,30,2,21,20,14,2,3,77,195,252,251,237,26,74,42,114,187,132,73,210,208,104,155,102,50,203,82,156,227,1,36,233,163,87,75, + 137,189,233,85,206,1,69,212,103,11,13,86,148,198,113,223,239,60,109,152,92,71,75,128,211,151,83,83,160,233,150,116,222,182,125,0,0,1,0,90, + 0,0,5,181,5,242,0,28,0,0,1,17,35,17,14,3,29,1,35,53,52,62,2,51,50,4,30,1,21,17,35,17,52,46,2,3,103,203,86,139, + 98,52,203,102,182,248,147,157,0,255,181,99,203,56,102,142,5,71,252,148,3,108,12,73,112,149,88,42,57,130,217,156,87,87,156,217,130,252,92,3, + 149,79,149,118,79,0,0,0,0,2,0,168,0,0,5,125,5,243,0,34,0,59,0,0,1,34,46,4,53,38,62,2,51,50,30,2,21,20,14,2, + 7,33,21,33,17,51,21,51,50,54,55,54,38,37,52,46,2,35,34,14,2,23,30,3,51,50,30,2,7,62,3,2,18,86,120,80,46,23,7,3, + 79,156,229,147,160,236,156,77,76,133,183,108,1,217,251,100,203,78,81,195,95,40,162,1,213,48,101,158,111,107,158,101,46,6,3,18,43,75,59,121, + 177,109,39,17,43,72,53,29,2,155,35,57,71,71,64,21,107,194,148,88,94,167,229,136,121,221,188,148,49,170,1,76,162,63,61,178,195,230,100,170, + 123,69,57,100,135,77,38,55,37,18,64,114,156,91,45,106,120,135,0,0,0,1,0,178,0,0,6,35,5,242,0,25,0,0,33,17,52,46,2,35, + 34,14,2,21,17,35,17,16,0,33,32,0,25,1,51,21,35,17,4,94,42,90,140,97,96,139,90,43,203,1,36,1,25,1,24,1,34,250,250,3, + 139,121,171,109,50,50,109,171,121,252,117,3,164,1,39,1,39,254,215,254,219,254,206,175,254,61,0,0,255,255,0,178,255,227,5,41,5,213,18,6, + 0,56,0,0,0,1,0,100,0,0,5,213,5,213,0,26,0,0,41,1,17,14,1,35,34,46,2,61,1,51,21,20,30,2,50,62,2,53,17,51, + 17,51,5,213,254,59,65,186,118,138,212,146,75,203,43,90,139,192,139,91,43,203,250,1,243,72,74,72,147,221,150,177,152,121,171,109,50,50,108,171, + 122,2,13,250,218,0,0,0,0,1,0,150,255,227,5,14,5,238,0,61,0,0,19,51,20,30,2,51,50,62,2,53,52,46,2,39,46,5,39,38, + 62,2,50,30,2,21,35,46,3,35,34,14,2,23,30,3,23,30,3,21,20,14,2,32,46,2,150,203,53,96,135,82,80,136,100,56,54,97,137,84, + 67,127,113,95,70,40,2,2,73,135,191,234,195,141,78,203,3,39,78,122,86,79,120,79,36,4,4,38,75,113,80,136,213,148,78,82,150,213,254,252, + 210,149,80,1,195,68,116,84,48,32,68,105,73,58,85,61,40,13,10,30,45,63,88,115,75,90,154,114,64,61,108,145,84,44,84,66,41,39,70,95, + 55,50,73,53,37,13,23,66,105,153,110,102,164,115,61,75,130,175,0,0,0,1,0,178,0,0,5,41,5,242,0,21,0,0,51,17,16,0,33,32, + 0,17,21,35,53,52,46,2,35,34,14,2,21,17,178,1,34,1,22,1,23,1,40,203,44,92,140,96,98,138,88,41,3,164,1,37,1,41,254,221, + 254,213,57,32,121,171,109,50,50,109,171,121,252,117,0,0,0,2,0,160,255,227,5,103,5,241,0,49,0,64,0,0,1,20,14,2,32,46,2,53, + 51,20,30,2,51,50,62,2,53,52,38,35,33,53,51,46,3,53,52,62,2,50,30,2,21,20,14,2,7,30,3,1,50,62,2,53,52,38,32,6, + 21,20,30,2,5,103,77,153,230,254,206,229,152,76,203,43,96,155,113,112,155,94,42,202,201,253,176,224,32,55,40,23,74,136,191,234,192,137,76,37, + 64,84,46,68,117,87,50,253,155,81,119,77,37,159,254,202,160,24,68,124,1,188,103,173,126,71,74,130,175,101,65,114,87,50,50,86,112,62,128,127, + 175,17,50,63,74,41,95,149,103,54,53,102,147,93,59,104,83,60,15,17,63,91,118,1,103,39,67,92,53,118,115,116,123,38,85,74,48,0,0,0, + 0,1,0,188,0,0,4,77,5,213,0,7,0,0,1,17,33,21,33,17,35,17,1,135,2,198,253,58,203,5,213,254,139,175,252,79,5,213,0,0, + 0,3,0,120,0,0,6,4,5,213,0,5,0,15,0,39,0,0,1,14,1,16,22,23,51,62,3,52,46,2,39,3,46,3,16,62,2,55,53,51, + 21,30,3,16,14,2,7,21,35,2,215,193,209,209,193,203,93,149,104,56,56,104,149,93,203,135,224,160,88,88,160,224,135,203,135,224,161,90,90,161, + 224,135,203,4,142,7,217,254,118,216,7,4,59,107,152,196,153,108,59,3,252,16,6,84,150,213,1,12,214,152,84,5,159,159,5,84,152,214,254,244, + 213,152,84,5,157,0,0,0,0,2,0,50,0,0,5,110,5,242,0,27,0,43,0,0,1,34,46,2,39,17,33,21,33,21,35,53,35,53,51,17, + 16,0,33,50,30,2,20,14,2,0,20,30,2,50,62,2,52,46,2,34,14,1,3,42,62,110,94,75,26,3,152,252,104,203,190,190,1,34,1,23, + 139,217,148,77,77,148,216,254,6,36,86,141,210,142,85,37,38,87,142,208,140,86,1,215,21,37,52,30,254,230,175,154,154,175,2,101,1,36,1,32, + 78,139,194,232,193,138,77,2,90,156,129,92,50,50,91,129,158,133,97,54,55,97,0,0,255,255,0,115,255,227,5,217,5,240,18,6,0,50,0,0, + 0,3,0,110,255,230,5,248,5,213,0,31,0,41,0,51,0,0,0,20,14,1,4,32,36,46,1,61,1,51,21,20,30,2,23,17,34,46,2,53, + 52,54,59,1,17,50,30,1,37,17,34,14,2,20,30,2,0,52,46,2,35,17,62,2,5,248,100,186,254,249,254,186,254,250,183,98,203,60,107,148, + 87,119,175,115,56,237,239,192,133,224,162,253,46,79,102,60,23,23,60,102,2,172,56,105,149,92,90,149,105,2,132,254,201,140,75,77,142,200,124,39, + 39,86,135,93,52,4,2,230,42,80,112,71,153,146,254,81,75,141,216,1,11,16,33,51,70,50,32,15,253,138,170,137,96,51,253,29,4,52,95,0, + 0,1,0,117,3,239,1,135,6,20,0,14,0,0,1,34,39,38,52,55,54,51,21,34,6,21,20,22,51,1,135,115,80,79,79,80,115,64,88,88, + 64,3,239,80,80,230,79,80,123,88,63,64,88,0,0,0,0,1,0,178,3,254,1,215,5,213,0,5,0,0,1,51,21,3,35,19,1,4,211,164, + 129,82,5,213,152,254,193,1,63,0,0,0,0,1,0,0,4,245,1,223,6,109,0,3,0,0,1,51,1,35,1,24,199,254,186,153,6,109,254,136, + 0,1,0,5,4,241,2,217,7,37,0,21,0,0,1,14,3,21,35,52,62,2,55,62,3,53,51,20,14,2,1,111,58,90,61,31,122,51,94,134, + 83,66,91,57,26,122,46,90,136,5,195,5,36,57,72,40,64,123,98,63,6,4,37,57,72,40,71,123,94,59,0,0,255,255,255,255,4,240,1,222, + 6,102,16,7,0,67,255,85,0,0,0,0,0,1,0,8,4,232,3,53,6,237,0,41,0,0,19,35,38,62,2,51,50,30,2,21,20,14,2,35, + 34,46,2,39,51,30,3,51,50,62,2,53,52,46,2,39,38,14,2,117,109,1,71,126,174,102,63,122,96,60,32,61,91,60,39,79,67,49,7,134, + 3,19,27,30,14,26,38,25,12,28,48,66,38,74,133,101,59,4,240,121,190,130,68,34,70,110,76,48,82,62,35,19,43,71,51,15,24,18,9,19, + 30,37,18,39,60,42,24,3,6,46,99,147,0,1,0,90,4,241,3,178,6,20,0,5,0,0,19,17,51,21,33,21,90,140,2,204,4,241,1,35, + 169,122,0,0,0,1,0,174,255,228,7,17,4,96,0,42,0,0,37,14,1,35,34,46,2,53,17,51,17,20,30,2,51,50,62,2,53,17,51,17, + 20,22,51,50,62,2,53,17,51,17,35,53,14,1,35,34,38,3,162,69,191,131,87,136,93,49,185,28,58,86,59,71,114,81,43,185,113,120,70,114, + 80,43,185,185,63,176,121,124,168,214,126,116,63,120,176,113,2,164,253,78,81,113,72,32,49,92,131,82,2,122,253,98,163,155,50,93,130,81,2,122, + 251,160,174,105,97,122,0,0,0,1,0,186,254,86,4,100,4,123,0,22,0,0,1,53,16,35,34,6,21,17,33,21,33,17,35,17,51,21,62,1, + 51,50,22,29,1,3,172,248,149,172,2,241,253,15,185,185,66,178,118,194,197,1,194,220,1,61,190,164,254,39,160,254,86,6,10,174,102,99,238,233, + 226,0,0,0,0,2,0,113,254,86,5,47,4,123,0,16,0,40,0,0,0,20,30,2,50,62,2,53,52,46,2,34,14,1,1,35,17,14,1,35, + 34,46,2,16,62,2,51,50,22,23,53,51,17,51,21,35,1,47,43,81,116,146,117,81,43,44,81,116,146,116,81,3,0,184,58,176,125,102,168,121, + 67,67,121,168,102,125,176,58,184,213,213,2,148,202,161,112,60,60,112,161,101,100,161,113,60,60,112,251,33,2,82,100,97,85,155,217,1,6,217,155, + 85,97,100,170,252,64,160,0,0,1,0,186,254,86,5,58,4,123,0,22,0,0,33,17,35,17,16,35,34,6,21,17,35,17,51,21,62,1,51,50, + 22,21,17,51,21,4,101,185,248,149,172,185,185,66,178,118,194,198,213,254,86,4,72,1,61,190,164,253,135,4,96,174,102,99,238,233,253,252,160,0, + 0,1,0,174,255,227,4,98,6,20,0,26,0,0,19,17,51,17,33,21,33,17,20,23,22,51,50,55,54,61,1,51,17,35,53,14,1,35,34,39, + 38,174,184,2,252,253,4,62,61,125,152,84,86,184,184,67,176,118,193,100,100,1,186,4,90,254,76,160,254,1,159,80,79,95,98,161,235,253,48,172, + 103,98,120,119,0,2,0,113,254,86,5,47,4,123,0,21,0,45,0,0,1,51,21,33,17,14,1,35,34,46,2,16,62,2,51,50,22,23,53,51, + 1,20,30,2,51,50,62,4,53,52,46,2,35,34,14,4,4,90,213,254,115,58,176,125,102,168,121,67,67,121,168,102,125,176,58,184,252,213,33,73, + 120,87,60,93,70,48,30,13,33,75,119,87,60,93,69,48,30,13,254,246,160,2,82,100,97,85,155,217,1,6,217,155,85,97,100,170,253,207,78,156, + 123,77,37,65,85,97,102,48,78,155,124,77,38,64,86,96,102,0,0,0,0,1,0,186,0,0,3,236,6,20,0,9,0,0,41,1,17,51,17,33, + 21,33,17,33,3,151,253,35,184,2,122,253,134,2,37,6,20,254,76,160,252,224,0,0,0,1,0,186,254,86,4,100,4,123,0,20,0,0,33,17, + 16,35,34,6,21,17,33,21,33,17,51,21,62,1,51,50,22,21,17,3,172,248,149,172,2,241,252,86,185,66,178,118,194,197,2,158,1,61,190,164, + 252,125,160,6,10,174,102,99,238,233,253,92,0,2,0,186,254,86,5,232,4,123,0,44,0,60,0,0,1,33,52,46,2,35,34,14,2,21,17,35, + 17,51,21,62,3,51,50,30,4,21,51,21,35,14,3,35,34,46,2,52,62,2,5,33,34,14,2,21,20,30,2,51,50,62,2,3,102,1,49,72, + 118,151,79,82,140,103,59,185,185,42,99,109,118,61,68,136,126,109,81,46,146,150,18,96,129,148,70,72,127,96,56,55,90,115,1,102,254,214,26,50, + 40,24,23,43,64,41,25,81,81,68,2,47,100,161,112,61,41,90,142,101,251,235,6,10,170,60,76,44,17,39,72,104,131,155,87,160,113,161,105,49, + 36,73,110,148,111,73,37,160,15,33,51,36,29,49,38,21,23,61,105,0,0,2,0,113,255,227,5,47,6,20,0,16,0,38,0,0,1,33,34,14, + 2,21,20,30,2,51,50,62,2,53,19,17,20,14,2,34,46,2,53,52,62,2,51,33,17,51,17,51,21,3,162,254,198,73,116,81,43,43,81,116, + 73,81,118,77,38,184,66,127,186,242,187,127,66,64,127,187,123,1,60,184,213,3,192,53,102,149,97,101,161,112,60,60,113,160,101,1,145,254,57,114, + 195,144,81,86,155,216,131,113,203,154,91,1,180,254,76,160,0,1,0,186,254,86,4,100,6,20,0,18,0,0,1,17,35,17,16,35,34,6,21,17, + 35,17,51,17,62,1,51,50,22,4,100,184,248,149,172,185,185,66,178,118,194,197,2,164,253,92,2,158,1,61,190,164,251,221,7,190,253,158,102,99, + 238,0,0,0,0,1,0,186,254,86,2,108,4,96,0,5,0,0,1,51,21,33,17,51,1,114,250,254,78,184,254,246,160,6,10,0,0,1,0,186, + 254,86,7,29,6,20,0,42,0,0,1,21,20,22,51,50,62,2,53,17,51,17,35,53,14,1,35,34,46,2,53,17,16,35,34,14,2,21,17,35, + 17,51,17,62,3,51,50,22,4,72,113,120,70,114,80,43,185,185,63,176,121,61,129,107,68,247,75,110,72,36,185,185,19,65,87,104,59,195,196,2, + 164,226,163,155,50,93,130,81,2,122,251,160,174,105,97,41,101,169,129,1,2,1,61,50,92,131,81,251,221,7,190,253,158,39,73,55,34,236,0,0, + 0,2,0,113,255,227,4,116,6,20,0,24,0,45,0,0,1,19,51,7,5,33,21,35,30,1,21,20,14,2,34,46,2,53,52,62,2,55,3,20, + 30,2,51,50,62,2,53,52,46,2,39,35,34,14,2,1,6,194,212,164,1,66,1,55,125,67,61,68,131,192,246,192,130,68,62,111,154,91,225,40, + 81,119,80,79,120,80,40,18,43,71,52,135,78,120,81,41,5,10,1,10,226,210,160,78,215,132,122,206,151,85,85,151,206,122,120,198,148,94,16,253, + 192,83,149,111,65,65,111,149,83,77,119,99,86,44,69,117,154,0,0,0,0,1,0,174,254,86,4,88,6,20,0,19,0,0,19,17,51,17,16,51, + 50,55,54,53,17,51,17,35,17,14,1,35,34,38,174,184,248,149,86,87,184,184,67,176,118,194,199,1,186,4,90,251,173,254,194,95,94,165,2,123, + 249,246,2,86,103,98,239,0,255,255,0,186,0,0,4,100,6,20,18,6,0,75,0,0,0,2,0,106,255,226,4,48,6,20,0,45,0,66,0,0, + 1,21,14,1,7,22,18,21,17,35,53,14,3,35,34,46,2,55,62,3,55,46,3,53,52,63,1,51,7,14,1,7,6,30,2,55,62,1,1,20, + 30,2,51,50,62,2,61,1,52,46,2,39,14,3,3,60,26,52,26,169,179,184,27,72,92,112,67,98,156,106,55,3,2,62,109,154,94,68,93,59, + 26,34,36,199,42,19,15,1,2,46,71,87,40,27,57,254,10,33,67,101,68,77,120,82,43,30,69,112,81,61,108,82,48,5,44,177,16,32,18,100, + 254,229,185,253,255,172,45,74,54,29,66,120,170,105,96,183,173,163,75,10,52,71,83,41,68,53,57,63,29,59,23,45,63,34,2,17,18,34,252,160, + 69,115,83,45,55,93,123,68,86,53,119,117,104,38,50,117,135,154,0,0,0,1,0,186,254,86,5,57,4,123,0,20,0,0,1,21,33,17,16,35, + 34,6,21,17,35,17,51,21,62,1,51,50,22,21,17,5,57,254,115,248,149,172,185,185,66,178,118,194,197,254,246,160,4,72,1,61,190,164,253,135, + 4,96,174,102,99,238,233,252,82,0,0,0,0,2,0,140,255,227,4,90,6,36,0,40,0,62,0,0,19,53,51,62,3,51,50,22,23,21,38,35, + 34,14,2,7,51,50,30,2,21,17,35,53,14,3,35,34,46,2,39,38,18,55,19,30,3,51,50,62,2,61,1,52,46,2,43,1,14,3,140,196, + 55,141,167,193,107,25,45,22,52,50,71,127,114,98,42,3,119,209,156,90,184,24,70,92,116,69,102,151,102,53,3,5,54,56,86,6,45,73,97,56, + 70,115,83,46,42,98,159,117,71,29,42,27,10,3,182,170,96,165,122,69,6,4,189,29,42,75,104,61,76,138,194,119,253,175,174,44,74,54,31,65, + 114,155,90,131,1,29,139,253,253,88,117,70,29,51,91,124,73,104,64,134,109,69,65,135,132,126,0,0,0,1,0,174,255,227,5,45,6,20,0,22, + 0,0,19,17,51,17,16,51,50,62,2,53,17,33,21,35,17,35,53,14,1,35,34,38,174,184,248,75,119,83,45,1,141,213,184,67,176,118,195,198, + 1,186,2,166,253,97,254,194,50,92,131,81,4,47,160,250,140,172,103,98,238,0,0,0,0,1,255,212,254,86,1,114,4,96,0,11,0,0,19,51, + 17,20,6,43,1,53,51,50,54,53,186,184,163,181,70,49,105,76,4,96,251,140,214,192,156,97,153,0,0,1,255,217,255,227,4,88,6,20,0,22, + 0,0,3,33,17,16,51,50,62,2,53,17,51,17,35,53,14,1,35,34,38,53,17,35,39,1,141,248,75,119,83,45,184,184,67,176,118,195,198,213, + 6,20,251,173,254,194,50,92,131,81,2,123,251,160,172,103,98,238,233,3,186,0,0,0,0,1,0,0,254,86,3,123,4,123,0,49,0,0,23,20, + 30,2,51,33,21,33,34,46,2,53,52,62,6,53,52,46,2,35,34,6,7,53,62,3,51,50,30,2,21,20,14,6,193,4,10,20,17,2,80,253, + 116,42,68,48,26,60,98,125,131,125,98,60,45,82,115,71,91,154,78,38,74,79,89,53,115,184,129,69,60,98,126,130,126,98,60,217,8,17,15,9, + 160,27,47,63,36,49,106,113,118,124,127,131,133,67,72,105,68,33,38,42,174,14,23,15,8,53,108,162,109,75,149,144,135,124,111,94,74,0,0,0, + 255,255,0,186,0,0,4,100,4,123,18,6,0,81,0,0,0,1,0,10,254,86,2,246,4,96,0,49,0,0,19,33,21,33,34,46,2,53,52,62, + 4,55,46,3,53,52,62,2,55,51,14,3,21,20,30,2,55,62,1,55,7,14,3,21,20,30,2,252,1,250,253,214,36,70,55,33,35,60,83,96, + 106,53,47,110,95,63,11,32,59,48,231,59,77,44,17,38,63,82,45,25,66,35,1,102,169,121,66,4,11,17,254,246,160,22,46,70,47,58,135,142, + 144,137,125,51,2,32,68,107,76,30,63,70,77,44,37,72,67,62,26,48,68,40,14,5,3,21,18,183,89,203,200,184,69,12,26,20,13,0,0,0, + 0,1,0,174,254,86,7,17,4,96,0,42,0,0,37,14,1,35,34,46,2,53,17,51,17,20,30,2,51,50,62,2,53,17,51,17,20,22,51,50, + 62,2,53,17,51,17,35,17,14,1,35,34,38,3,162,69,191,131,87,136,93,49,185,28,58,86,59,71,114,81,43,185,113,120,70,114,80,43,185,185, + 63,176,121,124,168,214,126,116,63,120,176,113,2,164,253,78,81,113,72,32,49,92,131,82,2,122,253,98,163,155,50,93,130,81,2,122,249,246,2,88, + 105,97,122,0,0,2,0,110,254,86,3,244,4,124,0,44,0,68,0,0,1,20,14,6,21,20,22,51,33,21,33,34,46,2,53,52,54,55,62,3, + 39,46,5,53,52,62,2,51,50,30,2,37,34,14,2,21,20,30,4,21,20,7,62,3,53,52,46,2,3,244,60,98,126,131,126,98,60,31,21,2, + 80,253,116,38,67,49,29,82,72,25,35,20,4,6,8,42,54,59,49,32,73,120,154,80,110,176,123,66,254,37,43,86,68,42,31,46,55,46,31,50, + 60,130,108,69,40,75,106,2,210,78,153,145,137,125,110,93,73,25,23,26,160,25,43,57,32,66,144,73,25,68,76,79,36,47,82,75,72,77,84,50, + 79,134,96,54,58,110,158,170,26,52,77,51,33,66,68,72,76,83,44,81,79,58,126,132,138,72,69,105,72,36,0,0,0,1,0,186,0,0,4,224, + 4,123,0,36,0,0,1,34,14,2,21,17,35,17,51,21,62,1,51,50,30,2,21,20,14,2,7,33,21,33,53,62,3,53,52,46,2,2,193,79, + 124,86,45,185,185,63,189,121,99,162,116,63,33,61,86,53,1,41,253,253,63,96,66,34,35,71,108,3,219,52,90,122,70,253,115,4,96,172,97,102, + 70,125,174,103,83,139,123,113,57,160,132,52,109,121,138,80,73,129,97,56,255,255,0,174,255,227,4,88,4,123,18,6,0,88,0,0,0,1,0,174, + 254,86,5,45,6,20,0,22,0,0,19,17,51,17,16,51,50,62,2,53,17,51,17,51,21,33,17,14,1,35,34,38,174,184,248,75,119,83,45,184, + 213,254,115,67,176,118,195,198,1,186,2,166,253,97,254,194,50,92,131,81,4,47,248,226,160,2,86,103,98,238,0,0,0,1,0,174,255,227,7,28, + 4,123,0,39,0,0,1,17,51,21,62,3,51,50,22,21,17,35,17,16,35,34,14,2,21,17,35,53,14,1,35,34,38,53,17,51,17,16,51,50, + 62,2,3,143,184,33,79,87,91,44,195,196,184,248,60,107,80,46,184,67,177,100,195,198,184,248,63,111,83,48,1,229,2,123,174,51,75,50,25,236, + 235,253,92,2,158,1,61,50,92,131,81,253,135,172,103,98,238,233,2,166,253,97,254,194,47,91,132,0,0,1,0,186,254,86,4,100,4,123,0,20, + 0,0,1,17,35,17,16,35,34,14,2,21,17,35,17,51,21,62,1,51,50,22,4,100,184,248,75,119,83,44,185,185,66,178,118,195,196,2,164,253, + 92,2,158,1,61,50,92,131,81,251,221,6,10,174,103,98,236,0,0,0,255,255,0,111,254,86,4,88,4,123,16,6,0,74,254,0,0,1,0,186, + 0,0,3,152,4,96,0,5,0,0,37,33,21,33,17,51,1,114,2,38,253,34,184,160,160,4,96,0,0,1,0,174,254,86,7,28,6,20,0,39, + 0,0,1,17,51,17,62,3,51,50,22,21,17,35,17,16,35,34,14,2,21,17,35,17,14,1,35,34,38,53,17,51,17,16,51,50,62,2,3,143, + 184,33,79,87,91,44,195,196,184,248,57,106,81,49,184,67,177,100,195,198,184,248,63,111,83,48,1,229,4,47,253,158,51,75,50,25,236,235,253,92, + 2,158,1,61,47,90,132,85,251,221,2,86,103,98,238,233,2,166,253,97,254,194,47,91,132,0,0,0,0,2,0,41,254,86,4,164,4,123,0,27, + 0,44,0,0,37,17,33,21,33,21,35,53,35,53,51,17,51,21,62,1,51,50,30,2,16,14,2,35,34,38,1,52,46,2,34,14,2,20,30,2, + 50,62,2,1,115,3,21,252,235,185,145,145,185,58,176,124,102,168,122,67,67,122,168,102,124,176,2,56,43,81,116,146,116,81,43,43,81,116,146,117, + 80,43,168,254,168,155,95,95,155,5,16,170,100,97,86,155,216,254,250,216,155,86,97,1,235,100,161,112,61,60,112,161,202,161,112,60,60,113,160,0, + 255,255,0,111,255,227,4,115,4,123,16,6,0,82,254,0,0,3,0,70,254,86,6,33,6,20,0,39,0,46,0,56,0,0,0,16,14,2,35,17, + 35,17,34,46,4,61,1,51,21,20,30,2,51,17,34,46,2,53,52,62,2,59,1,17,50,30,1,37,17,34,6,21,20,22,0,52,46,2,35,17, + 50,62,1,6,33,103,180,243,139,184,87,164,145,120,86,48,180,80,131,169,90,98,156,111,59,59,111,156,98,184,142,243,178,253,21,125,116,123,3,10, + 69,125,176,106,106,176,125,2,199,254,248,214,151,82,254,86,1,170,39,73,103,128,149,83,93,86,87,152,114,66,3,26,43,79,110,67,72,112,77,39, + 254,76,70,137,207,1,38,79,72,66,77,253,128,192,143,95,47,252,230,57,107,0,0,0,0,1,0,174,255,227,6,126,6,20,0,22,0,0,37,33, + 21,33,53,14,1,35,34,38,53,17,51,17,16,51,50,62,2,55,17,51,4,88,2,38,253,34,67,176,118,195,198,184,248,73,117,84,46,2,184,160, + 160,172,103,98,238,233,4,90,251,173,254,194,47,88,125,77,2,140,0,0,0,2,0,240,0,0,1,195,3,82,0,3,0,7,0,0,55,51,21,35, + 17,51,21,35,240,211,211,211,211,254,254,3,82,254,0,0,0,1,0,100,1,178,2,127,2,131,0,6,0,0,19,4,37,21,6,36,39,100,1,15, + 1,12,136,254,245,136,2,131,90,90,164,45,1,44,0,0,0,2,2,68,254,67,2,218,255,211,0,3,0,7,0,28,180,4,3,5,1,9,16,220, + 60,204,50,49,0,182,6,2,0,4,2,0,8,16,220,220,220,73,58,48,5,51,21,35,21,51,21,35,2,68,150,150,150,150,45,150,100,150,0,0, + 255,255,0,171,254,67,3,130,255,211,16,39,5,16,0,168,0,0,17,7,5,22,254,228,0,0,0,19,176,16,75,82,88,187,0,0,0,4,0,4, + 0,64,56,16,60,49,89,0,0,3,0,255,254,67,3,162,255,211,0,3,0,7,0,11,0,37,182,0,3,8,4,9,5,13,16,220,60,220,60,220, + 204,49,0,64,9,10,6,4,8,6,3,4,1,12,16,220,60,220,60,220,73,58,48,5,53,33,21,55,51,21,35,21,51,21,35,0,255,1,144,125, + 150,150,150,150,195,150,150,150,150,100,150,0,0,3,0,255,254,67,3,162,255,211,0,3,0,7,0,15,0,46,64,9,12,11,8,15,4,0,5,1, + 17,16,220,60,220,60,220,220,220,204,49,0,64,11,7,2,0,5,10,2,8,11,0,13,16,16,220,60,220,60,60,204,220,73,58,48,5,51,21,35, + 21,51,21,35,39,21,35,53,35,53,33,21,3,12,150,150,150,150,250,150,125,1,144,45,150,100,150,250,200,200,150,150,0,1,2,68,254,187,2,218, + 255,81,0,3,0,16,181,2,0,4,0,1,5,16,220,204,49,0,16,220,204,48,5,51,21,35,2,68,150,150,175,150,255,255,1,199,254,187,3,87, + 255,81,16,38,5,20,125,0,17,6,5,20,131,0,0,15,178,0,0,5,73,83,88,185,0,0,0,64,56,89,49,0,0,3,1,199,254,67,3,87, + 255,211,0,3,0,7,0,11,0,79,64,9,4,11,10,5,0,1,11,10,13,16,212,204,220,204,220,73,58,49,178,0,8,5,73,83,88,65,12,0, + 11,0,10,0,9,0,8,0,64,0,4,0,7,0,6,0,5,0,4,255,192,0,4,23,56,23,56,89,0,64,9,3,11,8,0,11,7,8,4,12, + 16,220,60,220,60,220,73,58,48,1,51,21,35,3,51,21,35,55,51,21,35,2,68,150,150,125,150,150,250,150,150,254,217,150,1,144,150,150,150,0, + 0,1,1,99,254,187,3,187,255,81,0,3,0,16,181,2,0,4,0,2,5,16,220,204,49,0,16,220,204,48,5,33,21,33,1,99,2,88,253,168, + 175,150,0,0,0,1,1,99,254,117,3,187,255,161,0,7,0,25,180,5,2,0,6,9,16,220,220,220,204,49,0,180,1,0,3,5,8,16,220,220, + 60,204,48,5,21,35,53,35,53,33,21,2,218,150,225,2,88,245,150,150,150,150,0,0,0,1,0,0,5,0,0,150,5,150,0,3,0,16,181,1, + 3,4,1,3,4,16,212,204,49,0,16,220,204,48,17,51,21,35,150,150,5,150,150,0,255,255,0,0,5,0,0,150,5,150,16,6,5,25,0,0, + 255,255,1,47,254,27,3,185,255,221,16,39,5,20,0,223,255,96,16,38,5,20,229,246,17,7,5,20,254,235,0,140,0,61,178,0,10,4,73,83, + 88,185,0,10,255,192,56,89,179,0,4,10,5,16,73,58,49,0,178,0,9,12,73,83,88,185,0,9,255,192,56,89,178,0,4,9,73,83,88,185, + 0,4,255,192,56,89,179,0,4,9,4,16,73,58,48,0,0,1,2,78,1,229,2,228,2,123,0,3,0,16,181,1,3,4,3,1,5,16,212,204, + 49,0,16,220,204,48,1,51,21,35,2,78,150,150,2,123,150,0,0,0,0,1,2,68,254,67,2,218,255,211,0,3,0,16,181,2,0,4,0,2, + 5,16,220,204,49,0,16,220,204,48,5,51,17,35,2,68,150,150,45,254,112,0,0,0,0,1,0,100,3,198,2,127,4,106,0,3,0,0,19,33, + 21,33,100,2,27,253,229,4,106,164,0,0,0,1,1,99,5,0,3,187,5,150,0,3,0,16,181,1,3,4,3,1,5,16,212,204,49,0,16,220, + 204,48,1,33,21,33,1,99,2,88,253,168,5,150,150,0,0,1,0,209,255,56,1,139,5,40,0,3,0,28,180,5,2,8,0,4,16,212,236,204, + 49,0,178,1,2,4,16,204,204,48,180,64,5,80,5,2,1,93,19,51,17,35,209,186,186,5,40,250,16,0,0,0,0,1,5,25,5,0,5,175, + 5,150,0,3,0,16,181,1,3,4,1,3,4,16,212,204,49,0,16,220,204,48,1,51,21,35,5,25,150,150,5,150,150,0,0,0,0,1,0,197, + 5,0,1,91,5,150,0,3,0,16,181,1,3,4,1,3,4,16,212,204,49,0,16,220,204,48,19,51,21,35,197,150,150,5,150,150,0,2,0,209, + 0,0,1,139,4,96,0,3,0,7,0,35,182,9,2,6,8,0,4,8,16,212,50,236,50,204,49,0,180,3,1,188,5,7,47,204,244,204,48,180, + 64,9,80,9,2,1,93,19,51,21,35,17,51,21,35,209,186,186,186,186,4,96,202,253,52,202,0,0,0,1,0,102,0,0,2,220,4,96,0,13, + 0,29,182,15,5,12,9,8,13,14,16,212,236,212,204,204,49,0,182,5,169,4,188,10,169,12,47,236,244,236,48,19,16,54,59,1,21,35,34,6, + 21,17,33,21,33,102,205,227,146,148,134,110,1,188,253,138,2,94,1,14,244,143,150,194,254,22,143,0,0,1,1,99,254,67,3,187,255,211,0,7, + 0,25,180,5,2,0,6,9,16,220,220,220,204,49,0,180,1,0,3,5,8,16,220,220,60,204,48,5,21,35,53,35,53,33,21,2,218,150,225,2, + 88,195,250,250,150,150,0,0,0,1,0,186,0,0,4,159,4,96,0,39,0,111,183,41,70,31,8,30,1,8,2,183,22,8,21,10,8,11,70,40, + 16,252,236,212,252,220,183,127,2,127,2,111,2,95,2,178,63,2,5,93,236,212,75,176,29,83,88,185,0,30,255,192,56,89,252,252,183,74,3,58, + 3,41,3,122,3,178,68,3,5,93,75,176,10,81,88,185,0,41,255,192,56,89,49,0,180,31,22,188,10,1,47,47,252,196,183,58,0,58,3,85, + 29,91,9,182,101,23,106,3,121,9,7,93,48,9,1,35,1,14,4,21,17,35,53,52,62,5,55,1,51,1,62,4,53,17,51,21,20,14,5,3, + 128,1,29,217,254,96,28,35,56,33,26,184,20,31,50,45,65,44,31,254,228,217,1,160,27,35,56,34,26,184,20,31,50,46,64,44,1,155,254,101, + 2,88,14,21,53,65,110,69,254,244,185,81,138,96,81,50,44,21,13,1,155,253,168,13,21,54,65,110,69,1,12,185,82,137,97,81,49,44,21,0, + 0,1,0,88,0,0,4,72,4,96,0,21,0,54,183,23,19,17,8,0,8,21,22,16,220,212,220,252,220,220,180,116,10,111,7,2,93,49,75,176, + 10,81,88,185,0,23,255,192,56,89,0,183,8,169,9,188,17,169,21,169,176,20,47,236,236,252,236,48,37,17,52,46,3,35,33,53,33,50,30,3, + 21,17,51,21,33,53,2,232,11,38,69,121,87,254,182,1,74,123,177,116,69,27,166,252,16,143,1,207,75,99,102,58,37,143,46,85,139,166,114,254, + 85,143,143,0,0,1,0,88,255,246,3,17,4,96,0,31,0,63,183,33,3,8,4,0,8,22,27,177,13,32,16,220,212,212,236,220,236,204,180,116, + 29,92,16,2,93,75,176,15,81,75,176,13,83,90,88,125,176,6,47,24,89,49,0,183,27,169,28,188,32,16,169,11,176,3,47,47,236,16,252,236, + 48,1,20,18,23,35,38,39,14,3,35,34,39,53,22,51,50,62,3,53,52,46,1,43,1,53,51,50,22,2,127,69,77,199,58,25,33,70,80,80, + 55,46,51,34,36,44,69,86,56,40,51,101,92,90,96,221,203,2,94,144,254,192,142,135,112,81,103,54,19,14,169,10,13,52,91,170,117,151,161,59, + 143,244,0,0,0,1,0,88,0,0,4,23,4,96,0,7,0,40,182,9,0,1,8,4,5,8,16,220,220,252,220,220,49,75,176,10,81,88,185,0, + 9,255,192,56,89,0,181,1,4,169,6,188,3,47,252,252,196,48,1,35,17,35,17,33,53,33,4,23,198,186,253,193,3,191,3,209,252,47,3,209, + 143,0,0,0,0,2,0,186,0,0,4,128,4,96,0,3,0,15,0,60,183,17,70,4,8,7,11,1,8,178,2,70,16,16,252,236,212,212,252,252, + 180,112,13,106,10,2,93,75,176,10,81,88,185,0,17,255,192,56,89,49,0,183,11,169,12,188,2,0,3,2,176,6,47,47,212,196,16,252,252,48, + 1,17,35,17,5,17,35,17,52,38,35,33,53,33,32,22,1,136,185,3,177,185,129,186,254,46,1,208,1,21,225,2,172,253,84,2,96,38,253,198, + 2,96,216,153,143,250,0,0,0,1,0,186,0,0,1,116,4,96,0,3,0,33,182,5,70,1,8,2,70,4,16,252,252,252,75,176,10,81,88,185, + 0,5,255,192,56,89,49,0,178,3,188,1,47,228,48,1,17,35,17,1,116,186,4,96,251,160,4,96,0,1,0,88,0,0,2,109,4,96,0,13, + 0,69,182,15,1,5,8,8,13,14,16,220,220,252,220,220,49,75,176,14,83,75,176,16,81,90,88,124,176,2,47,24,179,106,3,90,3,180,106,11, + 90,11,4,93,49,89,75,176,10,81,88,185,0,15,255,192,56,89,0,181,2,12,169,13,188,7,47,252,252,196,48,1,21,35,34,6,21,17,35,17, + 52,54,55,35,53,2,109,80,87,65,186,77,56,248,4,96,143,155,189,253,135,2,121,127,178,39,143,0,0,1,0,186,0,0,4,128,4,96,0,13, + 0,55,183,15,70,1,8,2,8,8,9,177,70,14,16,252,252,220,252,252,178,112,11,1,93,75,176,10,81,88,185,0,15,255,192,56,89,49,0,181, + 7,169,10,188,8,2,47,47,252,236,178,116,0,1,93,0,48,1,17,35,17,52,38,35,33,17,35,17,33,32,22,4,128,186,130,184,254,231,185,1, + 208,1,20,226,2,94,253,162,2,121,198,146,252,47,4,96,240,0,0,0,0,1,0,185,255,227,4,191,4,107,0,31,0,91,183,33,25,8,10,17, + 1,8,30,177,70,32,16,252,252,220,220,183,116,20,112,20,127,10,47,10,178,160,10,5,93,252,220,49,75,176,10,81,88,185,0,33,255,192,56,89, + 0,183,15,169,20,31,188,32,5,169,176,28,47,236,16,252,196,236,181,108,10,110,25,110,30,181,92,10,94,25,94,30,183,68,10,68,1,52,10,52, + 1,176,10,93,48,1,17,20,30,2,50,62,2,53,52,46,2,35,34,7,53,54,51,50,30,2,21,16,2,32,2,25,1,1,114,45,89,116,160,116, + 89,45,19,48,90,67,66,93,114,87,102,144,84,37,252,253,242,252,4,96,253,180,116,162,91,40,40,91,162,116,113,157,125,61,30,143,30,81,159,210, + 141,254,212,254,243,1,13,1,44,2,68,0,0,1,0,136,1,162,1,66,4,96,0,3,0,35,180,5,1,8,2,4,16,220,252,220,49,75,176,10, + 81,88,185,0,5,255,192,56,89,0,180,1,2,0,188,4,16,228,47,196,48,1,17,7,17,1,66,186,4,96,253,142,76,2,190,0,0,1,0,88, + 254,86,3,146,4,96,0,16,0,56,182,18,70,0,8,3,10,17,16,220,220,252,252,180,97,12,95,9,2,93,75,176,10,81,88,185,0,18,255,192, + 56,89,49,0,182,10,169,11,188,1,189,17,16,236,252,236,182,95,3,79,3,63,3,3,93,48,1,17,35,17,52,46,3,35,33,53,33,50,30,2, + 3,146,186,21,50,88,127,93,254,251,1,1,168,214,134,53,1,238,252,104,3,152,114,155,117,66,31,143,61,151,232,0,0,1,0,88,0,0,3,202, + 4,96,0,25,0,53,182,27,7,8,19,14,25,26,16,220,212,220,252,220,183,79,15,79,24,63,15,63,24,176,4,93,49,75,176,10,81,88,185,0, + 27,255,192,56,89,0,182,25,169,0,188,14,169,13,47,236,252,236,48,19,33,50,30,3,20,14,3,35,33,53,33,50,62,2,52,46,2,35,33,88, + 1,88,117,187,120,80,34,34,80,120,187,117,254,168,1,88,100,141,78,34,34,78,141,100,254,168,4,96,64,107,146,157,172,157,146,107,64,142,62,117, + 145,188,145,117,62,0,0,0,0,1,0,88,0,0,3,240,5,213,0,8,0,54,183,10,7,8,1,8,8,0,5,178,8,2,9,16,220,252,220,252, + 212,178,127,1,1,93,252,220,49,75,176,10,81,88,185,0,10,255,192,56,89,0,182,7,2,169,4,5,188,0,47,252,204,252,196,48,33,1,33,17, + 51,17,5,7,1,1,129,1,148,253,67,187,2,221,3,254,87,3,209,2,4,254,139,1,110,252,15,0,0,2,0,186,0,0,4,149,4,96,0,8, + 0,15,0,52,183,17,70,0,8,11,10,8,1,177,70,16,16,252,252,220,252,252,49,75,176,10,81,88,185,0,17,255,192,56,89,0,182,9,169,2, + 188,10,169,1,47,236,244,236,180,111,12,126,12,2,93,48,41,1,17,33,50,30,2,21,1,17,33,17,52,38,35,4,149,252,37,1,227,141,192,119, + 52,252,223,2,103,130,185,4,96,58,129,189,138,1,115,252,190,1,234,198,146,0,0,0,0,1,0,88,0,0,4,181,4,112,0,37,0,100,183,39, + 70,12,8,17,14,27,8,180,28,1,8,0,38,16,220,236,212,178,112,28,1,93,252,220,220,252,252,183,74,35,58,35,42,35,28,35,183,104,35,90, + 35,74,4,104,4,180,115,4,12,35,8,93,75,176,10,81,88,185,0,39,255,192,56,89,49,0,183,20,169,10,0,188,15,169,14,176,27,47,47,236, + 252,212,252,183,88,4,108,17,92,17,118,4,178,127,17,5,93,48,19,51,30,1,23,62,4,51,32,25,1,33,53,33,17,52,38,35,34,7,6,7, + 6,7,3,35,19,62,4,53,52,2,88,217,4,66,22,28,77,76,98,76,51,1,146,253,206,1,120,122,97,180,86,48,42,2,5,98,186,80,3,15, + 5,7,3,93,4,96,11,157,78,70,100,54,30,8,253,238,253,162,142,1,208,195,187,160,91,206,14,23,254,18,1,162,16,73,27,51,39,22,64,1, + 7,0,0,0,0,1,0,186,254,86,1,116,4,96,0,3,0,36,182,5,70,1,8,2,70,4,16,252,252,252,75,176,10,81,88,185,0,5,255,192, + 56,89,49,0,180,2,189,3,188,4,16,228,228,48,1,17,35,17,1,116,186,4,96,249,246,6,10,0,0,1,0,88,0,0,2,120,4,96,0,13, + 0,49,183,15,70,11,8,0,5,13,14,16,220,212,220,252,252,75,176,10,81,88,185,0,15,255,192,56,89,49,0,182,5,169,6,188,13,169,12,47, + 236,252,236,180,16,10,0,10,2,93,48,37,17,52,38,43,1,53,51,50,22,21,17,33,53,1,190,100,106,126,126,205,187,253,224,143,2,88,123,111, + 143,177,221,253,46,143,0,0,0,2,0,185,255,227,4,191,4,96,0,9,0,19,0,93,183,21,4,8,15,12,8,9,70,176,20,16,252,252,220,178, + 127,15,1,93,252,220,182,74,10,60,10,96,1,3,93,49,183,89,7,84,6,105,7,100,6,176,4,93,75,176,10,81,88,185,0,21,255,192,56,89, + 0,183,10,169,0,188,20,14,169,6,47,236,16,252,252,183,52,15,52,12,38,15,38,12,183,66,15,66,12,82,3,100,3,176,8,93,48,19,33,32, + 4,17,16,0,32,0,17,1,33,17,16,32,17,52,46,2,185,1,231,1,29,1,2,255,0,253,250,255,0,1,231,254,210,2,148,45,95,127,4,96, + 250,254,212,254,208,254,217,1,39,1,48,1,141,254,107,254,73,1,191,117,156,88,36,0,0,1,0,88,255,66,4,72,4,96,0,19,0,75,183,21, + 70,2,8,1,15,8,12,177,14,20,16,220,196,252,220,252,252,182,62,13,29,13,15,13,3,93,49,75,176,10,81,88,185,0,21,255,192,56,89,0, + 183,16,169,11,169,12,1,188,14,177,188,21,16,228,228,212,236,228,180,20,16,5,16,2,93,48,180,103,13,71,13,2,93,1,17,51,17,20,14,4, + 7,5,53,37,1,51,1,62,1,18,3,136,192,19,49,88,136,194,130,254,128,1,36,254,212,194,1,20,132,144,70,3,68,1,28,254,228,118,178,175, + 136,127,106,47,139,169,104,4,13,252,50,57,150,1,8,0,0,1,0,186,254,86,4,100,4,96,0,23,0,94,183,25,70,0,8,3,13,8,8,178, + 19,70,24,16,252,252,212,220,252,252,49,75,176,10,81,88,185,0,25,255,192,56,89,0,183,16,169,11,7,169,20,188,2,177,189,24,16,236,252,252, + 220,183,74,19,31,11,15,11,47,11,176,4,93,75,176,23,80,75,176,18,83,90,88,185,0,11,0,64,56,89,252,183,106,3,92,3,74,3,127,4, + 176,4,93,48,1,17,35,17,52,38,43,1,21,20,22,51,50,55,21,6,35,34,38,53,17,33,32,22,4,100,186,145,169,253,71,74,41,67,82,67, + 134,155,1,182,1,16,228,2,94,251,248,4,10,208,161,240,73,69,13,152,16,148,176,1,100,245,0,0,0,1,0,186,0,0,4,142,4,96,0,28, + 0,106,183,30,3,8,12,22,16,8,7,178,0,70,29,16,252,196,252,212,220,180,95,12,63,12,2,93,252,220,183,61,14,61,10,75,14,75,10,176, + 4,93,49,75,176,10,81,88,185,0,30,255,192,56,89,0,183,25,169,20,16,169,0,188,9,177,169,6,47,236,252,252,125,220,178,95,20,1,113,24, + 182,112,20,80,20,74,28,3,93,75,176,25,80,75,176,18,83,90,88,185,0,20,0,64,56,89,252,48,19,33,32,0,16,0,41,1,53,33,50,54, + 53,52,38,43,1,7,6,22,51,50,55,21,6,35,34,38,53,186,1,170,1,2,1,40,254,215,254,255,254,86,1,94,236,209,216,228,165,1,1,72, + 74,41,67,82,67,134,155,4,96,254,220,253,232,254,220,142,192,238,219,186,222,73,69,13,152,16,148,176,0,1,0,88,254,86,3,249,4,99,0,22, + 0,71,183,24,8,8,7,3,14,8,17,179,0,8,22,23,16,220,252,212,252,196,220,178,127,7,1,93,252,220,183,54,3,68,3,84,3,5,3,176, + 4,93,49,75,176,10,81,88,185,0,24,255,192,56,89,0,181,7,0,188,16,189,23,16,236,252,196,178,55,3,1,93,48,1,23,22,23,62,1,61, + 1,51,21,20,14,2,7,17,35,17,52,46,1,39,3,1,37,159,102,58,117,104,184,61,104,128,72,186,57,61,49,211,4,99,228,146,153,46,195,151, + 132,132,111,186,126,83,18,252,134,3,38,80,171,106,73,1,57,0,0,0,0,1,0,88,0,0,4,5,4,96,0,26,0,108,183,28,70,23,13,8, + 12,2,8,178,26,1,27,16,220,196,252,220,176,12,75,81,176,16,75,83,90,88,185,0,12,0,64,56,177,12,0,47,16,89,252,196,252,183,60,22, + 59,3,63,0,72,3,183,108,0,89,0,95,0,74,22,182,105,22,124,0,61,0,9,93,49,75,176,10,81,88,185,0,28,255,192,56,89,0,181,12, + 1,188,26,169,25,47,236,252,196,183,84,22,56,3,84,3,116,3,176,4,93,48,37,1,51,1,54,55,62,4,53,17,51,21,20,14,5,7,1,21, + 33,53,2,244,253,100,218,1,131,4,7,24,26,44,24,19,184,18,26,46,38,61,36,30,1,3,252,83,142,3,210,253,201,3,5,17,22,52,55,90, + 55,1,12,185,74,125,88,77,46,47,21,16,254,142,71,142,0,2,0,186,254,86,5,17,4,95,0,3,0,10,0,82,176,7,183,12,8,8,5,10, + 8,4,1,180,8,2,6,70,11,16,252,212,252,220,252,212,183,79,5,95,5,111,5,127,5,176,4,93,252,204,49,75,176,10,81,88,185,0,12,255, + 192,56,89,0,183,2,1,6,169,7,188,0,189,176,4,47,236,252,252,220,196,178,175,1,1,93,180,64,9,80,9,2,113,48,1,17,7,17,9,1, + 33,53,33,21,1,1,140,186,1,211,1,148,252,129,4,87,254,87,254,86,4,86,76,251,246,1,170,3,209,142,110,252,15,0,0,0,0,1,0,88, + 0,0,3,202,4,96,0,17,0,64,182,19,70,1,8,2,10,18,16,220,220,252,236,49,176,14,75,84,176,15,75,84,91,88,176,12,47,49,89,75, + 176,10,81,88,185,0,19,255,192,56,89,0,180,10,169,11,188,2,47,252,236,48,75,176,16,80,88,177,3,0,47,47,48,89,1,17,35,17,52,46, + 3,35,33,53,33,50,30,3,3,202,186,21,51,80,126,82,254,176,1,79,126,191,122,77,31,2,58,253,198,2,58,73,118,105,70,41,143,53,93,141, + 161,0,0,0,0,1,0,88,0,0,5,83,4,96,0,40,0,162,183,42,32,8,31,15,8,14,3,182,8,2,22,8,1,2,41,16,220,212,252,16, + 252,220,180,16,14,0,14,2,93,252,220,183,72,6,59,6,43,6,16,31,183,0,31,80,0,96,0,112,0,176,8,93,252,220,75,176,11,80,88,187, + 0,22,255,192,0,1,255,192,56,56,49,177,4,21,47,125,47,24,89,183,32,0,48,0,87,21,87,4,176,4,93,49,183,102,19,103,4,119,4,118, + 19,178,135,4,5,93,75,176,10,81,88,185,0,42,255,192,56,89,0,183,21,169,4,31,14,2,188,22,177,169,0,47,236,252,196,196,220,183,175,4, + 31,4,47,4,159,4,176,4,93,236,182,67,29,67,34,72,37,3,93,48,33,35,3,51,19,62,8,55,51,2,7,6,7,6,7,19,50,62,6,55, + 51,14,7,1,174,188,154,185,73,48,75,56,40,29,17,15,8,13,6,165,18,24,41,108,95,167,43,98,151,146,107,99,69,56,34,10,185,18,42,61, + 75,105,129,171,203,4,96,253,241,1,15,33,35,64,53,93,69,121,43,254,252,103,171,69,61,6,254,205,15,40,67,105,146,197,250,157,166,252,228,163, + 137,87,61,26,0,1,0,20,255,248,4,136,4,96,0,30,0,73,183,32,70,1,8,3,10,8,23,179,8,24,17,31,16,220,212,252,252,220,252,252, + 49,180,208,25,208,24,2,93,75,176,10,81,88,185,0,32,255,192,56,89,0,183,19,169,14,1,10,169,24,169,178,25,188,1,47,252,236,252,16,212, + 252,182,127,3,106,3,91,3,3,93,48,1,17,35,17,52,46,3,43,1,17,20,6,35,34,39,53,22,51,50,54,53,17,35,53,33,50,30,2,4, + 136,186,10,36,64,112,80,246,123,152,53,78,65,38,71,46,173,2,93,143,193,108,44,2,94,253,162,2,96,74,99,101,58,37,253,205,214,208,16,143, + 14,114,163,2,51,143,67,138,180,0,0,0,255,255,0,186,0,0,3,10,4,96,16,39,5,43,1,150,0,0,16,6,5,43,0,0,255,255,0,136, + 0,0,2,168,4,96,16,39,5,43,1,52,0,0,16,6,5,47,0,0,255,255,0,136,1,162,2,127,4,96,16,39,5,47,1,61,0,0,16,6, + 5,47,0,0,0,1,0,186,2,228,2,153,4,96,0,3,0,20,64,9,2,180,0,188,4,3,68,1,4,16,212,236,49,0,16,244,236,48,1,51, + 1,35,1,210,199,254,186,153,4,96,254,132,0,2,0,186,2,228,4,110,4,96,0,3,0,7,0,29,64,14,3,7,180,1,5,188,8,3,68,1, + 7,68,5,8,16,212,236,220,236,49,0,16,244,60,236,50,48,1,51,1,35,3,51,1,35,3,167,199,254,186,153,189,199,254,186,153,4,96,254,132, + 1,124,254,132,0,2,0,0,255,215,4,220,7,34,0,37,0,48,0,0,1,22,23,22,21,35,52,39,38,39,51,22,23,22,55,54,55,54,53,51, + 20,23,22,23,22,55,54,53,51,20,7,6,35,34,39,6,7,6,37,9,1,5,7,39,1,35,1,35,53,2,177,15,10,20,114,23,31,98,123,30, + 25,13,29,46,5,4,113,9,14,29,38,9,8,113,24,45,97,84,21,32,33,29,253,246,2,4,1,0,1,27,25,125,254,193,66,253,174,115,6,22, + 49,50,106,255,238,123,162,205,64,69,35,4,7,36,28,93,125,13,21,1,1,24,24,113,171,33,60,34,28,7,5,105,250,141,2,197,98,80,45,252, + 141,6,70,96,0,2,0,0,255,215,4,220,7,41,0,42,0,53,0,0,1,21,6,7,6,21,20,23,22,23,21,34,7,6,21,20,23,22,23,50, + 55,54,55,21,6,7,6,35,34,39,38,53,52,55,54,55,38,39,38,53,38,55,54,5,9,1,5,7,39,1,35,1,35,53,3,168,77,64,86,58, + 49,49,56,85,70,30,37,47,62,55,80,54,46,78,64,63,94,71,63,68,41,55,45,28,35,1,142,70,253,150,2,4,1,0,1,27,25,125,254,193, + 66,253,174,115,7,41,94,10,29,38,35,20,32,27,2,92,42,36,64,46,34,41,1,13,19,24,110,20,16,13,70,62,93,75,72,42,14,18,26,33, + 35,84,72,35,157,250,141,2,197,98,80,45,252,141,6,70,96,0,0,0,0,4,0,133,0,0,5,122,5,20,0,3,0,7,0,11,0,15,0,0, + 37,51,21,35,37,51,21,35,1,51,21,35,37,51,1,35,4,198,180,180,254,62,180,180,253,143,180,180,2,148,160,253,94,160,250,250,250,250,5,20, + 250,250,250,236,0,5,0,133,0,0,7,60,5,20,0,3,0,7,0,11,0,15,0,19,0,0,37,51,21,35,37,51,21,35,37,51,21,35,1,51, + 21,35,37,51,1,35,6,136,180,180,254,62,180,180,254,62,180,180,253,143,180,180,2,148,160,253,94,160,250,250,250,250,250,250,5,20,250,250,250,236, + 0,1,0,219,0,0,2,0,1,236,0,5,0,0,33,35,53,19,51,3,1,174,211,164,129,82,172,1,64,254,192,0,0,2,0,252,4,253,3,5, + 6,241,0,10,0,27,0,0,1,51,50,55,54,53,52,39,38,7,6,23,43,1,53,51,17,51,17,54,55,54,23,22,21,20,7,6,1,205,55,78, + 22,53,30,1,71,52,24,175,112,81,102,36,104,63,70,65,64,54,5,98,13,33,21,32,16,1,28,21,168,101,1,143,254,191,73,40,24,26,25,82, + 91,50,42,0,0,2,0,219,0,0,2,0,5,17,0,5,0,9,0,0,1,35,53,19,51,11,1,51,21,35,1,174,211,164,129,82,211,211,211,3, + 37,172,1,64,254,192,253,45,254,0,0,0,0,2,0,147,0,0,3,176,5,240,0,3,0,36,0,0,37,21,35,53,55,53,52,38,39,46,1,47, + 1,46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,29,1,2,188,203,6,6,6,8,39,47,88,90,72,223,184,103, + 193,94,97,179,79,108,131,51,57,90,90,56,254,254,254,147,123,52,60,21,25,53,47,86,86,137,76,159,194,56,57,188,67,70,110,89,49,94,53,89, + 86,130,101,154,0,1,0,163,0,85,3,30,3,222,0,34,0,0,55,53,54,55,54,55,38,39,38,53,52,55,54,55,54,51,50,23,21,38,7,6, + 7,6,23,20,23,22,55,54,55,21,6,7,6,163,47,83,68,52,142,51,53,21,30,103,99,98,110,90,100,70,51,49,96,1,200,57,58,72,58,90, + 205,231,85,176,6,25,20,33,24,76,79,84,65,75,118,63,61,22,185,31,2,1,26,48,112,115,50,14,15,19,35,185,60,80,90,0,255,255,255,181, + 0,0,2,133,7,131,16,39,5,123,255,29,1,194,16,6,5,84,0,0,255,255,0,108,0,0,1,195,7,253,16,39,5,124,255,29,1,134,16,6, + 5,84,0,0,255,255,255,171,254,12,3,64,4,181,16,39,5,124,255,194,254,62,16,6,5,112,0,0,255,255,0,108,254,12,1,195,6,20,16,39, + 5,125,255,29,0,0,16,6,5,84,0,0,255,255,0,130,254,243,5,192,4,181,16,39,5,124,255,244,254,62,16,6,5,113,0,0,0,1,0,193, + 0,0,1,121,6,20,0,3,0,0,19,51,17,35,193,184,184,6,20,249,236,0,0,0,255,255,0,130,254,162,6,235,2,157,16,38,5,142,0,0, + 16,7,22,196,3,57,254,162,255,255,0,139,255,198,3,160,4,26,16,38,5,111,0,0,16,7,22,197,0,250,3,132,255,255,0,130,255,236,6,235, + 3,32,16,38,5,142,0,0,16,7,22,197,2,188,2,138,255,255,0,130,255,236,6,235,4,26,16,38,5,142,0,0,16,7,22,198,2,188,2,138, + 255,255,0,157,254,12,5,40,3,102,16,38,5,90,0,0,16,7,22,196,3,7,0,25,0,1,0,157,254,12,5,40,3,102,0,30,0,0,19,36, + 51,32,23,21,32,7,6,17,20,23,22,33,50,55,21,6,35,32,39,38,53,16,55,54,55,34,7,6,7,157,1,20,195,1,36,196,254,218,215,224, + 74,127,1,75,193,212,150,250,254,94,169,131,212,96,137,101,159,126,104,3,39,63,54,154,167,174,254,251,135,96,164,118,184,99,194,150,224,1,2,223, + 101,52,19,15,45,0,0,0,255,255,0,157,254,12,5,40,4,176,16,38,5,90,0,0,16,7,22,196,2,63,4,26,0,1,0,125,255,218,3,27, + 3,82,0,25,0,0,37,54,55,54,53,52,39,38,39,51,22,23,22,21,20,7,6,5,6,35,34,39,53,22,51,50,1,135,172,35,8,60,66,173, + 227,113,66,82,32,80,254,250,46,45,102,103,115,84,33,151,49,112,27,42,78,116,129,146,91,124,152,105,99,75,194,41,7,38,184,42,255,255,0,125, + 255,218,3,27,4,176,16,38,5,92,0,0,16,7,22,196,1,69,4,26,0,1,255,171,254,12,3,98,2,38,0,17,0,0,37,54,53,52,39,51, + 22,21,20,7,2,5,4,33,53,32,55,54,2,163,10,53,184,50,8,46,254,221,254,228,254,190,1,48,203,218,158,58,72,126,136,118,132,82,62,254, + 162,155,151,184,128,138,0,0,255,255,255,171,254,12,3,98,3,182,16,38,5,94,0,0,16,7,22,196,2,113,3,32,0,1,0,130,254,12,9,26, + 2,238,0,63,0,0,37,6,7,6,7,6,35,38,39,36,17,52,55,51,6,23,22,23,22,51,50,55,54,55,54,39,38,47,1,51,23,22,23,22, + 51,50,55,54,53,51,20,23,22,51,50,25,1,51,17,20,7,6,7,6,35,34,39,38,39,6,7,6,7,6,4,252,24,84,133,193,80,120,128,109, + 254,237,105,184,108,1,1,147,95,81,98,95,121,94,64,1,1,16,64,184,36,16,28,59,115,82,44,37,184,19,64,110,142,184,92,75,102,37,32,73, + 48,138,17,49,95,50,70,132,44,179,107,170,62,26,1,28,71,1,72,246,180,206,220,179,38,24,37,48,158,108,142,125,61,234,156,74,60,129,122,103, + 194,205,50,169,1,24,1,38,254,170,199,113,92,24,9,25,70,123,159,30,15,3,6,0,255,255,0,130,254,12,9,26,4,176,16,38,5,96,0,0, + 16,7,22,198,4,226,3,32,0,2,0,130,254,12,9,19,2,229,0,50,0,63,0,0,5,6,7,6,35,38,39,36,17,52,55,51,6,23,22,23, + 22,51,50,55,54,55,54,53,52,39,51,6,23,22,23,54,55,54,55,54,23,22,23,22,21,20,7,6,41,1,34,39,38,53,20,1,34,7,6,7, + 51,50,55,54,39,38,39,38,4,144,88,238,80,120,128,109,254,237,105,184,108,1,1,147,95,81,102,91,162,43,33,39,171,1,14,10,40,115,123,126, + 129,79,81,125,97,186,184,202,254,228,254,236,38,52,45,2,161,76,126,168,145,187,237,129,187,1,2,137,37,242,155,77,26,1,28,71,1,72,246,180, + 206,220,179,38,24,37,68,138,108,127,147,138,15,55,40,50,146,108,110,54,34,1,2,37,71,233,169,109,120,30,26,16,186,2,169,81,108,194,63,91, + 70,135,19,5,255,255,0,130,254,12,9,19,3,182,16,38,5,98,0,0,16,7,22,196,4,251,3,32,0,2,0,144,0,0,6,220,6,20,0,12, + 0,31,0,0,37,51,50,55,54,39,38,39,38,35,34,7,6,19,41,1,53,33,17,51,17,18,37,54,51,50,23,22,21,20,7,6,3,65,187,237, + 129,187,1,2,137,37,48,80,122,177,117,253,193,254,145,1,111,184,217,1,20,92,68,120,102,186,184,202,184,63,93,68,135,19,5,81,120,254,146,184, + 5,92,251,14,1,63,99,33,39,69,235,169,109,120,0,0,255,255,0,144,0,0,6,220,6,20,16,38,5,100,0,0,16,7,22,196,3,207,3,82, + 0,1,0,117,254,12,4,178,4,42,0,42,0,0,5,22,33,50,55,21,6,35,32,39,38,53,52,55,54,55,38,39,38,53,52,55,54,51,21,34, + 7,6,21,20,23,22,51,50,55,54,55,21,4,7,6,21,20,1,83,119,1,83,193,212,150,250,254,91,166,98,87,113,77,51,47,88,204,124,252,195, + 116,93,48,45,46,40,41,158,254,254,239,236,209,177,158,118,184,99,188,111,201,177,101,131,25,4,30,56,130,208,127,77,169,65,52,104,75,25,24,18, + 69,29,184,26,149,131,185,117,255,255,0,117,254,12,4,178,5,70,16,38,5,102,0,0,16,7,22,196,1,119,4,176,0,1,255,236,0,0,2,108, + 0,184,0,3,0,0,35,53,33,21,20,2,128,184,184,0,255,255,0,130,255,164,7,158,5,20,16,38,5,186,0,0,16,7,22,196,5,245,4,126, + 255,255,0,107,254,72,5,155,5,20,16,38,5,143,0,0,16,7,22,197,3,82,4,126,0,2,0,144,255,201,5,199,6,20,0,33,0,61,0,0, + 1,21,6,7,6,21,20,23,22,23,22,21,20,7,6,35,34,39,53,22,51,50,55,54,53,52,39,38,39,38,55,54,55,54,1,54,25,1,51,17, + 16,7,6,7,6,39,38,39,36,53,52,55,51,6,21,22,23,22,51,50,55,54,3,208,74,38,80,14,12,68,102,88,82,78,66,56,68,45,60,57, + 60,78,74,18,32,1,2,75,85,1,102,76,184,110,149,221,136,118,207,101,254,219,16,184,14,2,160,121,127,140,89,152,4,111,82,4,14,30,33,28, + 18,16,10,15,88,110,42,39,11,88,10,26,26,30,38,17,16,28,47,46,81,38,43,252,174,73,1,1,3,177,252,79,254,185,123,167,31,19,1,2, + 30,88,195,75,53,58,44,92,46,35,27,47,0,1,0,144,254,200,5,24,6,20,0,27,0,0,37,54,53,17,51,17,16,7,6,5,6,35,34,39, + 36,3,38,55,51,6,21,20,23,22,51,50,55,54,4,18,78,184,98,121,254,251,134,85,95,73,254,220,1,1,64,184,65,166,40,73,80,109,174,73, + 126,227,4,106,251,150,254,195,144,177,66,34,22,92,1,17,138,92,115,115,130,62,16,34,53,0,0,0,0,2,0,140,254,20,4,94,2,243,0,17, + 0,46,0,0,1,22,51,50,55,54,53,52,39,38,39,38,35,34,7,6,21,20,7,38,7,6,21,17,35,17,52,55,54,51,38,53,52,55,54,51, + 50,23,22,23,22,21,20,7,6,35,6,2,98,122,76,44,21,53,6,21,59,40,46,59,27,68,110,50,75,25,200,120,65,90,2,162,77,92,77,79, + 182,28,8,98,120,88,178,1,39,42,22,57,58,24,20,88,17,12,27,68,68,40,193,28,78,26,79,254,20,1,236,173,102,55,42,40,148,132,63,36, + 83,167,45,56,146,65,80,2,255,255,0,147,254,181,5,72,3,182,16,38,5,211,0,0,16,7,22,196,2,63,3,32,0,2,0,139,255,198,3,160, + 2,222,0,15,0,31,0,0,1,34,7,6,23,22,23,22,51,50,55,54,53,52,39,38,39,50,23,22,21,6,7,6,35,34,39,38,53,52,55,54, + 1,187,66,33,26,1,1,55,57,57,91,93,75,66,123,152,198,182,141,1,147,165,132,96,81,167,37,84,2,42,87,69,123,82,44,44,57,46,85,77, + 65,120,179,160,124,148,200,75,85,35,74,239,181,78,185,0,0,2,255,171,254,12,3,64,2,134,0,11,0,38,0,0,1,34,7,6,21,20,23,22, + 51,52,39,38,1,16,7,6,7,6,33,53,32,55,54,55,34,39,38,39,38,53,52,55,54,51,50,23,22,23,22,1,238,63,44,24,51,47,192,86, + 37,1,46,172,95,93,192,254,147,1,103,134,168,62,118,45,150,40,116,89,104,137,89,72,130,25,17,1,196,57,33,36,51,47,44,184,59,25,254,244, + 254,204,160,88,42,86,184,76,95,148,10,33,34,98,137,141,87,103,51,90,143,102,0,0,0,1,0,130,254,243,5,192,3,74,0,54,0,0,37,6, + 5,6,35,34,39,36,17,52,55,51,6,23,22,23,22,55,54,55,54,55,54,53,52,39,38,39,38,39,38,39,52,55,54,50,23,22,23,35,38,39, + 38,39,38,7,6,21,20,23,22,23,22,23,22,5,86,102,254,169,177,120,129,72,254,219,63,184,66,1,2,164,97,61,126,129,177,84,59,126,66,114, + 67,58,64,1,190,95,208,96,141,27,184,13,66,40,69,78,62,60,125,248,57,77,2,1,12,170,73,38,26,104,1,5,117,113,131,99,147,45,26,6, + 11,24,33,80,56,53,74,29,15,46,27,51,57,115,150,74,37,42,61,173,61,33,20,2,2,39,38,34,55,42,83,64,85,89,68,0,255,255,0,130, + 254,12,5,192,3,74,16,38,5,113,0,0,16,7,22,197,1,244,254,12,0,2,0,220,4,186,3,36,6,154,0,3,0,7,0,0,19,53,37,21, + 1,53,37,21,220,2,72,253,184,2,72,5,170,110,130,110,254,142,110,130,110,0,0,0,0,2,0,220,4,186,3,36,6,253,0,38,0,53,0,0, + 1,54,55,38,39,38,53,52,55,54,51,50,23,22,21,20,7,22,51,22,51,21,34,47,1,6,7,6,35,34,39,38,53,51,20,23,22,51,50,55, + 54,55,54,53,52,38,35,34,7,6,21,20,23,22,2,11,37,21,33,23,108,69,28,63,73,40,55,12,19,14,18,20,47,20,52,26,75,85,94,114, + 56,15,90,12,35,48,56,159,3,3,9,34,20,23,11,18,45,20,5,100,36,42,7,13,57,94,87,52,21,39,54,79,39,38,1,1,110,2,5,61, + 78,86,154,41,113,97,26,75,238,7,7,21,24,34,28,9,13,28,37,18,8,0,0,0,0,2,0,220,254,22,3,36,255,246,0,3,0,7,0,0, + 19,53,37,21,37,53,37,21,220,2,72,253,184,2,72,254,22,110,130,110,110,110,130,110,0,1,0,220,4,186,3,36,5,170,0,3,0,0,19,53, + 37,21,220,2,72,4,186,110,130,110,0,0,0,2,0,220,4,185,3,36,6,253,0,30,0,45,0,0,1,38,39,38,53,52,55,54,51,50,23,22, + 21,20,7,30,1,51,21,34,39,38,39,6,7,6,35,53,50,55,54,55,54,55,54,53,52,38,35,34,7,6,21,20,23,22,2,41,9,19,108,69, + 28,63,73,40,55,14,17,36,20,35,32,30,28,43,69,200,147,152,139,23,86,3,3,9,34,20,23,11,18,45,20,5,186,2,10,56,95,87,52,21, + 39,54,79,32,45,1,1,110,2,2,3,61,42,123,110,109,18,112,7,7,21,24,34,28,9,13,28,37,18,8,0,0,0,1,0,220,254,232,3,36, + 255,216,0,3,0,0,19,53,37,21,220,2,72,254,232,110,130,110,0,0,0,1,0,200,4,203,3,56,6,244,0,40,0,0,1,6,7,6,35,34, + 39,38,53,52,55,51,6,21,20,23,22,55,54,55,54,53,51,22,21,20,51,50,53,52,39,51,22,21,20,7,6,7,6,39,38,2,16,15,33,57, + 69,79,41,34,16,97,11,25,19,50,61,4,2,96,3,89,71,13,103,12,27,45,83,71,31,27,5,132,76,40,69,63,52,109,109,98,125,56,84,34, + 25,20,24,170,82,89,36,54,195,174,115,57,73,116,133,54,89,10,9,33,30,0,0,0,0,2,0,236,4,225,3,16,7,6,0,11,0,19,0,0, + 1,52,38,35,34,6,21,20,22,51,50,62,1,20,6,34,38,52,54,50,2,150,88,64,65,87,87,65,64,88,122,159,230,159,159,230,5,244,63,88, + 87,64,65,87,88,179,230,160,160,230,159,0,0,1,0,152,4,185,3,104,5,193,0,19,0,0,19,55,22,23,22,51,50,55,54,55,21,6,7,6, + 35,34,39,38,39,7,152,160,103,67,42,54,58,41,107,88,90,90,67,53,34,76,77,68,165,5,54,123,83,21,13,16,41,76,125,64,29,22,17,17, + 70,128,0,0,255,255,1,79,4,191,2,166,6,119,16,7,5,145,0,213,255,141,0,0,255,255,1,79,254,12,2,166,255,196,16,7,5,145,0,213, + 248,218,0,0,0,2,0,220,4,235,3,36,7,47,0,30,0,45,0,0,1,22,23,22,21,20,7,6,35,34,39,38,53,52,55,46,1,35,53,50, + 23,22,23,54,55,54,51,21,34,7,6,7,6,7,6,21,20,22,51,50,55,54,53,52,39,38,1,215,9,19,108,69,28,63,73,40,55,14,17,36, + 20,35,32,30,28,43,69,200,147,152,139,23,86,3,3,9,34,20,23,11,18,45,20,6,46,2,10,56,95,87,52,21,39,54,79,32,45,1,1,110, + 2,2,3,61,42,123,110,109,18,112,7,7,21,24,34,28,9,13,28,37,18,8,0,0,0,1,0,243,4,238,3,13,6,52,0,6,0,0,1,3, + 51,23,55,51,3,1,182,195,139,130,130,139,195,4,238,1,70,195,195,254,186,0,0,0,0,1,1,184,1,194,2,148,2,188,0,3,0,0,1,51, + 21,35,1,184,220,220,2,188,250,0,0,0,0,1,1,22,0,0,2,188,5,20,0,9,0,0,33,35,16,39,2,3,51,18,19,22,2,188,180,37, + 49,156,196,121,73,32,1,169,220,1,33,1,110,254,221,254,148,155,0,0,0,1,0,82,0,0,3,240,5,20,0,24,0,0,1,22,23,22,17,35, + 16,39,2,3,51,22,23,22,51,22,55,54,55,51,6,7,2,35,34,1,166,27,23,32,180,37,49,156,199,66,3,82,180,123,54,31,8,180,8,41, + 99,243,111,3,97,106,114,155,254,22,1,169,220,1,33,1,110,155,5,152,2,149,85,80,121,109,254,250,0,1,0,76,0,0,4,18,5,20,0,37, + 0,0,1,22,23,22,17,35,16,39,2,3,51,22,23,22,55,54,55,54,53,51,20,23,22,23,22,55,54,53,51,16,7,6,35,34,39,6,7,6, + 1,171,24,15,32,180,37,49,156,196,47,40,20,47,72,8,6,180,14,22,47,59,15,13,180,39,71,155,133,32,52,52,46,3,53,87,89,190,254,57, + 1,169,220,1,33,1,110,114,124,62,8,12,64,50,166,222,25,37,2,2,44,42,202,254,207,59,108,62,51,12,10,0,0,1,0,175,255,236,3,167, + 5,32,0,42,0,0,1,21,6,7,6,21,20,23,22,23,21,34,7,6,21,20,23,22,23,50,55,54,55,21,6,7,6,35,34,39,38,53,52,55, + 54,55,38,39,38,39,38,55,54,3,35,122,102,136,92,77,79,89,135,112,48,59,74,99,88,126,86,73,124,101,101,149,112,100,107,65,88,72,44,55, + 1,2,226,112,5,32,168,17,52,67,64,35,57,48,4,164,76,64,114,82,60,74,1,23,33,43,196,37,28,23,125,112,165,134,128,76,24,32,48,58, + 63,150,128,63,0,2,0,135,255,236,3,197,5,36,0,13,0,28,0,0,0,34,7,6,7,6,23,22,50,55,54,39,38,39,3,22,19,22,21,16, + 7,6,32,39,38,17,52,55,18,2,105,134,86,78,4,4,71,41,254,41,71,4,4,78,153,191,134,90,85,105,254,62,105,85,90,135,4,104,212,192, + 174,199,115,66,66,115,199,174,192,1,144,1,254,161,235,179,254,203,117,144,144,117,1,53,179,235,1,97,0,1,0,85,0,0,3,242,5,20,0,17, + 0,0,1,16,19,18,19,35,2,3,2,39,6,35,34,39,53,22,51,50,3,78,37,29,98,196,85,31,28,2,96,142,178,167,180,165,210,5,20,254, + 220,254,159,254,235,254,134,1,68,1,75,1,42,145,28,50,180,50,0,0,0,1,0,60,0,0,4,16,5,20,0,18,0,0,33,38,3,2,39,51, + 18,19,22,23,54,55,18,19,51,2,3,2,7,1,204,17,98,159,126,196,154,90,48,2,2,48,90,154,196,165,120,85,30,246,1,58,1,254,230,254, + 202,254,197,168,11,11,168,1,59,1,54,254,211,254,73,254,202,250,0,0,0,1,0,60,0,0,4,16,5,20,0,18,0,0,1,51,22,19,18,19, + 35,2,3,38,39,6,7,2,3,35,54,19,18,1,204,180,30,85,120,165,196,154,90,48,2,2,48,90,154,196,126,159,98,5,20,250,254,202,254,73, + 254,211,1,54,1,59,168,11,11,168,254,197,254,202,230,1,254,1,58,0,0,2,0,100,0,0,3,242,5,30,0,20,0,35,0,0,1,34,39,38, + 39,38,53,52,55,54,51,50,23,22,23,22,23,18,19,35,2,3,53,52,39,38,35,34,7,6,21,20,23,22,23,22,2,191,206,61,173,58,105,95, + 123,149,154,92,129,13,10,18,37,90,196,91,44,44,71,92,79,57,56,60,27,83,71,2,85,18,51,55,101,123,143,97,125,85,119,166,135,150,254,205, + 254,164,1,156,1,110,87,108,60,97,55,54,71,57,54,24,20,17,0,0,0,3,0,133,0,0,3,199,5,20,0,3,0,7,0,11,0,0,37,51, + 21,35,1,51,21,35,37,51,1,35,3,4,180,180,253,143,180,180,2,148,160,253,94,160,250,250,5,20,250,250,250,236,0,1,0,0,255,31,2,102, + 2,139,0,17,0,0,21,54,55,54,55,54,53,52,39,51,22,21,20,7,6,7,6,7,169,112,107,47,26,22,150,25,76,79,165,105,189,70,5,113, + 109,143,80,79,96,96,78,111,170,160,166,113,72,6,0,0,0,1,0,178,3,254,1,215,5,213,0,5,0,0,1,51,21,3,35,19,1,4,211,164, + 129,82,5,213,152,254,193,1,63,0,0,0,0,1,0,87,0,206,4,5,4,76,0,9,0,0,19,33,27,1,33,5,19,37,5,19,87,1,103,112, + 112,1,103,254,222,111,254,220,254,220,111,2,247,1,85,254,171,212,254,171,211,211,1,85,0,1,0,130,255,236,6,235,2,157,0,29,0,0,1,22, + 21,20,7,6,5,4,35,34,39,36,17,52,55,51,6,21,20,23,22,51,50,37,36,55,54,53,52,39,6,220,15,76,128,254,195,254,227,185,191,129, + 254,182,63,184,65,203,104,151,185,1,9,0,255,67,55,25,2,157,90,70,135,101,171,64,58,38,97,1,12,138,92,94,136,125,67,34,57,54,113,93, + 75,59,61,0,0,2,0,107,254,72,5,155,3,217,0,15,0,56,0,0,1,54,53,52,39,38,7,6,7,6,7,20,23,22,51,50,1,50,55,36, + 17,6,35,34,39,38,53,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,37,38,39,38,53,52,55,51,6,7,6,23,22,4,168,41, + 66,31,44,52,40,40,1,55,40,42,72,253,128,240,162,1,74,63,122,133,75,98,8,23,150,78,76,99,57,103,39,33,60,92,243,206,254,206,211,133, + 77,82,183,85,3,1,12,53,2,25,43,77,59,51,25,1,1,42,41,51,80,38,25,253,6,115,234,1,72,75,67,87,129,52,44,148,69,36,50,90, + 119,102,160,204,140,213,189,159,1,1,191,110,174,180,216,185,155,60,52,229,0,1,1,201,4,209,2,55,7,25,0,3,0,0,1,17,51,17,1,201, + 110,4,209,2,72,253,184,0,0,1,0,122,5,50,1,209,6,234,0,24,0,0,19,55,38,39,38,53,52,55,54,51,50,23,21,38,35,34,7,6, + 21,20,23,22,55,21,5,122,78,44,16,16,56,58,92,62,52,50,64,66,17,29,94,33,120,254,169,5,150,18,20,36,37,45,96,43,45,33,100,33, + 18,32,26,77,27,10,29,102,77,0,0,0,255,255,0,130,255,236,6,235,4,153,16,38,5,142,0,0,16,7,5,75,1,132,253,168,255,255,0,130, + 255,236,6,235,4,26,16,38,5,142,0,0,16,7,22,200,3,57,3,132,255,255,0,130,254,12,6,235,2,157,16,38,5,142,0,0,16,7,22,200, + 3,57,255,6,255,255,0,130,254,144,6,235,3,32,16,38,5,142,0,0,16,39,22,197,2,188,2,138,16,7,22,213,2,169,254,144,255,255,0,130, + 255,236,6,235,3,182,16,38,5,142,0,0,16,7,22,199,2,188,3,32,255,255,0,130,254,12,6,235,2,157,16,38,5,142,0,0,16,7,22,199, + 2,188,255,6,255,255,0,130,255,236,6,235,4,26,16,38,5,142,0,0,16,7,22,201,2,188,3,132,255,255,0,130,254,12,6,235,2,157,16,38, + 5,142,0,0,16,7,22,201,2,188,255,6,255,255,0,157,254,12,5,40,5,175,16,38,5,90,0,0,16,7,5,124,0,138,255,56,255,255,0,157, + 254,12,5,40,5,170,16,38,5,90,0,0,16,7,22,200,2,63,5,20,255,255,0,157,254,12,5,40,3,102,16,38,5,90,0,0,16,7,22,197, + 2,138,0,25,255,255,0,157,254,12,5,40,3,102,16,38,5,90,0,0,16,7,22,200,3,7,0,175,255,255,0,157,254,12,5,40,5,170,16,38, + 5,90,0,0,16,7,22,198,1,194,4,26,255,255,0,157,254,12,5,40,3,102,16,38,5,90,0,0,16,7,22,199,2,150,0,150,255,255,0,157, + 254,12,5,40,3,102,16,38,5,90,0,0,16,7,22,201,2,150,0,175,255,255,0,125,255,218,3,27,5,247,16,38,5,92,0,0,16,7,5,75, + 255,194,255,6,255,255,0,125,254,144,3,27,3,82,16,38,5,92,0,0,16,7,22,213,1,25,254,144,255,255,0,125,254,162,3,27,3,82,16,38, + 5,92,0,0,16,7,22,196,1,169,254,162,255,255,0,125,254,162,3,27,5,247,16,39,22,196,1,169,254,162,16,38,5,92,0,0,16,7,5,75, + 255,194,255,6,255,255,0,125,255,218,3,27,4,176,16,38,5,92,0,0,16,7,22,197,0,250,4,26,255,255,0,125,254,212,3,27,3,82,16,38, + 5,92,0,0,16,7,22,197,1,43,254,212,255,255,0,125,255,218,3,27,5,170,16,38,5,92,0,0,16,7,22,198,0,250,4,26,255,255,0,125, + 255,218,3,27,5,120,16,38,5,92,0,0,16,7,22,199,0,250,4,226,255,255,0,125,255,218,3,27,5,170,16,38,5,92,0,0,16,7,22,201, + 0,250,5,20,255,255,255,171,254,12,3,193,5,47,16,39,5,75,0,188,254,62,16,6,5,94,0,0,255,255,255,171,254,12,3,201,4,114,16,39, + 5,127,0,188,254,62,16,6,5,94,0,0,255,255,255,171,254,12,4,14,2,38,16,38,5,94,0,0,16,7,22,213,2,88,254,12,255,255,255,171, + 254,12,3,202,2,38,16,38,5,94,0,0,16,7,22,196,3,52,254,72,255,255,255,171,254,12,5,19,2,38,16,39,5,127,2,6,249,30,16,6, + 5,94,0,0,255,255,255,171,254,12,3,202,2,38,16,39,22,196,3,52,254,72,16,38,5,94,0,0,16,7,22,196,0,180,0,40,255,255,255,171, + 254,12,3,132,3,182,16,38,5,94,0,0,16,7,22,197,1,244,3,32,255,255,255,171,254,12,3,132,4,176,16,38,5,94,0,0,16,7,22,198, + 1,244,3,32,255,255,255,171,254,12,3,132,4,176,16,38,5,94,0,0,16,7,22,201,1,244,4,26,255,255,0,130,254,12,9,26,3,182,16,38, + 5,96,0,0,16,39,22,196,5,95,3,32,16,7,22,196,5,245,254,162,255,255,0,130,254,12,9,26,2,238,16,38,5,96,0,0,16,7,22,199, + 5,120,255,6,255,255,0,130,254,12,9,26,4,176,16,38,5,96,0,0,16,39,22,198,4,226,3,32,16,7,22,199,5,120,255,6,255,255,0,130, + 254,12,9,19,2,229,16,38,5,98,0,0,16,7,22,197,5,120,254,162,255,255,0,130,254,12,9,19,4,176,16,38,5,98,0,0,16,7,22,198, + 4,126,3,32,255,255,0,144,0,0,6,220,6,20,16,38,5,100,0,0,16,7,22,198,3,132,3,82,255,255,0,117,254,12,4,178,6,64,16,38, + 5,102,0,0,16,7,22,198,1,44,4,176,0,2,0,130,255,164,7,158,3,217,0,15,0,58,0,0,1,54,53,52,39,38,7,6,7,6,7,20, + 23,22,51,50,19,6,5,4,33,32,39,36,3,38,55,51,6,21,20,23,22,33,32,55,54,55,54,55,6,35,34,39,38,53,52,55,54,55,54,51, + 50,23,22,23,22,7,6,6,181,41,66,31,44,52,40,40,1,55,40,42,72,179,110,254,195,254,239,254,225,254,217,130,254,183,1,1,64,184,65,203, + 90,1,24,1,65,209,215,100,35,20,63,122,133,75,98,8,23,150,78,76,90,66,96,46,24,1,2,2,25,43,77,59,51,25,1,1,42,41,51,80, + 38,25,254,218,180,70,61,41,100,1,9,138,92,94,136,116,76,34,57,59,108,38,78,75,67,87,129,52,44,148,69,36,50,72,102,54,137,226,0,0, + 255,255,0,130,254,162,7,158,3,217,16,38,5,186,0,0,16,7,22,196,3,107,254,162,255,255,0,130,254,162,7,158,5,20,16,38,5,186,0,0, + 16,39,22,196,5,245,4,126,16,7,22,196,3,107,254,162,255,255,0,130,255,164,7,158,6,14,16,38,5,186,0,0,16,7,22,198,5,120,4,126, + 255,255,0,130,253,168,7,158,3,217,16,38,5,186,0,0,16,7,22,199,2,238,254,162,255,255,0,130,255,164,7,158,6,14,16,38,5,186,0,0, + 16,7,22,201,5,120,5,120,255,255,0,107,254,72,5,155,5,20,16,38,5,143,0,0,16,7,22,196,3,207,4,126,255,255,0,107,254,72,5,155, + 6,14,16,38,5,143,0,0,16,7,22,198,3,82,4,126,0,1,0,130,255,167,7,41,6,20,0,45,0,0,37,50,55,54,55,54,53,52,39,1, + 38,53,52,55,54,55,1,21,5,6,7,6,21,20,23,1,22,21,20,7,6,5,6,35,34,39,36,17,52,55,51,6,21,20,23,22,3,2,184,194, + 157,36,16,54,254,202,50,10,35,100,2,233,253,173,71,21,6,31,1,19,102,62,53,254,247,227,161,192,128,254,182,63,184,65,203,104,88,80,65,55, + 26,46,69,66,1,124,61,81,35,33,119,42,1,54,186,250,30,40,11,25,32,37,254,182,123,123,113,101,86,85,73,38,98,1,11,138,92,94,136,126, + 66,34,0,0,0,1,0,130,255,167,8,0,6,20,0,46,0,0,1,53,52,55,54,55,1,33,1,6,7,6,23,22,23,5,22,21,20,7,6,4, + 35,33,34,39,36,17,52,55,51,6,21,20,23,22,51,33,50,36,54,61,1,52,39,37,36,1,199,11,17,162,2,176,1,96,252,104,95,15,9,4, + 6,174,3,202,248,62,53,254,20,161,254,12,192,128,254,182,63,184,65,203,104,151,1,244,184,1,109,47,121,252,89,254,157,3,107,8,5,62,98,97, + 1,155,253,232,55,35,10,35,53,27,150,38,248,113,101,86,158,38,98,1,11,138,92,94,136,126,66,34,150,106,8,8,106,19,145,55,255,255,0,130, + 255,167,7,41,6,20,16,38,5,194,0,0,16,7,22,213,5,70,3,132,255,255,0,144,255,201,5,199,6,20,16,38,5,107,0,0,16,7,22,196, + 2,238,5,70,255,255,0,144,255,201,5,199,6,214,16,38,5,107,0,0,16,7,22,198,2,113,5,70,255,255,0,144,253,168,5,199,6,20,16,38, + 5,107,0,0,16,7,22,199,2,88,254,162,255,255,0,130,255,167,7,41,7,43,16,38,5,194,0,0,16,7,22,232,3,202,0,0,255,255,0,130, + 255,167,7,41,7,43,16,38,5,200,0,0,16,7,22,213,5,70,3,132,255,255,0,130,255,167,7,41,7,58,16,38,5,200,0,0,16,7,22,197, + 3,132,6,164,255,255,0,130,254,162,7,41,7,43,16,38,5,200,0,0,16,7,22,197,2,88,254,162,255,255,0,130,253,168,7,41,7,43,16,38, + 5,200,0,0,16,7,22,200,2,213,254,162,255,255,0,130,255,167,7,41,8,52,16,38,5,200,0,0,16,7,22,198,3,132,6,164,255,255,0,144, + 254,200,5,201,7,196,16,38,5,108,0,0,16,7,5,127,2,188,1,144,255,255,0,144,254,200,5,24,7,158,16,38,5,108,0,0,16,7,22,196, + 4,106,7,8,255,255,0,144,254,200,5,120,8,52,16,38,5,108,0,0,16,7,22,198,3,232,6,164,255,255,0,144,252,224,5,24,6,20,16,38, + 5,108,0,0,16,7,22,199,2,38,253,218,255,255,0,147,253,118,5,72,3,182,16,38,5,211,0,0,16,39,22,196,2,63,3,32,16,7,22,196, + 2,188,253,118,0,1,0,147,254,181,5,72,2,238,0,29,0,0,1,20,7,6,7,6,35,34,39,36,17,52,55,51,6,21,20,23,22,51,50,55, + 54,55,54,53,52,39,51,22,5,72,100,110,249,97,80,132,109,254,184,47,184,49,201,93,93,76,71,193,76,34,102,184,104,1,56,173,178,197,68,27, + 37,106,1,100,235,81,144,172,237,52,24,20,53,222,98,96,184,222,156,0,255,255,0,147,254,181,5,72,5,22,16,38,5,211,0,0,16,7,5,75, + 0,200,254,37,255,255,0,147,253,93,5,72,3,182,16,38,5,211,0,0,16,39,22,196,2,63,3,32,16,7,22,213,2,38,253,93,255,255,0,147, + 254,181,5,72,4,176,16,38,5,211,0,0,16,7,22,198,1,244,3,32,0,3,0,144,255,189,5,27,3,229,0,10,0,50,0,63,0,0,1,52, + 35,34,6,20,23,22,23,62,1,3,6,35,34,39,38,53,52,55,51,6,21,20,22,51,50,54,55,38,39,38,53,52,55,54,51,50,23,38,39,53, + 22,23,0,17,20,7,6,35,34,19,22,21,20,15,1,22,51,50,55,54,52,38,3,95,95,65,45,7,21,68,36,73,108,150,110,57,101,193,16,184, + 14,124,27,26,56,45,72,29,18,44,45,67,7,7,44,81,218,221,1,78,40,74,175,132,127,6,98,29,52,49,125,17,7,62,1,237,135,88,65,37, + 118,51,27,136,254,104,79,32,61,172,74,54,62,40,69,38,9,33,66,132,81,72,74,81,83,1,39,14,185,66,181,254,239,254,245,103,61,113,2,63, + 37,39,147,105,33,46,67,30,93,147,0,0,255,255,0,157,254,12,5,40,4,176,16,39,22,199,2,150,0,150,16,38,5,90,0,0,16,7,22,196, + 2,63,4,26,255,255,255,171,254,12,3,64,4,114,16,39,5,127,255,244,254,62,16,6,5,112,0,0,255,255,0,130,254,243,5,192,3,74,16,6, + 5,113,0,0,255,255,0,130,254,243,5,192,4,114,16,38,5,113,0,0,16,7,5,127,255,244,254,62,255,255,0,139,255,198,3,160,2,222,16,6, + 5,111,0,0,255,255,1,184,1,194,2,148,2,188,16,6,5,128,0,0,255,255,1,22,0,0,2,188,5,20,16,6,5,129,0,0,255,255,0,82, + 0,0,3,240,5,20,16,6,5,130,0,0,255,255,0,76,0,0,4,18,5,20,16,6,5,131,0,0,0,1,0,82,0,0,3,197,5,37,0,39, + 0,0,1,38,53,52,55,54,51,50,23,21,38,7,6,7,6,21,20,23,22,55,54,55,21,6,35,34,39,22,23,22,17,35,16,39,2,3,51,22, + 23,22,1,200,4,88,92,108,84,88,92,68,56,30,31,25,47,48,69,141,195,61,141,146,27,23,32,180,37,49,156,199,66,3,27,4,20,15,19,120, + 58,61,25,156,36,2,1,33,34,21,52,21,39,2,2,17,180,26,81,106,114,155,254,22,1,169,220,1,33,1,110,155,5,56,0,0,0,2,0,106, + 255,245,3,226,5,36,0,20,0,40,0,0,1,22,51,50,55,54,53,52,39,38,35,34,7,6,21,20,23,22,51,50,55,23,6,35,34,39,38,53, + 16,55,18,51,50,19,22,17,20,7,6,35,34,2,128,45,50,33,19,27,87,90,87,88,90,86,27,15,37,50,45,90,40,145,160,46,53,95,179,170, + 159,190,95,53,50,156,145,1,90,161,74,107,86,215,216,224,224,213,218,60,133,74,161,208,149,158,184,121,1,38,196,1,118,254,138,187,254,209,139,166, + 158,0,0,0,0,1,0,208,0,0,3,144,5,31,0,32,0,0,51,18,55,54,55,34,39,38,53,52,55,54,51,50,23,21,38,35,34,7,6,21, + 20,23,22,51,50,55,21,6,7,6,7,208,65,111,68,100,78,46,134,98,112,140,120,88,87,115,62,48,66,55,44,103,140,96,225,112,134,53,0,255, + 181,111,85,37,109,151,174,97,111,31,180,51,47,65,98,77,51,41,41,180,73,152,183,225,255,255,0,60,0,0,4,16,5,20,16,6,5,135,0,0, + 255,255,0,60,0,0,4,16,5,20,16,6,5,136,0,0,255,255,0,100,0,0,3,242,5,30,16,6,5,137,0,0,0,2,0,135,255,227,4,143, + 5,240,0,11,0,21,0,40,64,11,23,27,9,28,15,30,3,28,20,27,22,16,252,236,244,236,236,49,0,64,10,6,160,22,0,160,13,145,18,140, + 22,16,228,244,236,16,236,48,1,34,2,17,16,18,51,50,18,17,16,2,36,32,0,17,16,0,32,0,17,16,2,139,156,157,157,156,157,157,157,254, + 104,1,246,1,9,254,247,254,10,254,247,5,80,254,205,254,204,254,205,254,205,1,51,1,51,1,52,1,51,160,254,115,254,134,254,135,254,115,1,141, + 1,121,1,122,0,1,0,225,0,0,4,90,5,213,0,10,0,40,64,9,3,31,5,28,8,0,31,10,12,16,212,236,204,252,252,49,0,64,11,8, + 160,7,9,160,6,129,4,0,160,2,47,236,50,244,236,212,236,48,37,21,33,53,33,17,51,5,21,37,17,4,61,252,164,1,74,202,1,101,254,153, + 170,170,170,5,43,72,184,72,251,141,0,0,0,1,0,225,0,0,4,61,5,213,0,9,0,31,183,1,28,2,4,8,28,7,10,16,220,236,50,212, + 236,49,0,182,3,160,9,2,8,129,6,47,228,50,212,236,48,1,17,51,17,33,17,35,17,51,17,3,117,200,253,108,200,200,3,231,1,238,253,104, + 252,195,5,213,254,18,0,0,0,1,0,225,0,0,4,61,5,213,0,9,0,31,182,3,7,28,9,5,1,10,16,220,50,212,236,50,49,0,183,6, + 160,4,9,129,3,160,1,47,236,244,212,236,48,41,1,53,33,17,33,53,33,17,51,4,61,252,164,2,148,253,108,2,148,200,170,1,185,170,2,200, + 0,1,0,225,0,0,4,61,5,213,0,9,0,32,183,5,28,1,7,9,28,3,10,16,220,236,212,50,236,49,0,183,4,160,8,7,129,0,160,2, + 47,236,228,212,236,48,37,33,21,33,17,33,17,51,17,33,1,169,2,148,252,164,2,148,200,253,108,170,170,3,13,2,200,252,142,0,0,1,0,225, + 0,0,4,61,5,213,0,7,0,27,181,0,5,1,28,3,8,16,220,236,50,196,49,0,182,12,6,160,0,4,129,2,47,228,212,236,48,1,33,17, + 35,17,51,17,33,4,61,253,108,200,200,2,148,2,214,253,42,5,213,253,171,0,0,0,0,1,0,225,0,0,4,61,5,213,0,7,0,27,182,1, + 28,7,5,28,3,8,16,220,236,212,236,49,0,181,6,160,2,4,129,0,47,228,212,236,48,33,35,17,33,17,51,17,33,4,61,200,253,108,200,2, + 148,2,99,3,114,253,56,0,0,1,0,214,0,0,4,65,5,213,0,7,0,39,181,2,0,6,28,4,8,16,220,252,204,57,49,0,180,1,0,5, + 129,3,47,236,220,204,48,182,7,135,6,135,1,2,1,7,16,4,236,5,236,1,21,1,35,17,51,17,1,4,65,253,147,254,201,2,83,4,117,195, + 252,78,5,213,250,219,3,197,0,2,0,214,0,0,4,65,5,213,0,2,0,9,0,40,182,11,7,5,0,28,3,10,16,220,252,60,220,204,0,181, + 2,160,6,4,129,9,47,244,220,236,180,0,1,7,8,8,16,7,5,220,4,60,49,48,37,1,33,3,51,17,33,21,1,35,1,159,1,254,254,2, + 201,201,2,162,253,147,254,176,3,29,2,8,254,160,195,252,78,0,0,0,0,2,0,157,0,0,4,123,5,238,0,11,0,30,0,50,64,14,32,69, + 7,28,26,22,30,28,14,1,28,19,69,31,16,252,236,220,178,64,14,1,93,252,57,220,236,236,49,0,64,9,3,149,14,30,9,149,22,145,12,47, + 244,236,212,60,236,48,0,20,30,1,50,62,1,52,46,1,34,6,1,35,17,38,39,46,1,52,62,1,51,50,30,1,20,6,7,6,7,1,57,91, + 156,184,157,90,90,157,184,156,1,95,200,80,71,114,133,133,228,134,135,228,132,132,114,69,77,4,187,112,96,55,55,96,112,95,56,56,250,230,3,31, + 11,30,49,167,197,167,98,98,167,197,167,49,29,12,0,0,0,1,0,193,0,0,1,121,5,213,0,3,0,21,64,10,0,175,2,5,4,2,8,0, + 4,4,16,252,252,236,49,0,47,236,48,19,51,17,35,193,184,184,5,213,250,43,0,0,0,2,0,113,255,227,4,33,3,147,0,7,0,15,0,47, + 64,10,17,69,5,28,13,1,28,9,69,16,16,244,236,212,182,16,13,48,13,160,13,3,93,236,236,49,0,64,9,7,160,11,16,3,160,15,140,16, + 16,244,236,16,212,236,48,0,16,22,32,54,16,38,32,0,16,0,32,0,16,0,32,1,13,185,1,6,185,185,254,250,254,171,1,21,1,134,1,21, + 254,235,254,122,2,62,254,250,185,185,1,6,185,254,1,1,134,1,21,254,235,254,122,254,235,0,0,0,0,1,0,61,0,0,3,39,5,217,0,8, + 0,43,64,11,0,6,3,2,1,3,28,7,8,6,9,16,220,196,50,252,196,50,17,18,57,49,0,64,9,0,6,3,3,4,1,7,129,4,47,236, + 50,17,23,57,48,1,19,51,1,17,35,17,1,51,1,178,179,194,254,231,184,254,231,194,4,54,1,163,253,81,252,214,3,42,2,175,0,1,0,61, + 0,0,4,127,3,113,0,6,0,0,51,1,51,1,35,9,1,61,1,164,250,1,164,195,254,162,254,162,3,113,252,143,2,189,253,67,0,1,0,186, + 0,0,4,129,3,113,0,7,0,32,64,10,9,4,7,28,5,4,28,2,4,8,16,252,236,212,252,236,49,0,181,6,3,163,5,160,1,47,236,244, + 60,48,41,1,17,51,17,33,17,51,4,129,252,57,185,2,85,185,3,113,253,34,2,222,0,1,0,186,0,0,4,129,3,113,0,7,0,32,64,9, + 9,4,0,28,5,3,6,4,8,16,252,60,212,252,236,49,0,182,6,160,0,163,4,160,2,47,236,244,236,48,1,17,33,53,33,17,33,53,4,129, + 252,57,3,14,252,242,3,113,252,143,147,2,75,147,0,0,0,2,0,113,0,0,4,79,5,226,0,21,0,33,0,62,64,15,35,69,1,29,28,17, + 21,28,6,23,28,4,11,69,34,16,252,196,236,220,178,64,6,1,93,252,220,178,64,17,1,93,236,196,236,49,0,64,12,26,149,6,21,32,149,14, + 145,0,5,160,2,47,236,50,244,236,212,60,236,48,37,33,21,33,53,33,17,38,39,46,1,52,62,1,32,30,1,20,6,7,6,7,0,20,30,1, + 50,62,1,52,46,1,34,6,2,188,1,135,252,58,1,135,82,74,114,133,133,228,1,12,230,131,131,115,75,82,254,81,91,156,184,157,90,90,157,184, + 156,147,147,147,2,123,11,32,49,168,197,169,98,98,169,197,168,49,32,11,1,159,112,96,56,56,96,112,96,56,56,0,0,2,0,186,0,0,4,129, + 4,166,0,8,0,12,0,37,64,10,3,6,0,5,12,4,14,11,4,13,16,236,220,252,212,204,204,50,49,0,182,2,3,6,8,11,160,9,47,236, + 220,220,220,204,48,1,16,51,21,34,7,51,21,35,1,33,53,33,2,17,242,132,2,133,241,2,112,252,57,3,199,3,156,1,10,102,154,158,252,248, + 147,0,0,0,0,2,0,113,0,0,5,231,5,238,0,17,0,27,0,50,64,14,29,3,8,5,8,18,8,6,0,25,8,13,69,28,16,252,236,212, + 60,236,50,212,252,204,49,0,64,11,7,9,5,160,27,1,22,160,14,145,3,47,244,236,212,60,236,50,204,48,1,21,33,17,35,17,33,17,35,17, + 35,34,38,16,54,32,23,22,3,53,52,39,38,34,6,20,22,51,3,113,2,118,185,254,67,156,248,188,176,177,1,102,94,139,156,93,56,198,109,114, + 94,4,58,201,252,143,2,222,254,196,1,60,214,1,85,229,102,152,254,129,201,131,93,56,152,198,131,0,0,1,0,193,0,0,3,68,5,213,0,9, + 0,39,64,10,11,5,9,19,0,6,28,3,4,10,16,252,252,60,252,60,204,49,0,64,9,7,160,9,1,6,160,4,175,1,47,244,236,16,220,236, + 48,1,17,35,17,33,21,33,17,33,21,1,121,184,2,131,254,53,1,203,2,223,253,33,5,213,147,254,47,146,0,0,0,1,0,61,0,0,2,192, + 5,213,0,9,0,39,64,10,11,4,3,18,1,7,19,9,5,10,16,220,60,252,60,252,236,49,0,64,9,7,160,9,2,6,160,4,175,2,47,244, + 236,16,220,236,48,1,17,51,17,33,21,33,17,33,21,2,8,184,253,125,1,203,254,53,2,223,253,33,5,213,147,254,47,146,0,0,0,2,0,186, + 0,0,4,8,5,213,0,10,0,23,0,37,64,11,25,27,7,28,15,23,2,28,21,4,24,16,252,252,60,212,236,236,49,0,183,1,160,11,22,129, + 3,160,20,47,236,236,212,236,48,1,33,17,33,50,55,54,53,52,39,38,39,50,23,22,21,20,7,6,35,33,17,51,17,2,156,254,208,1,44,82, + 52,44,44,61,25,105,127,88,88,88,108,253,206,185,2,222,253,181,93,79,122,125,73,95,147,135,95,210,173,135,133,5,213,253,156,0,0,1,0,193, + 0,0,4,36,5,213,0,16,0,59,64,10,18,4,16,6,28,12,7,13,4,17,16,244,220,178,95,7,1,93,57,252,212,236,0,64,9,1,12,6, + 13,0,160,14,129,6,47,244,236,57,17,57,57,64,7,1,18,0,18,12,13,12,7,16,5,236,236,49,48,1,19,22,23,22,18,7,35,52,2,39, + 38,39,3,53,33,21,1,189,157,136,52,66,11,1,184,27,53,77,137,195,3,99,5,65,254,239,234,184,230,254,201,113,153,1,95,150,220,220,1,57, + 86,147,0,0,0,1,0,61,0,0,2,12,5,213,0,6,0,52,183,8,3,2,4,28,0,2,7,16,212,220,252,17,57,204,49,0,64,11,1,18, + 0,18,2,3,2,2,3,129,5,47,244,204,178,31,2,1,93,7,16,4,236,236,180,141,1,141,0,2,93,48,9,1,53,1,51,17,35,1,84,254, + 233,1,21,186,184,4,223,254,199,246,1,57,250,43,0,0,0,3,0,193,0,0,6,235,4,26,0,15,0,24,0,33,0,45,64,13,35,4,14,28, + 16,22,28,25,31,28,1,4,34,16,252,236,212,236,212,252,236,49,0,64,10,19,160,10,28,160,4,24,33,160,0,47,236,50,212,236,212,236,48,51, + 17,52,18,51,50,22,23,62,1,51,50,23,22,21,17,3,52,38,35,34,6,21,17,33,1,52,38,35,34,6,29,1,33,193,244,198,125,120,53,37, + 150,211,210,94,136,186,164,90,129,127,1,254,253,72,164,90,108,148,1,254,1,238,166,0,255,75,45,45,210,88,128,104,253,38,2,124,130,128,197,149, + 254,110,1,99,131,127,167,210,242,0,0,0,0,1,0,61,0,0,3,139,5,213,0,11,0,38,64,11,13,8,31,10,6,28,4,0,31,2,12,16, + 220,252,60,252,60,252,204,49,0,182,9,1,2,6,4,129,11,47,244,220,60,220,60,48,1,33,53,33,17,51,17,33,21,33,17,35,1,136,254,181, + 1,75,184,1,75,254,181,184,3,128,148,1,193,254,63,148,252,128,0,0,0,1,0,61,0,0,6,8,5,213,0,19,0,57,64,16,21,12,31,10, + 14,28,16,8,6,18,28,0,4,31,2,20,16,220,252,60,252,60,220,60,252,60,252,204,49,0,64,12,1,17,13,160,3,7,11,5,9,129,19,15, + 47,60,244,60,220,60,60,252,60,60,48,33,17,33,53,33,17,51,17,33,17,51,17,33,21,33,17,35,17,33,17,1,136,254,181,1,75,185,1,195, + 184,1,76,254,180,184,254,61,3,129,147,1,193,254,63,1,193,254,63,147,252,127,3,129,252,127,0,0,0,2,0,186,0,0,4,129,3,113,0,3, + 0,7,0,33,64,10,9,4,1,28,7,5,28,3,4,8,16,252,236,212,252,236,49,0,182,4,160,0,163,6,160,2,47,236,244,236,48,1,17,33, + 17,23,17,33,17,4,129,252,57,185,2,85,3,113,252,143,3,113,147,253,181,2,75,0,0,2,0,61,0,0,4,195,5,213,0,2,0,6,0,61, + 179,8,3,6,7,16,212,196,196,49,0,183,66,1,149,6,129,2,149,5,47,236,244,236,48,75,83,88,64,18,2,17,4,1,2,0,17,3,3,4, + 2,17,5,1,17,6,6,5,5,7,16,236,16,236,7,16,236,8,16,236,89,1,33,9,2,35,1,3,198,253,116,1,70,2,67,254,48,230,254,48, + 5,66,251,126,5,21,250,43,5,213,0,0,0,3,0,193,0,0,5,110,5,213,0,10,0,14,0,29,0,52,64,15,31,27,5,28,20,26,0,28, + 15,14,12,28,28,4,30,16,252,236,220,60,252,60,212,236,236,49,0,64,12,25,11,160,1,29,10,160,16,129,13,160,27,47,236,244,236,220,60,236, + 50,48,1,51,50,55,54,53,52,39,38,43,1,1,17,33,25,1,33,50,23,22,21,6,7,6,47,1,17,33,17,33,3,109,168,93,37,31,31,29, + 105,164,254,13,1,59,1,176,132,64,69,1,68,92,140,212,253,84,1,244,3,113,81,69,61,60,100,94,253,156,253,181,2,75,2,247,133,144,124,145, + 91,124,1,1,253,34,3,113,0,1,0,193,0,0,3,125,5,213,0,11,0,40,64,12,13,4,0,28,10,2,8,4,28,6,4,12,16,252,252,60, + 220,60,252,236,49,0,183,5,3,160,7,9,11,129,1,47,244,220,204,252,204,48,33,35,17,33,17,35,17,51,17,33,17,51,3,125,184,254,181,185, + 185,1,75,184,3,129,254,252,2,155,254,252,1,193,0,0,0,2,0,112,0,0,5,10,5,213,0,10,0,27,0,46,64,13,29,4,26,31,24,11, + 28,13,1,7,19,27,28,16,252,204,212,60,252,60,252,236,49,0,64,10,27,14,160,0,25,2,160,23,129,12,47,244,236,212,60,236,50,48,1,33, + 17,33,34,7,6,21,20,23,22,5,17,35,17,33,34,39,38,53,52,55,54,51,33,17,33,21,1,220,1,48,254,212,82,52,44,44,61,2,39,185, + 254,171,107,125,88,88,88,108,2,50,1,76,2,247,2,75,93,79,122,125,73,95,147,253,156,2,100,135,95,210,173,135,133,253,34,147,0,1,0,61, + 0,0,3,139,5,213,0,7,0,31,64,9,9,0,31,2,28,4,31,6,8,16,220,252,252,252,204,49,0,181,5,2,160,7,129,3,47,244,236,50, + 48,1,21,33,17,35,17,33,53,3,139,254,181,184,254,181,5,213,147,250,190,5,66,147,0,2,0,61,0,0,4,195,5,213,0,2,0,6,0,61, + 179,8,3,4,7,16,212,196,196,49,0,183,66,1,149,5,129,2,160,4,47,236,244,236,48,75,83,88,64,18,1,17,6,2,1,0,17,3,3,6, + 1,17,5,2,17,4,4,5,5,7,16,236,16,236,7,16,236,8,16,236,89,37,9,1,5,33,1,51,3,198,254,186,254,186,3,137,251,122,1,208, + 230,147,4,130,251,126,147,5,213,0,0,0,0,2,0,113,0,0,4,79,5,213,0,26,0,38,0,0,1,53,33,53,33,17,22,23,30,1,20,6, + 7,6,7,17,35,17,38,39,46,1,52,55,54,55,54,2,20,30,1,50,62,1,52,46,1,34,6,2,4,254,181,2,3,88,69,114,132,132,114,74, + 83,184,82,74,114,133,67,69,111,74,165,91,156,184,157,90,90,157,184,156,4,79,243,147,254,123,13,30,50,166,198,166,49,32,11,254,123,1,134,11, + 31,49,166,198,83,86,47,31,254,222,112,95,56,56,95,112,96,56,56,0,0,1,0,193,0,0,3,125,5,213,0,7,0,32,64,10,9,4,3,28, + 1,5,28,7,4,8,16,252,236,212,236,236,49,0,181,6,4,160,0,129,2,47,244,252,204,48,1,17,35,17,33,17,35,17,3,125,184,254,181,185, + 5,213,250,43,5,66,254,197,1,206,0,0,0,1,0,193,0,0,3,125,4,230,0,9,0,35,64,11,11,4,1,28,3,9,5,28,7,4,10,16, + 252,252,60,220,252,236,49,0,181,8,0,160,6,4,2,47,212,204,252,204,48,1,17,35,17,33,17,35,17,51,17,3,125,184,254,181,185,185,3,226, + 252,30,3,79,254,252,2,155,254,252,0,0,0,2,0,193,0,0,3,109,5,213,0,3,0,11,0,43,64,12,13,4,10,28,6,3,1,28,4,8, + 4,12,16,252,60,236,220,60,252,236,49,0,64,10,0,160,5,7,160,9,129,2,160,11,47,236,244,236,212,236,48,1,17,33,17,37,33,17,33,53, + 33,17,33,1,122,1,59,254,12,1,244,254,12,2,172,253,84,2,222,253,181,2,75,147,1,209,147,250,43,0,0,0,0,2,0,113,0,0,4,79, + 5,213,0,11,0,36,0,61,64,15,38,69,7,28,17,12,21,28,34,24,1,28,29,69,37,16,252,236,220,178,64,24,1,93,60,252,60,220,178,64, + 17,1,93,236,236,49,0,64,11,3,149,24,21,10,149,12,34,35,129,22,47,236,212,60,236,212,60,236,48,0,20,30,1,50,62,1,52,46,1,34, + 6,37,22,23,30,1,20,6,7,6,7,17,35,17,38,39,46,1,52,55,54,55,54,55,17,51,1,13,91,156,184,157,90,90,157,184,156,1,84,88, + 69,114,132,132,114,74,83,184,82,74,114,133,67,69,111,74,82,184,3,34,112,95,56,56,95,112,96,56,56,206,13,30,50,166,198,166,49,32,11,254, + 123,1,134,11,31,49,166,198,83,86,47,31,11,1,134,0,0,2,0,113,0,0,4,79,5,213,0,28,0,40,0,0,1,22,23,30,1,20,6,7, + 6,7,17,35,17,38,39,46,1,52,55,54,55,54,55,53,33,53,33,21,33,0,20,30,1,50,62,1,52,46,1,34,6,2,188,88,69,114,132,132, + 114,74,83,184,82,74,114,133,67,69,111,74,82,254,181,3,78,254,181,254,81,91,156,184,157,90,90,157,184,156,4,80,13,30,50,166,198,166,49,32, + 11,254,123,1,134,11,31,49,166,198,83,86,47,31,11,243,147,147,253,224,112,95,56,56,95,112,96,56,56,0,0,0,0,1,0,217,5,98,3,47, + 5,246,0,3,0,16,178,2,0,4,16,220,204,49,0,178,1,160,3,47,236,48,19,33,21,33,217,2,86,253,170,5,246,148,0,0,0,1,0,66, + 4,224,3,190,6,102,0,19,0,0,1,3,14,1,35,34,38,47,1,7,35,19,51,23,30,1,51,50,63,1,3,190,162,17,69,61,57,81,27,99, + 180,139,245,148,116,5,50,13,37,19,120,6,102,254,188,34,32,37,47,175,245,1,120,224,10,28,36,226,0,1,1,164,5,68,2,112,6,16,0,3, + 0,15,178,2,8,0,47,236,49,0,178,1,8,3,47,236,48,1,51,21,35,1,164,204,204,6,16,204,0,1,0,191,4,238,3,61,6,102,0,6, + 0,55,180,4,2,117,6,7,16,220,236,57,49,0,182,4,5,2,180,0,179,7,16,244,236,50,57,48,0,75,176,9,84,75,176,14,84,91,88,189, + 0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,1,51,19,35,39,7,35,1,180,148,245,139,180,180,139,6,102,254,136,245,245,0,0, + 0,1,0,91,4,238,3,165,6,102,0,6,0,69,179,5,6,2,7,16,220,204,57,49,0,182,6,0,5,3,160,0,7,16,220,252,204,17,57,48, + 183,3,160,6,4,160,5,6,5,7,5,16,236,16,236,64,9,85,6,101,6,117,6,133,6,4,64,11,41,4,57,4,73,4,85,5,101,5,5,1, + 93,0,93,1,33,53,5,39,51,5,3,165,252,182,2,123,236,182,1,5,4,238,148,2,230,228,0,0,0,1,0,66,4,224,3,190,6,102,0,19, + 0,0,19,51,23,22,51,50,54,63,1,51,19,35,39,7,14,1,35,34,38,39,66,139,120,19,37,13,50,5,116,148,245,139,180,99,27,81,57,61, + 69,17,6,102,226,36,28,10,224,254,136,245,175,47,37,32,34,0,0,0,0,1,0,91,4,238,3,165,6,102,0,6,0,67,179,2,5,1,7,16, + 220,204,57,49,0,182,1,0,2,4,160,0,7,16,220,252,204,17,57,48,183,4,160,1,3,160,2,1,2,7,5,16,236,16,236,64,20,85,1,101, + 1,117,1,133,1,4,38,3,54,3,70,3,90,2,106,2,5,1,93,0,93,19,53,37,51,7,37,21,91,1,5,182,236,2,123,4,238,148,228,230, + 2,148,0,0,0,1,1,154,254,135,2,102,255,83,0,3,0,15,178,2,8,0,47,236,49,0,178,3,8,1,47,236,48,5,51,21,35,1,154,204, + 204,173,204,0,0,2,0,213,5,70,3,39,6,16,0,3,0,7,0,24,181,2,8,0,4,8,6,47,252,220,236,49,0,180,5,1,8,7,3,47, + 60,252,60,48,1,51,21,35,37,51,21,35,2,92,203,203,254,121,203,203,6,16,202,202,202,0,0,0,0,1,0,200,4,117,1,186,6,20,0,8, + 0,28,183,10,4,0,5,3,7,4,9,16,252,60,220,220,236,49,0,180,2,3,8,160,6,47,236,220,204,48,1,16,35,53,50,55,35,53,51,1, + 186,242,132,2,133,241,5,128,254,245,103,154,158,0,0,0,0,1,0,200,4,117,1,186,6,20,0,8,0,28,183,10,4,6,3,5,8,4,9,16, + 252,220,220,60,236,49,0,180,2,3,7,160,5,47,236,220,204,48,19,16,51,21,34,7,51,21,35,200,242,132,2,133,241,5,9,1,11,103,154,158, + 0,2,0,100,0,0,4,23,3,251,0,3,0,7,0,28,182,9,6,2,8,0,4,8,16,220,220,252,220,204,49,0,181,1,8,3,5,160,7,47, + 236,212,236,48,1,51,21,35,1,33,21,33,1,215,204,204,254,141,3,179,252,77,3,251,204,253,100,147,0,3,0,100,0,0,4,23,3,222,0,3, + 0,7,0,11,0,39,64,9,13,10,6,2,8,4,0,8,12,16,220,220,60,252,60,220,204,49,0,64,9,9,160,11,1,8,3,5,8,7,47,236, + 212,236,212,236,48,1,51,21,35,21,51,21,35,1,33,21,33,1,215,204,204,204,204,254,141,3,179,252,77,2,132,204,236,204,3,222,146,0,0,0, + 0,1,255,236,0,0,2,247,0,147,0,3,0,18,179,2,5,0,4,16,196,220,196,49,0,178,1,160,3,47,236,48,39,33,21,33,20,3,11,252, + 245,147,147,0,0,5,0,176,254,230,4,145,6,39,0,3,0,7,0,30,0,39,0,47,0,0,1,17,51,17,3,17,51,25,1,33,17,33,17,51, + 17,22,23,22,21,20,6,7,30,1,21,20,7,6,39,17,35,19,17,54,55,54,53,52,39,38,3,17,54,55,54,53,52,38,1,110,205,205,205,254, + 117,1,139,100,209,114,117,120,116,139,155,128,129,241,100,100,120,62,68,68,62,120,152,73,73,146,4,137,254,118,1,138,253,231,254,33,1,223,253,144, + 5,26,1,13,254,243,2,82,84,154,120,142,18,28,177,133,175,96,97,2,254,230,5,163,254,119,4,44,48,100,99,49,45,253,235,254,33,1,58,59, + 122,123,116,0,0,3,0,130,255,235,4,219,4,123,0,7,0,15,0,42,0,76,64,15,36,8,37,16,8,22,14,6,10,2,18,27,20,69,43,16, + 252,60,244,60,212,60,60,236,220,252,64,6,33,31,29,3,27,35,17,18,23,57,49,0,64,8,0,22,4,135,18,140,36,43,16,60,244,236,212,196, + 64,9,12,25,8,135,40,135,29,184,43,16,252,236,236,212,196,48,37,34,21,20,51,50,53,52,3,34,21,20,51,50,53,52,19,20,35,34,53,52, + 33,17,6,35,34,53,52,51,50,23,54,51,32,25,1,35,17,52,35,34,7,1,104,63,63,65,65,63,63,65,184,249,230,1,39,43,22,230,230,168, + 44,76,189,1,150,184,226,137,87,240,64,64,64,64,3,7,64,64,64,64,252,193,205,201,208,1,112,8,216,183,81,81,254,190,252,199,3,57,170,142, + 0,2,0,139,255,221,5,135,4,140,0,7,0,47,0,64,64,14,49,28,15,18,40,6,46,2,10,20,18,35,69,48,16,252,236,60,204,220,204,220, + 252,60,204,49,0,64,19,25,135,30,22,135,33,140,48,18,135,37,4,8,0,42,135,13,184,48,16,252,236,204,220,204,220,244,16,244,236,212,236,48, + 1,34,21,20,51,50,53,52,3,34,53,52,36,51,32,17,16,13,1,4,21,20,33,50,54,51,50,23,7,38,35,34,6,35,32,53,52,45,1,54, + 53,52,33,34,7,22,21,20,1,96,64,64,64,67,210,1,118,187,2,66,254,153,254,238,254,196,1,15,137,213,168,159,138,134,105,85,118,203,171,254, + 58,1,214,1,14,215,254,107,110,76,63,3,111,64,64,64,64,254,236,228,137,196,254,171,254,236,78,59,69,106,102,142,213,97,145,127,249,239,101,58, + 46,154,186,56,56,85,216,0,0,3,0,137,255,236,4,244,4,140,0,7,0,14,0,56,0,0,1,22,51,50,55,38,39,34,18,50,53,52,34,29, + 1,37,52,55,38,53,52,55,54,33,32,23,22,25,1,35,17,52,39,38,35,32,7,6,21,54,51,32,16,35,34,39,6,21,20,23,54,51,50,21, + 20,35,32,1,105,54,5,23,48,73,1,18,75,104,104,254,175,42,41,133,147,1,55,1,33,139,111,184,94,82,191,254,253,88,59,42,58,1,4,250, + 57,20,28,22,23,171,204,204,254,117,2,96,20,18,17,1,254,16,47,39,34,4,173,127,128,54,79,212,102,113,179,143,254,247,253,191,2,65,188,133, + 116,113,76,73,19,254,182,11,36,92,57,46,141,200,182,0,0,2,0,109,254,24,3,81,4,140,0,25,0,33,0,54,64,13,6,8,17,13,8,12, + 0,32,22,28,0,69,34,16,252,204,220,204,16,212,252,220,252,49,0,64,14,30,24,26,20,135,3,184,34,13,15,135,9,189,34,16,252,236,204,16, + 252,236,196,220,196,48,19,52,54,51,32,25,1,16,6,35,34,38,39,55,22,51,50,53,17,16,35,22,7,6,39,38,19,38,23,6,55,22,39,54, + 109,162,221,1,101,154,205,214,116,13,189,34,120,175,130,3,1,5,216,208,214,67,3,2,66,67,3,1,3,166,113,117,253,244,253,143,254,249,240,208, + 141,10,209,243,2,223,1,104,21,33,207,1,1,1,9,1,65,67,3,2,66,66,0,0,0,2,0,127,255,255,4,151,4,154,0,11,0,41,0,50, + 64,13,16,18,19,29,9,21,3,25,35,18,38,69,42,16,252,236,212,204,212,204,220,60,236,49,0,64,11,31,135,12,184,42,0,37,27,6,23,18, + 47,212,204,212,196,204,16,244,236,48,1,34,6,21,20,22,51,50,54,53,52,38,3,32,23,22,25,1,7,19,52,39,20,39,38,53,52,51,50,23, + 16,5,6,7,6,29,1,35,53,52,55,54,2,176,36,28,32,32,37,27,32,85,1,37,124,123,184,1,101,200,217,218,244,54,254,153,227,76,17,184, + 30,106,2,96,32,32,37,27,34,30,37,27,2,58,121,120,254,217,253,126,1,1,41,142,82,166,1,2,183,192,104,1,150,6,4,134,30,134,75,75, + 170,62,220,0,0,2,0,139,254,32,5,134,4,140,0,11,0,54,0,53,64,14,31,18,18,36,45,9,51,3,23,18,12,40,69,55,16,252,60,236, + 204,212,204,212,60,252,60,49,0,64,13,6,53,0,47,135,16,184,55,25,135,38,140,55,16,244,236,16,244,236,204,212,204,1,34,6,21,20,22,51, + 50,54,53,52,38,7,52,55,54,51,32,17,20,13,1,6,21,20,33,50,55,54,51,50,21,16,19,7,2,17,2,33,32,53,52,45,1,54,53,52, + 33,34,7,22,7,6,35,34,1,96,36,28,32,32,37,27,32,245,231,144,186,2,66,254,153,254,173,251,1,15,239,121,35,120,151,148,144,190,74,254, + 105,254,58,1,149,1,79,215,254,107,110,76,73,16,26,191,210,3,111,32,32,37,27,34,30,37,27,48,137,121,75,254,233,254,112,106,78,100,102,239, + 68,215,254,252,254,148,81,1,99,1,119,254,245,249,216,127,105,67,145,124,56,53,115,189,0,2,0,115,255,239,4,244,4,149,0,11,0,42,0,59, + 64,14,38,8,37,3,20,9,29,24,32,8,12,16,69,43,16,252,60,236,220,204,204,212,204,220,236,49,0,64,16,34,135,41,140,43,29,135,28,0, + 22,6,18,184,38,188,43,16,236,244,204,212,204,212,236,16,244,236,48,1,50,54,53,52,38,39,38,6,21,20,22,1,52,55,38,55,18,5,22,21, + 20,7,6,39,22,23,22,55,21,7,6,21,20,5,4,25,1,51,17,16,37,36,1,230,36,28,33,31,37,27,32,254,173,165,166,1,1,1,108,220, + 221,129,54,2,90,65,144,141,147,1,139,1,124,184,253,204,253,179,3,149,32,32,36,27,1,1,33,32,36,28,253,152,143,86,109,234,1,45,1,1, + 183,198,2,1,136,189,71,52,12,161,23,24,112,168,6,6,1,190,2,63,253,193,253,180,1,1,0,0,0,2,0,186,255,227,4,188,4,123,0,7, + 0,28,0,49,64,11,9,8,28,6,16,2,14,8,20,70,29,16,252,236,204,220,204,220,236,49,0,64,6,11,135,24,184,8,29,16,60,252,236,64, + 6,0,14,4,18,140,29,16,244,196,220,196,48,37,34,21,20,51,50,53,52,5,17,52,33,32,21,17,32,21,20,35,34,53,17,52,36,51,50,4, + 21,17,1,165,64,64,64,2,31,254,185,254,181,1,25,230,235,1,31,228,214,1,41,235,64,64,64,64,235,3,31,198,198,254,80,196,200,200,2,142, + 204,118,118,204,252,199,0,0,0,2,0,129,255,226,4,131,4,161,0,11,0,46,0,60,64,14,16,18,18,45,25,32,9,34,3,32,18,39,69,47, + 16,252,236,204,212,204,16,220,60,220,236,49,0,64,16,0,32,6,36,140,47,25,135,45,29,21,135,14,41,184,18,47,244,60,236,50,220,236,16,244, + 204,212,204,48,37,34,6,21,20,22,51,50,54,53,52,38,1,54,55,50,25,1,35,17,52,35,34,7,6,35,34,39,38,35,34,7,3,32,21,20, + 35,34,53,17,16,51,50,23,22,51,50,1,108,36,28,32,32,37,27,32,1,76,32,153,242,184,55,42,62,40,128,122,42,77,35,54,1,1,1,25, + 213,251,242,151,38,56,34,36,241,32,32,37,27,34,30,37,27,3,51,124,1,254,169,252,182,3,48,219,175,113,105,189,225,254,80,196,218,210,2,150, + 1,87,117,171,0,3,0,0,254,20,4,178,4,123,0,7,0,15,0,43,0,63,64,14,45,36,8,39,6,18,2,23,8,14,43,10,27,44,16,60, + 204,220,204,252,204,220,204,220,252,204,49,0,64,17,12,25,8,41,135,29,33,184,44,0,16,5,20,140,38,189,44,16,236,244,196,220,196,16,252,60, + 236,196,220,196,48,37,34,21,20,51,50,53,52,1,34,21,20,51,50,53,52,19,32,23,22,35,34,53,17,6,35,38,55,54,55,54,23,54,51,32, + 22,21,17,35,17,52,33,34,7,2,9,64,64,64,254,153,64,64,64,174,1,23,2,2,228,239,33,31,217,1,1,211,162,55,121,193,1,45,158,184, + 254,230,178,94,245,64,64,64,64,2,246,64,64,64,64,253,152,221,195,227,2,27,7,2,215,199,1,1,101,100,213,109,250,219,5,37,163,139,0,0, + 0,2,0,87,255,239,4,203,4,145,0,11,0,44,0,57,64,16,46,29,18,32,36,18,25,9,16,3,20,18,12,41,69,45,16,252,60,236,204,212, + 204,212,252,220,252,220,49,0,64,13,22,135,39,140,45,6,43,0,34,135,14,27,184,244,60,236,204,212,204,16,244,236,48,1,34,6,21,20,22,51, + 50,54,53,52,38,5,52,51,50,21,20,7,6,23,20,51,50,53,17,52,5,4,21,17,35,17,52,35,34,21,17,16,37,36,17,16,55,34,1,64, + 36,28,32,32,37,27,32,254,249,230,236,144,139,1,181,182,1,39,1,40,184,117,106,254,145,254,146,213,211,3,248,32,32,37,27,34,30,37,27,64, + 217,213,175,141,136,168,204,176,2,88,254,1,1,251,252,115,3,141,103,104,253,169,254,185,1,1,1,92,1,21,151,0,0,2,0,95,255,227,4,190, + 4,140,0,7,0,34,0,57,64,13,36,25,8,28,9,13,8,2,20,6,16,69,35,16,252,204,220,204,252,204,220,236,204,49,0,64,16,0,14,4, + 18,184,26,188,35,23,135,10,169,30,8,140,35,16,244,60,236,236,16,236,252,196,220,196,48,1,50,53,52,35,34,7,20,3,53,51,50,54,53,17, + 36,53,52,55,54,21,17,22,55,54,53,17,51,17,16,33,34,39,6,35,1,87,64,64,62,2,184,122,93,85,254,232,226,238,93,131,227,184,254,105, + 185,84,114,217,3,115,64,64,64,64,252,112,143,101,156,1,103,8,204,221,1,1,219,253,117,169,1,1,177,3,47,252,209,254,178,115,115,0,0,0, + 0,2,0,73,255,239,4,115,4,124,0,7,0,29,0,50,64,12,25,8,23,6,16,2,12,19,18,8,69,30,16,252,236,60,204,220,204,220,252,49, + 0,64,13,4,10,0,14,184,24,188,30,21,135,28,140,30,16,244,252,16,236,252,196,220,196,48,1,34,21,20,51,50,53,52,1,52,55,38,55,54, + 51,22,7,6,0,21,22,33,32,25,1,51,17,16,37,36,1,53,64,64,64,254,212,182,183,1,1,229,237,1,1,254,236,1,1,77,1,103,184,253, + 225,253,245,3,238,64,64,64,64,253,82,218,196,38,182,194,2,188,151,254,209,168,203,1,39,2,180,253,76,254,66,1,1,0,0,0,0,2,0,73, + 255,239,4,115,6,20,0,7,0,29,0,50,64,12,26,8,23,6,16,2,12,19,18,8,69,30,16,252,236,60,204,220,204,220,252,49,0,64,13,4, + 10,0,14,184,24,151,30,21,135,28,140,30,16,244,252,16,236,252,196,220,196,48,1,34,21,20,51,50,53,52,1,52,55,38,55,54,23,22,7,6, + 0,21,22,33,32,25,1,51,17,16,37,36,1,53,64,64,64,254,212,182,183,1,1,229,237,1,1,254,236,1,1,77,1,103,184,253,225,253,245,4, + 4,64,64,64,64,253,60,239,197,37,183,194,1,1,189,173,254,210,168,203,1,39,4,104,251,152,254,66,1,1,0,0,0,3,0,89,255,239,5,204, + 4,233,0,11,0,23,0,69,0,0,1,34,6,21,20,22,51,50,54,53,52,38,33,34,6,21,20,22,51,50,54,53,52,38,1,38,39,6,39,34, + 38,53,17,54,23,50,7,6,5,17,20,51,50,53,17,51,3,20,55,54,53,17,36,55,52,23,22,23,54,53,38,39,55,22,23,6,7,17,20,6, + 4,31,36,28,32,32,37,27,32,253,6,36,28,32,32,37,27,32,2,75,148,102,103,180,166,156,1,252,212,1,1,254,233,165,164,184,1,163,155,254, + 231,1,211,215,27,29,7,18,168,31,5,1,196,178,3,210,32,32,37,27,34,30,37,27,32,32,37,27,34,30,37,27,252,29,1,73,75,1,163,154, + 2,98,225,2,235,199,5,254,118,132,132,1,52,254,203,139,5,5,130,1,140,8,203,238,1,1,152,52,50,64,55,45,93,102,197,110,254,57,165,153, + 0,2,0,186,255,227,5,104,6,20,0,29,0,37,0,65,64,16,39,0,8,27,23,8,20,16,36,13,32,16,8,8,70,38,16,252,236,204,220,204, + 16,220,252,220,252,204,49,0,64,8,21,25,18,135,2,6,140,38,16,244,60,252,60,204,64,8,34,15,30,11,184,28,151,38,16,236,252,196,220,196, + 48,1,16,33,34,39,6,35,32,25,1,52,51,50,21,20,33,17,20,51,50,53,17,51,17,20,51,50,53,17,51,1,34,21,20,51,50,53,52,5, + 104,254,169,148,102,103,180,254,190,253,211,254,232,165,164,184,162,155,184,252,62,64,64,64,1,32,254,195,74,74,1,61,2,124,223,235,204,254,92,164, + 164,1,64,254,191,166,167,4,244,253,204,64,64,64,64,0,0,2,0,104,255,239,5,22,4,125,0,11,0,45,0,63,64,16,24,8,21,17,8,14, + 44,9,40,3,44,8,36,32,69,46,16,252,60,236,204,212,204,16,212,252,212,236,49,0,64,16,6,34,0,38,184,22,188,46,15,19,12,135,26,30, + 140,46,16,244,60,252,60,196,16,228,244,204,212,204,48,1,34,6,21,20,22,51,50,54,53,52,38,19,50,53,17,51,17,20,51,50,53,17,51,17, + 16,33,34,39,6,35,32,17,52,55,38,53,52,51,50,21,20,3,6,21,20,1,100,36,28,32,32,37,27,32,65,164,184,162,155,184,254,169,148,102, + 103,180,254,190,153,137,230,236,232,66,3,210,32,32,37,27,34,30,37,27,252,179,167,1,52,254,203,169,170,3,47,252,209,254,195,74,74,1,61,240, + 166,37,158,248,220,137,254,241,77,144,167,0,0,2,0,104,255,239,5,22,6,20,0,11,0,45,0,63,64,16,24,8,21,17,8,14,44,9,40,3, + 44,8,36,32,69,46,16,252,60,236,204,212,204,16,212,252,212,236,49,0,64,16,6,34,0,38,184,22,151,46,15,19,12,135,26,30,140,46,16,244, + 60,252,60,196,16,228,244,204,212,204,48,1,34,6,21,20,22,51,50,54,53,52,38,19,50,53,17,51,17,20,51,50,53,17,51,17,16,33,34,39, + 6,35,32,17,52,55,38,53,52,51,50,21,20,3,6,21,20,1,100,36,28,32,32,37,27,32,65,164,184,162,155,184,254,169,148,102,103,180,254,190, + 153,137,230,236,232,66,3,210,32,32,37,27,34,30,37,27,252,179,167,1,52,254,203,169,170,4,232,251,24,254,195,74,74,1,61,240,166,37,158,248, + 220,139,254,243,76,145,167,0,0,1,0,64,255,227,5,22,4,96,0,23,0,36,64,7,6,8,8,2,8,0,24,16,220,236,220,236,49,0,64,10, + 7,1,188,24,4,135,11,15,140,24,16,244,60,252,16,252,60,48,1,51,17,16,33,50,25,1,51,17,16,33,32,39,6,35,34,53,52,51,50,7, + 50,53,1,147,184,1,26,249,184,254,79,254,179,41,51,182,198,156,144,2,41,4,96,253,44,254,237,1,19,2,212,252,197,254,190,56,56,156,150,123, + 139,0,0,0,0,2,0,115,255,239,4,244,6,20,0,11,0,42,0,59,64,14,38,8,37,3,20,9,29,24,32,8,12,16,69,43,16,252,60,236, + 220,204,204,212,204,220,236,49,0,64,16,34,135,41,140,43,29,135,28,0,22,6,18,184,38,151,43,16,236,244,204,212,204,212,236,16,244,236,48,1, + 50,54,53,52,38,39,38,6,21,20,22,1,52,55,38,55,18,5,22,21,20,7,6,39,22,23,22,55,21,7,6,21,20,5,4,25,1,51,17,16, + 37,36,1,230,36,28,33,31,37,27,32,254,173,165,166,1,1,1,108,220,221,129,54,2,90,65,144,141,147,1,139,1,124,184,253,204,253,179,3,149, + 32,32,36,27,1,1,33,32,36,28,253,152,143,86,109,234,1,45,1,1,183,198,2,1,136,189,71,52,12,161,23,24,112,168,6,6,1,190,3,218, + 252,38,253,180,1,1,0,0,0,2,0,139,255,239,5,18,4,140,0,11,0,44,0,55,64,12,29,18,12,9,39,25,18,3,16,35,69,45,16,252, + 60,204,236,212,204,212,252,49,0,64,16,43,135,31,140,46,6,0,37,14,135,27,23,135,18,184,46,16,244,252,212,252,212,220,204,16,244,236,48,1, + 34,6,21,20,22,51,50,54,53,52,38,5,52,33,32,17,16,33,32,23,7,38,35,32,21,20,33,32,17,16,33,32,39,38,53,52,51,50,21,20, + 7,22,51,32,1,99,36,28,32,32,36,28,32,2,189,254,128,253,212,2,54,1,98,230,117,248,229,254,140,1,146,2,26,253,196,254,171,135,85,211, + 224,22,75,183,1,22,1,88,32,32,36,28,32,32,36,28,16,232,1,56,1,36,220,123,187,140,159,254,143,254,155,110,69,123,203,210,78,20,37,0, + 0,2,0,79,255,239,4,170,4,140,0,11,0,48,0,64,64,16,50,44,18,30,26,18,12,9,18,37,18,3,38,22,69,49,16,252,60,204,236,212, + 204,220,236,212,236,220,49,0,64,17,14,135,37,24,0,16,6,28,135,20,47,140,49,33,135,42,184,244,236,16,244,60,236,204,212,204,212,204,236,48, + 37,34,6,21,20,22,51,50,54,53,52,38,5,38,39,38,7,22,7,6,39,38,53,16,33,32,19,22,55,54,53,17,16,33,32,7,6,7,39,54, + 55,54,5,4,25,1,20,37,38,1,52,37,27,32,32,36,28,32,1,11,44,171,68,12,227,2,2,207,249,1,41,1,60,87,37,68,118,254,162,254, + 243,39,26,2,183,6,17,71,1,161,2,38,254,190,222,248,33,31,36,28,32,32,36,27,30,243,3,1,84,1,183,214,1,1,235,1,137,254,176,145, + 1,2,174,1,168,1,24,114,74,99,20,111,60,249,1,1,254,137,253,212,250,1,1,0,0,2,0,115,255,229,4,118,4,123,0,7,0,33,0,58, + 64,7,33,18,8,2,18,69,34,16,252,196,212,236,64,6,6,22,12,8,28,35,16,220,236,220,196,49,0,64,9,33,0,20,4,26,135,15,140,34, + 16,244,236,204,220,204,204,64,5,31,135,10,184,34,16,252,252,48,1,34,21,20,51,50,53,52,1,18,33,32,25,1,16,33,32,36,53,52,51,50, + 21,20,7,22,51,32,53,17,52,33,32,7,1,84,64,64,64,254,248,41,1,205,1,244,254,34,255,0,254,219,229,221,69,25,143,1,30,254,204,254, + 217,24,1,84,64,64,64,64,1,206,1,89,254,215,253,184,254,219,157,143,210,215,61,73,8,216,1,196,204,213,0,0,0,3,0,79,255,239,5,129, + 5,111,0,11,0,53,0,61,0,0,37,34,6,21,20,22,51,50,54,53,52,38,37,17,6,33,36,55,54,33,32,23,54,61,1,38,39,55,22,23, + 6,7,17,20,37,38,39,38,39,38,7,22,7,6,39,38,55,18,33,32,19,22,55,54,1,32,39,52,33,32,21,20,1,52,37,27,32,32,36,28, + 32,2,150,70,254,235,253,222,2,2,2,30,1,142,114,64,10,92,160,116,4,1,214,254,190,222,43,44,171,68,12,227,2,2,207,250,1,1,1,40, + 1,60,87,37,68,118,254,165,1,116,1,254,141,254,137,248,33,31,36,28,32,32,36,27,61,1,153,14,1,252,233,154,54,28,2,84,98,90,171,100, + 149,166,253,195,250,1,1,233,243,3,1,84,1,183,214,1,1,235,1,137,254,176,145,1,2,2,209,69,109,77,100,0,0,3,0,127,255,232,6,25, + 4,153,0,6,0,13,0,57,0,0,0,34,21,6,51,50,55,36,34,21,6,51,50,55,1,36,17,16,55,38,55,54,23,22,7,6,7,6,19,22, + 37,36,53,17,6,43,1,38,55,54,23,50,23,54,23,22,25,1,35,17,52,7,6,7,6,7,19,16,1,168,128,1,65,63,1,1,224,128,1,65, + 63,1,254,249,254,28,163,194,1,1,229,238,2,1,117,138,12,7,1,28,1,0,20,29,2,230,1,1,211,162,53,114,151,253,184,82,88,54,38,36, + 1,4,4,64,64,64,64,64,64,64,252,36,1,1,45,1,10,211,47,153,215,1,1,212,139,117,138,254,234,159,1,1,181,1,178,9,6,238,201,1, + 99,100,1,2,254,192,252,169,3,87,131,1,1,55,39,28,253,214,254,179,0,3,0,115,255,227,4,118,4,123,0,7,0,32,0,40,0,60,64,14, + 33,18,14,8,31,6,24,2,37,18,10,20,69,41,16,252,60,236,196,220,196,220,252,236,49,0,64,6,4,28,135,17,140,41,16,244,236,204,64,10, + 0,22,39,135,8,35,135,12,184,41,16,252,236,220,236,220,204,48,1,34,21,20,51,50,53,52,55,32,17,16,33,32,25,1,20,33,34,36,53,52, + 51,50,21,20,7,22,51,32,53,17,6,19,52,33,32,21,20,33,32,1,84,64,64,64,237,253,242,2,21,1,238,253,254,210,254,209,221,237,61,65, + 64,1,53,83,85,254,187,254,184,1,72,1,69,1,71,64,64,64,64,203,1,52,1,53,254,208,253,145,249,130,170,214,217,71,41,35,175,1,31,53, + 1,54,155,155,160,0,0,0,0,2,0,139,255,239,5,120,4,216,0,11,0,52,0,62,64,13,26,39,18,14,9,49,35,18,3,18,45,69,53,16, + 252,60,204,236,212,204,212,252,60,49,0,64,19,12,135,41,140,54,6,0,47,16,135,37,29,135,24,33,135,20,184,54,16,244,236,220,236,212,252,212, + 220,196,16,244,236,48,1,34,6,21,20,22,51,50,54,53,52,38,1,32,17,52,37,36,53,52,33,50,23,22,51,50,19,23,2,35,34,39,38,35, + 34,21,20,5,4,17,16,33,32,39,38,53,52,51,50,21,20,7,22,1,104,36,28,32,32,37,27,32,1,36,1,151,254,123,253,221,1,161,203,97, + 106,106,104,64,148,77,243,167,113,75,157,205,1,121,2,41,253,171,254,199,135,109,225,215,95,156,1,139,32,32,37,27,34,30,37,27,254,249,1,0, + 189,49,69,230,252,89,108,1,4,48,254,148,120,80,94,98,56,82,254,194,254,115,117,95,124,222,218,93,70,28,0,0,0,2,0,203,254,173,5,240, + 4,161,0,3,0,39,0,0,0,34,20,50,3,39,1,0,39,38,15,1,6,39,36,19,18,33,51,50,7,6,39,38,53,52,55,34,17,20,51,50, + 63,1,54,23,22,21,20,1,3,65,128,128,241,129,2,83,1,50,59,57,138,194,146,160,254,104,1,2,1,104,205,212,1,1,211,212,4,164,218,78, + 85,215,126,156,245,254,177,4,13,128,251,32,134,2,43,1,30,59,57,106,150,113,1,1,1,144,1,144,206,214,1,1,208,20,33,254,254,230,66,166, + 97,3,5,166,169,254,200,0,255,255,0,111,255,229,4,182,4,128,16,39,6,59,5,15,253,117,16,7,6,59,5,15,250,201,0,0,0,2,251,96, + 5,28,255,167,7,11,0,19,0,27,0,43,64,11,13,11,15,9,0,18,15,20,9,24,5,47,204,220,204,220,252,17,18,57,57,49,0,64,8,22, + 7,26,2,17,13,18,2,47,252,204,16,204,220,204,48,3,2,33,32,38,55,54,23,50,7,6,7,22,51,36,39,52,39,55,22,5,52,7,34,21, + 6,23,22,89,2,253,199,254,182,195,1,1,229,242,4,1,35,33,65,1,91,1,86,138,168,252,222,66,56,1,63,60,6,29,254,255,168,107,217,1, + 216,80,36,4,1,85,46,70,138,143,77,63,1,62,61,1,1,0,0,0,0,2,0,123,0,0,3,201,4,123,0,16,0,24,0,43,64,9,3,8, + 4,21,11,17,15,69,25,16,252,204,220,204,220,236,49,0,64,11,19,13,0,23,9,7,135,0,184,4,25,16,60,252,236,220,204,16,220,204,48,1, + 32,25,1,35,17,16,35,34,7,50,21,20,35,34,53,16,19,20,51,50,53,52,35,34,2,18,1,183,184,255,110,61,218,229,225,166,59,67,62,64, + 4,123,254,106,253,27,2,203,1,25,86,193,199,199,1,174,254,82,55,55,55,0,0,0,255,255,252,154,0,0,3,201,6,114,16,38,6,82,0,0, + 16,6,6,60,0,0,0,0,0,1,251,64,4,236,255,106,7,105,0,17,0,31,183,0,18,6,2,11,14,18,9,47,236,212,220,212,236,49,0,181, + 16,7,2,12,3,11,47,60,204,50,212,204,48,1,20,33,21,32,17,16,33,32,17,16,33,53,32,55,52,33,32,251,254,1,37,254,29,2,38,2, + 4,254,63,1,1,2,254,186,254,152,6,37,187,126,1,63,1,62,254,194,254,193,126,187,197,0,0,0,0,1,251,64,4,236,0,0,7,105,0,20, + 0,36,64,9,0,18,6,2,14,17,18,12,9,47,204,236,212,220,212,236,49,0,182,19,7,12,2,15,3,14,47,60,204,50,50,212,204,48,1,20, + 33,21,32,17,16,33,32,17,20,7,51,21,33,53,32,55,54,33,32,251,254,1,37,254,29,2,38,2,4,62,212,253,169,1,2,1,1,254,185,254, + 152,6,37,187,126,1,63,1,62,254,194,119,74,126,126,187,197,0,0,0,0,2,251,64,4,236,255,106,7,105,0,17,0,21,0,42,64,10,0,18, + 6,20,2,18,12,14,18,9,47,236,220,196,220,196,220,236,49,0,64,9,16,7,21,160,19,2,12,3,11,47,60,204,50,220,252,220,204,48,1,20, + 33,21,32,17,16,33,32,17,16,33,53,32,55,52,33,32,5,21,35,53,251,254,1,37,254,29,2,38,2,4,254,63,1,1,2,254,186,254,152,1, + 223,238,6,37,187,126,1,63,1,62,254,194,254,193,126,187,197,78,220,220,0,2,251,64,4,236,0,0,7,105,0,20,0,24,0,46,64,11,0,18, + 6,24,2,22,14,17,18,12,9,47,204,236,212,196,220,196,212,236,49,0,64,10,19,7,21,160,23,12,2,15,3,14,47,60,204,50,50,220,252,220, + 204,48,1,20,33,21,32,17,16,33,32,17,20,7,51,21,33,53,32,55,54,33,32,5,21,35,53,251,254,1,37,254,29,2,38,2,4,62,212,253, + 169,1,2,1,1,254,185,254,152,1,223,238,6,37,187,126,1,63,1,62,254,194,119,74,126,126,187,197,84,220,220,0,0,2,252,254,253,51,254,182, + 255,178,0,4,0,21,0,0,4,34,20,51,54,3,54,53,52,39,6,35,34,53,52,51,50,23,22,21,20,7,253,238,130,65,65,92,144,5,40,68, + 179,170,101,78,91,204,188,129,1,254,207,111,91,17,16,36,158,186,78,91,139,117,214,0,0,2,252,167,253,142,254,200,255,175,0,7,0,29,0,37, + 64,8,27,25,6,18,2,14,21,10,47,204,212,204,220,204,220,204,49,0,64,7,4,12,0,16,26,8,23,47,204,204,220,196,220,196,48,5,34,21, + 20,51,50,53,52,19,34,53,52,55,38,53,52,51,50,21,20,6,21,20,51,50,53,17,51,17,20,253,30,22,23,21,114,243,62,74,117,117,109,130, + 158,132,178,22,22,21,23,254,64,146,115,62,10,91,121,117,63,123,69,66,88,1,70,254,186,195,0,0,0,2,251,96,5,28,255,167,7,11,0,20, + 0,27,0,0,3,22,7,39,54,53,54,37,34,7,22,7,6,7,6,39,38,55,54,33,32,0,52,7,34,23,20,51,89,1,168,138,86,1,254,165, + 65,33,46,10,21,217,229,1,1,123,120,1,26,2,57,252,225,60,63,1,56,6,10,95,143,138,70,46,85,1,4,68,87,176,1,1,217,84,95,96, + 254,174,126,1,63,61,0,0,0,2,251,28,253,199,0,13,255,177,0,7,0,26,0,35,64,5,6,17,2,24,13,47,204,196,220,196,49,0,64,10, + 22,135,8,0,15,4,11,135,19,27,16,220,252,196,220,196,60,252,48,1,50,53,52,35,34,21,20,5,34,2,35,22,21,20,35,34,53,16,33,50, + 18,51,50,55,23,6,251,220,48,48,43,2,201,218,172,184,92,196,184,1,76,222,222,96,93,166,134,191,254,78,48,47,46,49,105,1,51,32,114,191, + 167,1,67,254,208,198,114,240,0,2,0,129,254,20,4,244,5,185,0,11,0,50,0,0,5,50,54,53,52,38,35,34,6,21,20,22,1,17,16,33, + 32,17,53,16,33,50,21,20,35,34,39,21,20,33,32,25,1,52,0,53,52,51,50,4,50,55,23,2,35,34,36,35,34,20,0,1,242,36,28,32, + 32,37,27,32,2,177,254,1,253,253,1,109,217,217,142,45,1,81,1,71,253,88,249,117,1,9,94,124,128,116,190,73,254,243,84,75,2,182,63,32, + 32,36,28,32,32,36,28,2,179,253,96,254,64,1,17,127,1,44,200,209,115,107,150,1,69,2,114,125,1,51,216,209,253,196,84,254,251,249,174,254, + 153,0,0,0,0,2,0,122,255,227,2,152,4,123,0,21,0,33,0,42,64,9,25,0,31,11,16,8,7,70,34,16,252,252,204,196,220,196,49,0, + 64,11,14,135,9,184,34,28,20,22,4,140,34,16,244,204,220,204,16,252,252,48,37,6,7,6,35,34,25,1,52,51,50,23,7,38,35,34,21,17, + 62,1,51,50,7,50,54,55,52,38,35,34,6,21,6,22,2,142,1,67,67,155,242,232,204,106,70,80,136,72,11,79,81,178,181,36,27,1,33,31, + 37,27,1,33,162,112,39,40,1,70,2,110,228,74,118,45,79,253,33,51,93,239,32,32,36,28,32,32,36,28,0,0,255,255,0,122,255,227,4,200, + 4,123,16,38,6,71,0,0,16,7,6,71,2,48,0,0,0,2,255,211,255,246,3,48,7,44,0,11,0,40,0,0,1,34,6,21,20,22,51,50, + 54,53,52,38,1,38,7,6,19,23,22,21,17,51,32,7,6,7,35,34,25,1,52,47,1,38,53,52,51,50,23,1,7,2,78,36,28,32,32,37, + 27,32,254,164,115,32,36,203,140,101,23,1,3,1,1,211,2,251,144,139,113,201,152,122,1,109,133,1,18,32,32,37,27,34,30,37,27,5,24,144, + 26,29,254,249,180,131,181,254,29,231,207,1,1,56,2,50,174,186,180,145,121,166,156,254,44,118,0,0,0,2,0,92,255,227,3,235,7,35,0,26, + 0,34,0,54,64,8,3,18,16,7,18,12,69,35,16,252,236,220,236,64,7,33,22,29,19,8,0,12,16,220,236,220,220,204,49,0,64,11,5,135, + 14,152,35,27,20,31,24,140,35,16,244,196,220,196,16,252,252,48,1,52,36,53,52,37,38,21,20,23,7,38,53,16,33,32,17,20,4,21,17,36, + 21,20,35,34,53,55,34,21,20,51,50,53,52,1,194,1,105,254,216,243,160,120,220,1,171,1,228,254,143,1,25,226,239,239,64,64,64,3,231,184, + 220,88,186,1,1,184,52,160,124,236,96,1,80,254,176,164,217,179,253,247,10,229,220,221,63,64,64,64,64,0,0,0,0,2,0,188,255,234,3,144, + 7,22,0,11,0,34,0,0,1,34,6,21,20,22,51,50,54,53,52,38,1,53,38,39,55,22,31,1,33,23,6,21,17,36,7,6,35,34,25,1, + 52,55,35,2,174,36,28,32,32,37,27,32,254,100,2,116,166,132,4,4,1,46,59,224,1,26,1,1,213,251,156,239,1,6,32,32,37,27,34,30, + 37,27,3,200,136,157,196,95,248,112,149,189,172,152,254,137,10,241,208,1,56,2,62,153,117,0,0,0,0,2,0,147,254,37,4,152,4,116,0,47, + 0,59,0,0,1,52,35,34,7,6,35,34,39,38,35,34,29,1,36,7,6,7,35,38,17,53,16,51,50,23,22,51,50,55,54,51,50,25,1,16, + 7,6,33,32,39,38,53,55,22,5,4,17,1,34,6,21,20,22,51,50,54,53,52,38,3,224,34,51,67,50,127,122,55,74,44,34,1,26,1,1, + 211,2,251,182,133,47,73,78,92,61,48,130,182,66,87,254,150,254,161,84,79,189,21,1,51,1,72,253,169,36,28,32,32,37,27,32,3,88,116,92, + 68,68,92,116,93,10,241,207,1,3,1,53,246,1,2,60,92,85,67,254,254,252,170,254,247,102,136,119,112,118,10,202,8,9,1,103,2,72,32,32, + 37,27,34,30,37,27,0,0,0,1,253,18,4,241,253,198,6,86,0,3,0,14,64,5,2,0,2,8,0,47,252,49,0,47,204,48,1,51,17,35, + 253,18,180,180,6,86,254,155,0,2,251,127,4,224,255,163,7,32,0,7,0,27,0,39,64,8,27,8,15,2,21,6,17,12,47,212,204,220,204,204, + 220,204,49,0,64,8,0,15,4,19,27,13,24,12,47,220,60,204,220,196,220,196,48,1,22,39,54,7,34,23,6,37,20,2,41,1,53,54,53,6, + 55,52,23,22,29,1,20,7,32,54,53,252,25,43,2,1,42,43,1,1,3,181,215,254,132,254,85,144,183,1,157,145,71,1,177,243,6,109,1,43, + 43,2,41,44,125,229,254,221,133,46,112,7,157,136,1,1,131,183,92,40,141,250,0,0,0,1,251,62,4,200,0,46,6,243,0,52,0,0,1,34, + 17,16,33,50,22,55,54,55,54,51,50,21,20,7,22,55,54,55,51,6,7,6,33,35,53,54,53,52,35,34,7,6,39,38,39,38,35,34,21,20, + 59,1,38,53,52,51,22,7,6,7,6,252,46,240,1,37,50,126,42,38,73,72,72,220,157,132,66,79,5,153,2,103,40,254,226,197,208,76,24,66, + 67,93,105,37,62,23,146,101,62,46,96,104,2,2,62,51,4,200,1,20,1,23,130,1,1,65,63,215,126,61,4,13,16,104,130,92,36,133,107,98, + 56,58,59,1,1,45,70,144,161,2,95,90,1,107,102,50,41,0,0,0,0,1,252,78,4,224,254,140,7,30,0,11,0,33,64,7,7,5,8,169, + 0,2,11,47,60,204,252,60,220,49,0,64,7,4,2,5,169,9,11,8,47,60,204,252,60,220,48,1,53,51,53,51,21,51,21,35,21,35,53,252, + 78,216,142,216,216,142,5,184,142,216,216,142,216,216,0,0,255,255,251,28,5,23,0,13,7,1,16,7,6,69,0,0,7,80,0,0,0,2,252,154, + 4,246,254,62,6,114,0,7,0,15,0,23,64,4,12,4,8,0,47,204,220,204,49,0,64,4,14,2,10,6,47,204,220,204,48,1,52,51,50,21, + 20,35,34,55,20,51,50,53,52,35,34,252,154,212,208,212,208,132,76,84,80,80,5,190,180,180,200,200,72,72,72,0,0,2,0,135,255,227,4,143, + 4,96,0,13,0,29,0,0,1,34,7,6,21,20,23,22,32,55,54,53,52,38,39,32,23,22,21,20,7,6,33,32,39,38,17,52,55,54,2,139, + 143,94,76,58,78,1,98,88,49,157,157,1,25,136,99,111,140,254,247,254,237,128,113,111,146,3,192,132,104,179,189,96,129,153,87,174,163,252,160,196, + 146,233,253,142,179,165,148,1,5,230,149,196,0,2,0,99,255,103,4,168,4,155,0,3,0,38,0,0,0,20,50,52,3,55,54,17,52,39,38,35, + 34,7,6,7,6,23,54,55,54,21,20,39,38,39,38,53,52,55,54,5,32,23,22,21,16,5,7,1,182,128,10,242,210,112,72,188,146,103,99,1, + 1,47,53,112,216,228,134,73,180,141,117,1,11,1,17,129,166,254,206,246,2,22,128,128,253,234,135,117,1,203,127,112,72,69,67,108,101,92,103,2, + 2,226,212,2,1,85,212,220,154,137,115,1,117,151,200,253,207,168,135,0,0,2,0,99,255,121,4,92,5,177,0,3,0,36,0,0,0,50,52,34, + 3,50,55,6,35,38,53,52,51,50,17,20,7,6,35,32,39,38,53,16,63,1,36,53,23,16,1,7,6,17,20,23,22,3,43,128,128,114,208,37, + 15,51,221,224,237,93,102,220,254,205,129,166,207,211,1,31,184,254,148,217,124,112,72,1,70,128,254,80,182,19,3,198,216,254,228,240,102,111,117,151, + 200,1,84,162,165,224,233,1,254,199,254,229,169,97,254,251,127,112,72,0,0,1,0,22,255,237,5,138,6,164,0,47,0,0,37,50,25,1,52,39, + 36,53,52,51,50,23,22,51,50,55,23,2,35,34,39,38,35,34,21,20,5,22,21,17,16,37,36,39,6,35,34,53,52,51,50,7,50,53,17,51, + 17,16,3,17,226,182,254,182,239,161,51,93,76,47,124,128,116,190,107,90,49,132,65,1,81,189,254,102,254,220,40,51,182,198,156,144,2,41,184,131, + 1,68,1,106,190,82,151,198,230,58,106,196,84,254,251,104,56,75,79,200,112,198,254,116,254,36,2,2,54,56,156,150,123,139,2,145,253,214,254,237, + 0,2,0,99,255,87,4,206,5,177,0,3,0,37,0,0,0,50,52,34,1,36,5,4,39,38,53,16,63,1,36,53,23,16,1,7,6,17,20,23, + 22,51,50,23,38,39,38,51,50,7,6,7,22,23,3,33,128,128,1,173,254,226,254,241,254,190,114,138,207,211,1,31,184,254,148,217,124,84,57,239, + 108,99,217,2,2,212,236,12,11,126,120,162,1,152,128,253,63,76,1,1,118,143,167,1,84,162,165,224,233,1,254,199,254,229,169,97,254,251,109,89, + 60,24,197,208,228,216,201,5,199,75,0,0,0,3,0,99,255,87,4,206,5,177,0,3,0,45,0,50,0,0,0,50,52,34,5,18,55,38,53,38, + 51,50,7,54,53,23,20,7,6,7,6,7,6,17,20,23,22,51,50,23,38,39,38,51,50,7,6,7,22,23,21,36,5,4,39,38,18,20,51,50, + 52,3,33,128,128,253,66,2,229,145,1,228,251,15,156,184,179,125,98,36,143,124,84,57,239,108,99,217,2,2,212,236,12,11,126,120,162,254,226,254, + 241,254,190,114,138,248,61,67,1,152,128,203,1,104,161,40,170,231,173,173,162,1,189,235,164,12,63,102,88,254,242,109,89,60,24,197,208,228,216,201, + 5,199,75,157,76,1,1,118,143,3,200,116,116,0,0,0,0,2,0,89,255,239,5,244,6,127,0,52,0,64,0,0,1,20,6,39,38,39,6,39, + 34,38,53,17,52,51,50,7,6,5,17,20,51,50,53,17,51,3,20,55,54,53,17,16,39,36,53,52,51,50,4,50,55,23,2,35,34,36,35,34, + 21,20,5,22,17,1,34,6,21,20,22,51,50,54,53,52,38,5,7,178,165,148,102,103,180,166,156,253,212,1,1,254,233,165,164,184,1,163,155,217, + 254,172,250,117,1,9,94,124,128,117,189,73,254,242,83,76,1,92,223,252,62,36,28,32,32,37,27,32,1,44,165,153,1,1,73,75,1,163,154,2, + 98,223,235,199,5,254,118,132,132,1,52,254,203,139,5,5,130,1,106,1,69,97,154,216,209,252,195,84,254,251,249,87,56,210,139,254,190,1,26,32, + 32,37,27,34,30,37,27,0,0,3,0,130,254,20,4,219,4,123,0,5,0,11,0,38,0,0,37,34,20,51,50,52,3,34,20,51,50,52,19,20, + 35,34,53,52,33,17,6,35,34,53,52,51,50,23,54,51,32,25,1,35,17,52,35,34,7,1,104,63,63,65,65,63,63,65,184,249,230,1,39,43, + 22,230,230,168,44,76,189,1,150,184,226,137,87,240,128,128,3,7,128,128,252,193,205,201,208,1,112,8,216,183,81,81,254,190,250,219,5,37,170,142, + 0,4,0,150,254,82,5,112,4,116,0,11,0,17,0,77,0,85,0,0,1,34,6,21,20,22,51,50,54,53,52,38,0,50,53,52,34,21,5,6, + 35,38,55,54,55,54,55,37,17,52,35,34,7,6,35,34,39,38,35,34,21,17,36,7,6,7,35,38,25,1,16,51,50,23,22,51,50,55,54,51, + 50,25,1,55,23,7,21,54,23,22,21,20,7,6,7,6,39,6,19,1,6,23,22,55,54,55,1,137,36,28,32,32,37,27,32,2,229,110,110,254, + 180,118,112,134,2,1,43,45,149,1,26,34,50,68,50,127,122,55,74,44,34,1,26,1,1,211,2,251,182,132,48,73,78,92,61,48,130,182,142,74, + 216,37,18,149,46,51,63,173,53,120,118,254,132,39,15,24,170,129,81,1,156,32,32,37,27,34,30,37,27,253,158,57,51,51,185,104,1,107,47,47, + 51,119,225,2,177,116,92,68,68,92,116,254,223,10,241,207,1,3,1,53,1,186,1,2,60,92,85,67,254,254,253,200,114,84,173,171,8,1,8,148, + 70,45,50,1,3,98,71,1,59,254,208,31,21,34,130,98,44,0,0,0,0,2,0,105,255,247,4,247,4,145,0,28,0,32,0,0,1,36,27,1, + 20,23,22,53,17,51,17,20,5,4,53,17,52,35,34,21,17,32,21,20,35,34,53,17,16,18,50,52,34,1,197,1,109,1,1,126,141,184,254,192, + 254,197,182,165,1,24,211,253,172,128,128,4,145,1,254,185,253,169,101,3,3,106,3,141,252,115,251,1,1,254,2,88,176,164,254,92,204,235,223,2, + 124,1,57,252,7,128,0,0,0,3,0,127,255,232,7,147,4,153,0,6,0,13,0,73,0,0,0,34,21,6,51,50,55,36,34,21,6,51,50,55, + 5,17,22,51,54,53,17,51,17,16,37,34,39,6,37,53,50,53,17,52,7,6,7,6,7,19,18,37,36,17,16,55,38,55,54,23,22,7,6,7, + 6,19,22,37,36,53,17,6,35,48,35,38,55,54,23,50,23,54,23,22,1,168,128,1,65,63,1,1,224,128,1,65,63,1,2,145,11,84,99,184, + 254,233,98,42,64,254,214,219,82,88,54,38,36,1,1,254,72,254,28,163,194,1,1,229,238,2,1,117,138,12,7,1,28,1,0,20,29,2,230,1, + 1,211,162,53,114,151,253,4,4,64,64,64,64,64,64,64,109,253,111,54,4,160,3,74,252,182,254,189,1,44,47,3,184,204,1,225,131,1,1,55, + 39,28,253,214,254,179,1,1,1,45,1,10,211,47,153,215,1,1,212,139,117,138,254,234,159,1,1,181,1,178,9,6,238,201,1,99,100,1,2,0, + 0,4,0,127,255,232,7,201,4,153,0,6,0,13,0,76,0,88,0,0,0,34,21,6,51,50,55,36,34,21,6,51,50,55,5,17,22,51,50,53, + 17,51,17,16,33,34,39,6,39,38,55,54,51,50,23,17,52,7,6,7,6,7,19,18,37,36,17,16,55,38,55,54,23,22,7,6,7,6,19,22, + 37,36,53,17,6,35,48,35,38,55,54,23,50,23,54,23,22,3,50,54,53,52,38,39,38,6,21,20,22,1,168,128,1,65,63,1,1,224,128,1, + 65,63,1,2,145,26,102,120,184,254,212,133,36,56,159,217,5,5,196,36,43,82,98,44,19,55,1,1,254,72,254,28,163,194,1,1,229,238,2,1, + 117,138,12,7,1,28,1,0,20,29,2,230,1,1,211,162,53,114,151,253,244,36,28,33,31,37,27,32,4,4,64,64,64,64,64,64,64,109,253,211, + 148,158,3,74,252,182,254,190,99,101,2,3,198,193,8,1,227,147,17,20,36,16,51,253,214,254,179,1,1,1,45,1,10,211,47,153,215,1,1,212, + 139,117,138,254,234,159,1,1,181,1,178,9,6,238,201,1,99,100,1,2,251,234,32,32,36,27,1,1,33,32,36,28,0,1,0,120,255,225,6,134, + 6,159,0,25,0,0,1,16,0,33,32,0,17,16,1,33,53,33,21,33,4,17,16,0,37,54,0,17,52,39,55,22,6,134,254,59,254,183,254,177, + 254,79,1,220,254,116,5,74,253,117,253,175,1,52,1,17,250,1,83,83,155,118,3,16,254,150,254,59,1,248,1,88,1,194,1,4,168,169,231,254, + 34,254,242,254,93,1,1,1,124,1,12,133,191,75,197,0,0,1,0,110,255,255,5,162,6,159,0,21,0,0,5,17,6,35,34,0,53,16,55,33, + 4,21,20,22,51,50,55,17,51,17,33,21,3,193,188,150,226,254,225,190,1,15,254,241,204,113,158,186,180,1,45,1,2,193,74,1,76,223,1,7, + 247,247,248,189,221,88,3,49,250,2,162,0,0,1,0,111,254,209,5,50,6,179,0,23,0,0,1,17,33,17,54,38,35,34,6,21,20,23,7,38, + 53,38,54,51,50,22,21,17,33,17,4,126,254,141,1,112,111,131,126,100,144,145,1,254,183,189,223,1,115,254,209,1,46,5,3,141,134,120,115,103, + 100,123,178,143,174,224,239,176,251,140,254,49,0,2,0,110,255,226,6,63,6,159,0,11,0,28,0,0,1,16,0,35,34,0,17,16,0,51,50,0, + 55,16,0,37,4,0,17,16,37,53,33,53,33,21,33,21,4,5,130,254,162,205,209,254,166,1,73,230,235,1,60,189,254,80,254,204,254,211,254,64, + 2,151,253,208,5,6,253,209,2,147,2,222,1,11,1,61,254,194,254,247,254,253,254,166,1,96,253,254,184,254,73,2,1,1,180,1,73,2,61,156, + 63,169,169,60,165,0,0,0,0,1,0,100,0,0,4,106,6,179,0,19,0,0,33,17,16,38,35,34,6,21,20,23,7,38,17,52,0,51,50,0, + 25,1,3,182,206,130,148,177,138,121,206,1,16,242,228,1,32,4,89,1,4,183,171,145,211,133,141,191,1,29,176,1,52,254,212,254,211,251,166,0, + 0,1,0,80,0,1,5,182,6,179,0,25,0,0,1,17,33,17,35,17,52,38,35,34,6,21,20,23,7,38,53,52,54,51,50,22,29,1,33,17, + 5,2,254,168,181,146,95,107,139,88,132,146,253,181,186,238,2,12,2,8,1,245,252,4,5,35,137,103,105,146,77,107,124,144,160,170,244,232,172,131, + 253,108,0,0,0,2,0,60,255,225,5,143,6,159,0,10,0,25,0,0,1,33,17,30,1,51,62,1,17,52,38,1,2,0,35,34,0,25,1,33, + 53,33,17,33,32,0,3,62,254,254,1,158,179,131,192,225,1,159,2,254,231,230,239,254,234,254,179,2,1,1,1,1,10,1,70,3,253,254,43,251, + 172,1,212,1,12,250,161,254,87,254,223,254,174,1,2,1,53,3,231,160,253,254,254,222,0,2,0,121,255,225,7,20,6,179,0,8,0,23,0,0, + 37,17,35,32,0,17,16,0,33,1,17,33,17,33,4,0,19,16,0,41,1,17,33,17,4,89,128,254,162,254,186,1,70,1,94,2,138,254,172,254, + 214,254,101,254,46,1,1,200,1,164,1,42,2,5,129,5,148,254,122,254,192,254,229,254,77,1,106,2,17,251,229,2,1,225,1,142,1,131,1,226, + 253,233,253,79,0,1,0,60,0,1,3,30,6,253,0,7,0,0,37,17,33,17,51,21,33,17,2,107,253,209,179,2,47,1,5,185,1,67,164,249, + 168,0,0,0,0,2,0,120,0,0,4,125,6,159,0,11,0,27,0,0,1,17,52,38,35,34,7,17,20,22,51,54,19,17,6,35,38,0,25,1, + 51,17,54,51,50,0,21,17,3,202,180,156,149,186,176,159,116,220,195,145,245,254,247,180,222,108,245,1,18,2,6,1,181,125,223,57,254,94,157,228, + 1,254,68,1,111,85,2,1,68,1,3,3,60,254,203,78,254,183,238,252,127,0,0,0,0,2,0,60,255,225,6,70,6,160,0,11,0,28,0,0, + 1,16,38,35,34,7,17,16,22,23,62,1,1,6,0,25,1,33,17,35,17,33,17,54,51,32,0,16,0,5,136,228,130,141,153,182,142,119,207,254, + 193,235,254,237,254,166,179,2,192,164,141,1,5,1,20,254,195,2,56,1,9,187,61,254,128,254,250,181,2,2,164,254,185,1,1,49,1,48,3,191, + 253,235,2,181,253,192,60,254,191,253,156,254,234,0,0,0,0,2,0,120,255,226,6,151,6,159,0,10,0,31,0,0,1,34,6,21,30,1,51,50, + 54,53,17,1,17,33,17,16,2,37,34,0,17,16,0,51,33,17,33,53,33,17,33,17,2,171,130,242,2,187,135,181,154,2,23,254,158,244,254,238, + 199,254,198,1,53,254,1,31,253,76,3,105,2,24,3,252,193,254,219,224,223,220,1,191,252,25,3,231,254,65,254,236,254,184,1,1,45,1,42,1, + 39,1,61,1,88,170,253,254,251,120,0,0,0,1,0,130,0,1,4,135,6,159,0,25,0,0,37,17,52,38,35,34,7,17,35,17,52,54,51,33, + 21,33,38,6,23,21,54,51,50,0,21,17,3,202,189,154,177,140,180,229,241,1,191,254,21,132,116,2,167,170,252,1,4,1,2,119,226,162,97,252, + 102,5,9,204,201,170,1,88,165,173,80,254,210,254,253,145,0,2,0,100,254,169,6,114,6,179,0,11,0,33,0,0,1,16,0,35,34,0,17,16, + 0,51,32,0,19,51,16,33,32,3,7,32,0,17,16,0,33,32,0,17,16,0,7,22,51,54,5,180,254,173,251,239,254,171,1,95,230,1,3,1, + 74,10,180,254,190,254,212,25,129,254,187,254,63,1,203,1,56,1,57,1,210,254,232,190,1,149,140,3,98,1,19,1,159,254,105,254,229,254,202,254, + 86,1,201,253,181,254,169,1,71,14,2,27,1,101,1,106,1,231,254,24,254,150,254,237,254,52,84,240,3,0,0,0,0,1,0,50,255,226,5,189, + 6,179,0,19,0,0,1,22,0,35,34,0,53,17,33,53,33,17,20,22,51,62,1,53,17,51,5,189,1,254,230,228,225,254,216,254,123,2,57,203, + 137,141,190,179,1,255,224,254,195,1,61,234,4,11,159,251,82,173,215,1,213,174,4,174,0,1,0,80,0,1,4,135,6,160,0,22,0,0,37,17, + 6,35,34,0,53,52,55,35,53,33,21,6,3,30,1,51,50,55,17,51,17,3,212,162,173,242,254,240,165,216,1,216,232,1,1,178,147,145,190,179, + 1,2,202,86,1,45,231,159,216,160,147,118,254,230,185,175,86,3,52,249,98,0,0,0,0,1,0,110,255,226,6,211,6,160,0,25,0,0,37,17, + 33,17,16,0,35,34,0,53,16,55,23,6,21,30,1,51,50,54,53,17,51,17,33,17,6,33,254,73,254,230,220,227,254,221,188,115,114,2,199,128, + 174,148,180,2,105,131,3,121,254,56,254,210,254,220,1,47,211,1,28,143,113,117,197,154,200,223,211,4,108,253,251,251,232,0,0,0,0,1,0,130, + 255,226,4,137,6,160,0,19,0,0,1,2,0,35,32,0,53,17,51,17,30,1,51,62,1,53,52,39,55,22,4,137,2,254,208,191,254,244,254,246, + 179,1,194,160,129,177,151,95,246,2,42,254,245,254,195,1,106,235,4,105,251,148,197,238,1,221,219,209,142,144,193,0,0,2,0,130,255,255,4,136, + 6,179,0,8,0,21,0,0,1,54,38,35,33,17,33,62,1,55,20,0,41,1,17,33,21,33,17,33,32,0,3,202,2,219,156,254,224,1,32,157, + 217,189,254,209,254,252,254,224,2,194,252,139,1,211,1,0,1,51,4,139,190,203,253,1,1,182,191,218,254,196,254,43,161,6,180,254,193,0,0,0, + 0,2,0,100,254,139,6,114,6,179,0,11,0,33,0,0,1,16,0,35,34,0,17,16,0,51,50,0,19,16,33,53,50,55,38,39,6,33,32,0, + 17,16,0,33,32,0,17,16,3,22,5,180,254,176,248,250,254,176,1,97,231,245,1,85,190,254,109,230,2,2,125,216,254,252,254,179,254,69,1,194, + 1,73,1,61,1,198,201,201,3,97,1,19,1,160,254,93,254,241,254,211,254,77,1,184,253,168,254,169,158,188,118,56,177,2,34,1,96,1,95,1, + 240,254,18,254,156,254,200,254,216,128,0,0,0,3,0,100,0,1,6,137,6,172,0,8,0,17,0,34,0,0,1,35,17,51,50,18,55,38,2,37, + 35,6,2,21,20,0,59,1,1,16,0,33,35,17,35,17,35,4,0,16,0,41,1,32,0,4,55,98,98,180,220,1,2,212,254,54,101,179,238,0, + 255,162,101,3,97,254,177,254,253,98,173,101,254,252,254,165,1,94,1,1,1,116,1,4,1,78,6,23,252,52,1,32,202,210,1,15,1,2,254,241, + 208,206,254,227,1,235,254,203,254,180,254,76,1,180,1,1,78,2,104,1,66,254,196,0,0,1,0,90,0,1,5,112,6,160,0,15,0,0,1,17, + 33,17,35,17,33,17,51,17,33,17,51,17,33,17,4,180,254,136,179,253,209,189,1,114,179,2,52,2,102,1,81,252,74,3,181,1,217,254,208,2, + 65,253,193,254,5,0,0,0,0,1,0,131,255,225,4,136,6,179,0,17,0,0,5,35,17,52,38,7,34,6,21,17,35,17,38,0,51,50,0,23, + 4,136,180,191,139,138,203,178,1,1,40,225,229,1,23,1,31,4,172,172,220,1,219,172,251,84,4,168,233,1,65,254,184,216,0,0,0,1,0,110, + 0,1,4,117,6,160,0,17,0,0,37,17,6,35,34,2,53,17,51,17,6,22,51,50,55,17,51,17,3,193,210,144,252,245,180,2,150,160,184,179, + 180,1,2,194,77,1,18,219,2,61,253,197,177,158,85,3,53,249,97,0,0,1,0,120,255,225,4,126,6,160,0,31,0,0,1,20,2,5,38,36, + 61,1,51,21,20,22,51,50,54,61,1,6,35,34,2,53,17,51,17,30,1,51,50,55,17,51,4,126,244,254,234,209,254,213,189,182,135,142,203,182, + 169,246,254,180,1,167,166,164,173,179,1,206,184,254,205,2,2,240,224,36,33,144,164,165,167,251,83,1,57,185,2,56,253,200,151,187,88,3,50,0, + 0,1,0,130,0,1,4,135,6,159,0,17,0,0,37,17,54,38,35,34,7,17,35,17,51,17,54,51,50,4,25,1,3,212,1,153,207,135,176,180, + 179,174,156,217,1,47,1,2,171,147,189,48,252,53,6,158,253,205,48,255,254,216,253,140,0,1,0,121,255,225,6,29,6,179,0,25,0,0,5,53, + 6,35,36,0,17,2,0,33,4,23,7,38,35,32,0,17,16,0,37,22,55,17,51,17,5,103,246,163,254,117,254,54,1,1,223,1,119,1,5,246, + 102,219,192,254,252,254,114,1,128,1,20,160,253,182,1,97,127,1,2,7,1,110,1,135,1,213,2,165,176,184,254,145,254,178,254,209,254,88,2,1, + 158,1,247,252,233,0,0,0,0,2,0,120,255,226,6,123,6,160,0,10,0,29,0,0,1,34,2,21,20,22,51,50,54,53,17,1,17,33,17,16, + 0,35,32,0,17,16,0,33,51,17,51,17,33,17,2,199,199,202,199,155,136,160,2,10,254,171,254,245,207,254,251,254,226,1,71,1,8,249,181,2, + 6,3,252,254,244,158,218,246,199,215,1,220,252,23,3,233,254,36,254,218,254,232,1,80,1,32,1,15,1,59,2,4,253,252,251,119,0,2,0,130, + 255,255,4,136,6,159,0,8,0,25,0,0,1,52,38,35,33,17,33,62,1,55,20,6,35,33,21,33,17,35,53,33,17,35,17,33,50,22,3,202, + 112,93,254,57,1,199,80,126,189,210,185,254,57,2,27,179,254,152,180,2,123,185,210,5,18,129,109,254,20,2,127,128,170,247,255,254,123,231,254,40, + 6,160,226,0,0,1,0,100,255,226,4,152,6,179,0,32,0,0,1,20,0,35,32,0,53,51,6,18,51,50,54,53,52,37,36,17,52,18,51,50, + 18,21,35,54,38,35,34,6,23,20,0,4,152,254,235,228,254,244,254,209,191,1,205,172,164,154,254,93,254,96,254,212,226,238,186,1,170,121,128,138, + 2,3,68,1,209,211,254,228,1,101,252,181,254,244,169,154,200,170,170,1,31,160,1,19,254,225,209,198,139,150,118,206,254,162,0,0,0,1,0,130, + 255,255,4,136,6,159,0,19,0,0,1,16,0,35,34,39,17,33,21,33,17,51,17,22,51,50,54,25,1,51,4,136,254,222,240,165,155,2,204,252, + 128,180,141,190,132,207,180,4,210,254,204,254,216,23,254,30,172,6,160,252,141,22,160,1,6,1,227,0,0,2,0,60,0,1,5,144,6,159,0,2, + 0,13,0,0,1,33,9,1,35,3,1,35,9,1,35,53,33,1,4,122,253,158,1,19,1,174,215,235,254,107,220,2,26,254,123,255,5,84,253,239, + 5,246,253,248,252,206,1,246,253,79,3,95,2,150,169,252,156,0,0,0,0,1,0,60,255,226,6,71,6,160,0,21,0,0,1,22,0,35,32,0, + 53,17,33,17,35,17,33,17,30,1,51,50,54,53,17,51,6,71,2,254,213,208,254,255,254,243,254,176,180,2,183,2,179,168,129,195,179,2,12,243, + 254,201,1,90,208,3,244,254,137,2,23,251,94,139,241,209,171,2,158,0,0,1,0,130,0,1,4,136,6,160,0,17,0,0,1,53,52,38,43,1, + 17,35,17,51,17,33,50,22,29,1,51,21,3,15,88,132,253,180,180,1,0,189,215,190,2,55,159,155,139,252,5,6,159,253,252,189,167,98,160,0, + 0,1,0,111,255,226,5,20,6,179,0,33,0,0,1,16,0,35,34,0,17,38,55,23,6,21,20,22,51,50,54,53,18,0,53,52,54,51,50,22, + 21,35,38,35,34,7,22,0,5,20,254,152,244,243,254,170,1,183,137,129,230,168,211,199,2,252,250,195,125,145,195,194,1,145,125,2,2,3,0,2, + 53,254,231,254,198,1,58,1,35,230,195,131,137,159,228,215,231,204,1,28,1,76,246,129,159,159,142,142,125,184,254,197,0,1,0,60,0,1,4,66, + 6,160,0,17,0,0,37,17,35,38,2,61,1,35,53,33,21,6,22,59,1,17,51,17,3,143,238,214,209,190,1,118,13,90,159,241,179,1,2,116, + 1,1,5,180,20,159,109,102,249,3,138,249,97,0,0,0,0,1,0,110,0,1,4,82,6,160,0,21,0,0,1,16,4,7,17,35,17,38,36,25, + 1,51,17,30,1,59,1,62,1,53,17,51,4,82,254,194,76,187,91,254,188,180,1,163,97,131,94,149,181,4,135,254,217,225,1,253,131,2,125,1, + 229,1,35,2,25,253,229,199,169,1,164,203,2,27,0,0,0,3,0,80,255,225,5,152,6,179,0,10,0,21,0,51,0,0,1,35,34,6,7,20, + 22,51,50,54,53,1,52,38,35,34,6,23,21,51,50,54,55,14,1,43,1,17,33,21,33,21,14,1,7,46,1,53,52,54,59,1,17,33,53,33, + 53,62,1,51,50,22,2,156,194,69,133,2,127,72,80,119,2,61,120,88,99,97,1,179,104,120,191,1,222,192,179,1,90,254,166,2,214,148,176,218, + 213,181,194,254,130,1,126,2,184,161,190,226,2,57,93,126,125,95,104,96,4,13,100,89,135,90,181,121,100,159,211,254,231,151,239,156,203,2,2,199, + 178,147,225,1,25,149,181,190,194,188,0,0,0,1,0,100,255,226,3,172,4,189,0,17,0,0,1,16,33,32,17,55,51,7,16,51,50,17,38,0, + 53,51,22,0,3,172,254,91,254,93,38,176,34,242,239,1,254,122,187,1,1,126,1,170,254,56,1,210,207,207,254,186,1,60,212,1,107,212,164,254, + 150,0,0,0,0,2,0,100,255,227,3,192,6,179,0,18,0,26,0,0,1,16,33,32,17,16,37,55,54,39,38,53,51,20,23,22,15,1,4,3, + 16,39,6,17,16,33,50,3,192,254,89,254,75,1,139,19,47,147,147,183,129,130,48,19,1,62,180,246,254,1,1,243,2,33,253,194,2,60,2,8, + 65,67,167,105,106,142,65,136,133,180,73,123,254,50,1,183,21,20,254,72,254,80,0,0,0,2,0,90,254,30,4,76,4,105,0,24,0,36,0,0, + 37,20,0,35,34,0,53,16,37,54,55,52,35,34,31,1,7,39,16,33,32,3,20,7,4,3,52,38,39,6,2,21,20,22,51,50,54,4,76,254, + 255,243,232,254,234,1,210,171,1,179,156,2,6,160,15,1,69,1,83,2,169,1,125,180,145,167,169,170,183,145,132,191,42,215,254,203,1,54,214,1, + 166,141,119,130,147,134,49,40,87,1,8,254,228,127,130,169,254,135,149,246,29,28,254,255,137,174,212,213,0,2,0,100,254,40,6,19,4,97,0,31, + 0,39,0,0,1,2,33,32,17,52,55,38,35,34,17,16,5,4,23,35,38,37,6,7,39,54,55,36,17,16,33,50,23,54,33,32,3,16,35,32, + 17,16,33,50,6,19,1,254,94,254,78,28,87,117,246,1,101,2,43,5,199,11,254,104,150,116,122,107,156,254,158,1,133,179,111,102,0,255,1,163, + 180,239,254,245,1,11,239,2,80,253,227,2,40,142,66,164,254,173,254,11,193,202,212,158,99,3,162,108,113,47,253,1,227,1,236,172,177,253,249,1, + 122,254,135,254,98,0,0,0,0,1,0,100,254,29,3,152,4,96,0,23,0,0,5,16,33,32,17,55,51,7,16,51,50,25,1,16,35,34,21,23, + 35,39,16,33,32,17,3,152,254,116,254,88,33,172,25,244,226,225,200,55,172,49,1,110,1,139,63,254,92,1,166,225,227,254,232,1,22,3,19,1, + 2,244,226,220,1,134,254,111,0,1,0,100,254,29,3,172,4,96,0,34,0,0,5,16,33,32,17,55,51,7,16,33,22,17,53,52,39,35,53,51, + 54,53,52,35,34,21,23,35,39,16,33,32,17,20,7,22,21,3,172,254,111,254,73,37,174,32,1,4,221,170,166,129,200,235,200,22,176,23,1,121, + 1,159,211,218,61,254,90,1,160,229,229,254,236,2,1,26,134,216,26,152,92,217,207,191,165,155,1,84,254,162,210,133,104,254,0,0,0,3,0,41, + 255,227,3,157,6,180,0,15,0,23,0,31,0,0,1,16,33,32,17,16,55,38,19,16,37,4,17,6,7,4,3,16,7,38,17,16,51,50,3,54, + 35,34,23,2,23,54,3,157,254,92,254,90,193,236,1,1,91,1,70,1,120,1,76,180,242,241,243,238,188,1,171,177,1,1,175,174,2,13,253,214, + 2,42,1,113,97,113,1,14,1,69,17,17,254,172,177,116,68,254,39,1,165,1,1,254,92,254,97,4,201,250,220,254,229,1,1,0,0,2,0,100, + 255,227,6,4,4,96,0,22,0,30,0,0,19,16,33,50,23,54,51,32,17,2,3,35,0,17,18,35,34,7,22,21,2,33,32,1,16,35,34,17, + 16,51,50,100,1,164,245,104,126,146,1,143,2,229,224,1,19,2,232,101,111,23,28,254,115,254,96,2,148,242,238,236,244,2,11,2,85,188,183,253, + 236,254,192,254,230,1,21,1,64,1,142,186,74,189,253,212,2,40,1,202,254,54,254,100,0,1,0,100,0,0,3,192,4,96,0,15,0,0,1,16, + 3,35,18,17,16,32,17,16,19,35,2,17,16,32,3,192,143,183,146,254,12,145,184,141,3,92,2,68,254,244,254,201,1,32,1,35,1,144,254,109, + 254,224,254,223,1,56,1,15,2,25,0,0,0,1,0,90,254,29,3,165,4,86,0,28,0,0,5,18,33,32,17,55,51,7,16,33,22,17,53,52, + 43,1,53,51,36,53,52,39,51,22,21,20,7,4,17,3,165,2,254,109,254,70,50,170,40,1,9,218,232,180,103,1,41,182,233,121,239,1,3,62, + 254,91,1,152,239,230,254,235,2,1,27,157,254,148,70,192,179,172,168,183,207,97,91,254,243,0,0,0,0,1,0,100,254,40,8,32,4,106,0,48, + 0,0,1,6,3,35,18,53,16,35,34,3,7,35,39,16,35,34,17,7,35,39,16,35,34,17,16,5,4,19,35,38,37,4,7,39,54,55,36,17, + 16,33,50,23,54,51,50,23,54,51,32,8,32,1,199,215,236,219,216,2,11,151,12,202,197,10,150,10,222,219,3,8,1,178,67,175,49,254,67,254, + 176,132,109,130,230,253,197,1,143,213,92,96,188,205,88,94,206,1,143,2,170,236,254,244,1,4,244,1,43,254,249,225,225,1,12,254,244,225,225,1, + 7,254,163,254,62,224,102,254,184,231,84,30,152,128,111,39,229,1,213,1,227,203,213,217,207,0,0,0,0,2,0,100,255,226,3,172,6,179,0,20, + 0,29,0,0,1,16,33,32,17,16,33,22,23,17,52,35,34,29,1,35,53,16,33,32,17,3,38,39,32,17,16,33,50,17,3,172,254,111,254,73, + 1,186,127,101,208,217,183,1,144,1,122,170,68,150,254,240,1,7,227,1,188,254,38,2,63,2,33,11,49,1,78,211,200,47,47,1,84,254,160,254, + 45,44,10,254,106,254,78,1,89,0,0,0,0,2,0,130,255,225,3,202,6,169,0,16,0,25,0,0,1,16,33,32,25,1,16,41,1,21,33,34, + 21,17,54,55,32,3,16,35,6,7,17,16,51,50,3,202,254,82,254,102,1,78,1,162,254,48,118,139,146,1,129,180,251,123,116,237,253,2,25,253, + 200,1,241,3,123,1,92,146,142,254,110,64,11,253,215,1,157,10,59,254,107,254,145,0,0,1,0,100,255,255,5,229,4,96,0,28,0,0,1,18, + 1,35,0,17,2,35,34,17,21,35,53,16,35,34,17,2,1,35,0,17,16,33,50,23,54,51,32,5,229,1,254,237,209,1,47,1,210,231,165,231, + 211,1,1,56,209,254,230,1,136,225,87,97,220,1,133,2,86,254,210,254,216,1,22,1,64,1,126,254,167,210,210,1,89,254,130,254,206,254,219,1, + 36,1,51,2,10,227,227,0,0,1,0,100,255,226,3,172,6,169,0,28,0,0,1,16,33,32,17,55,51,7,16,51,50,17,16,43,1,53,51,50, + 55,52,36,53,51,20,4,21,20,7,22,3,172,254,91,254,93,18,178,16,239,241,199,174,129,194,28,254,175,193,1,45,180,225,2,1,253,225,1,217, + 200,198,254,177,1,147,1,109,150,171,159,153,194,100,200,168,175,72,148,0,0,1,0,100,254,29,3,171,4,105,0,24,0,0,5,18,33,32,3,55, + 51,7,16,51,50,25,1,5,22,21,16,5,53,32,39,54,37,53,37,3,171,1,254,99,254,87,2,20,180,20,242,247,254,100,227,254,57,1,41,1, + 1,254,215,3,42,64,254,93,1,162,148,148,254,234,1,25,3,247,79,135,114,254,220,2,164,150,117,71,118,178,0,0,0,1,0,100,0,0,5,250, + 6,169,0,35,0,0,1,16,1,35,0,17,2,35,34,17,21,35,53,18,35,34,17,16,1,35,0,17,16,19,18,37,21,4,1,21,55,50,23,54, + 51,32,5,250,254,226,229,1,79,2,228,222,167,1,220,232,1,80,238,254,234,254,254,1,168,254,118,254,196,182,217,91,96,220,1,146,2,75,254,219, + 254,219,1,8,1,66,1,137,254,158,195,195,1,98,254,119,254,190,254,247,1,43,1,32,1,141,1,73,1,72,64,167,23,254,81,41,77,253,253,0, + 0,1,0,130,255,226,3,202,6,158,0,19,0,0,1,16,33,32,25,1,51,17,16,33,50,17,54,2,53,55,51,7,20,18,3,202,254,102,254,82, + 170,1,4,230,1,200,6,182,27,218,1,227,253,255,2,16,4,172,251,84,254,124,1,117,169,1,16,127,170,164,93,254,204,0,0,0,0,2,0,90, + 254,29,4,226,5,112,0,12,0,25,0,0,19,16,37,3,51,3,4,17,16,0,33,32,0,19,2,18,51,50,18,17,16,37,19,35,19,4,90,2, + 5,23,178,23,1,255,254,197,254,251,254,248,254,192,180,1,220,184,173,230,254,175,23,177,22,254,175,1,58,2,200,95,1,15,254,237,92,253,50,254, + 193,254,41,1,210,1,75,254,210,254,157,1,91,1,54,2,48,146,253,129,2,126,144,0,0,1,0,10,254,29,3,182,4,146,0,32,0,0,5,16, + 33,32,17,55,51,7,16,33,50,25,1,38,35,34,21,3,35,3,52,43,1,39,55,23,51,50,23,54,51,32,17,3,182,254,110,254,71,25,178,23, + 1,5,232,2,135,123,10,143,10,156,82,109,20,87,80,143,79,67,160,1,48,64,254,93,1,163,227,227,254,233,1,23,3,103,182,140,254,165,1,91, + 120,40,161,50,187,187,254,199,0,2,0,100,254,29,6,33,4,96,0,50,0,58,0,0,19,16,33,32,23,54,51,32,3,20,7,22,29,1,6,4, + 33,32,36,61,1,52,54,22,29,1,20,22,51,50,54,61,1,52,43,1,53,51,50,54,39,16,35,34,7,30,1,21,16,33,32,1,16,35,34,17, + 16,51,50,100,1,161,1,3,93,120,188,1,137,1,251,223,1,254,216,254,234,254,226,254,232,99,100,153,214,235,160,183,80,27,83,185,3,212,159,97, + 10,10,254,93,254,89,2,150,245,237,237,245,2,101,1,251,198,193,254,82,250,163,106,152,92,180,225,188,119,29,31,67,68,30,29,52,115,154,111,88, + 167,151,181,155,1,55,174,60,92,34,254,23,1,229,1,113,254,145,254,166,0,1,0,100,254,29,3,152,6,159,0,25,0,0,5,16,33,32,17,55, + 51,7,16,51,50,25,1,38,39,34,21,23,35,39,16,33,22,23,17,51,3,152,254,119,254,85,33,182,35,247,223,103,173,164,50,177,42,1,62,167, + 124,170,63,254,92,1,164,225,225,254,232,1,24,3,190,75,11,201,246,206,1,124,10,80,2,153,0,0,0,1,0,100,254,41,5,230,4,95,0,37, + 0,0,5,54,55,0,17,16,33,50,23,54,51,32,17,20,7,35,18,53,2,35,34,17,7,35,39,16,35,34,17,16,5,4,21,35,52,39,38,7, + 1,16,80,179,254,81,1,140,216,96,91,202,1,153,168,201,192,2,224,219,3,158,5,224,218,2,2,1,110,179,230,191,194,179,60,53,1,41,1,149, + 1,227,231,231,254,53,217,250,1,3,208,1,65,254,233,196,196,1,23,254,167,254,41,225,170,241,167,113,43,173,0,0,0,1,0,100,254,29,3,172, + 4,78,0,27,0,0,5,16,33,32,17,55,51,7,16,51,50,25,1,6,7,32,17,52,55,51,6,21,16,51,54,55,17,51,3,172,254,103,254,81, + 18,184,22,253,237,124,128,254,122,175,207,203,211,145,107,170,66,254,95,1,160,150,147,254,233,1,25,1,118,63,10,1,173,220,214,224,210,254,222,11, + 62,2,138,0,0,2,0,60,255,226,3,162,6,179,0,30,0,40,0,0,1,16,33,32,17,16,33,22,23,17,52,35,34,29,1,20,6,38,61,1, + 54,35,7,53,51,50,23,54,51,32,17,3,17,46,1,39,34,17,16,51,50,3,162,254,131,254,53,1,162,135,122,164,128,71,78,1,126,139,134,90, + 88,82,164,1,56,170,54,122,72,242,254,236,1,169,254,57,2,33,2,63,10,44,1,153,140,150,86,53,39,39,53,88,128,52,202,184,184,254,238,251, + 228,2,6,17,21,5,254,77,254,107,0,0,0,1,0,130,0,0,3,202,6,179,0,27,0,0,1,55,52,35,34,21,17,54,51,32,17,16,3,35, + 18,17,16,35,34,7,17,35,17,16,33,32,21,7,2,90,22,160,164,148,116,1,150,173,211,203,239,132,118,170,1,78,1,65,17,5,37,152,116,207, + 254,153,71,254,52,254,219,254,176,1,83,1,30,1,68,57,252,131,5,83,1,96,245,153,0,1,0,90,254,29,4,56,4,65,0,32,0,0,1,20, + 7,22,17,2,33,32,17,53,16,19,51,2,17,21,16,33,32,17,2,43,1,53,51,50,39,54,38,39,51,30,1,4,26,199,229,1,254,20,254,15, + 116,187,123,1,62,1,64,2,215,173,166,199,2,2,215,10,186,10,196,2,171,167,96,87,254,204,254,4,3,30,163,1,40,1,59,254,204,254,198,152, + 253,110,1,108,1,61,135,206,87,141,182,132,149,0,0,0,0,2,0,100,255,227,3,171,6,159,0,10,0,19,0,0,1,18,33,32,17,16,33,54, + 23,17,51,3,17,38,35,34,17,16,51,50,3,171,1,254,91,254,93,1,163,92,159,169,169,132,120,238,239,251,1,247,253,236,2,52,2,43,1,71, + 2,163,251,46,1,167,66,254,97,254,88,0,0,2,0,131,255,226,3,232,6,179,0,30,0,39,0,0,19,2,33,50,23,54,59,1,21,39,34,23, + 21,20,6,38,61,1,52,35,34,21,17,54,51,32,17,16,33,32,17,23,16,51,32,17,16,35,38,7,131,1,1,57,164,82,88,90,133,138,126,1, + 78,71,128,159,127,125,1,162,254,43,254,141,170,226,1,8,242,127,121,5,161,1,18,184,184,202,52,128,88,53,39,40,52,86,150,150,254,96,71,253, + 213,253,203,1,249,36,254,183,1,169,1,159,1,62,0,0,0,1,0,100,254,29,3,197,6,158,0,37,0,0,1,51,17,33,21,33,21,22,0,21, + 16,33,32,3,55,51,7,16,51,50,19,52,0,3,53,35,34,21,20,59,1,21,35,4,17,16,33,51,2,10,168,1,19,254,237,2,1,12,254,94, + 254,91,1,32,175,27,242,238,1,255,0,3,86,190,154,47,47,254,212,1,85,81,6,158,253,164,130,75,250,254,17,206,254,95,1,161,229,239,254,245, + 1,24,166,2,12,1,2,75,183,166,134,1,1,43,1,59,0,2,0,130,255,226,3,202,6,158,0,10,0,19,0,0,1,16,33,32,25,1,51,17, + 54,51,32,3,16,35,34,7,17,16,51,50,3,202,254,98,254,86,170,137,127,1,150,180,239,96,155,254,236,2,40,253,186,2,47,4,141,253,131,63, + 253,200,1,172,59,254,76,254,137,0,0,0,0,1,0,20,254,30,3,142,4,147,0,35,0,0,1,7,37,3,4,23,6,4,35,53,50,54,53,38, + 47,1,19,37,55,5,55,54,53,52,38,43,1,53,51,50,23,22,21,20,15,1,3,142,81,254,232,143,1,9,1,1,254,179,238,160,230,1,192,115, + 214,254,136,81,1,102,86,19,63,76,69,68,145,79,82,35,92,1,213,128,176,254,210,120,181,188,208,150,115,112,152,50,69,1,160,186,140,194,154,34, + 37,45,52,135,46,45,140,85,65,156,0,0,0,1,0,100,255,226,3,172,6,179,0,39,0,0,1,16,33,32,17,55,51,7,16,51,50,17,52,39, + 35,53,51,50,53,54,43,1,53,51,50,55,52,36,53,51,20,4,21,20,7,22,21,20,7,22,3,172,254,97,254,87,40,180,40,239,241,113,163,163, + 101,2,103,163,162,90,2,254,130,167,1,129,163,183,177,189,1,129,254,97,1,179,148,148,254,217,1,11,220,2,130,156,128,133,146,109,149,165,86,138, + 183,160,61,69,136,145,72,113,0,1,0,120,255,226,3,192,6,179,0,39,0,0,1,16,33,32,25,1,51,17,16,51,50,17,52,43,1,53,51,50, + 53,54,43,1,53,51,50,55,52,38,53,51,20,22,23,20,7,22,21,20,7,22,3,192,254,91,254,93,170,243,247,119,183,183,111,2,113,183,182,100, + 2,252,186,239,4,173,183,177,188,1,129,254,97,1,239,4,184,251,72,254,157,1,11,227,120,151,143,123,191,109,81,193,136,89,162,179,62,69,146,135, + 72,113,0,0,0,2,0,100,254,224,3,170,4,96,0,17,0,25,0,0,23,50,55,36,17,16,33,32,17,18,5,22,51,21,38,39,6,7,19,16, + 23,54,17,16,35,34,141,151,70,254,250,1,166,1,160,2,254,237,82,145,225,145,158,223,139,242,236,238,240,84,115,178,1,95,2,48,253,208,254,162, + 179,115,204,73,209,207,75,3,83,254,157,122,121,1,100,1,161,0,0,0,0,1,0,100,254,29,3,172,4,95,0,29,0,0,5,16,33,32,17,55, + 51,7,18,51,50,17,53,16,7,35,53,51,36,61,1,5,21,35,17,37,16,5,4,17,3,172,254,89,254,95,31,187,39,1,242,239,221,181,111,1, + 35,254,66,174,3,31,254,218,1,38,61,254,90,1,164,226,221,254,227,1,31,164,1,30,2,131,90,244,121,19,244,1,117,31,253,211,63,128,254,244, + 0,1,0,100,254,29,3,171,6,179,0,37,0,0,5,16,33,32,17,55,51,7,16,51,50,17,53,52,43,1,53,51,36,17,6,35,36,17,16,33, + 21,32,21,20,55,50,55,17,18,5,4,21,3,171,254,95,254,90,32,180,32,242,236,242,157,67,1,77,92,142,254,87,1,169,255,0,253,196,221,1, + 254,228,1,27,65,254,94,1,168,222,226,254,221,1,33,209,253,138,17,1,181,41,2,1,135,1,118,132,242,252,1,176,254,229,254,128,84,119,252,0, + 0,3,0,100,255,226,4,31,6,179,0,23,0,31,0,39,0,0,1,21,16,33,32,17,16,37,33,17,33,32,17,16,33,32,17,21,51,21,35,17, + 51,21,5,33,34,21,20,51,50,53,1,20,51,33,53,52,35,34,3,173,254,89,254,94,1,159,1,10,254,246,254,97,1,166,1,163,114,114,114,254, + 233,254,251,235,246,250,254,16,235,1,5,250,246,2,54,238,254,154,1,102,1,119,1,1,19,1,119,1,105,254,151,239,136,254,237,138,1,230,226,237, + 3,238,237,239,221,0,0,0,0,2,0,100,254,29,6,57,4,96,0,27,0,36,0,0,1,18,33,34,39,21,16,33,53,50,53,17,16,35,34,17, + 16,33,21,36,17,16,33,50,23,54,51,32,3,16,35,34,17,21,16,55,50,6,57,2,254,89,136,96,254,94,248,248,242,1,4,254,72,1,166,231, + 93,89,237,1,167,181,247,227,232,242,2,39,253,187,136,199,254,122,140,248,2,147,1,161,254,83,254,101,138,3,2,34,2,56,236,236,253,199,1,174, + 254,197,231,254,185,1,0,0,0,1,0,90,254,29,4,16,4,96,0,31,0,0,5,16,33,32,17,16,37,36,53,52,35,34,7,23,35,39,16,33, + 32,19,20,5,4,21,16,33,32,17,52,39,51,22,4,16,254,20,254,54,1,55,1,54,159,191,2,5,156,10,1,98,1,79,2,254,203,254,202,1, + 26,1,52,96,190,86,25,254,54,1,202,1,57,188,189,141,175,170,60,47,1,66,254,207,222,185,184,240,254,185,1,76,129,152,158,0,0,1,0,100, + 254,29,3,172,4,78,0,27,0,0,19,51,17,22,23,50,17,52,39,51,22,21,16,33,34,39,17,16,51,50,17,39,51,23,16,33,32,17,100,170, + 108,144,211,223,217,185,254,122,130,122,251,239,29,180,29,254,95,254,89,4,77,253,108,62,1,1,34,181,253,215,219,254,83,43,254,174,254,225,1,27, + 141,144,254,92,1,167,0,0,0,2,0,80,254,29,4,66,4,104,0,24,0,36,0,0,19,52,18,51,32,18,21,16,5,6,7,20,51,50,47,1, + 55,23,16,33,32,19,52,55,36,19,20,18,51,50,18,53,52,38,35,34,6,80,245,253,1,8,248,254,4,131,1,179,156,2,6,160,15,254,187,254, + 173,2,149,254,153,180,147,168,194,142,152,178,141,180,2,72,227,1,61,254,190,222,254,70,101,119,130,147,134,49,40,87,254,248,1,28,126,131,170,1, + 100,128,254,246,1,9,127,186,220,221,0,0,0,1,0,100,255,99,3,172,4,97,0,27,0,0,5,53,52,39,38,35,34,7,39,54,55,36,17,16, + 37,32,17,7,35,55,16,35,34,17,16,5,22,23,2,233,59,59,95,131,67,131,67,136,254,206,1,175,1,153,11,195,26,226,254,1,66,141,124,157, + 1,3,77,75,144,79,109,48,193,1,132,1,191,2,254,84,203,199,1,36,254,188,254,169,151,44,157,0,0,3,0,110,255,236,3,39,3,224,0,3, + 0,7,0,11,0,0,19,51,21,35,5,51,21,35,5,51,21,35,110,205,205,1,242,199,199,254,14,202,202,3,224,189,202,186,248,187,0,2,0,100, + 3,92,2,40,6,179,0,15,0,23,0,0,1,50,3,16,7,34,25,1,52,59,1,21,33,34,29,1,23,52,35,34,7,20,51,50,1,74,223,1, + 228,224,198,251,254,236,65,234,123,110,1,116,118,5,178,254,220,254,207,1,1,50,1,99,194,96,76,169,208,183,189,195,0,2,0,16,0,3,5,104, + 5,216,0,2,0,6,0,61,64,12,66,0,149,6,129,1,149,5,8,3,6,7,16,212,196,196,49,0,47,236,244,236,48,75,83,88,64,18,1,17, + 4,6,5,2,17,3,4,3,1,17,5,0,17,6,5,6,5,7,16,236,16,236,7,16,236,8,16,236,89,9,2,37,1,35,1,1,35,1,153,1, + 156,1,16,253,199,229,253,198,5,46,251,156,4,100,170,250,43,5,213,0,255,255,0,16,0,0,5,104,8,75,16,39,2,156,0,192,1,69,18,6, + 6,180,0,0,255,255,0,16,0,0,5,104,5,213,18,6,3,41,0,0,255,255,0,16,0,0,5,104,7,79,16,39,22,193,4,192,1,116,18,6, + 6,180,0,0,0,2,0,201,0,0,5,176,5,213,0,2,0,6,0,64,183,2,28,5,0,28,3,4,7,16,252,236,212,236,49,0,181,66,0,1, + 4,175,3,47,236,57,57,48,75,83,88,64,18,2,17,5,4,6,1,17,3,6,3,2,17,5,0,17,4,5,4,4,7,16,237,16,237,7,16,237, + 16,8,237,89,1,17,9,1,17,1,21,1,115,3,163,251,179,4,231,4,194,252,78,1,218,253,22,5,213,253,135,228,255,255,0,201,0,0,5,176, + 7,79,16,39,22,193,4,41,1,116,18,6,6,182,0,0,255,255,0,201,0,0,5,176,7,78,16,39,22,185,4,41,1,117,18,6,6,182,0,0, + 255,255,0,201,0,0,5,176,5,213,16,39,6,214,1,101,0,0,18,6,6,182,0,0,0,2,0,119,0,0,5,94,5,213,0,2,0,6,0,63, + 182,2,28,3,1,28,4,7,16,220,236,212,236,49,0,181,66,0,2,6,175,3,47,236,57,57,48,75,83,88,64,18,1,17,5,6,4,2,17,3, + 4,3,1,17,5,0,17,6,5,6,4,7,16,237,16,237,7,16,237,16,8,237,89,9,2,19,1,53,1,4,180,252,93,3,163,170,251,25,4,231, + 4,194,254,40,254,38,254,240,2,120,228,2,121,0,0,0,255,255,0,119,0,0,5,94,7,79,16,39,22,193,5,49,1,116,18,6,6,186,0,0, + 255,255,0,201,0,3,6,157,5,216,16,39,6,178,1,53,0,0,16,6,6,214,0,0,255,255,0,16,0,3,6,54,5,216,16,39,6,214,4,161, + 0,0,16,6,6,178,0,0,255,255,0,201,0,0,6,157,5,213,16,38,6,214,0,0,16,7,6,180,1,53,0,0,255,255,0,16,0,0,6,54, + 5,213,16,39,6,214,4,161,0,0,16,6,6,180,0,0,255,255,0,201,0,0,6,157,7,79,16,39,6,181,1,53,0,0,16,6,6,214,0,0, + 255,255,0,16,0,0,6,54,7,79,16,38,6,181,0,0,16,7,6,214,4,161,0,0,255,255,0,201,0,0,7,69,5,213,16,39,6,182,1,149, + 0,0,16,6,6,214,0,0,255,255,0,201,0,0,7,69,5,213,16,39,6,214,5,176,0,0,16,6,6,182,0,0,255,255,0,201,0,0,7,69, + 7,79,16,39,6,183,1,149,0,0,16,6,6,214,0,0,255,255,0,201,0,0,7,69,7,79,16,38,6,183,0,0,16,7,6,214,5,176,0,0, + 255,255,0,201,0,0,5,176,7,79,16,39,22,193,6,201,0,48,18,6,6,183,0,0,255,255,0,201,0,0,6,243,5,213,16,39,6,186,1,149, + 0,0,16,6,6,214,0,0,255,255,0,119,0,0,7,69,5,213,16,38,6,186,0,0,16,7,6,214,5,176,0,0,255,255,0,201,0,0,6,243, + 7,79,16,39,6,187,1,149,0,0,16,6,6,214,0,0,255,255,0,119,0,0,7,69,7,79,16,38,6,187,0,0,16,7,6,214,5,176,0,0, + 255,255,0,119,0,0,5,94,7,79,16,39,22,193,3,63,0,48,18,6,6,187,0,0,0,1,0,201,5,9,1,149,5,213,0,3,0,0,19,51, + 21,35,201,204,204,5,213,204,0,2,0,137,2,156,3,231,5,223,0,2,0,6,0,0,1,3,33,5,1,51,1,2,56,246,1,238,253,89,1,103, + 144,1,103,5,96,253,170,110,3,67,252,189,0,1,0,94,2,218,2,229,5,183,0,3,0,0,19,1,23,1,94,2,25,110,253,231,3,55,2,128, + 93,253,128,0,0,1,0,94,2,218,2,229,5,183,0,3,0,0,1,7,1,55,2,229,110,253,231,110,3,55,93,2,128,93,0,0,0,1,0,137, + 3,48,2,173,5,100,0,17,0,0,1,20,6,34,38,53,17,51,17,20,22,51,50,54,53,52,53,51,2,173,159,230,159,122,87,65,64,88,122,4, + 67,115,160,160,115,1,33,254,223,65,87,88,64,43,246,0,0,1,0,137,3,33,2,173,5,85,0,17,0,0,1,17,35,52,53,52,38,35,34,6, + 21,17,35,17,52,54,50,22,2,173,122,88,64,65,87,122,159,230,159,4,66,254,223,246,43,64,88,87,65,254,223,1,33,115,160,160,0,1,0,137, + 3,48,2,181,5,85,0,16,0,0,1,33,53,33,50,54,53,52,38,35,33,53,33,50,22,20,6,1,163,254,230,1,26,64,88,88,64,254,230,1, + 26,115,159,159,3,48,123,88,64,63,88,123,159,230,160,0,0,2,0,137,3,48,2,173,5,85,0,11,0,19,0,0,1,52,38,35,34,6,21,20, + 22,51,50,62,1,20,6,34,38,52,54,50,2,51,88,64,65,87,87,65,64,88,122,159,230,159,159,230,4,67,63,88,87,64,65,87,88,179,230,160, + 160,230,159,0,0,2,0,72,2,157,3,62,5,222,0,3,0,7,0,0,9,1,23,1,37,1,23,1,1,153,1,30,135,254,227,254,39,1,29,135, + 254,227,2,206,3,16,49,252,240,49,3,16,49,252,240,0,0,2,0,137,2,156,2,165,5,223,0,3,0,7,0,31,183,9,3,93,0,7,93,4, + 8,16,220,236,220,236,196,49,0,182,3,4,247,1,5,145,8,16,244,60,236,50,48,1,17,51,17,33,17,51,17,2,21,144,253,228,144,2,156,3, + 67,252,189,3,67,252,189,0,0,1,0,201,2,126,1,149,3,75,0,3,0,0,19,51,21,35,201,204,204,3,75,205,0,1,0,137,4,6,2,173, + 4,129,0,3,0,0,1,33,53,33,2,173,253,220,2,36,4,6,123,0,0,1,0,137,3,49,2,173,5,86,0,11,0,0,1,21,35,53,35,53, + 51,53,51,21,51,21,1,216,122,213,213,122,213,4,6,213,213,123,213,213,123,0,0,0,0,1,0,137,3,49,2,173,5,135,0,7,0,0,1,17, + 35,17,35,53,33,21,1,216,122,213,2,36,5,12,254,37,1,219,123,123,255,255,0,16,0,3,8,58,5,216,16,39,6,207,5,85,0,0,16,6, + 6,178,0,0,255,255,0,16,0,0,6,199,5,213,16,39,6,207,3,226,0,0,16,6,6,180,0,0,255,255,0,201,0,0,7,34,5,213,16,39, + 6,207,4,61,0,0,16,6,6,182,0,0,255,255,0,119,0,0,8,113,5,213,16,39,6,207,5,140,0,0,16,6,6,186,0,0,255,255,0,16, + 0,0,5,104,5,213,18,6,0,57,0,0,255,255,0,16,0,0,5,104,8,75,16,39,2,156,0,192,1,69,18,6,6,224,0,0,255,255,0,16, + 0,0,5,104,5,213,18,6,3,48,0,0,255,255,0,16,0,0,5,104,7,79,16,39,22,193,4,192,1,116,18,6,6,224,0,0,0,1,0,119, + 0,0,5,94,5,213,0,6,0,58,181,1,28,4,3,0,7,16,220,60,212,236,49,0,179,66,3,175,6,47,236,48,75,83,88,64,18,1,17,3, + 4,5,0,17,6,6,5,1,17,4,2,17,3,3,4,4,7,16,237,16,237,7,16,237,16,8,237,89,55,9,1,53,1,21,1,119,4,77,251,179, + 4,231,251,25,182,2,52,2,48,187,253,135,228,253,136,0,255,255,0,119,0,0,5,94,7,79,16,39,22,193,4,41,1,116,18,6,6,226,0,0, + 255,255,0,119,0,0,5,94,7,78,16,39,22,185,4,41,1,117,18,6,6,226,0,0,255,255,0,119,0,0,5,94,5,213,16,39,6,214,0,182, + 0,0,18,6,6,226,0,0,0,1,0,119,0,0,5,94,5,213,0,6,0,58,181,5,0,6,28,3,7,16,220,236,204,50,49,0,179,66,4,175, + 1,47,236,48,75,83,88,64,18,6,17,4,3,2,0,17,1,1,2,6,17,3,5,17,4,4,3,4,7,16,237,16,237,7,16,237,16,8,237,89, + 37,21,1,53,1,21,1,5,94,251,25,4,231,251,179,182,182,2,120,228,2,121,187,253,208,0,0,0,255,255,0,119,0,0,5,94,7,79,16,39, + 22,193,5,49,1,116,18,6,6,230,0,0,255,255,0,201,0,0,6,157,5,213,16,39,6,222,1,53,0,0,16,6,6,214,0,0,255,255,0,16, + 0,0,6,54,5,213,18,38,0,57,0,0,16,7,6,214,4,161,0,0,255,255,0,201,0,0,6,157,5,213,16,39,6,224,1,53,0,0,16,6, + 6,214,0,0,255,255,0,16,0,0,6,54,5,213,16,38,6,224,0,0,16,7,6,214,4,161,0,0,255,255,0,201,0,0,6,157,7,79,16,39, + 6,225,1,53,0,0,16,6,6,214,0,0,255,255,0,16,0,0,6,54,7,79,16,38,6,225,0,0,16,7,6,214,4,161,0,0,255,255,0,201, + 0,0,6,243,5,213,16,39,6,226,1,149,0,0,16,6,6,214,0,0,255,255,0,119,0,0,7,69,5,213,16,38,6,226,0,0,16,7,6,214, + 5,176,0,0,255,255,0,201,0,0,6,243,7,79,16,39,6,227,1,149,0,0,16,6,6,214,0,0,255,255,0,119,0,0,7,69,7,79,16,38, + 6,227,0,0,16,7,6,214,5,176,0,0,255,255,0,201,0,0,6,243,5,213,16,39,6,230,1,149,0,0,16,6,6,214,0,0,255,255,0,119, + 0,0,7,69,5,213,16,38,6,230,0,0,16,7,6,214,5,176,0,0,255,255,0,201,0,0,6,243,7,79,16,39,6,231,1,149,0,0,16,6, + 6,214,0,0,255,255,0,119,0,0,7,69,7,79,16,38,6,231,0,0,16,7,6,214,5,176,0,0,255,255,0,119,0,0,5,94,7,78,16,39, + 22,185,5,49,1,117,18,6,6,230,0,0,0,1,0,137,2,155,3,160,5,223,0,6,0,60,180,1,5,0,3,7,16,220,204,50,57,49,0,181, + 66,1,247,4,145,7,16,244,228,48,75,83,88,64,18,6,125,4,3,2,0,125,1,1,2,6,125,3,5,125,4,4,3,4,7,16,237,16,237,7, + 16,237,16,8,237,89,1,21,1,53,1,21,1,3,160,252,233,3,23,253,96,3,14,115,1,98,128,1,98,115,254,209,0,1,0,137,2,156,1,25, + 5,223,0,3,0,20,179,2,93,0,4,16,220,236,49,0,180,3,247,1,145,4,16,244,236,48,19,17,51,17,137,144,2,156,3,67,252,189,0,0, + 255,255,0,178,255,227,5,41,5,213,18,6,0,56,0,0,255,255,0,178,0,0,5,41,8,75,16,39,2,156,0,240,1,69,18,6,6,251,0,0, + 0,1,0,178,0,0,5,41,5,242,0,17,0,42,64,9,10,28,8,56,17,28,0,65,18,16,252,75,176,16,84,88,185,0,0,255,192,56,89,236, + 252,236,49,0,181,13,149,4,145,9,0,47,60,244,236,48,51,17,16,0,33,32,0,25,1,35,17,52,38,35,34,6,21,17,178,1,33,1,27,1, + 26,1,33,203,174,194,195,174,3,164,1,36,1,42,254,214,254,220,252,92,3,139,240,211,211,240,252,117,255,255,0,178,0,0,5,41,7,79,16,39, + 22,193,4,231,1,116,18,6,6,251,0,0,0,1,0,119,0,0,5,94,5,213,0,17,0,28,182,4,25,13,50,0,9,18,16,220,60,244,236,49, + 0,182,7,149,9,129,1,149,16,47,236,244,236,48,55,33,32,0,17,16,0,41,1,53,33,32,0,17,16,0,41,1,119,1,190,1,53,1,31,254, + 225,254,203,254,66,1,159,1,178,1,150,254,104,254,80,254,97,166,1,24,1,46,1,44,1,23,166,254,151,254,128,254,126,254,150,0,255,255,0,119, + 0,0,5,94,7,79,16,39,22,193,4,199,1,116,18,6,6,253,0,0,255,255,0,119,0,0,5,94,7,78,16,39,22,185,4,199,1,117,18,6, + 6,253,0,0,255,255,0,119,0,0,5,94,5,213,16,39,6,214,0,182,0,0,18,6,6,253,0,0,0,1,0,121,0,0,5,96,5,213,0,17, + 0,29,183,0,9,50,14,25,5,16,18,16,252,236,244,60,49,0,182,11,149,8,129,17,149,2,47,236,244,236,48,37,21,33,32,0,17,16,0,41, + 1,21,33,32,0,17,16,0,33,5,96,254,97,254,80,254,104,1,150,1,178,1,159,254,66,254,203,254,225,1,31,1,53,166,166,1,106,1,130,1, + 128,1,105,166,254,233,254,212,254,210,254,232,255,255,0,121,0,0,5,96,7,79,16,39,22,193,5,34,1,116,18,6,7,1,0,0,255,255,0,201, + 255,227,6,172,5,213,16,38,6,214,0,0,16,7,6,249,1,131,0,0,255,255,0,178,255,227,6,165,5,213,16,39,6,214,5,16,0,0,16,6, + 6,249,0,0,255,255,0,201,0,0,6,172,5,242,16,39,6,251,1,131,0,0,16,6,6,214,0,0,255,255,0,178,0,0,6,165,5,242,16,38, + 6,251,0,0,16,7,6,214,5,16,0,0,255,255,0,201,0,0,6,172,7,79,16,39,6,252,1,131,0,0,16,6,6,214,0,0,255,255,0,178, + 0,0,6,165,7,79,16,38,6,252,0,0,16,7,6,214,5,16,0,0,255,255,0,201,0,0,6,243,5,213,16,39,6,253,1,149,0,0,16,6, + 6,214,0,0,255,255,0,119,0,0,6,189,5,213,16,39,6,214,5,40,0,0,16,6,6,253,0,0,255,255,0,201,0,0,6,243,7,79,16,39, + 6,254,1,149,0,0,16,6,6,214,0,0,255,255,0,119,0,0,6,189,7,79,16,38,6,254,0,0,16,7,6,214,5,40,0,0,255,255,0,201, + 0,0,7,29,5,213,16,39,7,1,1,189,0,0,16,6,6,214,0,0,255,255,0,121,0,0,6,189,5,213,16,39,6,214,5,40,0,0,16,6, + 7,1,0,0,255,255,0,201,0,0,7,29,7,79,16,39,7,2,1,189,0,0,16,6,6,214,0,0,255,255,0,121,0,0,6,189,7,79,16,38, + 7,2,0,0,16,7,6,214,5,40,0,0,255,255,0,240,0,0,7,29,5,213,16,39,7,1,1,189,0,0,16,6,23,21,0,0,0,1,0,137, + 2,156,3,8,5,223,0,17,0,31,181,9,0,14,126,5,18,16,220,236,204,50,49,0,64,9,17,221,1,247,11,221,8,145,18,16,244,236,244,236, + 48,1,21,35,32,36,53,52,36,33,51,21,35,34,6,21,20,22,51,3,8,110,254,240,254,255,1,0,1,17,110,129,205,153,190,168,3,10,110,203, + 215,215,202,110,147,160,185,123,255,255,0,178,255,227,6,149,5,223,16,39,6,248,5,124,0,0,16,6,6,249,0,0,255,255,0,178,0,0,6,149, + 5,242,16,39,6,248,5,124,0,0,16,6,6,251,0,0,255,255,0,119,0,0,6,125,5,223,16,39,6,248,5,100,0,0,16,6,6,253,0,0, + 255,255,0,121,0,0,6,175,5,223,16,39,6,248,5,150,0,0,16,6,7,1,0,0,0,2,0,70,0,0,4,62,5,242,0,11,0,25,0,37, + 64,9,12,9,28,23,3,25,17,16,26,16,252,236,220,236,50,49,0,64,9,6,149,12,14,0,149,20,145,24,47,244,236,220,57,238,48,1,34,6, + 21,20,22,51,50,54,53,52,38,19,6,7,34,36,53,52,36,51,50,4,21,17,35,2,66,122,173,200,95,128,178,204,204,128,178,235,254,239,1,35, + 217,236,1,16,202,5,82,164,151,168,148,169,147,164,151,253,51,73,1,240,236,250,225,240,236,251,234,0,255,255,0,201,0,0,4,193,8,75,16,39, + 2,156,0,192,1,69,18,6,7,25,0,0,0,2,0,201,0,0,4,193,5,242,0,11,0,25,0,37,64,9,9,25,21,13,3,28,15,4,26,16, + 252,236,50,220,236,49,0,64,9,6,149,12,24,0,149,18,145,14,47,244,236,220,57,238,48,1,34,6,21,20,22,51,50,54,53,52,38,1,17,35, + 17,52,36,51,50,4,21,20,4,35,38,2,197,102,204,178,128,95,200,173,254,84,202,1,16,236,217,1,35,254,239,235,178,5,82,151,164,147,169,148, + 168,151,164,253,51,253,123,4,22,236,240,225,250,236,240,1,255,255,0,201,0,0,4,193,7,79,16,39,22,193,4,192,1,116,18,6,7,25,0,0, + 0,2,0,70,255,227,4,62,5,213,0,11,0,25,0,40,64,9,12,3,28,15,9,25,21,16,26,16,252,236,220,236,50,49,0,64,11,6,149,12, + 24,0,149,18,140,14,145,26,16,236,244,238,212,57,236,48,37,50,54,53,52,38,35,34,6,21,20,22,1,17,51,17,20,4,35,34,36,53,52,36, + 51,22,2,66,102,204,178,128,95,200,173,1,172,202,254,240,236,217,254,221,1,17,235,178,131,151,164,147,169,148,168,151,164,2,205,2,133,251,234,236, + 240,225,250,236,240,1,0,0,255,255,0,70,255,227,4,62,7,79,16,39,22,193,5,211,1,116,18,6,7,27,0,0,255,255,0,70,255,227,4,252, + 7,78,16,39,22,185,5,211,1,117,18,6,7,27,0,0,0,2,0,201,255,227,4,193,5,213,0,11,0,25,0,40,64,9,3,25,17,25,9,28, + 23,4,26,16,252,236,50,220,236,49,0,64,11,6,149,12,14,0,149,20,140,24,145,26,16,236,244,238,212,57,236,48,37,50,54,53,52,38,35,34, + 6,21,20,22,3,54,55,50,4,21,20,4,35,34,36,53,17,51,2,197,122,173,200,95,128,178,204,204,128,178,235,1,17,254,221,217,236,254,240,202, + 131,164,151,168,148,169,147,164,151,2,205,73,1,240,236,250,225,240,236,4,22,0,0,0,255,255,0,201,255,227,4,193,7,79,16,39,22,193,3,53, + 1,116,18,6,7,30,0,0,255,255,0,201,0,0,6,24,5,242,16,39,7,23,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,5,179, + 5,242,16,39,6,214,4,30,0,0,16,6,7,23,0,0,255,255,0,201,0,0,6,63,5,242,16,39,7,25,1,126,0,0,16,6,6,214,0,0, + 255,255,0,201,0,0,6,17,5,242,16,39,6,214,4,124,0,0,16,6,7,25,0,0,255,255,0,201,0,0,6,63,7,79,16,38,6,214,0,0, + 16,7,7,26,1,126,0,0,255,255,0,201,0,0,6,17,7,79,16,38,7,26,0,0,16,7,6,214,4,124,0,0,255,255,0,201,255,227,6,24, + 5,213,16,39,7,27,1,218,0,0,16,6,6,214,0,0,255,255,0,70,255,227,5,179,5,213,16,38,7,27,0,0,16,7,6,214,4,30,0,0, + 255,255,0,201,255,227,6,24,7,79,16,39,7,28,1,218,0,0,16,6,6,214,0,0,255,255,0,70,255,227,5,179,7,79,16,38,7,28,0,0, + 16,7,6,214,4,30,0,0,255,255,0,201,255,227,6,63,5,213,16,39,7,30,1,126,0,0,16,6,6,214,0,0,255,255,0,201,255,227,6,17, + 5,213,16,38,7,30,0,0,16,7,6,214,4,124,0,0,255,255,0,201,255,227,6,63,7,79,16,39,7,31,1,126,0,0,16,6,6,214,0,0, + 255,255,0,201,255,227,6,17,7,79,16,38,7,31,0,0,16,7,6,214,4,124,0,0,255,255,0,240,255,227,6,63,5,213,16,38,23,21,0,0, + 16,7,7,30,1,126,0,0,0,2,0,137,2,139,3,9,5,223,0,11,0,25,0,36,183,3,126,17,9,25,93,24,26,16,220,236,50,212,236,49, + 0,64,10,6,221,14,0,221,20,247,24,145,26,16,244,244,252,212,236,48,1,50,54,53,52,38,35,34,6,21,20,22,3,54,51,50,22,21,20,6, + 35,34,38,53,17,51,1,201,88,80,94,74,92,84,97,97,81,95,148,172,183,137,149,171,144,2,249,86,70,84,72,85,71,81,75,1,125,41,134,132, + 140,126,134,132,2,74,0,0,0,2,0,56,2,139,2,184,5,223,0,11,0,26,0,0,1,50,54,53,52,38,35,34,6,21,20,22,1,48,17,51, + 17,20,6,35,34,38,53,52,54,51,50,1,120,79,97,84,92,74,94,80,1,8,144,171,149,137,183,172,148,95,2,249,75,81,71,85,72,84,70,86, + 1,125,1,105,253,182,132,134,126,140,132,134,255,255,0,70,0,0,5,145,5,242,16,39,6,248,4,120,0,0,16,6,7,23,0,0,255,255,0,201, + 0,0,5,195,5,242,16,39,6,248,4,170,0,0,16,6,7,25,0,0,255,255,0,70,255,227,5,145,5,223,16,39,6,248,4,120,0,0,16,6, + 7,27,0,0,255,255,0,201,255,227,5,195,5,223,16,39,6,248,4,170,0,0,16,6,7,30,0,0,0,1,0,70,0,0,4,62,5,242,0,15, + 0,27,182,10,28,7,0,28,1,16,16,220,236,220,236,49,0,181,0,13,149,4,145,8,47,244,236,204,48,1,35,52,36,51,50,4,21,17,35,17, + 52,38,35,34,6,1,16,202,1,35,217,236,1,16,202,204,102,128,178,4,23,250,225,240,236,251,234,4,23,164,151,169,255,255,0,201,0,0,4,193, + 8,75,16,39,2,156,0,192,1,69,18,6,7,55,0,0,0,1,0,201,0,0,4,193,5,242,0,15,0,28,183,0,28,15,6,28,9,4,16,16, + 252,236,220,236,49,0,181,15,3,149,12,145,8,47,244,236,204,48,1,52,38,35,34,6,21,17,35,17,52,36,51,50,4,21,3,247,178,128,102,204, + 202,1,16,236,217,1,35,4,23,146,169,151,164,251,233,4,22,236,240,225,250,0,0,0,255,255,0,201,0,0,4,193,7,79,16,39,22,193,4,192, + 1,116,18,6,7,55,0,0,0,1,0,70,255,227,4,62,5,213,0,15,0,30,182,6,28,9,0,28,15,16,16,220,236,220,236,49,0,183,0,3, + 149,12,140,7,145,16,16,228,244,238,204,48,1,20,22,51,50,54,53,17,51,17,20,4,35,34,36,53,1,16,178,128,102,204,202,254,240,236,217,254, + 221,1,190,146,169,151,164,4,23,251,234,236,240,225,250,0,255,255,0,70,255,227,4,62,7,79,16,39,22,193,5,211,1,116,18,6,7,57,0,0, + 255,255,0,70,255,227,4,252,7,78,16,39,22,185,5,211,1,117,18,6,7,57,0,0,0,1,0,201,255,227,4,193,5,213,0,15,0,31,183,0, + 28,1,10,28,7,4,16,16,252,236,220,236,49,0,183,0,13,149,4,140,8,145,16,16,228,244,238,204,48,1,51,20,4,35,34,36,53,17,51,17, + 20,22,51,50,54,3,247,202,254,221,217,236,254,240,202,204,102,128,178,1,190,250,225,240,236,4,22,251,233,164,151,169,255,255,0,201,255,227,4,193, + 7,79,16,39,22,193,3,53,1,116,16,6,7,60,0,0,255,255,0,201,0,0,6,24,5,242,16,39,7,53,1,218,0,0,16,6,6,214,0,0, + 255,255,0,70,0,0,5,179,5,242,16,38,7,53,0,0,16,7,6,214,4,30,0,0,255,255,0,201,0,0,6,63,5,242,16,39,7,55,1,126, + 0,0,16,6,6,214,0,0,255,255,0,201,0,0,6,17,5,242,16,38,7,55,0,0,16,7,6,214,4,124,0,0,255,255,0,201,0,0,6,63, + 7,79,16,39,7,56,1,126,0,0,16,6,6,214,0,0,255,255,0,201,0,0,6,17,7,79,16,38,7,56,0,0,16,7,6,214,4,124,0,0, + 255,255,0,201,255,227,6,24,5,213,16,39,7,57,1,218,0,0,16,6,6,214,0,0,255,255,0,70,255,227,5,179,5,213,16,38,7,57,0,0, + 16,7,6,214,4,30,0,0,255,255,0,201,255,227,6,24,7,79,16,39,7,58,1,218,0,0,16,6,6,214,0,0,255,255,0,70,255,227,5,179, + 7,79,16,38,7,58,0,0,16,7,6,214,4,30,0,0,255,255,0,201,255,227,6,63,5,213,16,39,7,60,1,126,0,0,16,6,6,214,0,0, + 255,255,0,201,255,227,6,17,5,213,16,38,7,60,0,0,16,7,6,214,4,124,0,0,255,255,0,201,255,227,6,63,7,79,16,39,7,61,1,126, + 0,0,16,6,6,214,0,0,255,255,0,201,255,227,6,17,7,79,16,38,7,61,0,0,16,7,6,214,4,124,0,0,255,255,0,240,255,227,6,63, + 5,213,16,38,23,21,0,0,16,7,7,60,1,126,0,0,0,1,0,137,2,139,3,9,5,223,0,15,0,30,182,0,93,1,10,93,7,16,16,220, + 236,212,236,49,0,183,0,13,221,4,247,8,145,16,16,244,244,252,204,48,1,51,20,6,35,34,38,53,17,51,17,20,22,51,50,54,2,121,144,183, + 137,149,171,144,97,79,92,84,3,149,140,126,134,132,2,74,253,182,80,77,76,0,0,0,0,1,0,137,2,139,3,9,5,223,0,15,0,0,1,20, + 22,51,50,54,53,17,51,17,20,6,35,34,38,53,1,25,84,92,79,97,144,171,149,137,183,3,149,81,76,77,80,2,74,253,182,132,134,126,140,0, + 0,1,0,119,0,0,4,24,5,213,0,5,0,23,181,2,28,0,58,3,6,16,220,252,236,49,0,180,3,149,4,129,1,47,244,236,48,33,35,17, + 33,53,33,4,24,202,253,41,3,161,5,43,170,0,0,0,255,255,0,201,0,0,4,106,8,75,16,39,2,156,0,169,1,69,18,6,7,81,0,0, + 0,1,0,201,0,0,4,106,5,213,0,5,0,24,64,12,4,149,1,129,0,4,28,2,58,0,4,6,16,252,236,236,49,0,47,244,236,48,51,17, + 33,21,33,17,201,3,161,253,41,5,213,170,250,213,0,0,255,255,0,201,0,0,4,106,7,79,16,39,22,193,4,169,1,116,18,6,7,81,0,0, + 0,1,0,119,0,0,4,24,5,213,0,5,0,23,181,4,28,1,58,3,6,16,220,252,236,49,0,180,3,149,0,129,2,47,228,236,48,1,17,33, + 53,33,17,4,24,252,95,2,215,5,213,250,43,170,5,43,255,255,0,119,0,0,4,25,7,79,16,39,22,193,5,179,1,116,18,6,7,83,0,0, + 255,255,0,119,0,0,4,220,7,78,16,39,22,185,5,179,1,117,18,6,7,83,0,0,255,255,0,201,0,0,4,106,5,213,18,6,0,47,0,0, + 255,255,0,201,0,0,4,106,7,79,16,39,22,193,3,53,1,116,18,6,7,86,0,0,255,255,0,201,0,0,5,53,5,213,16,38,6,214,0,0, + 16,7,7,79,1,29,0,0,255,255,0,119,0,0,5,175,5,213,16,39,6,214,4,26,0,0,16,6,7,79,0,0,255,255,0,201,0,0,5,237, + 5,213,16,38,6,214,0,0,16,7,7,81,1,131,0,0,255,255,0,201,0,0,5,165,5,213,16,39,6,214,4,16,0,0,16,6,7,81,0,0, + 255,255,0,201,0,0,5,237,7,79,16,39,7,82,1,131,0,0,16,6,6,214,0,0,255,255,0,201,0,0,5,165,7,79,16,38,7,82,0,0, + 16,7,6,214,4,16,0,0,255,255,0,201,0,0,5,53,5,213,16,39,7,83,1,29,0,0,16,6,6,214,0,0,255,255,0,119,0,0,5,175, + 5,213,16,38,7,83,0,0,16,7,6,214,4,26,0,0,255,255,0,201,0,0,5,54,7,79,16,39,7,84,1,29,0,0,16,6,6,214,0,0, + 255,255,0,119,0,0,5,175,7,79,16,38,7,84,0,0,16,7,6,214,4,26,0,0,255,255,0,201,0,0,5,237,5,213,16,39,7,86,1,131, + 0,0,16,6,6,214,0,0,255,255,0,201,0,0,5,165,5,213,16,38,7,86,0,0,16,7,6,214,4,16,0,0,255,255,0,201,0,0,5,237, + 7,79,16,39,7,87,1,131,0,0,16,6,6,214,0,0,255,255,0,201,0,0,5,165,7,79,16,38,7,87,0,0,16,7,6,214,4,16,0,0, + 255,255,0,240,0,0,5,237,5,213,16,38,23,21,0,0,16,7,7,86,1,131,0,0,0,1,0,137,2,156,2,165,5,223,0,5,0,25,180,1, + 0,93,3,6,16,220,236,204,49,0,182,0,221,2,247,4,145,6,16,244,244,236,48,1,33,21,33,17,51,1,25,1,140,253,228,144,3,10,110,3, + 67,0,0,0,0,1,0,137,2,156,3,160,5,223,0,17,0,31,181,9,0,14,126,5,18,16,220,236,204,50,49,0,64,9,17,221,1,247,11,221, + 8,145,18,16,244,236,244,236,48,1,21,33,32,36,53,52,36,41,1,21,33,34,6,21,20,22,51,3,160,254,250,254,240,254,255,1,0,1,17,1, + 6,254,231,205,153,190,168,3,10,110,203,215,215,202,110,147,160,185,123,0,0,1,0,137,2,156,2,165,5,223,0,5,0,0,1,17,51,17,33,53, + 2,21,144,253,228,3,10,2,213,252,189,110,0,2,0,119,255,227,6,138,3,125,0,11,0,25,0,40,64,9,3,25,23,21,9,25,15,25,26,16, + 220,212,236,212,57,236,49,0,64,10,6,149,18,140,26,23,0,149,12,26,16,212,236,50,16,244,238,48,1,34,6,21,20,22,51,50,54,53,52,38, + 39,50,4,21,20,4,35,34,36,53,52,55,33,53,4,141,156,139,200,95,95,200,152,143,250,1,3,254,239,236,235,254,239,76,253,154,2,211,166,110, + 168,148,148,168,131,145,170,225,221,236,240,240,236,170,106,170,255,255,0,70,255,227,6,89,6,10,16,39,2,156,0,105,255,4,18,6,7,108,0,0, + 0,2,0,70,255,227,6,89,3,125,0,11,0,25,0,41,64,10,9,25,15,17,3,25,13,23,16,26,16,252,196,236,212,57,236,49,0,64,10,6, + 149,20,140,26,15,0,149,12,26,16,212,236,50,16,244,238,48,1,34,6,21,20,22,51,50,54,53,52,38,39,33,21,33,22,21,20,4,35,34,36, + 53,52,36,2,67,143,153,200,96,94,200,139,155,4,22,253,153,77,254,239,235,236,254,239,1,3,2,211,145,131,168,148,148,168,110,166,170,170,106,170, + 236,240,240,236,221,225,0,0,255,255,0,11,255,227,6,30,5,23,16,39,22,193,4,105,255,60,18,6,7,108,197,0,0,2,0,119,0,0,6,138, + 3,154,0,11,0,25,0,34,64,9,9,25,15,17,3,25,23,13,26,16,220,212,236,212,57,236,49,0,182,6,149,19,0,15,149,12,47,236,50,212, + 236,48,37,50,54,53,52,38,35,34,6,21,20,22,23,33,53,33,38,53,52,36,51,50,4,21,20,4,4,141,143,152,200,95,95,200,139,156,251,234, + 2,102,76,1,17,235,236,1,17,254,253,170,145,131,168,148,148,168,110,166,170,170,106,170,236,240,240,236,221,225,0,0,255,255,0,119,0,0,6,138, + 5,23,16,39,22,193,6,170,255,60,18,6,7,110,0,0,255,255,0,119,0,0,6,138,5,21,16,39,22,185,6,170,255,60,18,6,7,110,0,0, + 0,2,0,70,0,0,6,89,3,154,0,11,0,25,0,35,64,10,3,25,23,21,9,25,24,15,16,26,16,252,196,236,212,57,236,49,0,182,6,149, + 18,0,24,149,12,47,236,50,212,236,48,37,50,54,53,52,38,35,34,6,21,20,22,23,34,36,53,52,36,51,50,4,21,20,7,33,21,2,67,155, + 139,200,94,96,200,153,143,250,254,253,1,17,236,235,1,17,77,2,103,170,166,110,168,148,148,168,131,145,170,225,221,236,240,240,236,170,106,170,0,0, + 255,255,0,70,0,0,6,89,5,23,16,39,22,193,4,84,255,60,18,6,7,113,0,0,255,255,0,201,255,227,8,72,3,125,16,39,7,106,1,190, + 0,0,16,6,6,214,0,0,255,255,0,119,255,227,7,208,3,125,16,39,6,214,6,59,0,0,16,6,7,106,0,0,255,255,0,201,0,0,8,51, + 3,154,16,39,7,113,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,6,89,3,154,16,39,6,214,4,121,0,0,18,6,7,113,0,0, + 255,255,0,201,0,0,8,51,5,23,16,39,7,114,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,6,89,5,23,18,38,7,114,0,0, + 16,7,6,214,4,121,0,0,255,255,0,70,0,0,6,89,5,21,16,39,22,185,4,84,255,60,18,6,7,113,0,0,0,2,0,137,3,223,4,92, + 5,228,0,11,0,24,0,0,1,50,54,53,52,38,35,34,6,21,20,22,23,34,38,53,52,54,32,22,21,20,7,33,21,1,201,106,62,95,73,69, + 99,73,95,157,163,172,1,40,172,48,1,131,4,77,74,66,83,75,70,88,67,73,110,126,124,132,135,135,132,81,59,110,0,1,0,137,2,139,3,46, + 5,223,0,17,0,0,1,34,38,53,17,51,17,20,22,51,50,54,53,17,51,17,20,6,1,220,168,171,144,97,98,97,97,144,171,2,139,134,132,2, + 74,253,182,80,77,77,80,2,74,253,182,132,134,0,0,0,0,2,0,137,3,223,4,92,5,228,0,11,0,25,0,0,1,50,54,53,52,38,35,34, + 6,21,20,22,23,48,33,53,33,38,53,52,54,32,22,21,20,6,3,28,95,73,99,69,73,95,62,106,253,109,1,131,48,172,1,40,172,163,4,77, + 73,67,88,70,75,83,66,74,110,110,59,81,132,135,135,132,124,126,0,0,0,1,0,119,0,0,6,138,3,154,0,15,0,26,181,0,3,25,12,8, + 16,16,220,212,236,204,49,0,181,6,149,9,0,149,15,47,236,212,236,48,37,50,54,53,52,38,35,33,53,33,50,4,21,20,4,35,4,141,98,197, + 152,143,251,234,4,22,250,1,3,254,239,236,165,146,165,131,145,170,225,221,236,240,0,0,255,255,0,70,0,0,6,89,6,10,16,39,2,156,0,164, + 255,4,18,6,7,127,0,0,0,1,0,70,0,0,6,89,3,154,0,15,0,27,182,0,13,25,8,4,16,16,16,252,196,236,204,49,0,181,10,149, + 7,0,149,1,47,236,212,236,48,37,21,34,36,53,52,36,51,33,21,33,34,6,21,20,22,2,67,236,254,239,1,3,250,4,22,251,234,143,153,198, + 165,165,240,236,221,225,170,145,131,165,146,0,255,255,0,70,0,0,6,89,5,23,16,39,22,193,4,164,255,60,18,6,7,127,0,0,0,1,0,119, + 0,0,6,138,3,154,0,15,0,26,181,0,13,25,4,9,16,16,220,212,236,204,49,0,181,0,149,1,10,149,7,47,236,212,236,48,1,53,50,4, + 21,20,4,35,33,53,33,50,54,53,52,38,4,141,236,1,17,254,253,250,251,234,4,22,143,152,197,2,245,165,240,236,221,225,170,145,131,165,146,0, + 255,255,0,119,0,0,6,138,5,23,16,39,22,193,6,170,255,60,18,6,7,129,0,0,255,255,0,119,0,0,6,138,5,21,16,39,22,185,6,170, + 255,60,18,6,7,129,0,0,0,1,0,70,0,0,6,89,3,154,0,15,0,27,182,0,3,25,8,12,16,16,16,252,196,236,204,49,0,181,0,149, + 15,6,149,9,47,236,212,236,48,1,34,6,21,20,22,51,33,21,33,34,36,53,52,36,51,2,67,98,198,153,143,4,22,251,234,250,254,253,1,17, + 236,2,245,146,165,131,145,170,225,221,236,240,255,255,0,70,0,0,6,89,5,23,16,39,22,193,4,164,255,60,18,6,7,132,0,0,255,255,0,201, + 0,0,8,72,3,154,16,39,7,125,1,190,0,0,16,6,6,214,0,0,255,255,0,119,0,0,7,208,3,154,16,38,7,125,0,0,16,7,6,214, + 6,59,0,0,255,255,0,201,0,0,8,51,3,154,16,39,7,127,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,7,198,3,154,16,38, + 7,127,0,0,16,7,6,214,6,49,0,0,255,255,0,201,0,0,8,51,5,23,16,39,7,128,1,218,0,0,16,6,6,214,0,0,255,255,0,70, + 0,0,7,198,5,23,16,38,7,128,0,0,16,7,6,214,6,49,0,0,255,255,0,201,0,0,8,72,3,154,16,39,7,129,1,190,0,0,16,6, + 6,214,0,0,255,255,0,119,0,0,7,208,3,154,16,38,7,129,0,0,16,7,6,214,6,59,0,0,255,255,0,201,0,0,8,72,5,23,16,39, + 7,130,1,190,0,0,16,6,6,214,0,0,255,255,0,119,0,0,7,208,5,23,16,38,7,130,0,0,16,7,6,214,6,59,0,0,255,255,0,201, + 0,0,8,51,3,154,16,39,7,132,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,7,198,3,154,16,38,7,132,0,0,16,7,6,214, + 6,49,0,0,255,255,0,201,0,0,8,51,5,23,16,39,7,133,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,7,198,5,23,16,38, + 7,133,0,0,16,7,6,214,6,49,0,0,0,1,0,137,3,223,4,92,5,228,0,15,0,0,1,34,6,21,20,22,51,33,21,33,34,38,53,52, + 54,51,1,220,82,105,80,89,2,146,253,110,158,163,172,167,5,118,68,90,72,67,110,126,131,125,135,0,0,1,0,119,0,0,5,94,5,213,0,12, + 0,0,37,21,1,53,45,1,53,1,21,13,1,21,5,5,94,251,25,3,106,252,150,4,231,252,20,3,236,252,20,182,182,1,50,228,212,213,228,1, + 50,187,233,236,184,233,0,0,0,1,0,70,0,0,4,10,5,213,0,12,0,28,183,7,28,4,63,0,28,11,13,16,220,236,252,236,49,0,181,3, + 149,7,11,129,6,47,244,212,236,48,1,16,0,33,51,17,35,17,36,0,17,53,51,1,16,1,84,1,67,99,202,254,250,254,12,202,5,168,254,153, + 254,189,253,2,2,88,3,1,111,1,157,110,255,255,0,201,0,0,5,50,8,75,16,39,2,156,2,32,1,69,18,6,7,152,0,0,0,1,0,201, + 0,0,4,141,5,213,0,12,0,30,64,9,1,28,2,63,6,28,8,4,13,16,252,236,252,236,49,0,181,10,149,6,1,129,8,47,244,212,236,48, + 1,53,51,21,16,0,5,17,35,17,51,32,0,3,195,202,254,12,254,250,202,99,1,67,1,84,5,168,45,110,254,99,254,145,3,253,168,2,254,1, + 67,0,0,0,255,255,0,201,0,0,4,141,7,79,16,39,22,193,6,32,1,116,18,6,7,152,0,0,0,1,0,70,0,0,4,10,5,213,0,12, + 0,28,183,6,28,9,63,0,28,3,13,16,220,236,252,236,49,0,181,10,149,6,7,129,2,47,228,212,236,48,37,21,35,53,16,0,37,17,51,17, + 35,32,0,1,16,202,1,244,1,6,202,99,254,189,254,172,45,45,110,1,157,1,111,3,2,88,253,2,254,189,0,0,255,255,0,70,0,0,4,10, + 7,79,16,39,22,193,5,163,1,116,18,6,7,154,0,0,255,255,0,70,0,0,4,204,7,78,16,39,22,185,5,163,1,117,18,6,7,154,0,0, + 0,1,0,201,0,0,4,141,5,213,0,12,0,30,64,9,0,28,10,63,6,28,5,4,13,16,252,236,252,236,49,0,181,3,149,7,5,129,11,47, + 228,212,236,48,37,16,0,33,35,17,51,17,4,0,17,21,35,3,195,254,172,254,189,99,202,1,6,1,244,202,45,1,103,1,67,2,254,253,168,3, + 254,145,254,99,110,0,0,0,255,255,0,201,0,0,4,141,7,79,16,39,22,193,3,51,1,116,18,6,7,157,0,0,255,255,0,201,0,0,5,228, + 5,213,16,39,7,150,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,5,145,5,213,16,39,6,214,3,252,0,0,16,6,7,150,0,0, + 255,255,0,201,0,0,6,16,5,213,16,39,7,152,1,131,0,0,16,6,6,214,0,0,255,255,0,201,0,0,5,180,5,213,16,39,6,214,4,31, + 0,0,16,6,7,152,0,0,255,255,0,201,0,0,6,16,7,79,16,39,7,153,1,131,0,0,16,6,6,214,0,0,255,255,0,201,0,0,5,180, + 7,79,16,38,7,153,0,0,16,7,6,214,4,31,0,0,255,255,0,201,0,0,5,228,5,213,16,39,7,154,1,218,0,0,16,6,6,214,0,0, + 255,255,0,70,0,0,5,145,5,213,16,38,7,154,0,0,16,7,6,214,3,252,0,0,255,255,0,201,0,0,5,228,7,79,16,39,7,155,1,218, + 0,0,16,6,6,214,0,0,255,255,0,70,0,0,5,145,7,79,16,38,7,155,0,0,16,7,6,214,3,252,0,0,255,255,0,201,0,0,6,16, + 5,213,16,39,7,157,1,131,0,0,16,6,6,214,0,0,255,255,0,201,0,0,5,180,5,213,16,38,7,157,0,0,16,7,6,214,4,31,0,0, + 255,255,0,201,0,0,6,16,7,79,16,39,7,158,1,131,0,0,16,6,6,214,0,0,255,255,0,201,0,0,5,180,7,79,16,38,7,158,0,0, + 16,7,6,214,4,31,0,0,255,255,0,240,0,0,6,16,5,213,16,38,23,21,0,0,16,7,7,157,1,131,0,0,0,1,0,137,2,156,2,232, + 5,223,0,12,0,30,182,12,93,11,7,93,4,13,16,220,236,212,236,49,0,183,7,221,4,12,247,5,145,13,16,244,244,220,236,48,1,52,38,43, + 1,17,51,17,30,1,29,1,35,2,88,184,207,72,144,227,236,144,2,198,199,156,1,182,254,185,21,229,172,86,0,0,0,1,0,137,2,139,2,236, + 5,238,0,43,0,0,1,21,46,1,35,34,6,21,20,23,22,31,1,22,23,22,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,39,38,47, + 1,38,39,38,53,52,54,51,50,22,2,184,67,119,55,66,104,35,45,56,71,127,67,62,169,164,61,139,74,71,137,66,65,109,39,46,47,71,127,63, + 59,162,143,61,126,5,195,135,31,30,72,41,64,19,28,15,14,24,64,60,102,121,126,27,26,132,39,39,76,56,61,35,40,9,13,23,59,54,95,111, + 128,22,0,0,0,1,0,137,2,156,2,232,5,223,0,14,0,0,1,48,21,35,53,52,54,55,48,17,51,17,35,34,6,1,25,144,236,227,144,72, + 207,184,2,198,42,86,172,229,21,1,71,254,74,156,0,0,0,1,0,70,255,227,5,108,5,242,0,27,0,0,1,20,22,51,50,54,53,51,16,6, + 35,34,38,25,1,52,38,35,34,6,21,35,16,54,51,50,22,17,3,62,86,92,96,82,202,186,194,170,210,86,92,96,82,202,186,194,170,210,1,190, + 211,104,90,225,254,231,194,183,1,37,2,88,211,104,90,225,1,25,194,183,254,219,0,0,0,1,0,70,255,227,5,108,5,242,0,27,0,0,1,17, + 16,54,51,50,22,17,35,52,38,35,34,6,21,17,16,6,35,34,38,17,51,20,22,51,50,54,2,116,210,170,194,186,202,82,96,92,86,210,170,194, + 186,202,82,96,92,86,1,190,2,88,1,37,183,194,254,231,225,90,104,211,253,168,254,219,183,194,1,25,225,90,104,0,255,255,0,70,255,227,5,108, + 7,79,16,39,22,193,5,243,1,116,16,6,7,178,0,0,0,1,0,70,255,227,6,220,3,183,0,39,0,0,1,30,1,51,50,54,53,52,38,35, + 53,32,18,21,6,2,33,34,2,47,1,46,1,35,34,6,21,20,22,51,21,34,2,53,52,18,33,50,18,23,3,250,33,132,114,122,124,75,171,1, + 3,200,1,163,254,217,172,215,52,50,32,132,115,127,119,85,161,249,210,164,1,39,173,214,52,1,176,88,203,167,124,96,229,165,254,195,173,149,254,200, + 1,25,126,112,88,203,167,124,96,229,165,1,74,160,154,1,51,254,231,126,255,255,0,70,255,227,6,220,5,23,16,39,22,193,5,139,255,60,16,6, + 7,180,0,0,0,1,0,70,255,227,6,220,3,183,0,39,0,0,1,55,54,18,51,32,18,23,20,2,35,53,50,54,53,52,38,35,34,6,15,1, + 6,2,35,32,2,39,52,18,33,21,34,6,21,20,22,51,50,54,3,40,50,52,215,172,1,39,163,1,210,249,161,85,118,128,114,132,33,50,52,214, + 173,254,217,163,1,200,1,3,171,75,124,122,115,132,1,176,112,126,1,25,254,200,149,166,254,188,165,229,96,124,167,203,88,112,126,254,231,1,56,149, + 173,1,61,165,229,96,124,167,203,0,0,0,255,255,0,70,255,227,6,220,5,23,16,39,22,193,5,139,255,60,16,6,7,182,0,0,255,255,0,201, + 255,227,7,1,5,242,16,38,6,214,0,0,16,7,7,177,1,149,0,0,255,255,0,70,255,227,6,131,5,242,16,38,7,177,0,0,16,7,6,214, + 4,238,0,0,255,255,0,201,255,227,7,1,5,242,16,39,7,178,1,149,0,0,16,6,6,214,0,0,255,255,0,70,255,227,6,131,5,242,16,38, + 7,178,0,0,16,7,6,214,4,238,0,0,255,255,0,201,255,227,7,1,7,79,16,39,7,179,1,149,0,0,16,6,6,214,0,0,255,255,0,70, + 255,227,6,131,7,79,16,38,7,179,0,0,16,7,6,214,4,238,0,0,255,255,0,201,255,227,8,217,3,183,16,39,7,180,1,253,0,0,16,6, + 6,214,0,0,255,255,0,70,255,227,8,85,3,183,16,39,6,214,6,192,0,0,16,6,7,180,0,0,255,255,0,201,255,227,8,217,5,23,16,39, + 7,181,1,253,0,0,16,6,6,214,0,0,255,255,0,70,255,227,8,85,5,23,16,38,7,181,0,0,16,7,6,214,6,192,0,0,255,255,0,201, + 255,227,8,217,3,183,16,39,7,182,1,253,0,0,16,6,6,214,0,0,255,255,0,70,255,227,8,85,3,183,16,38,7,182,0,0,16,7,6,214, + 6,192,0,0,255,255,0,201,255,227,8,217,5,23,16,39,7,183,1,253,0,0,16,6,6,214,0,0,255,255,0,70,255,227,8,85,5,23,16,38, + 7,183,0,0,16,7,6,214,6,192,0,0,0,1,0,137,3,207,4,175,5,230,0,39,0,0,1,62,2,55,50,22,23,20,6,35,53,50,54,53, + 52,38,35,34,6,15,1,14,1,35,34,38,39,52,54,51,21,34,6,21,20,22,51,50,54,2,91,42,39,115,111,190,98,1,132,157,73,61,74,60, + 75,50,23,65,11,145,115,186,102,1,126,163,77,56,75,58,66,69,4,204,70,61,150,1,168,77,93,181,110,119,45,27,108,65,35,118,21,186,174,84, + 97,177,107,121,46,49,101,77,0,1,0,119,0,0,4,59,5,213,0,8,0,46,181,2,28,8,6,4,9,16,220,204,212,236,49,0,182,66,8,149, + 2,6,129,0,47,244,212,236,48,75,83,88,183,6,17,5,7,17,4,4,5,5,7,16,237,16,237,89,33,35,17,33,53,1,51,1,33,4,59,202, + 253,6,2,61,202,253,195,2,250,2,88,173,2,208,253,45,255,255,0,201,0,0,4,141,8,75,16,39,2,156,255,226,1,69,18,6,7,201,0,0, + 0,1,0,201,0,0,4,141,5,213,0,8,0,47,182,4,5,7,28,0,4,9,16,252,236,212,204,49,0,182,66,1,149,7,3,129,0,47,244,212, + 236,48,75,83,88,183,2,17,5,3,17,4,4,5,5,7,16,237,16,237,89,51,17,33,1,51,1,21,33,17,201,2,250,253,195,202,2,61,253,6, + 3,2,2,211,253,48,173,253,168,0,0,0,255,255,0,201,0,0,4,141,7,79,16,39,22,193,3,226,1,116,18,6,7,201,0,0,0,1,0,119, + 0,0,4,59,5,213,0,8,0,46,181,7,28,1,3,6,9,16,220,204,212,236,49,0,182,66,2,149,7,0,129,4,47,228,212,236,48,75,83,88, + 183,2,17,5,3,17,4,4,5,5,7,16,237,16,237,89,1,17,33,1,35,1,53,33,17,4,59,253,6,2,61,202,253,195,2,250,5,213,252,254, + 253,45,2,208,173,2,88,0,255,255,0,119,0,0,4,64,7,79,16,39,22,193,5,218,1,116,18,6,7,203,0,0,255,255,0,119,0,0,5,3, + 7,78,16,39,22,185,5,218,1,117,18,6,7,203,0,0,0,1,0,201,0,0,4,141,5,213,0,8,0,47,182,5,4,1,28,0,4,9,16,252, + 236,212,204,49,0,182,66,7,149,3,0,129,6,47,228,212,236,48,75,83,88,183,6,17,5,7,17,4,4,5,5,7,16,237,16,237,89,19,51,17, + 33,21,1,35,1,33,201,202,2,250,253,195,202,2,61,253,6,5,213,253,168,173,253,48,2,211,0,0,255,255,0,201,0,0,4,141,7,79,16,39, + 22,193,3,53,1,116,18,6,7,206,0,0,255,255,0,201,0,0,5,248,5,213,16,39,7,199,1,189,0,0,16,6,6,214,0,0,255,255,0,119, + 0,0,5,200,5,213,16,39,6,214,4,51,0,0,16,6,7,199,0,0,255,255,0,201,0,0,6,16,5,213,16,39,7,201,1,131,0,0,16,6, + 6,214,0,0,255,255,0,201,0,0,6,21,5,213,16,39,6,214,4,128,0,0,16,6,7,201,0,0,255,255,0,201,0,0,6,16,7,79,16,39, + 7,202,1,131,0,0,16,6,6,214,0,0,255,255,0,201,0,0,6,21,7,79,16,38,7,202,0,0,16,7,6,214,4,128,0,0,255,255,0,201, + 0,0,5,248,5,213,16,39,7,203,1,189,0,0,16,6,6,214,0,0,255,255,0,119,0,0,5,200,5,213,16,38,7,203,0,0,16,7,6,214, + 4,51,0,0,255,255,0,201,0,0,5,253,7,79,16,39,7,204,1,189,0,0,16,6,6,214,0,0,255,255,0,119,0,0,5,200,7,79,16,38, + 7,204,0,0,16,7,6,214,4,51,0,0,255,255,0,201,0,0,6,16,5,213,16,39,7,206,1,131,0,0,16,6,6,214,0,0,255,255,0,201, + 0,0,6,21,5,213,16,38,7,206,0,0,16,7,6,214,4,128,0,0,255,255,0,201,0,0,6,16,7,79,16,39,7,207,1,131,0,0,16,6, + 6,214,0,0,255,255,0,201,0,0,6,21,7,79,16,38,7,207,0,0,16,7,6,214,4,128,0,0,255,255,0,240,0,0,6,16,5,213,16,38, + 23,21,0,0,16,7,7,206,1,131,0,0,0,1,0,137,2,155,2,232,5,223,0,8,0,52,182,5,7,3,2,93,8,9,16,220,236,212,57,204, + 49,0,64,9,66,2,221,8,5,247,0,145,9,16,244,244,220,236,48,75,83,88,183,6,125,5,7,125,4,4,5,7,16,5,237,16,237,89,19,51, + 17,33,21,1,35,1,33,137,144,1,207,254,165,145,1,109,254,32,5,223,254,183,121,254,126,1,141,0,255,255,0,137,3,49,2,173,5,86,18,6, + 6,216,0,0,0,1,0,137,2,156,3,111,5,223,0,11,0,0,19,51,27,1,51,9,1,35,11,1,35,1,176,145,197,198,145,254,237,1,37,145, + 225,227,145,1,47,5,223,254,222,1,34,254,121,254,68,1,82,254,174,1,188,0,0,0,0,1,0,201,255,227,6,220,3,125,0,19,0,39,64,9, + 9,28,12,1,28,10,0,4,20,16,252,196,236,212,236,49,0,64,10,5,149,16,140,20,12,149,9,0,20,16,212,60,236,16,244,238,48,19,51,17, + 20,22,51,50,54,53,17,33,21,33,17,20,4,35,34,36,53,201,202,206,101,94,212,2,228,253,230,254,239,235,236,254,239,3,125,254,66,164,152,148, + 168,1,190,170,254,236,236,240,240,236,0,0,0,1,0,119,255,227,6,138,3,125,0,19,0,37,183,11,28,8,19,28,0,10,20,16,220,212,236,212, + 236,49,0,64,10,15,149,4,140,20,8,149,10,0,20,16,212,60,236,16,244,238,48,1,17,20,4,35,34,36,53,17,33,53,33,17,20,22,51,50, + 54,53,17,6,138,254,239,236,235,254,239,253,230,2,228,211,95,101,206,3,125,254,66,236,240,240,236,1,20,170,254,66,168,148,152,164,1,190,0,0, + 0,1,0,119,0,0,6,138,3,154,0,19,0,31,183,9,28,13,1,28,0,10,20,16,220,212,236,212,236,49,0,182,5,149,16,12,149,10,0,47, + 60,236,212,236,48,33,35,17,52,38,35,34,6,21,17,33,53,33,17,52,36,51,50,4,21,6,138,202,206,101,95,211,253,28,2,26,1,17,235,236, + 1,17,1,190,164,152,148,168,254,66,170,1,20,236,240,240,236,0,0,0,255,255,0,201,0,0,6,220,6,10,16,39,2,156,0,192,255,4,16,6, + 7,230,0,0,0,1,0,201,0,0,6,220,3,154,0,19,0,33,64,9,11,28,7,19,28,9,0,4,20,16,252,196,236,212,236,49,0,182,15,149, + 4,8,149,10,0,47,60,236,212,236,48,51,17,52,36,51,50,4,21,17,33,21,33,17,52,38,35,34,6,21,17,201,1,17,236,235,1,17,2,26, + 253,28,212,94,101,206,1,190,236,240,240,236,254,236,170,1,190,168,148,152,164,254,66,0,255,255,0,201,0,0,6,220,5,23,16,39,22,193,4,192, + 255,60,18,6,7,230,0,0,0,1,0,201,0,0,4,141,5,213,0,19,0,35,64,10,16,25,5,63,10,28,0,11,4,20,16,252,60,236,252,236, + 49,0,183,13,149,8,0,149,1,129,11,47,244,236,212,236,48,19,53,33,50,4,21,20,4,43,1,17,35,17,33,50,54,53,52,38,35,201,1,200, + 251,1,1,254,255,251,254,202,1,200,141,154,154,141,5,47,166,227,219,221,226,253,168,2,254,146,135,134,146,0,0,0,255,255,0,201,0,0,4,141, + 7,79,16,39,22,193,4,22,1,116,18,6,7,232,0,0,0,1,0,201,0,0,4,141,5,213,0,19,0,35,64,10,4,25,15,63,10,28,0,9, + 4,20,16,252,60,236,252,236,49,0,183,7,149,11,0,149,9,129,19,47,228,236,212,236,48,55,33,50,54,53,52,38,35,33,17,51,17,51,50,4, + 21,20,4,35,33,201,1,200,141,154,154,141,254,56,202,254,251,1,1,254,255,251,254,56,166,146,134,135,146,2,254,253,168,226,221,219,227,0,0,0, + 0,1,0,70,0,0,4,10,5,213,0,19,0,34,64,9,11,28,19,8,63,4,25,15,20,16,220,236,252,60,236,49,0,183,7,149,11,0,149,19, + 129,10,47,244,236,212,236,48,1,33,34,6,21,20,22,51,33,17,35,17,35,34,36,53,52,36,51,33,4,10,254,56,141,154,154,141,1,200,202,254, + 251,254,255,1,1,251,1,200,5,47,146,134,135,146,253,2,2,88,226,221,219,227,0,0,255,255,0,70,0,0,4,10,7,79,16,39,22,193,4,132, + 1,116,18,6,7,235,0,0,0,1,0,70,0,0,4,10,5,213,0,19,0,34,64,9,9,28,12,0,63,16,25,5,20,16,220,236,252,60,236,49, + 0,183,13,149,9,0,149,10,129,1,47,228,236,212,236,48,37,21,33,34,36,53,52,36,59,1,17,51,17,33,34,6,21,20,22,51,4,10,254,56, + 251,254,255,1,1,251,254,202,254,56,141,154,154,141,166,166,227,219,221,226,2,88,253,2,146,135,134,146,255,255,0,201,0,0,5,228,7,79,16,39, + 7,236,1,218,0,0,16,6,6,214,0,0,255,255,0,70,0,0,5,145,7,79,16,39,6,214,3,252,0,0,16,6,7,236,0,0,0,1,0,137, + 2,155,2,232,5,223,0,20,0,36,183,11,93,8,0,4,126,16,21,16,220,236,212,60,236,49,0,64,10,8,221,11,0,221,9,247,20,145,21,16, + 244,228,252,212,236,48,1,33,34,6,21,20,22,51,33,17,35,17,35,34,39,38,53,52,54,51,33,2,232,254,225,86,82,88,80,1,31,144,143,148, + 91,81,162,158,1,31,5,113,69,80,66,74,254,75,1,72,71,63,124,123,127,0,0,0,0,1,0,119,0,0,5,94,5,213,0,12,0,0,55,45, + 1,53,45,1,53,1,21,13,1,21,1,119,3,236,252,20,3,236,252,20,4,231,252,150,3,106,251,25,182,238,233,184,236,233,187,254,206,228,213,212, + 228,254,206,0,0,2,0,150,0,0,5,104,5,243,0,11,0,28,0,80,182,9,23,20,3,26,14,29,16,212,196,204,212,57,204,49,0,64,9,66, + 6,23,0,17,24,25,175,28,47,252,57,212,204,212,204,48,75,83,88,64,22,22,21,23,20,24,17,27,12,28,25,17,26,27,26,24,17,28,23,17, + 12,12,28,5,7,16,237,16,237,7,16,237,8,16,237,17,18,57,57,89,1,34,6,21,20,22,51,50,54,53,52,38,1,38,53,52,54,23,50,22, + 21,20,6,7,9,1,51,1,35,1,166,52,60,60,50,44,66,58,254,231,41,176,96,106,167,159,126,1,34,1,218,210,253,199,229,5,78,47,48,64, + 46,66,44,34,61,254,190,106,121,105,156,1,145,115,102,156,8,252,226,5,14,250,43,0,255,255,0,150,255,226,5,104,8,75,16,39,2,156,0,192, + 1,69,18,6,7,244,0,0,0,2,0,150,255,226,5,104,5,213,0,11,0,28,0,80,182,9,3,21,9,15,27,29,16,212,196,204,212,57,204,49, + 0,64,9,66,6,18,0,24,17,13,175,16,47,236,57,212,204,212,204,48,75,83,88,64,22,20,19,28,21,17,17,14,12,13,16,17,15,15,14,17, + 17,13,18,17,12,12,13,5,7,16,237,16,237,7,16,237,8,16,237,17,18,57,57,89,37,50,54,53,52,38,35,34,6,21,20,22,3,1,51,1, + 35,9,1,30,1,21,20,6,35,6,38,53,52,1,166,50,58,66,44,50,60,60,179,1,139,229,2,57,210,254,38,254,222,126,159,167,106,96,176,135, + 61,34,44,66,46,64,48,47,1,66,4,12,250,43,5,14,252,226,8,156,102,115,145,1,156,105,121,0,255,255,0,150,255,226,5,104,7,79,16,39, + 22,193,4,192,1,116,18,6,7,244,0,0,0,2,0,77,0,0,5,88,5,75,0,11,0,28,0,84,64,10,3,12,9,18,28,28,25,18,27,29, + 16,220,196,212,236,16,204,212,204,49,0,183,66,0,12,15,6,28,21,26,47,220,57,204,212,57,204,48,75,83,88,64,22,14,13,15,12,28,17,25, + 26,24,12,17,23,24,23,28,17,25,27,17,26,25,26,4,7,16,237,16,237,7,16,237,16,8,237,17,18,57,57,89,1,50,54,53,52,38,35,34, + 6,21,20,22,37,14,1,35,34,38,53,52,54,51,50,23,1,21,1,53,1,1,93,50,58,66,44,50,60,60,1,68,12,164,96,109,163,174,71,65, + 74,3,139,251,25,4,77,3,221,61,34,44,66,46,64,48,47,59,97,127,161,99,142,129,37,254,54,228,253,136,182,2,52,0,0,0,255,255,0,77, + 0,0,5,88,7,79,16,39,22,193,4,174,1,116,18,6,7,246,0,0,0,2,0,119,0,0,5,130,5,75,0,11,0,28,0,82,64,9,9,12, + 3,23,15,13,28,16,29,16,220,236,212,212,204,212,204,49,0,183,66,0,12,26,6,13,20,15,47,220,57,204,212,57,204,48,75,83,88,64,22,28, + 27,26,12,13,17,16,15,17,12,17,18,17,18,13,17,16,14,17,15,16,15,4,7,16,237,16,237,7,16,237,16,8,237,17,18,57,57,89,1,50, + 54,53,52,38,35,34,6,21,20,22,39,9,1,21,1,53,1,54,51,50,22,21,20,6,35,34,38,4,114,52,60,60,50,44,66,58,222,253,175,4, + 77,251,25,3,139,74,65,71,174,180,90,110,153,3,221,47,48,64,46,66,44,34,61,59,254,210,253,204,182,2,120,228,1,202,37,129,142,109,151,135, + 255,255,0,119,0,0,5,130,7,79,16,39,22,193,5,49,1,116,18,6,7,248,0,0,255,255,0,201,0,0,7,23,7,79,16,39,7,249,1,149, + 0,0,16,6,6,214,0,0,255,255,0,119,0,0,7,69,7,79,16,38,7,249,0,0,16,7,6,214,5,176,0,0,0,2,0,137,2,155,3,178, + 5,144,0,11,0,32,0,0,1,50,54,53,52,38,35,34,6,21,20,22,39,5,1,21,1,53,37,54,51,50,23,22,21,20,7,6,35,34,35,34, + 38,3,6,33,38,38,31,28,42,37,136,254,161,2,160,252,233,2,55,46,41,44,39,72,50,48,71,1,2,64,98,4,194,27,27,36,25,37,24,19, + 35,25,158,254,209,115,1,98,128,254,20,25,47,79,59,44,43,73,0,0,0,2,0,178,255,227,5,41,5,242,0,10,0,39,0,0,1,50,54,53, + 52,38,34,6,21,20,22,7,17,20,22,51,50,54,53,17,51,17,16,0,33,32,0,25,1,52,54,51,50,22,21,20,7,6,35,34,1,235,40,66, + 58,100,58,66,66,174,195,194,174,203,254,223,254,230,254,229,254,223,173,138,106,167,73,74,126,60,4,128,66,44,34,62,62,34,44,66,136,254,82,240, + 211,211,240,3,139,252,92,254,220,254,214,1,42,1,36,2,178,106,165,144,116,95,85,86,0,2,0,178,255,227,5,41,5,242,0,10,0,39,0,0, + 1,50,54,53,52,38,34,6,21,20,22,23,6,35,34,39,38,53,52,54,51,50,22,21,17,16,0,33,32,0,25,1,51,17,20,22,51,50,54,53, + 3,240,44,66,58,100,58,66,150,48,60,126,74,73,167,106,138,173,254,223,254,229,254,230,254,223,203,174,194,195,174,4,128,66,44,34,62,62,34,44, + 66,136,20,86,85,95,116,144,165,106,253,78,254,220,254,214,1,42,1,36,3,164,252,117,240,211,211,240,0,2,0,178,255,227,5,41,5,242,0,10, + 0,39,0,0,1,34,6,21,20,22,50,54,53,52,38,39,54,51,50,23,22,21,20,6,35,34,38,53,17,16,0,33,32,0,25,1,35,17,52,38, + 35,34,6,21,1,235,44,66,58,100,58,66,150,48,60,126,74,73,167,106,138,173,1,33,1,27,1,26,1,33,203,174,194,195,174,1,85,66,44,34, + 62,62,34,44,66,136,20,86,85,95,116,144,165,106,2,178,1,36,1,42,254,214,254,220,252,92,3,139,240,211,211,240,0,2,0,178,255,227,5,41, + 5,242,0,10,0,39,0,0,1,34,6,21,20,22,50,54,53,52,38,55,17,52,38,35,34,6,21,17,35,17,16,0,33,32,0,25,1,20,6,35, + 34,38,53,52,55,54,51,50,3,240,40,66,58,100,58,66,66,174,195,194,174,203,1,33,1,26,1,27,1,33,173,138,106,167,73,74,126,60,1,85, + 66,44,34,62,62,34,44,66,136,1,174,240,211,211,240,252,117,3,164,1,36,1,42,254,214,254,220,253,78,106,165,144,116,95,85,86,255,255,0,178, + 255,227,5,41,7,79,16,39,22,193,4,231,1,116,18,6,7,255,0,0,255,255,0,178,255,227,5,41,7,79,16,39,22,193,4,231,1,116,18,6, + 8,0,0,0,0,2,0,83,0,0,5,94,5,213,0,8,0,36,0,0,18,20,22,50,54,52,38,7,34,5,22,21,20,6,7,6,38,53,52,54, + 59,1,32,0,17,16,0,41,1,53,33,32,0,17,16,39,38,243,60,104,60,59,53,53,1,49,20,139,133,115,157,163,109,179,1,178,1,150,254,104, + 254,80,254,97,1,190,1,53,1,31,143,134,5,1,96,47,47,96,47,1,1,44,49,106,151,3,3,151,112,99,161,254,151,254,128,254,126,254,150,166, + 1,24,1,46,1,44,140,129,255,255,0,83,0,0,5,94,7,79,16,39,22,193,4,199,1,116,18,6,8,3,0,0,0,2,0,121,0,0,5,132, + 5,213,0,8,0,36,0,0,0,52,38,35,38,6,20,22,50,37,4,7,6,17,16,0,41,1,21,33,32,0,17,16,0,33,51,50,22,21,20,6, + 39,46,1,53,52,4,228,59,53,53,59,60,104,254,208,254,235,133,144,1,31,1,53,1,190,254,97,254,80,254,104,1,150,1,178,179,109,163,157,115, + 133,139,4,161,96,46,1,47,96,47,188,9,129,140,254,212,254,210,254,232,166,1,106,1,130,1,128,1,105,161,99,112,151,3,3,151,106,49,0,0, + 255,255,0,121,0,0,5,132,7,79,16,39,22,193,5,34,1,116,18,6,8,5,0,0,255,255,0,201,0,0,7,65,7,79,16,39,8,6,1,189, + 0,0,16,6,6,214,0,0,255,255,0,121,0,0,6,189,7,79,16,38,8,6,0,0,16,7,6,214,5,40,0,0,0,2,0,137,2,156,3,189, + 5,223,0,11,0,38,0,0,1,34,6,21,20,22,51,50,54,53,52,38,7,34,38,53,52,55,6,7,6,21,20,22,51,33,21,33,32,36,16,36, + 33,51,50,22,21,20,6,3,21,31,38,38,33,27,38,38,30,70,99,13,193,73,77,190,168,1,25,254,250,254,240,254,255,1,0,1,17,114,82,95, + 98,5,113,25,36,27,27,27,27,36,25,207,86,60,33,28,3,70,74,160,185,123,110,203,1,174,202,89,82,59,87,0,0,2,0,70,0,0,6,46, + 5,242,0,11,0,28,0,0,1,34,6,21,20,22,51,50,54,53,52,38,19,17,6,7,34,36,53,52,36,51,50,4,21,17,1,23,1,2,66,122, + 173,200,95,128,178,204,204,128,178,235,254,239,1,35,217,236,1,16,1,86,154,254,104,5,82,164,151,168,148,169,147,164,151,250,174,2,133,73,1,240, + 236,250,225,240,236,252,168,2,12,102,253,156,0,2,0,119,0,0,6,95,5,242,0,11,0,28,0,0,1,34,6,21,20,22,51,50,54,53,52,38, + 1,33,1,55,1,17,52,36,51,50,4,21,20,4,35,38,39,4,99,102,204,178,128,95,200,173,254,84,254,222,254,104,154,1,86,1,16,236,217,1, + 35,254,239,235,178,128,5,82,151,164,147,169,148,168,151,164,250,174,2,100,102,253,244,3,88,236,240,225,250,236,240,1,73,0,0,0,255,255,0,119, + 0,0,6,95,7,79,16,39,22,193,6,94,1,116,18,6,8,11,0,0,0,2,0,70,255,227,6,46,5,213,0,11,0,28,0,0,37,50,54,53, + 52,38,35,34,6,21,20,22,1,33,1,7,1,17,20,4,35,34,36,53,52,36,51,22,23,2,66,102,204,178,128,95,200,173,1,172,1,34,1,152, + 154,254,170,254,240,236,217,254,221,1,17,235,178,128,131,151,164,147,169,148,168,151,164,5,82,253,156,102,2,12,252,168,236,240,225,250,236,240,1,73, + 255,255,0,70,255,227,6,46,7,79,16,39,22,193,5,211,1,116,18,6,8,13,0,0,0,2,0,119,255,227,6,95,5,213,0,11,0,28,0,0, + 37,50,54,53,52,38,35,34,6,21,20,22,3,17,54,55,50,4,21,20,4,35,34,36,53,17,1,39,1,4,99,122,173,200,95,128,178,204,204,128, + 178,235,1,17,254,221,217,236,254,240,254,170,154,1,152,131,164,151,168,148,169,147,164,151,5,82,253,123,73,1,240,236,250,225,240,236,3,88,253,244, + 102,2,100,0,255,255,0,119,255,227,6,95,7,79,16,39,22,193,4,211,1,116,18,6,8,15,0,0,0,2,0,137,2,139,4,17,5,223,0,16, + 0,28,0,0,1,17,3,39,19,51,17,54,51,50,22,21,20,6,35,34,38,5,50,54,53,52,38,35,34,6,21,20,22,1,145,198,66,247,161,81, + 95,148,172,183,137,149,171,1,64,88,80,94,74,92,84,97,3,149,1,192,254,254,61,1,79,254,151,41,134,132,140,126,134,24,86,70,84,72,85,71, + 81,75,0,0,255,255,0,201,0,0,5,59,5,213,18,6,0,43,0,0,255,255,0,137,2,156,3,111,5,223,18,6,7,225,0,0,255,255,0,137, + 0,0,8,26,8,75,16,39,7,24,3,89,0,0,16,6,7,240,0,0,255,255,0,137,0,0,8,26,5,242,16,38,7,240,0,0,16,7,7,25, + 3,89,0,0,255,255,0,137,0,0,8,26,7,79,16,38,7,240,0,0,16,7,7,26,3,89,0,0,255,255,0,137,255,227,7,151,5,223,16,38, + 7,240,0,0,16,7,7,27,3,89,0,0,255,255,0,137,255,227,7,151,7,79,16,38,7,240,0,0,16,7,7,28,3,89,0,0,255,255,0,137, + 255,227,8,26,5,223,16,38,7,240,0,0,16,7,7,30,3,89,0,0,255,255,0,137,255,227,8,26,7,79,16,38,7,240,0,0,16,7,7,31, + 3,89,0,0,255,255,0,137,2,139,6,98,5,223,16,39,7,47,3,89,0,0,16,6,7,240,0,0,0,1,0,70,0,0,6,46,5,242,0,18, + 0,58,64,9,3,2,5,28,18,11,28,12,19,16,220,236,220,236,204,57,49,0,64,9,66,11,8,149,0,15,145,1,4,47,204,244,57,236,204,48, + 75,83,88,183,1,17,2,0,17,3,3,2,4,7,16,237,16,14,237,89,37,1,23,1,33,17,52,38,35,34,6,21,35,52,36,51,50,4,21,4, + 62,1,86,154,254,104,254,222,204,102,128,178,202,1,35,217,236,1,16,190,2,12,102,253,156,4,23,164,151,169,146,250,225,240,236,0,0,1,0,119, + 0,0,6,95,5,242,0,18,0,58,64,9,8,28,7,15,28,16,0,17,19,16,220,220,57,236,220,236,49,0,64,9,66,7,11,149,0,4,145,18, + 15,47,204,244,57,236,204,48,75,83,88,183,18,17,17,0,17,16,17,16,4,7,16,237,16,14,237,89,37,17,52,36,51,50,4,21,35,52,38,35, + 34,6,21,17,33,1,55,2,103,1,16,236,217,1,35,202,178,128,102,204,254,222,254,104,154,190,3,88,236,240,225,250,146,169,151,164,251,233,2,100, + 102,0,0,0,0,1,0,70,255,227,6,46,5,213,0,18,0,61,64,9,16,17,14,28,1,8,28,7,19,16,220,236,220,236,49,0,64,12,66,18, + 15,7,11,149,4,140,0,15,145,19,16,228,57,244,238,204,16,204,48,75,83,88,183,18,17,17,0,17,16,17,16,4,7,16,237,16,14,237,89,1, + 17,20,4,35,34,36,53,51,20,22,51,50,54,53,17,33,1,7,4,62,254,240,236,217,254,221,202,178,128,102,204,1,34,1,152,154,5,23,252,168, + 236,240,225,250,146,169,151,164,4,23,253,156,102,0,0,0,0,1,0,119,255,227,6,95,5,213,0,18,0,63,64,9,11,28,12,5,28,3,0,2, + 19,16,220,220,57,236,220,236,49,0,64,12,66,1,4,12,8,149,15,140,0,4,145,19,16,228,57,244,238,204,16,204,48,75,83,88,183,1,17,2, + 0,17,3,3,2,4,7,16,237,16,14,237,89,9,1,39,1,33,17,20,22,51,50,54,53,51,20,4,35,34,36,53,2,103,254,170,154,1,152,1, + 34,204,102,128,178,202,254,221,217,236,254,240,5,23,253,244,102,2,100,251,233,164,151,169,146,250,225,240,236,0,0,0,255,255,0,137,0,0,9,205, + 8,75,16,39,7,54,5,12,0,0,16,6,8,39,0,0,255,255,0,137,0,0,9,205,5,242,16,39,7,55,5,12,0,0,16,6,8,39,0,0, + 255,255,0,137,0,0,9,205,7,79,16,39,7,56,5,12,0,0,16,6,8,39,0,0,255,255,0,137,255,227,7,59,5,228,16,39,7,57,2,253, + 0,0,16,6,8,39,0,0,255,255,0,137,255,227,7,59,7,79,16,39,7,58,2,253,0,0,16,6,8,39,0,0,255,255,0,137,255,227,9,205, + 5,228,16,39,7,60,5,12,0,0,16,6,8,39,0,0,255,255,0,137,255,227,9,205,7,79,16,39,7,61,5,12,0,0,16,6,8,39,0,0, + 0,2,0,137,2,168,5,40,5,228,0,10,0,40,0,0,1,50,54,53,52,38,34,6,21,20,22,23,34,38,53,52,54,51,50,22,21,20,7,51, + 21,20,22,51,50,54,61,1,51,21,20,6,35,34,38,61,1,1,201,98,70,110,116,110,80,88,148,172,172,148,149,171,47,185,81,44,67,69,144,171, + 109,97,172,4,90,84,58,75,77,77,75,70,72,110,133,124,112,135,135,112,88,59,167,111,66,71,106,167,167,132,135,136,131,57,0,0,0,3,0,137, + 2,168,8,36,5,228,0,10,0,51,0,62,0,0,1,50,54,53,52,38,34,6,21,20,22,33,38,53,52,54,51,50,22,21,20,7,51,21,20,22, + 51,50,54,61,1,51,21,20,6,35,34,38,61,1,33,34,38,53,52,54,51,50,22,21,20,7,33,50,54,53,52,38,34,6,21,20,22,1,201,98, + 70,110,116,110,80,2,63,43,172,148,149,171,47,185,81,44,67,69,144,171,109,97,172,251,202,148,172,172,148,149,171,47,1,235,98,70,110,116,110,80, + 4,90,84,58,75,77,77,75,70,72,59,88,112,135,135,112,88,59,167,111,66,71,106,167,167,132,135,136,131,57,133,124,112,135,135,112,88,59,84,58, + 75,77,77,75,70,72,0,0,0,1,0,70,0,0,6,89,5,137,0,18,0,60,64,10,16,18,1,9,5,25,1,12,16,19,16,252,196,236,204,16, + 204,57,49,0,183,66,18,2,149,15,8,149,9,47,236,212,236,204,48,75,83,88,64,10,17,17,17,18,18,16,17,0,18,0,5,7,16,237,16,8, + 237,89,1,17,33,34,6,21,20,22,51,21,34,36,53,52,36,51,33,1,55,6,89,251,234,143,153,198,98,236,254,239,1,3,250,3,88,253,242,104, + 3,242,254,254,145,131,165,146,165,240,236,221,225,1,85,154,255,255,0,70,0,0,6,89,5,137,16,39,22,193,4,164,255,60,18,6,8,41,0,0, + 0,1,0,119,254,17,6,138,3,154,0,18,0,56,183,9,5,25,12,16,18,0,19,16,204,57,220,212,236,204,49,0,183,66,8,149,9,1,149,18, + 16,47,204,236,212,236,48,75,83,88,64,10,17,17,17,18,18,16,17,0,18,0,5,7,16,237,16,8,237,89,23,17,33,50,54,53,52,38,35,53, + 50,4,21,20,4,35,33,1,7,119,4,22,143,153,198,98,236,1,17,254,253,250,252,168,2,13,103,88,1,2,145,131,165,146,165,240,236,221,225,254, + 171,154,0,0,255,255,0,119,254,17,6,138,5,23,16,39,22,193,6,92,255,60,18,6,8,43,0,0,0,1,0,70,254,17,6,89,3,154,0,18, + 0,58,64,9,3,1,18,14,25,10,7,16,19,16,252,204,236,212,204,57,49,0,183,66,11,149,10,17,149,1,3,47,204,236,212,236,48,75,83,88, + 64,10,2,17,1,1,1,3,17,0,1,0,5,7,16,237,16,8,237,89,5,1,39,1,33,34,36,53,52,36,51,21,34,6,21,20,22,51,33,6, + 89,253,156,104,2,14,252,168,250,254,253,1,17,236,98,198,153,143,4,22,88,254,105,154,1,85,225,221,236,240,165,146,165,131,145,0,255,255,0,70, + 254,17,6,89,5,23,16,39,22,193,4,105,255,60,18,6,8,45,0,0,0,1,0,137,2,181,4,92,5,228,0,18,0,0,1,5,39,37,33,34, + 38,53,52,54,51,21,34,6,21,20,22,51,33,4,92,254,177,61,1,46,253,204,158,163,172,167,82,105,80,89,2,146,3,172,247,66,232,126,131,125, + 135,110,68,90,72,67,0,0,0,1,0,119,0,0,5,4,5,213,0,16,0,0,37,35,53,51,53,33,53,1,51,1,33,17,51,21,35,21,35,3, + 113,201,201,253,6,2,61,202,253,195,2,250,201,201,202,224,164,212,173,2,208,253,45,254,130,164,224,0,0,1,0,33,0,0,4,174,5,213,0,16, + 0,0,37,21,35,53,35,53,51,17,33,1,51,1,21,33,21,51,21,1,180,202,201,201,2,250,253,195,202,2,61,253,6,201,224,224,224,164,1,126, + 2,211,253,48,173,212,164,0,255,255,0,33,0,0,4,174,7,79,16,39,22,193,4,3,1,116,18,6,8,49,0,0,0,1,0,119,0,0,5,4, + 5,213,0,16,0,0,1,53,51,21,51,21,35,17,33,1,35,1,53,33,53,35,53,3,113,202,201,201,253,6,2,61,202,253,195,2,250,201,4,245, + 224,224,164,254,130,253,45,2,208,173,212,164,255,255,0,119,0,0,5,4,7,79,16,39,22,193,5,218,1,116,18,6,8,51,0,0,0,1,0,33, + 0,0,4,174,5,213,0,16,0,0,1,51,21,35,21,33,21,1,35,1,33,17,35,53,51,53,51,1,180,201,201,2,250,253,195,202,2,61,253,6, + 201,201,202,4,245,164,212,173,253,48,2,211,1,126,164,224,255,255,0,33,0,0,4,174,7,79,16,39,22,193,3,86,1,116,18,6,8,53,0,0, + 0,1,0,10,2,155,2,232,5,223,0,16,0,0,19,51,21,51,21,35,21,33,21,1,35,1,33,53,35,53,51,137,144,127,127,1,207,254,165,145, + 1,109,254,32,127,127,5,223,117,110,102,121,254,126,1,141,212,110,0,0,0,2,0,201,255,227,4,193,5,213,0,11,0,27,0,44,64,10,3,25, + 17,22,27,9,28,25,4,28,16,252,236,50,50,220,236,49,0,64,12,6,149,22,12,14,0,149,20,140,26,145,25,47,236,244,238,212,57,57,236,48, + 37,50,54,53,52,38,35,34,6,21,20,22,3,54,55,50,4,21,20,4,35,34,39,21,34,35,17,51,2,197,122,173,200,95,128,178,204,204,128,178, + 235,1,17,254,221,217,183,123,79,123,202,131,164,151,168,148,169,147,164,151,2,205,73,1,240,236,250,225,72,43,5,213,255,255,0,201,0,0,5,176, + 5,213,18,6,0,39,0,0,0,2,0,115,0,0,5,90,5,213,0,8,0,17,0,31,64,9,0,28,10,50,4,25,14,16,18,16,252,236,244,236, + 49,0,182,0,149,9,129,7,149,11,47,236,244,236,48,1,35,32,0,17,16,0,33,51,19,17,33,32,0,17,16,0,33,4,144,244,254,203,254,225, + 1,31,1,53,244,202,254,97,254,80,254,104,1,150,1,178,5,47,254,233,254,212,254,210,254,232,5,47,250,43,1,106,1,130,1,128,1,105,0,0, + 0,1,0,137,2,156,3,78,5,223,0,9,0,0,19,33,21,1,33,21,33,53,1,33,151,2,169,253,249,2,21,253,59,2,8,254,6,5,223,86, + 253,129,110,86,2,127,0,0,0,3,0,137,1,236,3,78,6,143,0,19,0,22,0,25,0,0,1,21,35,53,33,53,1,17,33,53,33,53,51,21, + 33,21,1,17,33,21,1,21,55,3,53,7,2,36,105,254,206,1,50,254,220,1,36,105,1,28,254,228,1,42,254,214,109,214,130,2,156,176,176,86, + 1,120,1,7,110,176,176,86,254,162,254,223,110,2,213,134,134,253,153,160,160,0,0,0,0,1,0,117,0,0,3,33,2,115,0,11,0,0,1,3, + 1,35,39,7,35,1,3,51,23,55,3,20,255,1,12,137,205,205,137,1,18,251,137,187,187,2,115,254,207,254,190,246,246,1,72,1,43,223,223,0, + 255,255,0,137,0,0,7,151,5,242,16,39,7,23,3,89,0,0,16,6,7,240,0,0,255,255,0,137,0,0,9,177,5,242,16,38,8,39,0,0, + 16,7,7,53,5,115,0,0,255,255,0,137,0,0,12,201,5,242,16,38,8,40,0,0,16,7,7,55,8,8,0,0,255,255,0,137,0,0,12,201, + 7,79,16,38,8,40,0,0,16,7,7,56,8,8,0,0,255,255,0,137,255,227,10,55,5,228,16,38,8,40,0,0,16,7,7,57,5,249,0,0, + 255,255,0,137,255,227,10,55,7,79,16,38,8,40,0,0,16,7,7,58,5,249,0,0,255,255,0,137,255,227,12,201,5,228,16,38,8,40,0,0, + 16,7,7,60,8,8,0,0,255,255,0,137,255,227,12,201,7,79,16,38,8,40,0,0,16,7,7,61,8,8,0,0,0,1,255,236,1,247,3,229, + 2,159,0,3,0,0,3,33,21,33,20,3,249,252,7,2,159,168,0,0,0,1,255,236,255,1,4,5,2,159,0,7,0,0,3,33,21,33,17,35, + 17,33,20,4,25,254,89,202,254,88,2,159,168,253,10,2,246,0,0,0,0,1,255,236,255,1,5,198,2,159,0,11,0,0,3,33,21,33,17,35, + 17,35,17,35,17,33,20,5,218,254,89,202,247,202,254,88,2,159,168,253,10,2,246,253,10,2,246,0,0,1,255,236,255,1,7,135,2,159,0,15, + 0,0,3,33,21,33,17,35,17,35,17,35,17,35,17,35,17,33,20,7,155,254,89,202,247,202,247,202,254,88,2,159,168,253,10,2,246,253,10,2, + 246,253,10,2,246,0,0,0,0,1,255,236,255,1,9,72,2,159,0,19,0,0,3,33,21,33,17,35,17,35,17,35,17,35,17,35,17,35,17,35, + 17,33,20,9,92,254,89,202,247,202,247,202,247,202,254,88,2,159,168,253,10,2,246,253,10,2,246,253,10,2,246,253,10,2,246,0,0,1,255,236, + 255,1,11,9,2,159,0,23,0,0,3,33,21,33,17,35,17,35,17,35,17,35,17,35,17,35,17,35,17,35,17,35,17,33,20,11,29,254,89,202, + 247,202,247,202,247,202,247,202,254,88,2,159,168,253,10,2,246,253,10,2,246,253,10,2,246,253,10,2,246,253,10,2,246,0,0,0,0,1,255,236, + 1,247,4,5,5,148,0,7,0,0,3,33,17,51,17,33,21,33,20,1,168,202,1,167,251,231,2,159,2,245,253,11,168,0,0,0,0,1,255,236, + 1,247,5,198,5,148,0,11,0,0,3,33,17,51,17,51,17,51,17,33,21,33,20,1,168,202,247,202,1,167,250,38,2,159,2,245,253,11,2,245, + 253,11,168,0,0,1,255,236,1,247,7,135,5,148,0,15,0,0,3,33,17,51,17,51,17,51,17,51,17,51,17,33,21,33,20,1,168,202,247,202, + 247,202,1,167,248,101,2,159,2,245,253,11,2,245,253,11,2,245,253,11,168,0,0,0,0,1,255,236,1,247,9,71,5,148,0,19,0,0,3,33, + 17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,33,21,33,20,1,168,202,247,202,247,202,247,202,1,166,246,165,2,159,2,245,253,11,2,245, + 253,11,2,245,253,11,2,245,253,11,168,0,0,1,255,236,1,247,11,9,5,148,0,23,0,0,3,33,17,51,17,51,17,51,17,51,17,51,17,51, + 17,51,17,51,17,51,17,33,21,33,20,1,168,202,247,202,247,202,247,202,247,202,1,167,244,227,2,159,2,245,253,11,2,245,253,11,2,245,253,11, + 2,245,253,11,2,245,253,11,168,0,0,0,0,1,255,236,255,1,4,16,5,148,0,11,0,0,3,33,19,51,3,33,21,33,3,35,19,33,20,1, + 194,234,213,234,1,141,254,63,234,213,234,254,114,2,159,2,245,253,11,168,253,10,2,246,0,1,255,236,255,1,5,211,5,148,0,19,0,0,3,33, + 19,51,3,51,19,51,3,33,21,33,3,35,19,35,3,35,19,33,20,1,194,234,213,234,238,234,213,234,1,141,254,63,234,213,234,238,234,213,234,254, + 114,2,159,2,245,253,11,2,245,253,11,168,253,10,2,246,253,10,2,246,0,1,255,236,255,1,7,150,5,148,0,27,0,0,3,33,19,51,3,51, + 19,51,3,51,19,51,3,33,21,33,3,35,19,35,3,35,19,35,3,35,19,33,20,1,194,234,213,234,238,234,213,234,238,234,213,234,1,141,254,63, + 234,213,234,238,234,213,234,238,234,213,234,254,114,2,159,2,245,253,11,2,245,253,11,2,245,253,11,168,253,10,2,246,253,10,2,246,253,10,2,246, + 0,1,255,236,255,1,9,89,5,148,0,35,0,0,3,33,19,51,3,51,19,51,3,51,19,51,3,51,19,51,3,33,21,33,3,35,19,35,3,35, + 19,35,3,35,19,35,3,35,19,33,20,1,194,234,213,234,238,234,213,234,238,234,213,234,238,234,213,234,1,141,254,63,234,213,234,238,234,213,234,238, + 234,213,234,238,234,213,234,254,114,2,159,2,245,253,11,2,245,253,11,2,245,253,11,2,245,253,11,168,253,10,2,246,253,10,2,246,253,10,2,246, + 253,10,2,246,0,1,255,236,255,1,11,28,5,148,0,43,0,0,3,33,19,51,3,51,19,51,3,51,19,51,3,51,19,51,3,51,19,51,3,33, + 21,33,3,35,19,35,3,35,19,35,3,35,19,35,3,35,19,35,3,35,19,33,20,1,194,234,213,234,238,234,213,234,238,234,213,234,238,234,213,234, + 238,234,213,234,1,141,254,63,234,213,234,238,234,213,234,238,234,213,234,238,234,213,234,238,234,213,234,254,114,2,159,2,245,253,11,2,245,253,11,2, + 245,253,11,2,245,253,11,2,245,253,11,168,253,10,2,246,253,10,2,246,253,10,2,246,253,10,2,246,253,10,2,246,0,1,255,236,0,83,4,5, + 4,67,0,11,0,0,3,33,17,51,17,33,21,33,17,35,17,33,20,1,168,202,1,167,254,89,202,254,88,2,159,1,164,254,92,168,254,92,1,164, + 0,1,255,236,0,83,5,198,4,67,0,19,0,0,3,33,17,51,17,51,17,51,17,33,21,33,17,35,17,35,17,35,17,33,20,1,168,202,246,202, + 1,168,254,88,202,246,202,254,88,2,159,1,164,254,92,1,164,254,92,168,254,92,1,164,254,92,1,164,0,1,255,236,0,83,7,132,4,67,0,27, + 0,0,3,33,17,51,17,51,17,51,17,51,17,51,17,33,21,33,17,35,17,35,17,35,17,35,17,35,17,33,20,1,168,202,246,202,248,202,1,164, + 254,92,202,248,202,246,202,254,88,2,159,1,164,254,92,1,164,254,92,1,164,254,92,168,254,92,1,164,254,92,1,164,254,92,1,164,0,1,255,236, + 0,83,9,70,4,67,0,35,0,0,3,33,17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,33,21,33,17,35,17,35,17,35,17,35,17,35, + 17,35,17,35,17,33,20,1,168,202,246,202,248,202,246,202,1,166,254,90,202,246,202,248,202,246,202,254,88,2,159,1,164,254,92,1,164,254,92,1, + 164,254,92,1,164,254,92,168,254,92,1,164,254,92,1,164,254,92,1,164,254,92,1,164,0,1,255,236,0,83,11,9,4,67,0,43,0,0,3,33, + 17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,33,21,33,17,35,17,35,17,35,17,35,17,35,17,35,17,35,17,35,17,35, + 17,33,20,1,168,202,246,202,248,202,246,202,248,202,1,167,254,89,202,248,202,246,202,248,202,246,202,254,88,2,159,1,164,254,92,1,164,254,92,1, + 164,254,92,1,164,254,92,1,164,254,92,168,254,92,1,164,254,92,1,164,254,92,1,164,254,92,1,164,254,92,1,164,0,1,255,236,255,1,4,16, + 5,148,0,17,0,0,3,33,3,51,27,1,51,3,33,21,33,19,35,11,1,35,19,33,20,1,141,234,213,154,154,213,234,1,141,254,114,234,213,153, + 153,213,234,254,114,2,159,2,245,254,14,1,242,253,11,168,253,10,1,239,254,17,2,246,0,3,255,236,255,1,6,25,5,148,0,2,0,14,0,17, + 0,0,1,27,1,37,33,1,51,1,33,21,33,1,35,1,33,1,3,33,2,50,208,209,252,25,1,94,1,68,233,1,68,1,94,254,163,254,187,233, + 254,187,254,163,3,22,207,1,159,1,247,254,26,1,230,168,2,245,253,11,168,253,10,2,246,2,141,254,27,0,0,0,0,1,255,236,255,87,6,99, + 2,159,0,13,0,0,3,33,21,33,17,33,53,33,53,33,17,33,17,33,20,6,119,251,251,1,249,254,209,1,249,252,115,254,88,2,159,168,254,8, + 168,168,254,8,2,160,0,0,0,5,255,236,254,21,9,183,2,159,0,20,0,24,0,27,0,31,0,35,0,0,3,53,33,21,33,9,1,33,1,7, + 5,33,39,7,33,37,39,1,33,9,1,33,1,55,37,33,23,55,1,23,55,39,55,23,1,33,20,9,203,254,186,253,244,2,12,254,250,254,119,131, + 1,6,254,250,131,131,254,250,1,6,131,254,119,254,250,2,12,253,244,1,6,1,137,131,254,250,1,6,131,131,254,250,131,131,131,131,131,1,137,254, + 250,1,247,168,168,254,15,254,15,1,117,124,249,124,124,249,124,254,139,1,241,1,241,254,139,124,249,124,124,254,15,124,124,124,124,124,1,117,0,0, + 0,10,255,236,1,247,9,71,7,55,0,43,0,47,0,51,0,55,0,59,0,63,0,67,0,71,0,75,0,79,0,0,3,33,53,35,53,51,53,35, + 53,51,53,35,53,51,53,51,21,51,53,51,21,51,53,51,21,51,53,51,21,51,21,35,21,51,21,35,21,51,21,35,21,33,21,33,1,35,21,51, + 37,35,21,51,37,35,21,51,5,35,21,51,37,35,21,51,37,35,21,51,5,35,21,51,37,35,21,51,37,35,21,51,20,1,168,202,202,202,202,202, + 202,202,247,202,247,202,247,202,202,202,202,202,202,202,1,166,246,165,6,235,247,247,254,63,247,247,254,63,247,247,3,130,247,247,254,63,247,247,254,63, + 247,247,3,130,247,247,254,63,247,247,254,63,247,247,2,159,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,3,240,168, + 168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,0,2,255,236,0,167,5,139,2,159,0,3,0,7,0,0,19,33,21,33,3,33,21,33, + 182,3,248,252,8,202,5,159,250,97,1,79,168,1,248,168,0,1,0,113,0,58,4,35,4,91,0,8,0,0,1,21,33,1,39,9,1,55,1,4, + 35,254,125,254,67,114,1,159,254,97,114,1,188,2,159,168,254,67,114,1,159,1,158,114,254,68,0,0,0,1,255,236,0,58,3,158,4,91,0,8, + 0,0,3,33,1,23,9,1,7,1,33,20,1,132,1,188,114,254,97,1,159,114,254,67,254,125,2,159,1,188,114,254,98,254,97,114,1,189,0,0, + 0,2,0,61,0,0,4,127,4,96,0,7,0,10,0,0,33,35,3,33,3,35,1,51,1,33,3,4,127,195,102,254,16,102,195,1,164,250,254,195, + 1,128,192,1,19,254,237,4,96,253,71,2,5,0,0,0,0,2,0,11,0,0,5,91,4,96,0,15,0,19,0,0,51,1,33,21,33,17,33,21, + 33,17,33,21,33,17,33,3,1,3,33,17,11,1,217,3,106,253,246,1,243,254,13,2,23,253,47,254,190,116,1,154,232,1,4,4,96,148,254,211, + 148,254,136,147,1,19,254,237,3,205,253,218,2,38,0,0,0,3,0,123,255,227,7,111,4,123,0,52,0,61,0,74,0,0,37,14,1,35,34,39, + 38,61,1,33,46,1,35,34,7,6,7,53,62,1,51,50,23,22,23,62,1,51,50,23,22,21,20,7,6,35,33,21,20,23,22,51,50,54,55,21, + 6,7,6,35,34,39,38,1,22,23,22,51,50,55,54,55,37,50,54,53,52,39,38,35,34,7,6,29,1,4,7,74,212,132,226,132,132,3,78,12, + 204,183,104,100,100,100,100,208,106,167,124,124,77,73,216,143,189,105,105,127,126,251,254,254,83,84,151,96,182,84,101,95,95,90,142,106,107,252,247,1, + 83,82,137,153,92,93,14,1,105,223,172,65,64,111,153,92,93,155,90,94,145,146,250,90,191,200,27,26,53,174,42,44,61,60,119,120,120,93,94,168, + 189,96,96,18,127,70,69,46,46,170,39,20,19,48,48,1,135,151,90,90,87,87,158,96,102,123,98,58,57,109,108,180,41,0,0,0,0,3,0,62, + 0,0,4,62,4,96,0,10,0,17,0,35,0,0,37,32,53,52,41,1,21,51,21,35,21,1,52,43,1,17,51,50,55,20,7,30,1,21,20,6, + 35,33,53,35,53,51,17,33,50,22,2,120,1,2,254,254,254,250,220,220,1,222,236,242,242,236,185,214,127,140,231,214,254,57,124,124,1,182,197,212, + 153,181,180,102,164,95,2,157,145,254,218,170,208,31,24,152,114,150,164,248,164,2,196,144,255,255,0,113,255,227,3,231,4,123,16,6,0,70,0,0, + 0,2,0,186,0,0,4,103,4,96,0,8,0,17,0,0,1,17,51,50,54,53,52,38,35,37,33,32,0,17,16,0,41,1,1,115,141,217,203,203, + 217,254,186,1,55,1,70,1,48,254,206,254,188,254,201,3,205,252,199,199,214,213,199,147,254,241,254,224,254,223,254,240,0,2,0,36,0,0,4,103, + 4,96,0,12,0,25,0,0,19,33,32,0,17,16,0,41,1,17,35,53,51,33,21,35,17,51,50,54,53,52,38,43,1,17,186,1,55,1,70,1, + 48,254,206,254,188,254,201,150,150,1,122,193,141,217,203,203,217,141,4,96,254,241,254,224,254,223,254,240,1,245,164,164,254,159,199,214,213,199,254,204, + 0,1,0,186,0,0,3,139,4,96,0,11,0,0,19,33,21,33,17,33,21,33,17,33,21,33,186,2,196,253,246,1,243,254,13,2,23,253,47,4, + 96,148,254,211,148,254,136,147,0,1,0,130,255,227,3,197,4,124,0,49,0,0,1,22,23,22,21,20,7,6,35,34,38,39,53,22,23,22,51,50, + 55,54,53,52,39,38,43,1,53,51,50,55,54,53,52,39,38,35,34,7,6,7,53,54,55,54,51,50,4,21,20,6,2,191,112,60,60,114,113,196, + 76,170,98,97,80,81,71,119,69,70,68,67,116,155,148,137,72,78,84,85,151,93,85,85,71,90,84,85,80,238,1,2,138,2,3,24,65,64,93,141, + 79,78,24,24,167,29,13,13,46,46,64,70,45,44,152,51,56,88,90,56,56,18,19,37,171,28,14,14,182,173,108,146,0,2,0,193,254,76,1,121, + 4,96,0,3,0,7,0,0,19,51,17,35,17,53,51,21,193,184,184,184,4,96,251,160,254,76,233,233,0,1,0,0,255,227,2,123,4,96,0,16, + 0,0,61,1,30,1,51,50,55,54,53,17,51,17,16,6,35,34,38,68,146,78,103,46,43,151,158,186,71,143,61,185,60,61,77,70,215,2,121,253, + 135,254,230,234,44,0,0,0,255,255,0,186,0,0,4,156,4,96,16,6,0,250,0,0,0,1,0,2,0,0,3,252,4,123,0,13,0,0,19,51, + 17,55,23,7,17,33,21,33,17,7,39,55,186,185,137,76,213,2,137,252,190,110,74,184,4,123,254,100,97,106,151,254,107,170,1,188,78,106,131,0, + 255,255,0,186,0,0,5,79,4,96,16,6,3,208,0,0,255,255,0,186,0,0,4,121,4,96,16,6,3,204,0,0,255,255,0,113,255,227,4,117, + 4,123,16,6,0,82,0,0,255,255,0,127,255,227,3,245,4,123,16,6,2,22,0,0,0,2,0,113,0,45,5,9,4,49,0,10,0,22,0,0, + 1,52,38,32,6,21,20,22,51,50,54,55,20,0,33,32,0,53,52,0,33,32,0,4,109,231,254,110,231,232,200,199,233,156,254,200,254,236,254,237, + 254,199,1,57,1,19,1,20,1,56,2,47,148,172,171,149,147,172,172,147,240,254,238,1,18,240,241,1,17,254,239,0,0,1,0,113,0,116,5,9, + 3,234,0,24,0,0,37,35,62,1,53,52,38,32,6,21,20,22,23,35,46,1,53,52,0,33,32,0,17,20,6,4,195,172,43,43,227,254,102,227, + 43,43,170,36,36,1,62,1,14,1,18,1,58,35,116,78,157,80,179,198,198,179,80,157,78,77,165,93,253,1,42,254,211,254,250,85,162,0,0,0, + 0,3,0,51,0,5,5,77,4,89,0,9,0,19,0,43,0,0,9,1,14,1,21,20,22,51,50,54,55,62,1,53,52,38,35,34,6,7,39,62, + 1,51,32,0,21,20,6,7,23,7,39,14,1,35,32,0,53,52,54,55,39,55,3,178,253,176,42,40,232,200,79,117,154,41,41,235,211,72,110,46, + 151,77,197,119,1,20,1,56,51,52,168,79,179,77,198,120,254,237,254,199,52,51,168,78,1,24,1,231,41,103,65,147,172,20,92,42,103,62,151,169, + 19,20,125,54,54,254,239,241,93,159,67,139,95,146,53,54,1,18,240,96,161,63,139,96,0,3,0,113,255,227,7,195,4,123,0,38,0,47,0,61, + 0,0,19,53,33,38,39,38,35,34,6,7,53,62,1,51,50,22,23,54,55,54,51,50,23,22,17,16,7,6,35,34,39,38,39,14,1,35,34,39, + 38,55,22,23,22,51,50,55,54,55,1,50,55,54,16,39,38,35,34,6,21,20,23,22,113,3,78,12,102,102,183,106,200,98,100,208,106,160,242,81, + 71,104,105,140,241,136,137,137,136,241,140,105,106,66,78,232,143,226,132,132,185,2,82,82,137,153,92,93,14,2,8,148,86,86,85,86,149,147,172,86, + 86,2,0,90,190,100,99,52,52,174,42,44,110,109,110,54,55,157,156,254,237,254,236,156,156,55,56,108,107,112,145,146,196,152,90,89,87,87,158,254, + 180,115,116,1,146,116,115,232,200,199,116,117,0,1,0,113,2,47,4,117,4,123,0,13,0,0,1,52,38,35,34,6,21,35,16,0,51,50,0,17, + 3,178,172,147,148,172,194,1,17,241,240,1,18,2,47,199,233,231,201,1,20,1,56,254,200,254,236,0,0,1,0,113,255,227,4,117,2,47,0,13, + 0,0,1,20,22,51,50,54,53,51,16,0,35,34,0,17,1,52,172,147,148,172,194,254,239,241,240,254,238,2,47,199,233,231,201,254,236,254,200,1, + 56,1,20,0,0,2,0,151,0,0,3,204,4,96,0,7,0,17,0,0,1,17,33,50,54,52,38,35,37,33,50,22,16,6,35,33,17,35,1,78, + 1,1,91,99,99,91,254,72,1,184,188,193,193,188,254,255,183,3,197,254,152,94,172,94,155,170,254,182,170,254,62,0,0,2,0,50,0,0,4,15, + 4,96,0,22,0,33,0,0,1,46,1,53,52,55,54,51,33,17,35,17,35,34,7,6,7,3,35,19,54,55,54,1,35,34,7,6,21,20,23,22, + 59,1,1,181,106,112,107,108,217,1,132,185,169,97,59,59,63,162,195,174,53,52,53,1,216,198,119,63,64,64,63,119,198,2,13,27,140,105,162,81, + 80,251,160,1,217,37,36,113,254,225,1,50,94,54,54,1,201,42,42,84,83,43,43,0,0,2,0,50,0,0,4,15,4,96,0,22,0,33,0,0, + 1,38,39,38,39,3,51,19,22,23,22,59,1,17,51,17,33,34,39,38,53,52,54,1,17,35,34,7,6,21,20,23,22,51,1,181,55,53,52,53, + 174,195,162,63,59,59,97,169,185,254,124,217,108,107,112,2,11,198,119,63,64,64,63,119,2,83,17,54,54,94,1,50,254,225,113,36,37,1,217,251, + 160,80,81,162,105,140,254,99,1,81,43,43,83,84,42,42,255,255,0,60,0,0,4,109,4,96,16,6,3,214,0,0,0,1,0,186,255,224,4,20, + 4,96,0,15,0,0,36,32,54,53,17,51,17,20,6,32,38,53,17,51,17,20,1,230,1,2,115,185,217,254,88,217,185,125,142,162,2,179,253,59, + 219,224,224,219,2,197,253,77,162,0,0,0,0,1,0,174,0,76,5,43,3,246,0,19,0,0,37,33,53,33,50,54,53,52,38,35,33,53,33,21, + 35,30,1,21,20,6,3,84,253,90,2,159,159,159,190,164,253,133,4,96,172,102,99,240,76,184,124,124,150,172,184,184,66,178,116,194,200,0,0,0, + 0,3,0,174,0,78,6,219,3,248,0,3,0,7,0,27,0,0,19,53,51,21,3,53,51,21,5,33,53,33,50,54,53,52,38,35,33,53,33,21, + 35,30,1,21,20,6,174,202,202,202,3,140,253,90,2,159,159,159,190,164,253,133,4,96,172,102,99,240,2,120,204,204,254,122,202,202,164,184,124,124, + 148,174,184,184,68,176,118,192,200,0,0,0,0,1,0,47,254,24,4,170,4,123,0,38,0,0,1,30,1,21,20,7,6,35,33,53,33,50,54,53, + 52,38,35,33,53,33,50,55,54,53,52,39,38,35,33,53,33,21,35,30,1,21,20,7,6,3,184,124,118,122,123,226,253,92,2,158,161,156,190,164, + 253,135,2,158,162,77,78,96,95,163,253,135,4,96,174,103,98,62,62,1,12,69,192,130,175,95,95,185,114,117,143,166,185,57,57,119,141,83,83,185, + 185,63,176,121,122,86,85,0,255,255,0,61,0,0,4,127,4,96,16,6,0,89,0,0,255,255,0,86,0,0,6,53,4,96,16,6,0,90,0,0, + 255,255,0,88,0,0,3,219,4,96,16,6,0,93,0,0,0,1,0,120,255,227,3,186,4,96,0,23,0,0,55,22,51,50,54,52,38,43,1,53, + 1,37,53,33,21,1,50,30,1,21,20,6,32,39,138,161,211,128,132,123,110,127,1,10,253,212,3,0,254,246,70,151,111,228,254,125,201,189,66,100, + 187,100,144,1,62,1,147,147,254,194,74,159,109,160,182,55,0,1,0,179,0,0,3,252,4,123,0,5,0,0,51,17,33,21,33,17,179,3,73,253, + 129,4,123,170,252,47,0,0,255,255,0,61,0,0,4,127,4,96,16,6,2,78,0,0,0,1,0,151,0,0,3,236,4,96,0,7,0,0,1,17, + 35,17,33,17,35,17,3,236,182,254,23,182,4,96,251,160,3,183,252,73,4,96,0,0,255,255,0,151,0,0,3,204,4,96,16,6,8,122,0,0, + 0,1,0,90,0,0,4,94,4,96,0,27,0,0,1,51,17,54,55,54,53,17,51,17,16,7,6,7,21,35,53,38,39,38,25,1,51,17,20,23, + 22,23,2,0,184,85,57,86,194,136,109,177,184,175,109,138,196,86,57,83,4,96,253,49,26,77,115,201,1,44,254,212,254,236,156,125,25,238,238,25, + 125,156,1,20,1,44,254,212,199,117,77,26,255,255,0,76,0,0,4,115,4,96,16,6,3,207,0,0,0,2,0,10,2,156,3,104,5,224,0,2, + 0,10,0,0,1,3,33,3,51,1,35,39,33,7,35,1,185,173,1,90,245,144,1,103,132,86,254,88,86,134,5,113,254,96,2,15,252,188,214,214, + 0,2,0,5,2,156,4,150,5,224,0,15,0,19,0,0,1,21,33,21,33,21,33,17,33,21,33,53,33,7,35,1,23,3,33,17,4,138,254,46, + 1,191,254,65,1,222,253,162,254,179,101,129,1,138,87,208,1,34,5,224,95,248,95,254,209,95,214,214,3,68,88,254,73,1,183,0,0,3,0,127, + 2,156,3,26,5,224,0,10,0,21,0,38,0,0,19,17,51,50,55,54,53,52,39,38,35,3,21,51,50,55,54,53,52,39,38,35,37,33,50,23, + 22,21,20,7,6,7,30,1,21,20,6,35,33,254,204,103,49,50,50,49,103,204,188,94,45,46,46,45,94,254,197,1,69,145,79,79,41,40,78,94, + 104,172,158,254,175,4,43,254,206,38,38,77,79,37,37,1,88,252,31,31,64,63,32,31,93,54,53,100,76,46,45,11,18,114,85,112,122,0,0,0, + 0,2,0,127,2,156,3,149,5,224,0,10,0,21,0,0,19,17,51,50,55,54,53,52,39,38,35,37,33,32,23,22,21,20,7,6,41,1,254,154, + 194,91,90,90,91,194,254,231,1,5,1,18,127,128,128,129,254,240,254,251,5,131,253,118,78,79,169,168,78,78,93,101,101,215,216,102,101,0,0,0, + 0,1,0,127,2,156,2,221,5,224,0,11,0,0,19,33,21,33,21,33,21,33,17,33,21,33,127,2,82,254,45,1,192,254,64,1,223,253,162,5, + 224,95,248,95,254,209,95,0,0,1,0,83,2,156,2,177,5,224,0,11,0,0,1,17,33,53,33,17,33,53,33,53,33,53,2,177,253,162,1,222, + 254,64,1,192,254,45,5,224,252,188,95,1,47,95,248,95,0,1,0,72,2,140,3,126,5,239,0,36,0,0,1,53,35,53,33,17,6,7,6,35, + 34,39,38,53,52,55,54,51,50,23,22,23,21,38,39,38,35,34,7,6,21,20,23,22,51,50,54,3,0,208,1,78,74,89,88,101,221,124,125,125, + 124,221,92,83,82,70,70,80,79,87,173,87,86,86,87,173,67,106,3,19,225,93,254,153,47,23,24,114,115,204,205,115,114,20,20,39,121,53,27,27, + 85,86,170,169,86,85,20,0,0,1,0,127,2,156,3,76,5,224,0,11,0,0,19,51,17,33,17,51,17,35,17,33,17,35,127,127,1,206,128,128, + 254,50,127,5,224,254,169,1,87,252,188,1,142,254,114,0,0,1,0,127,2,156,0,254,5,224,0,3,0,0,19,51,17,35,127,127,127,5,224,252, + 188,0,0,0,0,1,255,189,1,182,0,254,5,224,0,12,0,0,19,51,17,20,7,6,43,1,53,51,50,54,53,127,127,65,64,143,49,40,84,70, + 5,224,252,246,151,68,69,96,84,108,0,0,0,1,0,127,2,156,3,105,5,224,0,10,0,0,19,51,17,1,51,9,1,35,1,17,35,127,127,1, + 166,164,254,45,1,244,167,254,60,127,5,224,254,159,1,97,254,122,254,66,1,147,254,109,0,1,0,127,2,156,2,200,5,224,0,5,0,0,19,51, + 17,33,21,33,127,127,1,202,253,183,5,224,253,27,95,0,0,1,0,127,2,156,3,219,5,224,0,12,0,0,19,51,27,1,51,17,35,17,3,35, + 3,17,35,127,189,240,242,189,124,242,128,243,123,5,224,253,199,2,57,252,188,2,222,253,195,2,61,253,34,0,0,0,0,1,0,127,2,156,3,71, + 5,224,0,9,0,0,19,51,1,17,51,17,35,1,17,35,127,171,1,161,124,172,254,95,123,5,224,253,69,2,187,252,188,2,187,253,69,0,0,0, + 0,1,0,127,2,156,3,71,5,224,0,9,0,0,1,17,35,17,1,35,17,51,17,1,3,71,124,254,95,171,123,1,161,5,224,252,188,2,187,253, + 69,3,68,253,69,2,187,0,0,2,0,72,2,140,3,175,5,239,0,15,0,27,0,0,1,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38, + 36,32,23,22,21,20,7,6,32,39,38,16,1,252,138,82,81,81,82,138,139,81,81,81,81,254,175,1,140,119,118,118,119,254,116,119,119,5,147,91, + 92,159,158,92,91,91,92,158,159,92,91,92,118,118,198,197,118,118,117,118,1,140,0,0,0,2,0,71,2,140,3,62,5,239,0,15,0,64,0,0, + 1,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38,3,6,7,6,21,20,23,22,51,50,55,54,53,52,39,38,39,53,50,23,22,21,20,7, + 6,7,22,23,22,21,20,7,6,35,34,38,53,52,55,54,55,38,39,38,53,52,55,54,51,1,194,115,67,68,68,67,115,116,68,67,67,66,154,82, + 54,53,60,37,128,106,60,61,48,69,82,144,94,88,54,53,96,108,60,61,99,97,184,183,196,61,61,108,108,42,54,82,73,162,4,41,43,43,76,75, + 44,43,43,44,75,76,43,43,1,53,2,35,35,44,38,41,25,36,37,76,89,24,43,4,56,58,54,105,71,50,50,18,19,55,56,80,121,65,65,130, + 121,80,56,55,19,18,39,50,49,73,46,42,0,2,0,127,2,156,2,222,5,224,0,9,0,21,0,0,19,17,51,50,55,54,52,39,38,35,37,33, + 50,23,22,20,7,6,43,1,17,35,254,160,89,48,49,49,48,89,254,225,1,31,158,81,81,81,81,158,160,127,5,131,254,198,41,41,150,41,41,93, + 63,64,246,64,63,254,176,0,0,2,0,127,2,156,3,91,5,224,0,23,0,32,0,0,1,22,23,22,31,1,35,39,38,39,38,43,1,17,35,17, + 33,50,23,22,21,20,7,6,1,17,51,50,54,53,52,38,35,2,61,41,38,39,39,129,136,121,46,44,44,76,138,127,1,31,161,80,79,41,42,254, + 115,160,92,94,94,92,4,36,12,41,40,71,228,214,84,28,27,254,159,3,68,60,60,121,79,52,52,1,75,254,215,76,73,74,74,0,0,1,255,252, + 2,156,3,24,5,224,0,7,0,0,3,33,21,33,17,35,17,33,4,3,28,254,178,128,254,178,5,224,95,253,27,2,229,0,0,0,0,1,0,112, + 2,140,3,64,5,224,0,19,0,0,19,51,17,20,22,51,50,55,54,53,17,51,17,20,7,6,32,39,38,53,112,128,110,122,123,55,54,128,91,91, + 254,156,91,91,5,224,254,4,134,118,59,59,134,1,252,253,246,163,84,83,83,84,163,0,0,1,0,43,2,156,4,210,5,224,0,12,0,0,19,51, + 27,1,51,27,1,51,3,35,11,1,35,43,128,198,197,143,198,197,130,237,160,198,201,160,5,224,253,61,2,195,253,61,2,195,252,188,2,214,253,42, + 0,2,0,77,2,140,2,161,5,30,0,12,0,43,0,0,1,34,7,6,21,20,22,51,50,55,54,61,1,55,17,35,53,6,7,6,35,34,38,53, + 52,54,59,1,53,52,38,35,34,7,6,7,53,54,55,54,51,50,23,22,1,186,140,54,55,82,70,96,58,59,115,115,40,59,60,85,109,128,160,158, + 163,106,95,60,58,57,53,64,60,59,57,153,76,75,3,215,28,29,69,55,64,61,61,100,23,43,254,154,95,57,27,27,108,91,105,108,10,71,78,13, + 13,26,96,21,11,11,70,71,0,2,0,77,2,140,2,161,5,30,0,12,0,45,0,0,1,50,55,54,53,52,38,35,34,7,6,29,1,7,17,51, + 21,54,55,54,51,50,23,22,21,20,7,6,43,1,21,20,22,51,50,55,54,55,21,6,7,6,35,34,39,38,1,53,140,54,55,82,70,96,58,59, + 116,116,40,59,60,85,109,64,63,80,79,158,163,106,95,60,58,57,53,64,60,60,56,153,76,76,3,211,28,29,69,55,64,61,60,101,23,43,1,102, + 95,57,27,27,54,54,90,106,54,54,10,71,78,13,13,26,96,21,12,10,70,71,0,0,0,2,0,71,2,140,2,190,5,30,0,19,0,31,0,0, + 1,53,51,17,35,53,6,7,6,35,34,39,38,16,55,54,51,50,23,22,4,20,23,22,50,55,54,52,39,38,34,7,2,74,116,116,37,55,56,78, + 128,81,80,80,81,128,78,56,55,254,154,52,53,184,53,53,53,53,184,53,4,176,95,253,141,94,56,27,27,90,91,1,40,91,90,27,27,161,228,65, + 64,64,65,228,65,64,64,0,0,3,0,77,2,140,4,175,5,30,0,51,0,60,0,74,0,0,1,14,1,35,34,39,38,61,1,33,38,39,38,35, + 34,6,7,53,54,55,54,51,50,23,22,23,54,55,54,51,50,22,21,20,7,6,43,1,21,20,23,22,51,50,54,55,21,14,1,35,34,38,37,22, + 23,22,51,50,55,54,63,1,50,55,54,53,52,39,38,35,34,7,6,29,1,2,138,47,134,83,142,83,84,2,21,7,64,65,115,65,126,63,63,65, + 66,66,106,78,78,48,46,68,68,91,119,132,80,79,159,162,52,53,95,61,114,53,63,120,57,89,134,254,22,1,52,52,86,96,59,58,9,227,141,54, + 54,41,40,70,97,58,58,2,243,51,52,81,82,140,50,107,56,56,30,29,97,24,12,12,34,33,67,67,34,33,104,94,106,54,54,10,71,39,39,26, + 26,96,21,22,54,218,84,50,51,49,49,88,54,28,29,69,55,32,32,61,60,101,23,0,0,2,0,117,2,140,2,236,6,3,0,11,0,29,0,0, + 0,52,39,38,34,7,6,20,23,22,50,55,1,62,1,51,50,23,22,16,7,6,35,34,38,39,21,35,17,51,2,116,52,53,184,53,52,52,53,184, + 53,254,170,36,112,77,129,80,80,80,80,129,77,112,36,117,117,3,99,228,64,65,65,64,228,64,65,65,1,141,56,54,90,91,254,216,91,90,54,56, + 94,3,103,0,0,2,0,71,2,140,2,190,6,3,0,19,0,31,0,0,1,17,51,17,35,53,6,7,6,35,34,39,38,16,55,54,51,50,23,22, + 4,20,23,22,50,55,54,52,39,38,34,7,2,74,116,116,37,55,56,78,128,80,81,81,80,128,78,56,55,254,154,52,53,184,53,53,53,53,184,53, + 4,176,1,83,252,153,94,56,27,27,90,91,1,40,91,90,27,27,161,228,64,65,65,64,228,64,65,65,0,2,0,71,2,140,2,213,5,30,0,26, + 0,35,0,0,1,21,33,22,23,22,51,50,55,54,55,21,6,7,6,35,34,39,38,53,52,55,54,51,50,23,22,7,38,39,38,35,34,7,6,7, + 2,213,253,235,8,64,65,115,67,63,62,62,62,66,65,68,169,98,99,94,93,159,142,83,83,116,1,52,52,86,97,58,58,9,3,239,50,106,56,56, + 15,14,29,97,24,12,12,87,87,149,154,91,90,81,82,109,84,51,50,49,48,88,0,0,0,2,0,71,2,140,2,213,5,30,0,20,0,27,0,77, + 75,176,12,83,88,64,7,2,27,15,9,21,0,28,16,212,204,196,212,204,50,75,176,21,83,75,176,24,81,90,75,176,17,84,91,88,189,0,2,255, + 192,0,15,255,192,0,27,255,192,56,56,56,89,49,0,64,9,3,9,21,2,5,12,24,18,28,16,212,204,47,204,212,204,212,204,48,89,19,53,33, + 46,1,35,34,6,7,53,62,1,51,50,22,21,20,6,35,34,38,55,30,1,51,50,54,55,71,2,21,7,130,115,67,125,62,63,131,67,169,197,187, + 159,142,166,116,1,104,86,97,117,8,3,187,50,107,111,29,29,97,24,24,174,149,154,181,163,109,84,101,98,88,0,0,0,1,0,84,2,140,2,98, + 5,31,0,50,0,0,19,38,39,38,53,52,55,54,51,50,23,22,23,21,46,1,35,34,7,6,21,20,23,22,59,1,21,35,34,7,6,21,20,23, + 22,51,50,55,54,55,21,6,7,6,35,34,38,53,52,55,54,249,71,38,37,72,71,123,48,54,53,62,61,102,44,75,44,44,43,42,73,98,93,87, + 45,49,53,53,95,59,54,53,45,57,53,53,51,150,162,43,44,3,238,14,36,36,52,79,44,44,7,7,13,94,17,14,25,26,36,39,25,25,85,29, + 31,49,51,31,32,11,10,21,96,16,7,8,102,97,60,41,41,0,0,0,0,1,0,82,2,140,2,96,5,31,0,49,0,0,1,30,1,21,20,7, + 6,35,34,39,38,39,53,22,23,22,51,50,54,53,52,39,38,43,1,53,51,50,55,54,53,52,39,38,35,34,7,6,7,53,62,1,51,50,23,22, + 21,20,7,6,1,187,70,76,72,71,123,48,54,53,62,61,50,51,45,75,88,43,42,73,98,93,86,46,49,53,54,95,58,54,53,45,57,106,50,150, + 82,81,44,43,3,188,13,72,52,79,45,43,6,7,14,93,16,7,8,52,36,39,25,25,85,28,32,49,50,32,31,10,11,20,96,15,16,51,51,97, + 60,41,41,0,0,2,0,71,1,173,2,190,5,30,0,13,0,49,0,0,0,52,39,38,35,34,7,6,20,23,22,51,50,55,23,20,7,6,35,34, + 39,38,39,53,22,23,22,51,50,55,54,61,1,6,7,6,35,34,39,38,16,55,54,51,50,23,22,23,53,51,2,74,52,52,94,93,52,52,52,52, + 93,94,52,168,80,80,165,61,55,54,51,51,50,50,51,114,57,57,36,56,56,78,130,79,80,80,79,130,78,56,56,36,116,3,109,224,61,62,62,61, + 224,61,62,62,70,160,78,79,9,8,16,101,25,12,11,52,53,107,51,55,28,27,88,88,1,34,88,88,27,28,55,95,0,2,0,122,1,168,0,238, + 5,15,0,3,0,7,0,0,19,51,17,35,21,53,51,21,122,116,116,116,5,15,253,141,244,130,130,0,0,1,0,117,2,156,2,231,6,3,0,10, + 0,0,19,51,17,1,51,9,1,35,1,17,35,117,117,1,90,148,254,137,1,134,151,254,154,117,6,3,253,254,1,14,254,219,254,178,1,50,254,206, + 0,1,0,117,2,156,4,123,5,30,0,34,0,52,64,10,36,27,28,20,0,3,14,10,11,35,16,212,220,60,47,204,57,47,220,204,49,178,127,36, + 1,93,0,64,10,32,6,12,23,17,35,28,2,11,35,16,212,60,60,16,212,60,196,204,50,48,1,17,35,17,52,38,35,34,6,21,17,35,17,51, + 21,62,1,51,50,22,23,62,1,51,50,22,21,17,35,17,52,38,35,34,6,2,178,116,72,75,89,104,117,117,39,111,77,76,108,26,43,121,82,111, + 119,116,72,74,90,105,3,254,254,158,1,119,91,87,107,92,254,158,2,115,97,57,55,69,66,69,66,137,126,254,133,1,119,90,88,107,0,1,0,117, + 1,173,2,196,5,30,0,30,0,52,64,7,7,0,12,23,19,20,31,16,212,220,60,47,204,204,75,176,13,81,88,177,32,64,56,89,49,178,127,32, + 1,93,0,64,8,15,21,27,31,7,6,20,31,16,212,212,204,16,212,196,204,48,1,17,20,7,6,43,1,53,51,50,54,53,17,52,38,35,34,6, + 21,17,35,17,51,21,54,55,54,51,50,23,22,2,196,52,51,114,160,147,66,48,78,78,94,108,117,117,41,56,57,74,121,63,62,4,23,254,122,120, + 54,54,88,54,86,1,130,89,89,107,92,254,158,2,115,97,56,28,28,66,68,0,0,0,0,2,0,71,2,140,2,207,5,30,0,11,0,23,0,54, + 64,5,9,15,3,21,24,16,212,204,212,204,75,176,21,83,75,176,24,81,90,75,176,17,84,91,88,187,0,15,255,192,0,9,255,192,56,56,89,49, + 0,64,5,0,12,6,18,24,16,212,204,47,204,48,1,34,6,21,20,22,51,50,54,53,52,38,39,50,22,21,20,6,35,34,38,53,52,54,1,139, + 93,109,108,94,93,108,108,93,151,173,173,151,152,172,172,4,199,129,113,113,129,130,112,111,131,87,174,155,154,175,175,154,155,174,0,0,0,1,0,71, + 2,140,2,117,5,30,0,32,0,0,19,54,55,54,51,50,23,22,21,20,7,6,35,34,39,38,39,53,22,23,22,51,50,55,54,52,39,38,35,34, + 7,6,7,71,48,51,51,54,165,94,95,93,94,160,58,53,51,49,49,50,49,51,112,63,62,62,63,112,51,49,50,49,4,247,20,10,9,88,88,153, + 151,89,89,10,10,20,95,24,12,12,63,64,230,64,63,12,12,24,0,0,0,1,0,71,3,213,2,207,5,30,0,16,0,0,1,52,39,38,34,7, + 6,21,35,52,54,51,50,23,22,21,48,2,84,54,54,186,54,55,122,172,152,151,87,86,3,213,111,66,65,65,64,113,155,174,87,87,155,0,0,0, + 0,1,0,71,2,140,2,207,3,213,0,16,0,0,19,20,23,22,50,55,54,53,51,20,6,35,34,39,38,53,48,194,54,54,186,54,55,122,172,152, + 151,86,87,3,213,111,66,65,65,64,113,155,174,87,87,155,0,2,0,117,1,173,2,236,5,30,0,17,0,29,0,0,19,17,35,17,51,21,62,1, + 51,50,23,22,16,7,6,35,34,38,36,52,39,38,34,7,6,20,23,22,50,55,234,117,117,36,112,77,129,80,80,80,80,129,77,112,1,102,52,53, + 184,53,52,52,53,184,53,2,250,254,179,3,98,95,56,54,90,91,254,216,91,90,54,161,228,64,65,65,64,228,64,65,65,0,0,0,0,1,0,35, + 2,156,1,219,5,193,0,20,0,0,19,21,51,21,35,17,20,22,59,1,21,35,34,39,38,53,17,35,53,51,53,236,239,239,48,72,119,119,134,51, + 51,85,85,5,193,178,80,254,172,77,44,86,45,44,118,1,84,80,178,0,0,1,0,110,2,140,2,189,5,15,0,22,0,0,19,17,51,17,20,23, + 22,51,50,55,54,53,17,51,17,35,53,6,7,6,35,34,38,110,116,39,39,78,94,54,55,116,116,43,55,56,74,121,126,3,148,1,123,254,136,89, + 44,45,54,53,92,1,99,253,141,96,57,28,27,134,0,0,0,1,0,110,2,199,3,65,4,212,0,22,0,0,1,33,53,33,50,55,54,53,52,39, + 38,35,33,53,33,21,35,30,1,21,20,7,6,2,25,254,85,1,166,101,50,50,60,60,103,254,112,2,193,108,64,62,75,76,2,199,103,35,34,70, + 83,49,48,103,103,37,100,65,108,56,56,0,0,1,0,117,2,141,4,123,5,16,0,40,0,0,1,6,7,6,35,34,38,53,17,51,17,20,23,22, + 51,50,55,54,53,17,51,17,20,23,22,51,50,55,54,53,17,51,17,35,53,6,7,6,35,34,38,2,81,43,60,61,82,110,120,117,36,36,73,90, + 53,52,116,36,36,75,89,52,53,116,116,40,55,56,76,77,108,3,21,69,33,34,138,127,1,122,254,137,91,43,44,54,52,92,1,99,254,137,91,43, + 44,54,54,90,1,99,253,141,98,59,27,28,70,0,0,0,0,1,0,38,2,156,2,213,5,15,0,6,0,0,19,51,27,1,51,1,35,38,123,221, + 220,123,254,248,158,5,15,253,242,2,14,253,141,0,0,0,0,2,0,121,1,173,2,219,6,11,0,14,0,28,0,0,19,17,35,17,16,33,32,23, + 22,7,22,23,18,33,38,39,22,51,50,53,52,5,53,22,53,52,35,34,21,237,116,1,12,1,17,1,1,110,176,1,1,254,207,133,57,70,125,181, + 254,219,230,148,165,2,195,254,234,3,94,1,0,216,153,56,51,149,254,246,1,184,97,176,158,12,95,4,183,123,175,0,0,1,0,20,1,173,2,213, + 5,15,0,14,0,0,27,2,51,1,21,35,53,3,38,43,1,53,51,50,227,155,220,123,254,227,116,185,28,60,31,44,124,4,173,254,124,1,230,253, + 141,239,239,1,212,71,88,0,0,2,0,71,2,140,2,207,5,239,0,27,0,43,0,0,1,38,35,34,21,20,23,22,23,22,21,20,7,6,32,39, + 38,53,52,55,54,55,38,53,52,33,50,23,1,6,7,6,20,23,22,51,50,54,53,52,39,38,39,38,2,121,65,150,160,167,130,74,90,86,87,254, + 210,86,87,87,33,47,98,1,22,139,76,254,204,43,34,55,54,54,94,93,108,57,61,80,40,5,114,40,66,52,26,21,63,75,156,148,87,88,88,87, + 154,114,93,36,20,44,79,152,39,254,248,17,40,64,228,63,65,130,106,112,54,57,6,4,0,2,0,71,1,173,3,9,5,20,0,10,0,41,0,0, + 1,34,21,17,50,55,54,53,52,39,38,39,50,23,22,21,20,7,6,35,21,35,53,34,39,38,53,52,55,54,55,21,6,7,6,21,20,23,22,51, + 17,52,2,10,41,61,59,54,55,45,33,88,81,86,86,81,129,115,126,83,86,86,64,104,41,37,54,54,49,70,4,188,81,254,127,58,53,125,116,63, + 51,88,74,79,165,152,90,85,226,225,85,88,154,160,82,61,16,92,12,44,65,106,113,64,58,1,129,169,0,1,0,37,1,173,2,196,5,16,0,23, + 0,0,1,39,3,35,1,3,38,43,1,53,23,22,31,1,19,51,1,19,22,59,1,21,39,38,1,205,94,193,137,1,18,115,31,97,31,44,163,40, + 94,193,137,254,239,114,31,97,31,44,163,2,16,215,254,198,1,188,1,7,71,88,1,4,93,215,1,58,254,68,254,248,70,89,2,4,255,255,0,122, + 0,0,0,238,3,103,18,7,11,74,0,0,253,100,0,0,255,255,0,117,0,0,2,18,2,130,18,7,2,117,0,0,253,100,0,0,255,255,0,110, + 255,240,2,189,2,115,18,7,8,183,0,0,253,100,0,0,255,255,0,38,0,0,2,213,2,115,18,7,8,186,0,0,253,100,0,0,255,255,0,121, + 255,17,2,219,3,111,18,7,8,187,0,0,253,100,0,0,255,255,0,20,255,17,2,213,2,115,18,7,8,188,0,0,253,100,0,0,0,2,0,121, + 255,17,2,239,2,130,0,16,0,28,0,0,19,54,55,54,51,50,22,16,6,35,34,38,39,17,35,17,52,5,52,38,35,34,6,21,20,22,51,50, + 54,178,38,95,37,115,128,160,160,128,78,111,37,116,1,254,105,92,91,106,106,91,92,105,2,3,57,50,20,181,254,216,182,55,56,254,179,2,34,129, + 123,113,130,130,113,114,129,129,255,255,0,71,255,17,3,9,2,120,18,7,8,190,0,0,253,100,0,0,255,255,0,37,255,17,2,196,2,116,18,7, + 8,191,0,0,253,100,0,0,0,2,0,186,254,86,4,163,4,123,0,28,0,40,0,0,19,16,18,33,50,22,23,21,46,1,35,34,6,29,1,62, + 1,51,50,18,17,16,2,35,34,38,39,21,35,19,20,22,51,50,54,53,52,38,35,34,6,186,254,1,6,97,172,81,81,158,82,181,180,57,178,124, + 206,252,252,206,124,178,57,184,184,165,149,148,165,165,148,149,165,2,70,1,30,1,23,29,30,179,44,42,189,191,91,99,98,254,198,254,253,254,252,254, + 198,98,99,170,2,35,200,220,220,200,199,220,220,0,0,0,255,255,0,127,2,156,3,76,5,224,16,6,8,147,0,0,0,1,0,116,0,0,2,132, + 4,96,0,19,0,0,19,53,33,21,35,17,51,21,35,17,51,21,33,53,51,17,35,53,51,17,116,2,16,168,168,168,168,253,240,176,176,176,3,188, + 164,164,254,172,164,254,224,164,164,1,32,164,1,84,0,0,0,3,0,50,254,86,5,36,4,123,0,25,0,34,0,43,0,0,37,17,35,17,35,53, + 51,17,51,21,62,1,51,50,23,22,23,51,21,35,6,7,6,35,34,38,1,33,22,23,22,51,50,55,54,1,33,38,39,38,35,34,7,6,1,115, + 185,136,136,185,58,177,123,203,128,102,21,133,129,11,116,128,203,123,177,2,55,253,144,8,74,84,146,146,84,74,253,157,2,102,15,62,84,146,146,84, + 62,168,253,174,3,174,144,1,204,170,100,97,162,130,195,144,234,149,162,97,1,192,174,102,116,116,102,1,62,132,86,116,116,86,0,0,0,1,0,145, + 254,86,2,47,6,20,0,16,0,0,37,21,20,6,43,1,53,51,50,55,54,39,55,35,17,51,17,2,47,164,180,70,48,106,38,42,4,2,184,184, + 154,174,214,192,156,48,54,148,20,6,20,250,134,0,0,0,0,2,0,71,2,140,2,190,5,30,0,19,0,31,0,0,19,21,35,17,51,21,54,55, + 54,51,50,23,22,16,7,6,35,34,39,38,36,52,39,38,34,7,6,20,23,22,50,55,187,116,116,37,56,55,78,128,80,81,81,80,128,78,55,56, + 1,102,53,52,184,53,53,53,53,184,52,2,250,95,2,115,94,56,27,27,90,91,254,216,91,90,27,27,161,228,65,64,64,65,228,65,64,64,0,0, + 0,1,0,71,2,140,2,117,5,30,0,29,0,0,1,21,38,39,38,35,34,7,6,20,23,22,51,50,55,54,55,21,14,1,35,34,38,53,52,54, + 51,50,23,22,2,117,49,49,50,50,113,62,63,63,62,113,50,50,49,49,48,104,59,159,188,190,165,53,51,51,4,247,96,24,12,12,64,63,230,63, + 64,12,12,24,95,20,20,178,151,153,176,9,10,0,0,0,0,2,0,71,2,75,2,117,5,30,0,7,0,43,0,0,1,22,51,50,53,38,35,34, + 7,6,21,7,52,55,38,39,38,53,52,54,51,50,23,22,23,21,38,39,38,35,34,7,6,20,23,22,23,54,51,50,23,22,35,34,1,90,37,48, + 92,1,82,64,53,4,96,8,36,30,94,190,165,52,52,49,50,47,52,49,50,113,62,63,63,2,6,53,123,188,1,1,210,51,2,238,11,32,42,154, + 32,38,2,59,47,19,29,90,150,153,176,9,10,20,96,23,13,12,63,64,230,64,2,5,98,138,105,0,0,2,0,71,2,140,2,207,6,3,0,17, + 0,46,0,0,1,38,39,38,35,34,7,6,21,20,22,51,50,54,53,52,39,38,55,22,23,22,21,20,7,6,35,34,38,53,52,54,51,50,23,22, + 23,39,7,39,55,39,51,23,55,23,7,2,16,32,27,28,26,105,58,59,110,92,91,110,17,17,6,79,36,36,90,89,145,146,178,174,139,12,16,16, + 27,100,201,21,177,114,144,80,209,21,186,4,156,10,4,5,61,60,109,106,124,124,106,68,53,52,165,80,81,80,97,143,87,87,174,143,140,174,2,1, + 3,101,60,56,51,114,81,62,54,55,0,0,0,1,0,84,2,140,2,98,5,31,0,49,0,0,1,22,23,22,21,20,7,6,35,34,39,38,39,53, + 22,23,22,51,50,55,54,53,52,39,38,43,1,53,51,50,54,53,52,39,38,35,34,7,6,7,53,62,1,51,50,23,22,21,20,6,1,189,78,43, + 44,81,82,150,50,54,53,56,45,53,54,58,95,54,53,49,46,86,93,97,73,86,45,43,75,45,51,50,61,61,108,47,124,71,72,76,3,238,13,41, + 41,60,97,51,51,8,7,16,96,21,10,11,32,31,51,49,31,29,85,50,39,36,26,25,7,7,17,94,13,14,44,44,79,52,72,0,0,1,0,30, + 2,156,1,223,6,3,0,21,0,0,1,21,35,34,7,6,29,1,51,21,35,17,35,17,35,53,51,53,52,55,54,51,1,223,111,62,25,24,191,191, + 117,110,110,55,55,119,6,3,85,23,22,58,56,80,253,221,2,35,80,44,105,47,48,0,0,1,255,233,1,173,1,92,5,15,0,21,0,0,19,21, + 20,7,6,43,1,53,51,50,55,54,61,1,35,53,51,17,51,17,51,21,238,52,51,114,44,31,66,24,24,114,114,116,110,2,156,11,120,54,54,88, + 27,28,85,11,80,2,35,253,221,80,0,0,0,2,0,71,1,173,2,190,5,15,0,12,0,44,0,0,1,53,35,34,7,6,20,23,22,51,50,55, + 54,19,17,20,7,6,35,34,39,38,39,53,22,23,22,51,50,55,54,61,1,6,7,6,35,34,39,38,53,52,55,54,51,2,74,198,93,52,52,52, + 52,93,94,52,52,116,80,80,165,61,55,54,51,51,50,50,51,114,57,57,36,56,56,78,130,79,80,80,79,130,3,221,235,62,61,224,61,62,62,61, + 1,162,253,219,160,78,79,8,9,16,101,25,12,11,52,53,107,51,55,28,27,88,88,145,130,88,88,0,0,1,0,110,1,173,2,189,5,15,0,22, + 0,0,19,17,51,17,20,23,22,51,50,55,54,53,17,51,17,35,17,6,7,6,35,34,38,110,116,39,39,78,94,54,55,116,116,43,56,55,74,121, + 126,3,148,1,123,254,136,89,44,45,54,53,92,1,99,252,158,1,79,57,28,27,134,0,0,2,0,73,2,156,1,150,6,3,0,11,0,15,0,0, + 19,53,51,17,51,17,51,21,35,21,35,53,17,51,21,35,73,114,116,103,103,116,116,116,3,153,92,1,26,254,230,92,253,253,2,106,130,0,0,0, + 0,1,0,122,2,156,1,126,5,15,0,12,0,0,19,17,20,23,22,59,1,21,35,34,38,53,17,238,23,24,67,30,44,114,102,5,15,254,112,85, + 28,27,87,108,119,1,144,0,0,1,0,73,2,156,1,150,5,15,0,11,0,0,19,53,33,21,35,17,51,21,33,53,51,17,73,1,77,106,106,254, + 179,111,4,179,92,92,254,69,92,92,1,187,0,1,0,73,2,156,1,150,5,15,0,19,0,0,19,53,33,21,35,21,51,21,35,21,51,21,33,53, + 51,53,35,53,51,53,73,1,77,106,106,106,106,254,179,111,111,111,4,179,92,92,190,92,161,92,92,161,92,190,0,0,0,3,255,86,1,173,1,96, + 6,3,0,3,0,18,0,27,0,0,19,51,21,35,3,34,53,52,59,1,17,51,17,51,21,35,6,7,6,39,35,34,23,22,51,50,55,54,122,116, + 116,101,191,170,122,116,114,121,11,34,51,20,114,75,2,2,78,66,24,11,6,3,130,252,44,124,115,2,115,253,141,87,63,35,53,152,29,36,27,13, + 0,1,0,122,1,173,1,126,6,3,0,14,0,0,19,17,51,17,21,20,23,22,59,1,21,35,34,38,53,122,116,23,24,67,30,44,114,102,2,228, + 3,31,252,225,83,86,27,27,88,108,120,0,0,1,0,91,1,173,1,96,6,3,0,17,0,0,1,21,20,7,6,43,1,53,51,50,55,54,39,55, + 35,17,51,17,1,96,51,52,114,44,31,66,24,27,3,2,116,116,2,242,97,120,54,54,88,27,30,83,11,3,103,252,239,0,0,0,0,1,0,113, + 2,156,2,131,5,30,0,5,0,0,19,51,17,33,21,33,113,127,1,147,253,238,5,30,253,221,95,0,0,1,0,117,1,173,4,123,5,30,0,52, + 0,0,1,54,55,54,51,50,23,22,21,17,20,6,43,1,53,51,50,54,53,38,55,52,53,52,38,35,34,7,6,21,17,35,17,52,39,38,35,34, + 7,6,21,17,35,17,51,21,54,55,54,51,50,23,22,2,159,43,61,60,82,111,59,60,102,114,161,147,66,48,1,1,72,74,90,52,53,116,36,36, + 75,89,52,52,117,117,39,56,55,77,76,54,54,4,151,69,33,33,69,68,126,254,122,120,108,88,54,86,48,232,61,45,90,88,53,54,92,254,158,1, + 119,91,44,43,53,54,92,254,158,2,115,97,57,28,27,34,35,0,0,0,0,1,0,117,1,173,4,123,5,16,0,40,0,0,1,6,7,6,35,34, + 38,53,17,51,17,20,23,22,51,50,55,54,53,17,51,17,20,23,22,51,50,55,54,53,17,51,17,35,17,6,7,6,35,34,38,2,81,43,60,61, + 82,110,120,117,36,36,73,90,53,52,116,36,36,75,89,52,53,116,116,40,55,56,76,77,108,3,21,69,34,33,138,126,1,123,254,137,91,43,44,53, + 53,92,1,99,254,137,91,43,44,54,53,91,1,99,252,157,1,81,58,27,28,70,0,0,0,1,255,233,1,173,2,201,5,30,0,31,0,0,19,20, + 7,6,43,1,53,51,50,54,53,17,51,21,62,1,51,50,23,22,21,17,35,17,52,39,38,35,34,7,6,21,238,52,51,114,44,31,66,48,116,42, + 112,74,122,62,63,116,39,40,78,94,54,54,2,145,120,54,54,88,54,86,2,126,97,56,56,66,68,129,254,133,1,119,89,44,45,53,54,92,0,0, + 0,1,0,117,1,173,3,85,5,30,0,32,0,0,1,52,39,38,35,34,7,6,21,17,35,17,51,21,54,55,54,51,50,23,22,21,17,20,22,59, + 1,21,35,34,39,38,53,2,80,39,39,78,94,54,54,117,117,41,56,57,74,121,63,62,48,66,31,44,114,51,52,4,19,89,44,45,53,54,92,254, + 158,2,115,97,56,28,28,66,68,129,254,122,86,54,88,54,54,120,0,0,0,1,0,113,2,156,2,196,5,30,0,9,0,0,19,51,1,17,51,17, + 35,1,17,35,113,171,1,45,123,171,254,211,123,5,30,254,7,1,249,253,126,1,250,254,6,0,0,0,0,3,0,71,2,140,2,207,5,30,0,15, + 0,23,0,32,0,0,1,50,23,22,21,20,7,6,35,34,39,38,53,52,55,54,22,34,7,6,7,33,38,39,23,33,22,23,22,51,50,55,54,1, + 139,151,87,86,86,87,151,152,85,87,87,85,245,186,54,47,7,1,145,6,47,49,254,119,11,38,54,94,93,54,38,5,30,87,87,155,154,87,88,88, + 87,154,155,87,87,87,64,57,92,91,56,239,69,45,65,65,46,0,0,0,0,3,0,71,1,174,2,207,6,3,0,29,0,38,0,46,0,0,1,35, + 53,33,21,35,21,22,23,22,21,20,7,6,7,21,51,21,33,53,51,53,38,39,38,53,52,55,54,55,23,17,54,55,54,53,52,39,38,3,17,6, + 7,6,20,23,22,1,79,151,1,162,151,112,70,86,86,70,112,151,254,94,151,110,67,87,87,67,110,116,54,37,54,54,37,170,52,35,55,54,36,5, + 167,92,92,140,14,70,87,155,154,87,71,14,133,92,92,134,14,70,87,154,155,87,69,15,91,254,42,14,44,65,112,111,65,45,254,57,1,212,14,42, + 65,226,64,43,0,1,0,70,1,173,2,97,5,30,0,58,0,0,1,21,46,1,35,34,7,6,21,20,23,22,31,1,22,23,22,21,20,7,6,35, + 34,47,1,21,20,22,59,1,21,35,34,39,38,61,2,22,23,22,51,50,54,53,52,39,38,47,1,46,1,53,52,55,54,51,50,22,2,59,49,106, + 56,87,42,44,31,31,93,40,123,52,52,77,78,136,57,62,13,48,66,147,160,114,51,52,64,63,62,61,82,88,31,32,108,41,107,96,71,70,130,64, + 114,4,253,98,23,22,23,24,47,36,21,20,18,8,24,43,42,77,87,51,51,9,3,7,86,54,88,54,54,120,34,106,29,15,15,50,45,42,23,22, + 21,8,20,84,73,88,48,48,16,0,0,0,0,1,255,233,1,173,1,202,6,3,0,23,0,0,19,2,3,52,55,54,59,1,21,35,34,7,6,21, + 19,20,7,6,43,1,53,51,50,54,122,1,1,55,51,122,110,111,62,24,25,2,52,51,114,44,31,66,48,2,145,1,93,1,77,101,51,48,85,23, + 22,58,253,74,120,54,54,88,54,0,0,0,0,1,0,35,1,173,1,219,5,193,0,31,0,0,19,21,51,21,35,17,20,22,59,1,21,20,7,6, + 43,1,53,51,50,54,61,1,35,34,39,38,53,17,35,53,51,53,236,239,239,48,72,119,52,51,114,44,31,66,48,3,134,51,51,85,85,5,193,178, + 80,254,172,77,44,97,120,54,54,88,54,86,11,45,44,118,1,84,80,178,0,2,0,94,2,140,3,144,5,15,0,23,0,33,0,0,19,53,51,17, + 51,17,33,17,51,17,51,21,35,21,35,53,6,7,6,35,34,38,61,1,41,1,21,20,23,22,51,50,55,54,94,110,116,1,103,116,117,117,116,43, + 56,55,74,121,126,1,218,254,154,39,39,78,94,54,49,3,153,92,1,26,254,230,1,26,254,230,92,253,96,57,28,27,134,130,5,2,89,44,45,54, + 47,0,0,0,0,1,0,71,2,139,2,216,5,15,0,38,0,0,19,53,33,21,6,7,6,21,20,23,22,51,50,55,54,53,52,39,38,39,53,33, + 21,35,22,23,22,21,20,7,6,32,39,38,53,52,55,54,55,71,1,23,69,40,41,55,56,90,91,55,56,42,44,63,1,18,148,71,36,34,90,89, + 254,228,89,90,33,34,74,4,179,92,123,39,58,63,75,89,55,54,54,55,89,82,56,62,35,123,92,56,63,62,76,131,82,82,81,82,128,82,60,61, + 58,0,0,0,0,1,0,117,2,138,2,146,5,15,0,19,0,0,1,50,54,53,17,51,17,20,7,6,35,34,39,38,53,17,51,17,20,22,1,132, + 81,72,117,68,69,133,134,69,68,117,72,2,226,80,90,1,131,254,115,123,62,63,63,62,123,1,141,254,125,90,80,0,0,1,0,122,2,156,2,191, + 5,15,0,30,0,0,1,51,22,23,22,21,20,7,6,43,1,34,38,53,17,51,17,20,23,22,63,1,50,55,54,53,52,39,38,39,38,1,103,203, + 72,35,34,89,90,142,44,114,102,116,23,26,65,32,90,56,55,41,50,58,48,4,196,56,63,62,76,131,82,82,108,119,1,144,254,112,85,28,28,1, + 1,54,55,89,81,56,67,31,24,0,0,0,0,1,0,38,2,156,2,213,5,15,0,6,0,0,1,35,11,1,35,1,51,2,213,123,220,221,123,1, + 9,158,2,156,2,14,253,242,2,115,0,0,0,1,0,55,2,156,2,110,5,15,0,9,0,0,19,33,21,1,33,21,33,53,1,33,71,2,39,254, + 76,1,180,253,201,1,180,254,92,5,15,94,254,61,82,94,1,195,0,0,0,1,0,55,1,173,2,253,5,15,0,22,0,0,19,33,21,1,33,21, + 35,21,20,23,22,59,1,21,35,34,38,61,1,33,53,1,33,71,2,39,254,76,1,180,1,23,24,67,30,44,114,102,254,62,1,180,254,92,5,15, + 94,254,61,82,11,86,27,27,88,108,120,11,94,1,195,0,0,2,0,55,2,94,2,110,5,15,0,20,0,27,0,0,1,6,21,35,52,55,35,53, + 1,33,53,33,21,1,51,54,51,50,23,20,35,39,51,50,53,52,35,6,1,124,2,96,2,229,1,180,254,92,2,39,254,76,110,38,138,143,1,210, + 13,13,109,44,55,2,156,29,33,33,29,94,1,195,82,94,254,61,162,138,106,82,31,51,1,0,0,0,0,1,0,55,1,168,2,163,5,15,0,33, + 0,0,1,50,23,22,23,22,21,20,7,6,35,34,39,38,39,53,30,1,51,50,55,54,53,52,39,38,43,1,53,1,33,53,33,21,1,104,67,81, + 62,54,51,96,96,176,59,63,63,67,53,126,69,120,62,63,58,58,104,110,1,15,254,92,2,38,3,167,32,23,61,59,77,124,67,68,10,11,20,109, + 27,28,42,42,80,74,42,41,93,1,24,82,94,0,0,0,0,3,0,71,2,143,2,207,6,12,0,8,0,16,0,29,0,0,1,33,22,23,22,51, + 50,55,54,55,38,39,38,34,7,6,7,19,50,23,22,16,7,6,35,34,38,16,55,54,2,83,254,111,6,47,54,94,93,54,47,5,9,43,54,186, + 54,44,8,199,151,87,86,86,87,151,152,172,86,86,4,42,128,77,87,88,77,222,109,71,89,88,70,111,1,131,118,119,254,94,119,119,238,1,162,119, + 118,0,0,0,0,1,252,91,4,238,255,165,6,102,0,5,0,0,1,33,53,33,55,51,254,176,253,171,2,23,168,139,4,238,148,228,0,1,252,91, + 4,238,255,165,6,102,0,5,0,0,1,3,51,23,33,21,253,80,245,139,168,2,23,4,238,1,120,228,148,0,0,0,0,1,252,91,4,238,255,165, + 6,102,0,5,0,0,1,19,35,39,33,53,254,176,245,139,168,253,233,6,102,254,136,228,148,0,0,0,0,1,252,91,4,238,255,165,6,102,0,5, + 0,0,1,33,21,33,7,35,253,80,2,85,253,233,168,139,6,102,148,228,0,1,252,66,4,238,255,190,6,102,0,9,0,0,1,51,19,35,39,7, + 35,3,51,23,254,53,148,245,139,180,180,148,245,139,180,6,102,254,136,245,245,1,120,245,0,1,252,66,4,238,255,190,6,102,0,9,0,0,1,23, + 55,51,3,35,39,7,35,19,253,203,180,180,139,245,148,180,180,139,245,6,102,245,245,254,136,245,245,1,120,0,0,0,255,255,0,16,254,19,5,104, + 5,213,16,39,2,214,4,188,0,1,18,6,0,36,0,0,255,255,0,123,254,19,4,45,4,123,16,39,2,214,4,84,0,1,18,6,0,68,0,0, + 255,255,0,201,0,0,4,236,7,80,16,39,22,193,4,188,1,117,18,6,0,37,0,0,255,255,0,184,255,227,4,164,7,82,16,39,2,184,3,22, + 1,62,18,6,0,69,0,0,255,255,0,201,254,137,4,236,5,213,18,38,0,37,0,0,16,7,2,212,4,165,0,0,255,255,0,186,254,137,4,164, + 6,20,18,38,0,69,0,0,16,7,2,212,4,154,0,0,255,255,0,201,254,192,4,236,5,213,18,38,0,37,0,0,16,7,2,143,0,151,0,0, + 255,255,0,186,254,192,4,164,6,20,18,38,0,69,0,0,16,7,2,143,0,143,0,0,255,255,0,115,254,117,5,39,7,108,16,39,22,186,5,76, + 1,118,18,6,0,137,0,0,255,255,0,113,254,117,3,231,6,102,18,38,0,169,0,0,16,6,0,118,67,0,0,0,255,255,0,201,0,0,5,176, + 7,80,16,39,22,193,4,236,1,117,18,6,0,39,0,0,255,255,0,113,255,227,4,90,7,137,16,39,2,184,5,254,1,117,18,6,0,71,0,0, + 255,255,0,201,254,138,5,176,5,213,16,39,2,212,4,236,0,1,18,6,0,39,0,0,255,255,0,113,254,138,4,90,6,20,16,39,2,212,4,102, + 0,1,18,6,0,71,0,0,255,255,0,201,254,193,5,176,5,213,16,39,2,226,4,236,0,1,18,6,0,39,0,0,255,255,0,113,254,193,4,90, + 6,20,16,39,2,226,4,102,0,1,18,6,0,71,0,0,255,255,0,201,254,119,5,176,5,213,18,38,0,39,0,0,16,6,0,122,91,2,0,0, + 255,255,0,113,254,117,4,90,6,20,18,38,0,71,0,0,16,6,0,122,246,0,0,0,255,255,0,201,254,21,5,176,5,213,16,39,2,222,4,236, + 0,1,18,6,0,39,0,0,255,255,0,113,254,21,4,90,6,20,16,39,2,222,4,102,0,1,18,6,0,71,0,0,255,255,0,201,0,0,4,139, + 8,90,18,38,0,40,0,0,16,6,22,242,238,0,0,0,255,255,0,113,255,227,4,127,7,94,16,39,22,242,255,217,255,4,18,6,0,72,0,0, + 255,255,0,201,0,0,4,139,8,90,18,38,0,40,0,0,16,6,22,241,236,0,0,0,255,255,0,113,255,227,4,127,7,94,18,38,0,72,0,0, + 16,7,22,241,255,215,255,4,255,255,0,201,254,75,4,139,5,213,18,38,0,40,0,0,16,7,2,222,4,177,0,55,255,255,0,113,254,75,4,127, + 4,123,18,38,0,72,0,0,16,7,2,222,4,176,0,55,255,255,0,201,254,118,4,139,5,213,18,38,0,40,0,0,16,7,2,176,0,179,0,0, + 255,255,0,113,254,118,4,127,4,123,18,38,0,72,0,0,16,7,2,176,0,155,0,0,255,255,0,201,254,117,4,139,7,109,16,39,22,192,4,161, + 1,117,18,38,0,40,0,0,16,7,0,122,0,190,0,0,255,255,0,113,254,117,4,127,6,72,18,38,0,72,0,0,16,39,2,154,0,135,0,0, + 16,6,0,122,75,0,0,0,255,255,0,201,0,0,4,35,7,79,16,39,22,193,4,118,1,116,18,6,0,41,0,0,255,255,0,47,0,0,2,248, + 7,137,16,39,2,184,3,224,1,117,18,6,0,73,0,0,255,255,0,115,255,227,5,139,7,24,18,38,0,42,0,0,16,7,2,139,1,50,1,34, + 255,255,0,113,254,86,4,90,5,246,18,38,0,74,0,0,16,6,2,139,73,0,0,0,255,255,0,201,0,0,5,59,7,78,16,39,22,193,5,20, + 1,115,18,6,0,43,0,0,255,255,0,184,0,0,4,100,7,82,16,39,2,184,3,22,1,62,18,6,0,75,0,0,255,255,0,201,254,137,5,59, + 5,213,16,39,2,212,5,2,0,0,18,6,0,43,0,0,255,255,0,186,254,137,4,100,6,20,16,39,2,212,4,143,0,0,18,6,0,75,0,0, + 255,255,0,201,0,0,5,59,7,80,18,38,0,43,0,0,16,7,0,106,1,8,1,64,255,255,255,237,0,0,4,100,7,78,16,39,2,185,3,22, + 1,62,18,6,0,75,0,0,255,255,0,17,254,116,5,59,5,213,18,38,0,43,0,0,16,7,0,122,254,238,255,255,255,255,0,2,254,116,4,100, + 6,20,18,38,0,75,0,0,16,7,0,122,254,223,255,255,255,255,0,201,254,57,5,59,5,213,18,38,0,43,0,0,16,7,2,223,5,10,0,0, + 255,255,0,186,254,57,4,100,6,20,18,38,0,75,0,0,16,7,2,223,4,149,0,0,255,255,0,0,254,118,2,148,5,213,18,38,0,44,0,0, + 16,7,2,176,255,74,0,0,255,255,255,211,254,118,2,103,6,20,16,39,2,176,255,29,0,0,18,6,0,76,0,0,255,255,0,7,0,0,2,89, + 8,90,18,38,0,44,0,0,16,7,22,239,254,116,0,0,255,255,255,244,0,0,2,70,7,22,18,38,0,243,0,0,16,7,22,239,254,97,254,188, + 255,255,0,201,0,0,5,106,7,108,16,39,22,186,4,226,1,118,18,6,0,46,0,0,255,255,0,186,0,0,4,156,7,108,16,39,22,186,3,90, + 1,118,18,6,0,78,0,0,255,255,0,201,254,137,5,106,5,213,18,38,0,46,0,0,16,7,2,212,4,220,0,0,255,255,0,186,254,137,4,156, + 6,20,18,38,0,78,0,0,16,7,2,212,4,145,0,0,255,255,0,201,254,192,5,106,5,213,18,38,0,46,0,0,16,7,2,143,1,13,0,0, + 255,255,0,186,254,192,4,156,6,20,18,38,0,78,0,0,16,6,2,143,118,0,0,0,255,255,0,201,254,137,4,106,5,213,16,39,2,212,4,154, + 0,0,16,6,0,47,0,0,255,255,0,201,254,137,1,132,6,20,16,39,2,212,3,39,0,0,16,6,0,79,11,0,255,255,0,3,254,138,4,106, + 7,107,16,39,2,181,3,42,1,117,16,39,2,212,4,153,0,1,18,6,0,47,0,0,255,255,255,253,254,137,2,83,7,49,16,39,0,113,255,40, + 1,59,16,6,9,48,0,0,255,255,0,201,254,192,4,106,5,213,18,38,0,47,0,0,16,7,2,143,0,142,0,0,255,255,255,244,254,192,2,74, + 6,20,16,39,2,143,255,31,0,0,18,6,0,79,0,0,255,255,0,201,254,20,4,106,5,213,16,39,2,136,0,151,249,38,18,6,0,47,0,0, + 255,255,255,222,254,20,2,92,6,20,16,39,2,136,255,29,249,38,18,6,0,79,0,0,255,255,0,201,0,0,6,31,7,108,16,39,22,186,5,115, + 1,118,18,6,0,48,0,0,255,255,0,186,0,0,7,29,6,102,18,38,0,80,0,0,16,7,0,118,1,148,0,0,255,255,0,201,0,0,6,31, + 7,79,16,39,22,193,5,119,1,116,18,6,0,48,0,0,255,255,0,186,0,0,7,29,6,20,16,39,2,184,5,233,0,0,18,6,0,80,0,0, + 255,255,0,201,254,137,6,31,5,213,16,39,2,212,5,116,0,0,16,6,0,48,0,0,255,255,0,186,254,137,7,29,4,123,16,39,2,212,5,230, + 0,0,16,6,0,80,0,0,255,255,0,201,0,0,5,51,7,80,16,39,22,193,4,245,1,117,18,6,0,49,0,0,255,255,0,186,0,0,4,100, + 6,20,16,39,2,184,4,137,0,0,18,6,0,81,0,0,255,255,0,201,254,137,5,51,5,213,16,39,2,212,4,254,0,0,16,6,0,49,0,0, + 255,255,0,186,254,137,4,100,4,123,16,39,2,212,4,143,0,0,16,6,0,81,0,0,255,255,0,201,254,192,5,51,5,213,18,38,0,49,0,0, + 16,7,2,143,0,247,0,0,255,255,0,186,254,192,4,100,4,123,18,38,0,81,0,0,16,7,2,143,0,140,0,0,255,255,0,201,254,20,5,51, + 5,213,16,39,2,136,0,254,249,38,18,6,0,49,0,0,255,255,0,186,254,20,4,100,4,123,16,39,2,136,0,149,249,38,18,6,0,81,0,0, + 255,255,0,115,255,227,5,217,8,90,18,38,0,50,0,0,16,6,22,247,102,0,0,0,255,255,0,113,255,227,4,117,7,12,18,38,0,82,0,0, + 16,7,22,247,255,178,254,178,255,255,0,115,255,227,5,217,8,86,18,38,0,50,0,0,16,6,22,245,108,0,0,0,255,255,0,113,255,227,4,117, + 7,15,18,38,0,82,0,0,16,39,0,106,0,111,0,255,16,7,22,187,4,114,0,18,255,255,0,115,255,227,5,217,8,90,18,38,0,50,0,0, + 16,6,22,242,106,0,0,0,255,255,0,113,255,227,4,117,7,94,16,38,0,82,0,0,16,7,22,242,255,181,255,4,255,255,0,115,255,227,5,217, + 8,90,18,38,0,50,0,0,16,6,22,241,104,0,0,0,255,255,0,113,255,227,4,117,7,94,16,39,22,241,255,185,255,4,16,6,0,82,0,0, + 255,255,0,201,0,0,4,141,7,108,16,39,22,186,4,158,1,118,18,6,0,51,0,0,255,255,0,186,254,86,4,164,6,102,18,38,0,83,0,0, + 16,6,0,118,50,0,0,0,255,255,0,201,0,0,4,141,7,79,16,39,22,193,4,132,1,116,18,6,0,51,0,0,255,255,0,186,254,86,4,164, + 6,20,16,39,2,184,4,166,0,0,18,6,0,83,0,0,255,255,0,201,0,0,5,84,7,78,16,39,22,193,4,131,1,115,18,6,0,53,0,0, + 255,255,0,186,0,0,3,74,6,20,16,39,2,184,4,23,0,0,18,6,0,85,0,0,255,255,0,201,254,137,5,84,5,213,16,39,2,212,4,125, + 0,0,16,6,0,53,0,0,255,255,0,186,254,137,3,74,4,123,16,39,2,212,3,32,0,0,16,6,0,85,0,0,255,255,0,201,254,137,5,84, + 7,49,16,39,0,113,0,125,1,59,16,6,9,83,0,0,255,255,0,186,254,137,3,74,5,245,16,38,0,113,24,255,16,6,9,84,0,0,0,0, + 255,255,0,201,254,192,5,84,5,213,18,38,0,53,0,0,16,7,2,143,0,229,0,0,255,255,0,84,254,192,3,74,4,123,18,38,0,85,0,0, + 16,7,2,143,255,127,0,0,255,255,0,135,255,227,4,162,7,79,16,39,22,193,4,184,1,116,18,6,0,54,0,0,255,255,0,111,255,227,3,199, + 6,20,16,39,2,184,4,39,0,0,18,6,0,86,0,0,255,255,0,135,254,137,4,162,5,240,16,39,2,212,4,138,0,0,16,6,0,54,0,0, + 255,255,0,111,254,138,3,199,4,123,16,39,2,212,4,37,0,1,18,6,0,86,0,0,255,255,0,135,255,227,4,162,7,109,16,39,22,186,4,226, + 1,118,16,39,22,193,3,164,1,146,18,6,0,54,0,0,255,255,0,111,255,227,3,226,6,102,18,38,0,86,0,0,16,38,2,155,140,86,16,7, + 0,118,0,144,0,0,0,0,255,255,0,135,255,227,4,162,8,87,16,38,22,246,228,0,18,6,0,54,0,0,0,0,255,255,0,111,255,227,3,199, + 7,201,16,39,2,184,4,45,1,181,18,6,1,35,0,0,255,255,0,135,254,137,4,162,7,79,16,39,22,193,4,155,1,116,18,6,9,91,0,0, + 255,255,0,111,254,138,3,199,5,222,16,39,2,184,4,39,255,202,18,6,9,92,0,0,255,255,255,250,0,0,4,233,7,79,16,39,22,193,4,114, + 1,116,18,6,0,55,0,0,255,255,0,55,0,0,2,242,7,137,16,39,2,184,3,26,1,117,18,6,0,87,0,0,255,255,255,250,254,137,4,233, + 5,213,16,39,2,212,4,113,0,0,16,6,0,55,0,0,255,255,0,55,254,137,2,242,5,158,16,39,2,212,3,232,0,0,16,6,0,87,0,0, + 255,255,255,250,254,192,4,233,5,213,18,38,0,55,0,0,16,6,2,143,98,0,0,0,255,255,0,55,254,192,3,31,5,158,16,38,2,143,244,0, + 18,6,0,87,0,0,0,0,255,255,255,250,254,20,4,233,5,213,16,39,2,136,0,114,249,38,18,6,0,55,0,0,255,255,0,55,254,20,3,39, + 5,158,16,39,2,136,255,232,249,38,18,6,0,87,0,0,255,255,0,178,254,137,5,41,5,213,16,39,2,213,4,240,0,0,18,6,0,56,0,0, + 255,255,0,174,254,137,4,88,4,123,16,39,2,213,4,123,0,0,18,6,0,88,0,0,255,255,0,178,254,118,5,41,5,213,18,38,0,56,0,0, + 16,7,2,176,0,242,0,0,255,255,0,174,254,118,4,88,4,123,18,38,0,88,0,0,16,7,2,176,0,143,0,0,255,255,0,178,254,75,5,41, + 5,213,18,38,0,56,0,0,16,7,2,222,4,224,0,55,255,255,0,174,254,75,4,88,4,123,18,38,0,88,0,0,16,7,2,222,4,117,0,55, + 255,255,0,178,255,227,5,41,8,90,16,38,22,247,46,0,18,6,0,56,0,0,0,0,255,255,0,174,255,227,4,88,7,236,16,38,1,43,0,0, + 16,7,0,118,0,150,1,134,255,255,0,178,255,227,5,41,8,52,16,38,22,237,50,0,18,6,0,56,0,0,0,0,255,255,0,174,255,227,4,88, + 6,244,16,39,22,237,255,200,254,192,18,6,0,88,0,0,255,255,0,16,0,0,5,104,7,125,18,38,0,57,0,0,16,7,2,158,0,237,1,70, + 255,255,0,61,0,0,4,127,6,55,18,38,0,89,0,0,16,6,2,158,109,0,0,0,255,255,0,16,254,137,5,104,5,213,16,38,0,57,0,0, + 16,7,2,212,4,188,0,0,255,255,0,61,254,137,4,127,4,96,16,38,0,89,0,0,16,7,2,212,4,94,0,0,255,255,0,68,0,0,7,166, + 7,114,16,39,22,188,5,245,1,124,18,6,0,58,0,0,255,255,0,86,0,0,6,53,6,107,16,39,0,67,1,9,0,5,18,6,0,90,0,0, + 255,255,0,68,0,0,7,166,7,114,16,39,22,186,5,245,1,124,18,6,0,58,0,0,255,255,0,86,0,0,6,53,6,109,16,39,0,118,1,134, + 0,7,18,6,0,90,0,0,255,255,0,68,0,0,7,166,7,78,16,39,0,106,1,245,1,62,18,6,0,58,0,0,255,255,0,86,0,0,6,53, + 6,16,16,39,0,106,1,69,0,0,18,6,0,90,0,0,255,255,0,68,0,0,7,166,7,78,16,39,22,193,5,245,1,115,18,6,0,58,0,0, + 255,255,0,86,0,0,6,53,6,20,16,39,2,184,5,71,0,0,18,6,0,90,0,0,255,255,0,68,254,137,7,166,5,213,18,38,0,58,0,0, + 16,7,2,212,5,251,0,0,255,255,0,86,254,137,6,53,4,96,18,38,0,90,0,0,16,7,2,212,5,74,0,0,255,255,0,61,0,0,5,59, + 7,79,16,39,22,193,4,202,1,115,18,6,0,59,0,0,255,255,0,59,0,0,4,121,6,20,16,39,2,184,4,98,0,0,18,6,0,91,0,0, + 255,255,0,61,0,0,5,59,7,78,18,38,0,59,0,0,16,7,0,106,0,202,1,62,255,255,0,59,0,0,4,121,6,16,18,38,0,91,0,0, + 16,6,0,106,102,0,0,0,255,255,255,252,0,0,4,231,7,80,16,39,22,193,4,114,1,117,18,6,0,60,0,0,255,255,0,61,254,86,4,127, + 6,20,16,39,2,184,4,96,0,0,18,6,0,92,0,0,255,255,0,92,0,0,5,31,7,109,16,39,22,189,4,190,1,117,18,6,0,61,0,0, + 255,255,0,88,0,0,3,219,6,102,18,38,0,93,0,0,16,6,2,136,26,0,0,0,255,255,0,92,254,137,5,31,5,213,18,38,0,61,0,0, + 16,7,2,212,4,217,0,0,255,255,0,88,254,137,3,219,4,96,18,38,0,93,0,0,16,7,2,212,4,49,0,0,255,255,0,92,254,192,5,31, + 5,213,18,38,0,61,0,0,16,7,2,143,0,199,0,0,255,255,0,88,254,192,3,219,4,96,18,38,0,93,0,0,16,6,2,143,27,0,0,0, + 255,255,0,186,254,192,4,100,6,20,18,38,0,75,0,0,16,6,2,143,102,0,0,0,255,255,0,4,0,0,2,242,7,78,18,38,0,87,0,0, + 16,7,0,106,255,45,1,62,255,255,0,86,0,0,6,53,7,6,18,38,0,90,0,0,16,7,2,156,1,66,0,0,255,255,0,61,254,86,4,127, + 7,6,18,38,0,92,0,0,16,7,2,156,0,129,0,0,255,255,0,123,255,227,5,97,6,20,18,38,0,68,0,0,16,7,2,128,3,218,0,0, + 255,255,0,47,0,0,2,248,7,137,16,39,2,184,3,224,1,117,18,6,1,65,0,0,0,1,0,2,0,0,2,248,6,20,0,24,0,0,33,35, + 17,7,39,55,17,35,53,51,53,52,54,59,1,21,35,34,7,6,21,17,55,23,5,1,152,185,147,74,221,176,176,174,189,174,176,100,38,38,214,75, + 254,223,2,20,104,106,157,1,30,143,78,187,171,153,40,41,103,254,116,152,105,207,0,0,0,1,0,47,0,0,2,248,6,20,0,23,0,0,33,35, + 17,35,53,51,53,35,53,51,54,55,54,59,1,21,35,34,7,6,7,51,21,35,1,152,185,176,176,176,179,13,71,87,189,174,176,100,38,30,6,253, + 255,3,69,143,140,143,137,70,86,153,40,32,68,143,0,0,0,1,0,178,255,227,5,180,5,242,0,55,0,0,1,38,35,34,14,3,21,17,35,17, + 52,62,3,51,50,4,23,34,4,21,20,30,5,21,20,4,35,34,39,53,30,1,51,50,54,53,52,46,7,53,52,54,4,3,109,174,64,102,95,64, + 38,203,57,100,144,166,99,217,1,48,55,207,254,255,67,106,129,129,106,67,254,247,211,180,201,109,177,111,98,151,41,70,91,100,100,91,70,41,223,4, + 244,90,24,64,104,167,111,252,136,3,145,131,207,139,92,40,197,189,125,95,45,67,45,45,62,84,140,92,164,201,95,208,69,70,118,88,53,80,51,41, + 32,36,50,66,103,67,143,187,255,255,0,113,255,227,4,117,5,240,16,6,3,72,0,0,255,255,0,16,254,137,5,104,5,213,16,39,2,212,4,183, + 0,0,18,6,0,36,0,0,255,255,0,123,254,137,4,45,4,123,16,39,2,212,4,33,0,0,18,6,0,68,0,0,255,255,0,16,0,0,5,104, + 7,240,18,38,0,36,0,0,16,7,2,186,4,188,1,117,255,255,0,123,255,227,4,45,6,123,18,38,0,68,0,0,16,7,2,186,4,84,0,0, + 255,255,0,16,0,0,5,104,8,58,18,38,0,36,0,0,16,6,22,248,0,0,0,0,255,255,0,123,255,227,4,175,6,197,16,39,22,248,255,151, + 254,139,16,6,0,68,0,0,255,255,0,16,0,0,5,104,8,58,18,38,0,36,0,0,16,6,22,249,0,0,0,0,255,255,0,123,255,227,4,45, + 6,198,16,38,0,68,0,0,16,7,22,249,255,148,254,140,255,255,0,16,0,0,5,104,8,91,18,38,0,36,0,0,16,6,22,255,0,0,0,0, + 255,255,0,123,255,227,4,157,6,230,16,39,22,255,255,150,254,139,16,6,0,68,0,0,255,255,0,16,0,0,5,104,8,117,18,38,0,36,0,0, + 16,6,22,250,0,0,0,0,255,255,0,123,255,227,4,45,7,0,16,39,22,250,255,150,254,139,16,6,0,68,0,0,255,255,0,16,254,137,5,104, + 7,109,18,38,0,132,0,0,16,7,2,212,4,175,0,0,255,255,0,123,254,137,4,45,6,102,18,38,0,164,0,0,16,7,2,212,4,34,0,0, + 255,255,0,16,0,0,5,104,8,90,18,38,0,36,0,0,16,6,22,252,0,0,0,0,255,255,0,123,255,227,4,45,7,4,16,39,22,252,255,145, + 254,170,16,6,0,68,0,0,255,255,0,16,0,0,5,104,8,90,18,38,0,36,0,0,16,6,22,253,0,0,0,0,255,255,0,123,255,227,4,45, + 7,4,16,39,22,253,255,146,254,170,16,6,0,68,0,0,255,255,0,16,0,0,5,104,8,139,18,38,0,36,0,0,16,6,22,254,0,0,0,0, + 255,255,0,123,255,227,4,45,7,53,16,39,22,254,255,148,254,170,16,6,0,68,0,0,255,255,0,16,0,0,5,104,8,89,18,38,0,36,0,0, + 16,6,22,251,0,0,0,0,255,255,0,123,255,227,4,45,7,3,16,38,0,68,0,0,16,7,22,251,255,146,254,170,255,255,0,16,254,137,5,104, + 7,146,18,38,0,196,0,0,16,7,2,212,4,192,0,0,255,255,0,123,254,137,4,45,6,31,18,38,0,197,0,0,16,7,2,212,4,51,0,0, + 255,255,0,201,254,137,4,139,5,213,16,38,0,40,0,0,16,7,2,212,4,158,0,0,255,255,0,113,254,137,4,127,4,123,16,38,0,72,0,0, + 16,7,2,212,4,139,0,0,255,255,0,201,0,0,4,139,7,240,18,38,0,40,0,0,16,7,2,186,4,158,1,117,255,255,0,113,255,227,4,127, + 6,123,18,38,0,72,0,0,16,7,2,186,4,141,0,0,255,255,0,201,0,0,4,139,7,94,16,39,22,187,4,158,1,117,18,6,0,40,0,0, + 255,255,0,113,255,227,4,127,6,55,16,39,2,158,0,151,0,0,18,6,0,72,0,0,255,255,0,201,0,0,5,24,8,58,18,38,0,40,0,0, + 16,6,22,248,0,0,0,0,255,255,0,113,255,227,4,232,6,197,16,39,22,248,255,208,254,139,16,6,0,72,0,0,255,255,0,201,0,0,4,139, + 8,58,18,38,0,40,0,0,16,6,22,249,238,0,0,0,255,255,0,113,255,227,4,127,6,198,16,39,22,249,255,208,254,140,16,6,0,72,0,0, + 255,255,0,201,0,0,4,245,8,91,18,38,0,40,0,0,16,6,22,255,238,0,0,0,255,255,0,113,255,227,4,215,6,230,16,38,0,72,0,0, + 16,7,22,255,255,208,254,139,255,255,0,201,0,0,4,139,8,117,18,38,0,40,0,0,16,6,22,250,234,0,0,0,255,255,0,113,255,227,4,127, + 7,0,16,39,22,250,255,209,254,139,16,6,0,72,0,0,255,255,0,201,254,137,4,139,7,109,18,38,0,140,0,0,16,7,2,212,4,158,0,0, + 255,255,0,113,254,137,4,127,6,102,16,39,2,212,4,139,0,0,16,38,9,178,0,0,16,7,2,136,0,139,0,0,255,255,0,90,0,0,2,26, + 7,240,18,38,0,44,0,0,16,7,2,186,3,35,1,117,255,255,0,68,0,0,2,4,6,124,18,38,0,243,0,0,16,7,2,186,3,13,0,1, + 255,255,0,201,254,137,1,147,5,213,16,38,0,44,0,0,16,7,2,212,3,46,0,0,255,255,0,191,254,137,1,121,6,20,16,38,0,76,0,0, + 16,7,2,212,3,29,0,0,255,255,0,115,254,137,5,217,5,240,16,38,0,50,0,0,16,7,2,212,5,39,0,0,255,255,0,113,254,137,4,117, + 4,123,16,38,0,82,0,0,16,7,2,212,4,115,0,0,255,255,0,115,255,227,5,217,7,240,18,38,0,50,0,0,16,7,2,186,5,39,1,117, + 255,255,0,113,255,227,4,117,6,123,18,38,0,82,0,0,16,7,2,186,4,125,0,0,255,255,0,115,255,227,5,217,8,58,18,38,0,50,0,0, + 16,6,22,248,108,0,0,0,255,255,0,113,255,227,4,206,6,197,16,39,22,248,255,182,254,139,16,6,0,82,0,0,255,255,0,115,255,227,5,217, + 8,58,18,38,0,50,0,0,16,6,22,249,106,0,0,0,255,255,0,113,255,227,4,117,6,198,16,39,22,249,255,181,254,140,16,6,0,82,0,0, + 255,255,0,115,255,227,5,217,8,91,18,38,0,50,0,0,16,6,22,255,106,0,0,0,255,255,0,113,255,227,4,189,6,230,16,39,22,255,255,182, + 254,139,16,6,0,82,0,0,255,255,0,115,255,227,5,217,8,117,18,38,0,50,0,0,16,6,22,250,101,0,0,0,255,255,0,113,255,227,4,117, + 7,0,16,39,22,250,255,182,254,139,16,6,0,82,0,0,255,255,0,115,254,137,5,217,7,109,18,38,0,150,0,0,16,7,2,212,5,39,0,0, + 255,255,0,113,254,137,4,117,6,102,16,39,2,212,4,115,0,0,16,38,9,198,0,0,16,6,2,136,115,0,0,0,255,255,0,103,255,227,6,29, + 7,107,16,39,22,186,5,39,1,117,18,6,1,98,0,0,255,255,0,118,255,227,4,211,6,102,16,38,0,118,115,0,18,6,1,99,0,0,0,0, + 255,255,0,103,255,227,6,29,7,107,16,39,22,188,5,39,1,117,18,6,1,98,0,0,255,255,0,118,255,227,4,211,6,102,16,38,0,67,115,0, + 18,6,1,99,0,0,0,0,255,255,0,103,255,227,6,29,7,240,18,38,1,98,0,0,16,7,2,186,5,39,1,117,255,255,0,118,255,227,4,211, + 6,123,18,38,1,99,0,0,16,7,2,186,4,125,0,0,255,255,0,103,255,227,6,29,7,94,16,39,22,187,5,39,1,117,18,6,1,98,0,0, + 255,255,0,118,255,227,4,211,6,55,16,38,2,158,115,0,18,6,1,99,0,0,0,0,255,255,0,103,254,137,6,29,6,20,18,38,1,98,0,0, + 16,7,2,212,5,39,0,0,255,255,0,118,254,137,4,211,4,235,18,38,1,99,0,0,16,7,2,212,4,115,0,0,255,255,0,178,254,137,5,41, + 5,213,16,38,0,56,0,0,16,7,2,212,4,245,0,0,255,255,0,174,254,137,4,88,4,123,16,38,0,88,0,0,16,7,2,212,4,123,0,0, + 255,255,0,178,255,227,5,41,7,240,18,38,0,56,0,0,16,7,2,186,4,238,1,117,255,255,0,174,255,227,4,88,6,123,18,38,0,88,0,0, + 16,7,2,186,4,125,0,0,255,255,0,173,255,247,6,95,7,107,16,39,22,186,4,238,1,117,18,6,1,113,0,0,255,255,0,176,255,227,5,105, + 6,102,16,38,0,118,123,0,18,6,1,114,0,0,0,0,255,255,0,173,255,247,6,95,7,107,16,39,22,188,4,238,1,117,18,6,1,113,0,0, + 255,255,0,176,255,227,5,105,6,102,16,38,0,67,123,0,18,6,1,114,0,0,0,0,255,255,0,173,255,247,6,95,7,240,18,38,1,113,0,0, + 16,7,2,186,4,238,1,117,255,255,0,176,255,227,5,105,6,123,18,38,1,114,0,0,16,7,2,186,4,125,0,0,255,255,0,173,255,247,6,95, + 7,94,16,39,22,187,4,238,1,117,18,6,1,113,0,0,255,255,0,176,255,227,5,105,6,55,16,39,2,158,0,128,0,0,18,6,1,114,0,0, + 255,255,0,173,254,137,6,95,6,20,18,38,1,113,0,0,16,7,2,212,4,245,0,0,255,255,0,176,254,137,5,105,4,235,18,38,1,114,0,0, + 16,7,2,212,4,123,0,0,255,255,255,252,0,0,4,231,7,114,18,38,0,60,0,0,16,7,22,188,4,114,1,124,255,255,0,61,254,86,4,127, + 6,107,18,38,0,92,0,0,16,6,0,67,33,5,0,0,255,255,255,252,254,137,4,231,5,213,16,39,2,212,4,118,0,0,18,6,0,60,0,0, + 255,255,0,61,254,86,4,127,4,96,16,39,2,212,5,116,0,0,18,6,0,92,0,0,255,255,255,252,0,0,4,231,7,247,18,38,0,60,0,0, + 16,7,2,186,4,114,1,124,255,255,0,61,254,86,4,127,6,130,18,38,0,92,0,0,16,7,2,186,4,96,0,7,255,255,255,252,0,0,4,231, + 7,94,16,39,22,187,4,114,1,117,18,6,0,60,0,0,255,255,0,61,254,86,4,127,6,55,16,38,2,158,119,0,18,6,0,92,0,0,0,0, + 0,1,0,201,0,0,6,28,5,213,0,9,0,0,19,51,17,51,17,51,17,33,21,33,201,202,232,202,2,215,250,173,5,213,250,213,5,43,250,213, + 170,0,0,0,0,1,0,32,0,0,3,178,6,20,0,19,0,0,19,51,21,51,53,51,21,51,21,35,17,35,17,35,17,35,17,35,53,51,193,184, + 224,184,161,161,184,224,184,161,161,6,20,147,147,147,125,250,252,5,4,250,252,5,4,125,255,255,0,113,255,231,4,228,6,97,16,38,3,69,0,0, + 16,6,10,165,112,0,0,0,255,255,0,113,255,231,4,228,6,97,16,38,3,69,0,0,16,6,10,221,72,0,0,0,255,255,0,113,255,231,4,228, + 6,102,16,38,3,69,0,0,16,7,10,178,0,148,0,0,255,255,0,113,255,231,4,228,6,102,16,38,3,69,0,0,16,7,10,191,0,132,0,0, + 255,255,0,113,255,231,4,228,6,102,16,38,3,69,0,0,16,7,10,179,0,132,0,0,255,255,0,113,255,231,4,228,6,102,16,38,3,69,0,0, + 16,7,10,192,0,160,0,0,255,255,0,113,255,231,4,228,7,109,16,38,3,69,0,0,16,6,10,180,118,0,0,0,255,255,0,113,255,231,4,228, + 7,109,16,38,3,69,0,0,16,6,10,193,68,0,0,0,255,255,0,16,0,0,5,104,6,97,16,38,3,38,0,0,16,7,10,165,255,35,0,0, + 255,255,0,16,0,0,5,104,6,97,16,38,3,38,0,0,16,7,10,221,254,243,0,0,255,255,0,5,0,0,6,244,6,102,16,39,3,38,1,140, + 0,0,16,7,10,178,255,124,0,0,0,0,255,255,0,6,0,0,6,244,6,102,16,39,3,38,1,140,0,0,16,6,10,191,136,0,255,255,0,7, + 0,0,6,22,6,102,16,39,3,38,0,174,0,0,16,7,10,179,255,83,0,0,0,0,255,255,0,4,0,0,6,88,6,102,16,39,3,38,0,240, + 0,0,16,7,10,192,255,111,0,0,0,0,255,255,0,7,0,0,5,153,7,109,16,38,3,38,49,0,16,7,10,180,255,81,0,0,255,255,0,4, + 0,0,5,224,7,109,16,38,3,38,120,0,16,7,10,193,255,78,0,0,255,255,0,133,255,227,3,200,6,97,16,38,3,73,0,0,16,6,10,165, + 68,0,0,0,255,255,0,133,255,227,3,200,6,97,16,38,3,73,0,0,16,6,10,221,57,0,0,0,255,255,0,133,255,227,3,200,6,102,16,38, + 3,73,0,0,16,6,10,178,32,0,0,0,255,255,0,133,255,227,3,200,6,102,16,38,3,73,0,0,16,6,10,191,37,0,0,0,255,255,0,133, + 255,227,3,227,6,102,16,38,3,73,0,0,16,6,10,179,79,0,0,0,255,255,0,133,255,227,4,3,6,102,16,38,3,73,0,0,16,6,10,192, + 82,0,0,0,255,255,0,7,0,0,5,45,6,97,16,39,3,42,0,162,0,0,16,7,10,165,254,129,0,0,0,0,255,255,0,7,0,0,5,45, + 6,97,16,39,3,42,0,162,0,0,16,7,10,221,254,129,0,0,0,0,255,255,0,5,0,0,7,55,6,102,16,39,3,42,2,172,0,0,16,7, + 10,178,255,124,0,0,0,0,255,255,0,6,0,0,7,73,6,102,16,39,3,42,2,190,0,0,16,6,10,191,136,0,255,255,0,7,0,0,6,173, + 6,102,16,39,3,42,2,34,0,0,16,7,10,179,255,83,0,0,0,0,255,255,0,4,0,0,6,233,6,102,16,39,3,42,2,94,0,0,16,7, + 10,192,255,111,0,0,0,0,255,255,0,186,254,86,4,100,6,97,16,38,3,75,0,0,16,7,10,165,0,166,0,0,255,255,0,186,254,86,4,100, + 6,97,16,38,3,75,0,0,16,7,10,221,0,162,0,0,255,255,0,186,254,86,4,100,6,102,16,38,3,75,0,0,16,7,10,178,0,128,0,0, + 255,255,0,186,254,86,4,100,6,102,16,38,3,75,0,0,16,6,10,191,112,0,0,0,255,255,0,186,254,86,4,100,6,102,16,38,3,75,0,0, + 16,7,10,179,0,132,0,0,255,255,0,186,254,86,4,100,6,102,16,38,3,75,0,0,16,7,10,192,0,174,0,0,255,255,0,186,254,86,4,100, + 7,109,16,38,3,75,0,0,16,7,10,180,0,156,0,0,255,255,0,186,254,86,4,100,7,109,16,38,3,75,0,0,16,7,10,193,0,135,0,0, + 255,255,0,7,0,0,5,233,6,97,16,39,3,44,0,174,0,0,16,7,10,165,254,129,0,0,0,0,255,255,0,7,0,0,5,230,6,97,16,39, + 3,44,0,171,0,0,16,7,10,221,254,129,0,0,0,0,255,255,0,5,0,0,7,231,6,102,16,39,3,44,2,172,0,0,16,7,10,178,255,124, + 0,0,0,0,255,255,0,6,0,0,7,237,6,102,16,39,3,44,2,178,0,0,16,6,10,191,136,0,255,255,0,7,0,0,7,110,6,102,16,39, + 3,44,2,51,0,0,16,7,10,179,255,83,0,0,0,0,255,255,0,4,0,0,7,159,6,102,16,39,3,44,2,100,0,0,16,7,10,192,255,111, + 0,0,0,0,255,255,0,7,0,0,6,175,7,109,16,39,3,44,1,116,0,0,16,7,10,180,255,81,0,0,0,0,255,255,0,4,0,0,6,202, + 7,109,16,39,3,44,1,143,0,0,16,7,10,193,255,78,0,0,0,0,255,255,0,155,0,0,2,110,6,97,16,38,3,77,0,0,16,7,10,165, + 255,21,0,0,255,255,0,145,0,0,2,110,6,97,16,38,3,77,0,0,16,7,10,221,255,11,0,0,255,255,255,176,0,0,2,185,6,102,16,38, + 3,77,0,0,16,7,10,178,255,39,0,0,255,255,255,186,0,0,2,199,6,102,16,38,3,77,0,0,16,7,10,191,255,60,0,0,255,255,0,5, + 0,0,2,229,6,102,16,38,3,77,0,0,16,7,10,179,255,81,0,0,255,255,255,210,0,0,2,238,6,102,16,38,3,77,0,0,16,7,10,192, + 255,61,0,0,255,255,255,203,0,0,2,110,7,109,16,38,3,77,0,0,16,7,10,180,255,21,0,0,255,255,255,198,0,0,2,110,7,109,16,38, + 3,77,0,0,16,7,10,193,255,16,0,0,255,255,0,7,0,0,2,65,6,97,16,39,3,46,0,174,0,0,16,7,10,165,254,129,0,0,0,0, + 255,255,0,7,0,0,2,53,6,97,16,39,3,46,0,162,0,0,16,7,10,221,254,129,0,0,0,0,255,255,0,5,0,0,4,75,6,102,16,39, + 3,46,2,184,0,0,16,7,10,178,255,124,0,0,0,0,255,255,0,6,0,0,4,75,6,102,16,39,3,46,2,184,0,0,16,6,10,191,136,0, + 255,255,0,7,0,0,3,199,6,102,16,39,3,46,2,52,0,0,16,7,10,179,255,83,0,0,0,0,255,255,0,4,0,0,4,3,6,102,16,39, + 3,46,2,112,0,0,16,7,10,192,255,111,0,0,0,0,255,255,0,7,0,0,3,34,7,109,16,39,3,46,1,143,0,0,16,7,10,180,255,81, + 0,0,0,0,255,255,0,4,0,0,3,41,7,109,16,39,3,46,1,150,0,0,16,7,10,193,255,78,0,0,0,0,255,255,0,113,255,227,4,117, + 6,97,16,38,3,83,0,0,16,6,10,165,120,0,0,0,255,255,0,113,255,227,4,117,6,97,16,38,3,83,0,0,16,6,10,221,110,0,0,0, + 255,255,0,113,255,227,4,117,6,102,16,38,3,83,0,0,16,6,10,178,101,0,0,0,255,255,0,113,255,227,4,117,6,102,16,38,3,83,0,0, + 16,6,10,191,84,0,0,0,255,255,0,113,255,227,4,117,6,102,16,38,3,83,0,0,16,7,10,179,0,136,0,0,255,255,0,113,255,227,4,117, + 6,102,16,38,3,83,0,0,16,7,10,192,0,145,0,0,255,255,0,7,255,227,5,252,6,97,16,38,3,52,35,0,16,7,10,165,254,129,0,0, + 255,255,0,7,255,227,6,86,6,97,16,38,3,52,125,0,16,7,10,221,254,129,0,0,255,255,0,5,255,227,8,79,6,102,16,39,3,52,2,118, + 0,0,16,7,10,178,255,124,0,0,0,0,255,255,0,6,255,227,8,89,6,102,16,39,3,52,2,128,0,0,16,6,10,191,136,0,255,255,0,7, + 255,227,7,15,6,102,16,39,3,52,1,54,0,0,16,7,10,179,255,83,0,0,0,0,255,255,0,4,255,227,7,80,6,102,16,39,3,52,1,119, + 0,0,16,7,10,192,255,111,0,0,0,0,255,255,0,149,255,227,4,42,6,97,16,38,3,89,0,0,16,6,10,165,61,0,0,0,255,255,0,149, + 255,227,4,42,6,97,16,38,3,89,0,0,16,6,10,221,27,0,0,0,255,255,0,149,255,227,4,42,6,102,16,38,3,89,0,0,16,6,10,178, + 39,0,0,0,255,255,0,149,255,227,4,42,6,102,16,38,3,89,0,0,16,6,10,191,33,0,0,0,255,255,0,149,255,227,4,42,6,102,16,38, + 3,89,0,0,16,6,10,179,96,0,0,0,255,255,0,149,255,227,4,42,6,102,16,38,3,89,0,0,16,6,10,192,87,0,0,0,255,255,0,149, + 255,227,4,42,7,109,16,38,3,89,0,0,16,6,10,180,56,0,0,0,255,255,0,149,255,227,4,42,7,109,16,38,3,89,0,0,16,6,10,193, + 24,0,0,0,255,255,0,7,0,0,6,73,6,97,16,39,3,57,1,98,0,0,16,7,10,221,254,129,0,0,0,0,255,255,0,6,0,0,7,255, + 6,102,16,39,3,57,3,24,0,0,16,6,10,191,136,0,255,255,0,4,0,0,8,29,6,102,16,39,3,57,3,54,0,0,16,7,10,192,255,111, + 0,0,0,0,255,255,0,4,0,0,7,51,7,109,16,39,3,57,2,76,0,0,16,7,10,193,255,78,0,0,0,0,255,255,0,135,255,227,6,39, + 6,97,16,38,3,93,0,0,16,7,10,165,1,94,0,0,255,255,0,135,255,227,6,39,6,97,16,38,3,93,0,0,16,7,10,221,1,84,0,0, + 255,255,0,135,255,227,6,39,6,102,16,38,3,93,0,0,16,7,10,178,1,89,0,0,255,255,0,135,255,227,6,39,6,102,16,38,3,93,0,0, + 16,7,10,191,1,94,0,0,255,255,0,135,255,227,6,39,6,102,16,38,3,93,0,0,16,7,10,179,1,164,0,0,255,255,0,135,255,227,6,39, + 6,102,16,38,3,93,0,0,16,7,10,192,1,139,0,0,255,255,0,135,255,227,6,39,7,109,16,38,3,93,0,0,16,7,10,180,1,99,0,0, + 255,255,0,135,255,227,6,39,7,109,16,38,3,93,0,0,16,7,10,193,1,94,0,0,255,255,0,7,0,0,6,29,6,97,16,38,3,61,78,0, + 16,7,10,165,254,129,0,0,255,255,0,7,0,0,6,113,6,97,16,39,3,61,0,162,0,0,16,7,10,221,254,129,0,0,0,0,255,255,0,5, + 0,0,8,105,6,102,16,39,3,61,2,154,0,0,16,7,10,178,255,124,0,0,0,0,255,255,0,6,0,0,8,117,6,102,16,39,3,61,2,166, + 0,0,16,6,10,191,136,0,255,255,0,7,0,0,7,67,6,102,16,39,3,61,1,116,0,0,16,7,10,179,255,83,0,0,0,0,255,255,0,4, + 0,0,7,121,6,102,16,39,3,61,1,170,0,0,16,7,10,192,255,111,0,0,0,0,255,255,0,7,0,0,7,17,7,109,16,39,3,61,1,66, + 0,0,16,7,10,180,255,81,0,0,0,0,255,255,0,4,0,0,7,80,7,109,16,39,3,61,1,129,0,0,16,7,10,193,255,78,0,0,0,0, + 255,255,0,113,255,231,4,228,6,102,16,38,3,69,0,0,16,6,10,209,116,0,0,0,255,255,0,113,255,231,4,228,6,102,16,6,3,64,0,0, + 255,255,0,133,255,227,3,200,6,102,16,38,3,73,0,0,16,6,10,209,84,0,0,0,255,255,0,133,255,227,3,200,6,102,16,6,3,65,0,0, + 255,255,0,186,254,86,4,100,6,102,16,38,3,75,0,0,16,7,10,209,0,198,0,0,255,255,0,186,254,86,4,100,6,102,16,6,3,66,0,0, + 255,255,255,141,0,0,2,110,6,102,16,38,3,77,0,0,16,7,10,209,254,227,0,0,255,255,0,166,0,0,2,152,6,102,16,6,3,67,0,0, + 255,255,0,113,255,227,4,117,6,102,16,38,3,83,0,0,16,6,10,209,123,0,0,0,255,255,0,113,255,227,4,117,6,102,16,6,3,96,0,0, + 255,255,0,149,255,227,4,42,6,102,16,38,3,89,0,0,16,6,10,209,48,0,0,0,255,255,0,149,255,227,4,42,6,102,16,6,3,97,0,0, + 255,255,0,135,255,227,6,39,6,102,16,38,3,93,0,0,16,7,10,209,1,77,0,0,255,255,0,135,255,227,6,39,6,102,16,6,3,98,0,0, + 255,255,0,113,254,86,4,228,6,97,16,38,9,245,0,0,16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228,6,97,16,38,9,246,0,0, + 16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228,6,102,16,38,9,247,0,0,16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228, + 6,102,16,38,9,248,0,0,16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228,6,102,16,38,9,249,0,0,16,6,3,22,72,0,0,0, + 255,255,0,113,254,86,4,228,6,102,16,38,9,250,0,0,16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228,7,109,16,38,9,251,0,0, + 16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228,7,109,16,38,9,252,0,0,16,6,3,22,72,0,0,0,255,255,0,16,254,86,5,104, + 6,97,16,38,9,253,0,0,16,7,10,164,0,186,0,0,255,255,0,16,254,86,5,104,6,97,16,38,9,254,0,0,16,7,10,164,0,186,0,0, + 255,255,0,5,254,86,6,244,6,102,16,38,9,255,0,0,16,7,10,164,2,70,0,0,255,255,0,6,254,86,6,244,6,102,16,38,10,0,0,0, + 16,7,10,164,2,70,0,0,255,255,0,7,254,86,6,22,6,102,16,38,10,1,0,0,16,7,10,164,1,104,0,0,255,255,0,4,254,86,6,88, + 6,102,16,38,10,2,0,0,16,7,10,164,1,170,0,0,255,255,0,7,254,86,5,153,7,109,16,38,10,3,0,0,16,7,10,164,0,235,0,0, + 255,255,0,4,254,86,5,224,7,109,16,38,10,4,0,0,16,7,10,164,1,50,0,0,255,255,0,186,254,86,4,100,6,97,16,38,10,17,0,0, + 16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100,6,97,16,38,10,18,0,0,16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100, + 6,102,16,38,10,19,0,0,16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100,6,102,16,38,10,20,0,0,16,7,3,22,255,56,0,0, + 255,255,0,186,254,86,4,100,6,102,16,38,10,21,0,0,16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100,6,102,16,38,10,22,0,0, + 16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100,7,109,16,38,10,23,0,0,16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100, + 7,109,16,38,10,24,0,0,16,7,3,22,255,56,0,0,255,255,0,7,254,86,5,233,6,97,16,38,10,25,0,0,16,7,10,164,1,158,0,0, + 255,255,0,7,254,86,5,230,6,97,16,38,10,26,0,0,16,7,10,164,1,155,0,0,255,255,0,5,254,86,7,231,6,102,16,38,10,27,0,0, + 16,7,10,164,3,156,0,0,255,255,0,6,254,86,7,237,6,102,16,38,10,28,0,0,16,7,10,164,3,162,0,0,255,255,0,7,254,86,7,110, + 6,102,16,38,10,29,0,0,16,7,10,164,3,35,0,0,255,255,0,4,254,86,7,159,6,102,16,38,10,30,0,0,16,7,10,164,3,84,0,0, + 255,255,0,7,254,86,6,175,7,109,16,38,10,31,0,0,16,7,10,164,2,100,0,0,255,255,0,4,254,86,6,202,7,109,16,38,10,32,0,0, + 16,7,10,164,2,127,0,0,255,255,0,135,254,86,6,39,6,97,16,38,10,73,0,0,16,7,3,22,1,89,0,0,255,255,0,135,254,86,6,39, + 6,97,16,38,10,74,0,0,16,7,3,22,1,89,0,0,255,255,0,135,254,86,6,39,6,102,16,38,10,75,0,0,16,7,3,22,1,89,0,0, + 255,255,0,135,254,86,6,39,6,102,16,38,10,76,0,0,16,7,3,22,1,89,0,0,255,255,0,135,254,86,6,39,6,102,16,38,10,77,0,0, + 16,7,3,22,1,89,0,0,255,255,0,135,254,86,6,39,6,102,16,38,10,78,0,0,16,7,3,22,1,89,0,0,255,255,0,135,254,86,6,39, + 7,109,16,38,10,79,0,0,16,7,3,22,1,89,0,0,255,255,0,135,254,86,6,39,7,109,16,38,10,80,0,0,16,7,3,22,1,89,0,0, + 255,255,0,7,254,86,6,29,6,97,16,38,10,81,0,0,16,7,10,164,1,92,0,0,255,255,0,7,254,86,6,113,6,97,16,38,10,82,0,0, + 16,7,10,164,1,176,0,0,255,255,0,5,254,86,8,105,6,102,16,38,10,83,0,0,16,7,10,164,3,168,0,0,255,255,0,6,254,86,8,117, + 6,102,16,38,10,84,0,0,16,7,10,164,3,180,0,0,255,255,0,7,254,86,7,67,6,102,16,38,10,85,0,0,16,7,10,164,2,130,0,0, + 255,255,0,4,254,86,7,121,6,102,16,38,10,86,0,0,16,7,10,164,2,184,0,0,255,255,0,7,254,86,7,17,7,109,16,38,10,87,0,0, + 16,7,10,164,2,80,0,0,255,255,0,4,254,86,7,80,7,109,16,38,10,88,0,0,16,7,10,164,2,143,0,0,255,255,0,113,255,231,4,228, + 6,72,16,38,3,69,0,0,16,6,2,154,122,0,0,0,255,255,0,113,255,231,4,228,5,246,16,38,3,69,0,0,16,6,0,113,121,0,0,0, + 255,255,0,113,254,86,4,228,6,102,16,38,10,89,0,0,16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228,4,121,16,38,3,69,0,0, + 16,6,3,22,72,0,0,0,255,255,0,113,254,86,4,228,6,102,16,38,3,64,0,0,16,6,3,22,72,0,0,0,255,255,0,113,255,231,4,228, + 6,55,16,38,3,69,0,0,16,6,10,166,110,0,0,0,255,255,0,113,254,86,4,228,6,55,16,38,10,156,0,0,16,6,3,22,72,0,0,0, + 255,255,0,16,0,0,5,104,7,109,16,38,3,38,0,0,16,7,22,192,4,186,1,117,255,255,0,16,0,0,5,104,7,49,16,38,3,38,0,0, + 16,7,0,113,0,188,1,59,255,255,255,252,0,0,5,170,6,102,16,38,3,38,66,0,16,7,10,209,255,82,0,0,255,255,0,16,0,0,5,104, + 6,102,16,6,3,29,0,0,255,255,0,16,254,86,5,104,5,213,16,38,3,38,0,0,16,7,10,164,0,186,0,0,255,255,1,134,4,194,2,120, + 6,97,16,6,10,165,0,0,255,255,1,182,254,86,2,146,255,164,16,6,3,22,0,0,0,1,1,134,4,194,2,120,6,97,0,8,0,72,180,5, + 8,7,2,9,16,212,60,220,178,63,8,1,93,192,49,182,0,6,7,6,3,2,9,0,16,212,180,63,2,95,2,2,93,176,17,75,80,88,204,27, + 192,89,204,204,178,63,7,1,93,17,57,48,177,6,3,73,177,7,6,73,80,88,179,5,64,6,64,56,56,89,1,16,35,53,22,53,35,53,51,2, + 120,242,134,133,241,5,205,254,245,103,3,157,158,0,0,0,255,255,0,182,5,29,3,74,6,55,16,6,2,158,0,0,255,255,0,182,5,70,3,74, + 7,109,16,39,22,187,4,0,1,132,18,6,0,106,0,0,255,255,0,186,254,86,4,100,6,102,16,38,10,93,0,0,16,7,3,22,255,56,0,0, + 255,255,0,186,254,86,4,100,4,123,16,38,3,75,0,0,16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100,6,102,16,38,3,66,0,0, + 16,7,3,22,255,56,0,0,255,255,0,186,254,86,4,100,6,55,16,38,3,75,0,0,16,7,10,166,0,144,0,0,255,255,0,186,254,86,4,100, + 6,55,16,38,10,171,0,0,16,7,3,22,255,56,0,0,255,255,255,252,0,0,5,237,6,102,16,39,3,42,1,98,0,0,16,7,10,209,255,82, + 0,0,0,0,255,255,255,231,0,0,5,117,6,102,16,6,3,31,0,0,255,255,255,252,0,0,6,169,6,102,16,39,3,44,1,110,0,0,16,7, + 10,209,255,82,0,0,0,0,255,255,255,243,0,0,6,31,6,102,16,6,3,32,0,0,255,255,0,201,254,86,5,59,5,213,16,38,3,44,0,0, + 16,7,10,164,0,255,0,0,255,255,0,137,4,194,3,146,6,102,16,39,10,165,255,3,0,0,16,7,10,209,1,9,0,0,0,0,255,255,0,180, + 4,194,3,148,6,102,16,39,10,165,255,46,0,0,16,6,10,220,66,0,255,255,0,182,4,194,3,74,7,109,16,39,22,187,4,0,1,132,16,6, + 10,165,0,0,255,255,255,235,0,0,2,110,6,72,16,38,3,77,0,0,16,7,2,154,255,36,0,0,255,255,255,227,0,0,2,110,5,246,16,38, + 3,77,0,0,16,7,0,113,255,14,0,0,255,255,255,216,0,0,2,110,7,210,16,38,3,77,0,0,16,7,10,207,255,46,0,0,255,255,0,5, + 0,0,2,128,7,210,16,6,3,37,0,0,255,255,255,228,0,0,2,120,6,55,16,38,3,77,0,0,16,7,10,166,255,46,0,0,255,255,255,230, + 0,0,2,122,7,109,16,38,3,77,0,0,16,7,10,167,255,48,0,0,255,255,255,245,0,0,2,103,7,109,16,38,3,46,0,0,16,7,22,192, + 3,46,1,117,255,255,0,3,0,0,2,89,7,49,16,38,3,46,0,0,16,7,0,113,255,46,1,59,255,255,255,252,0,0,3,4,6,102,16,39, + 3,46,1,113,0,0,16,7,10,209,255,82,0,0,0,0,255,255,255,237,0,0,2,125,6,102,16,6,3,33,0,0,255,255,0,126,4,194,3,139, + 6,102,16,39,10,221,254,248,0,0,16,7,10,209,1,2,0,0,0,0,255,255,0,149,4,194,3,177,6,102,16,39,10,221,255,15,0,0,16,6, + 10,220,95,0,255,255,0,182,4,194,3,74,7,109,16,39,22,187,4,0,1,132,16,6,10,221,0,0,255,255,0,149,255,227,4,42,6,72,16,38, + 3,89,0,0,16,6,2,154,39,0,0,0,255,255,0,149,255,227,4,42,5,246,16,38,3,89,0,0,16,6,0,113,36,0,0,0,255,255,0,149, + 255,227,4,42,7,210,16,38,3,89,0,0,16,6,10,207,27,0,0,0,255,255,0,149,255,227,4,42,7,210,16,6,3,68,0,0,255,255,0,186, + 254,86,4,164,6,97,16,38,3,85,0,0,16,7,10,165,0,187,0,0,255,255,0,186,254,86,4,164,6,97,16,38,3,85,0,0,16,7,10,221, + 0,177,0,0,255,255,0,149,255,227,4,42,6,55,16,38,3,89,0,0,16,6,10,166,39,0,0,0,255,255,0,149,255,227,4,42,7,109,16,38, + 3,89,0,0,16,6,10,167,26,0,0,0,255,255,255,252,0,0,4,231,7,109,16,38,3,57,0,0,16,7,22,192,4,118,1,117,255,255,255,252, + 0,0,4,231,7,49,16,38,3,57,0,0,16,7,0,113,0,128,1,59,255,255,255,252,0,0,6,199,6,102,16,39,3,57,1,224,0,0,16,7, + 10,209,255,82,0,0,0,0,255,255,255,225,0,0,6,145,6,102,16,6,3,35,0,0,255,255,0,7,0,0,5,53,6,97,16,39,3,54,0,168, + 0,0,16,7,10,221,254,129,0,0,0,0,255,255,0,170,5,70,3,41,7,210,18,38,0,106,0,0,16,7,10,209,0,0,1,108,255,255,0,215, + 5,70,3,82,7,210,16,6,3,28,0,0,255,255,0,170,4,240,2,137,6,102,16,6,0,67,0,0,255,255,0,135,254,86,6,39,6,102,16,38, + 10,101,0,0,16,7,3,22,1,89,0,0,255,255,0,135,254,86,6,39,4,96,16,38,3,93,0,0,16,7,3,22,1,89,0,0,255,255,0,135, + 254,86,6,39,6,102,16,38,3,98,0,0,16,7,3,22,1,89,0,0,255,255,0,135,255,227,6,39,6,55,16,38,3,93,0,0,16,7,10,166, + 1,79,0,0,255,255,0,135,254,86,6,39,6,55,16,38,10,213,0,0,16,7,3,22,1,89,0,0,255,255,255,252,255,227,7,20,6,102,16,39, + 3,52,1,59,0,0,16,7,10,209,255,82,0,0,0,0,255,255,255,242,255,227,6,1,6,102,16,6,3,34,0,0,255,255,255,252,0,0,7,19, + 6,102,16,39,3,61,1,68,0,0,16,7,10,209,255,82,0,0,0,0,255,255,255,219,0,0,6,5,6,102,16,6,3,36,0,0,255,255,0,78, + 254,86,5,207,5,231,16,38,3,61,0,0,16,7,10,164,1,14,0,0,255,255,1,115,4,238,3,82,6,102,16,6,0,118,0,0,0,1,1,134, + 4,194,2,120,6,97,0,8,0,72,180,2,7,4,0,9,16,212,192,220,178,63,7,1,93,60,49,182,0,3,2,3,6,7,9,0,16,212,180,63, + 7,95,7,2,93,176,17,75,80,88,204,27,192,89,204,204,178,63,2,1,93,17,57,48,177,3,6,73,177,2,3,73,80,88,179,3,64,4,64,56, + 56,89,1,53,51,21,35,20,55,21,34,1,134,242,134,134,242,5,205,148,158,157,3,103,0,1,0,100,1,223,2,127,2,131,0,3,0,17,182,0, + 156,2,4,1,0,4,16,220,204,49,0,16,212,236,48,19,33,21,33,100,2,27,253,229,2,131,164,0,255,255,0,100,1,223,2,127,2,131,18,6, + 10,238,0,0,0,1,0,100,1,233,4,179,2,121,0,3,0,16,182,2,169,0,233,4,1,0,47,198,49,0,16,252,236,48,19,33,21,33,100,4, + 79,251,177,2,121,144,0,0,0,1,0,100,1,233,3,156,2,121,0,3,0,16,182,2,169,0,233,4,1,0,47,198,49,0,16,252,236,48,19,33, + 21,33,100,3,56,252,200,2,121,144,0,0,0,1,0,100,1,233,7,156,2,121,0,3,0,15,181,2,169,0,4,1,0,47,204,49,0,16,212,236, + 48,19,33,21,33,100,7,56,248,200,2,121,144,0,0,0,0,1,0,0,1,233,8,0,2,121,0,3,0,15,181,2,169,0,4,1,0,47,204,49, + 0,16,212,236,48,17,33,21,33,8,0,248,0,2,121,144,255,255,1,4,254,29,2,248,6,29,16,38,0,95,0,0,16,7,0,95,1,74,0,0, + 255,255,255,236,254,29,4,20,255,238,16,38,0,66,0,0,16,7,0,66,0,0,1,66,0,1,0,174,3,233,1,211,5,213,0,5,0,24,64,11, + 0,158,3,129,6,3,4,0,25,1,6,16,220,252,212,204,49,0,16,244,236,48,1,35,53,19,51,3,1,129,211,164,129,82,3,233,173,1,63,254, + 193,0,0,0,0,1,0,178,3,254,1,215,5,213,0,5,0,24,64,11,3,158,0,129,6,3,4,1,25,0,6,16,220,236,212,204,49,0,16,244, + 236,48,1,51,21,3,35,19,1,4,211,164,129,82,5,213,152,254,193,1,63,0,0,0,0,1,0,174,255,18,1,211,0,254,0,5,0,24,64,11, + 3,158,0,131,6,3,4,1,25,0,6,16,212,236,212,204,49,0,16,252,236,48,37,51,21,3,35,19,1,0,211,164,129,82,254,172,254,192,1,64, + 0,1,0,178,3,254,1,215,5,213,0,5,0,0,1,21,19,35,3,53,1,133,82,129,164,5,213,152,254,193,1,63,152,0,0,0,0,2,0,174, + 3,233,3,109,5,213,0,5,0,11,0,39,64,19,6,0,158,9,3,129,12,9,10,6,25,7,3,4,7,0,25,1,12,16,220,252,204,212,204,16, + 254,212,206,49,0,16,244,60,236,50,48,1,35,53,19,51,3,5,35,53,19,51,3,1,129,211,164,129,82,1,154,211,164,129,82,3,233,173,1,63, + 254,193,173,173,1,63,254,193,0,2,0,174,3,233,3,109,5,213,0,5,0,11,0,39,64,19,9,3,158,6,0,129,12,9,10,7,25,6,1,3, + 4,1,25,0,12,16,220,236,212,204,16,220,238,212,206,49,0,16,244,60,236,50,48,1,51,21,3,35,19,37,51,21,3,35,19,1,0,211,164,129, + 82,1,154,211,164,129,82,5,213,172,254,192,1,64,172,172,254,192,1,64,0,2,0,174,255,18,3,109,0,254,0,5,0,11,0,39,64,19,9,3, + 158,6,0,131,12,3,4,1,25,0,7,9,10,7,25,6,12,16,220,236,212,204,16,220,238,212,206,49,0,16,252,60,236,50,48,37,51,21,3,35, + 19,37,51,21,3,35,19,2,154,211,164,129,82,254,102,211,164,129,82,254,172,254,192,1,64,172,172,254,192,1,64,0,0,2,0,174,3,233,3,109, + 5,213,0,5,0,11,0,0,1,21,19,35,3,53,33,21,19,35,3,53,1,129,82,129,164,2,109,82,129,164,5,213,173,254,193,1,63,173,173,254, + 193,1,63,173,0,1,0,57,255,59,3,199,5,213,0,11,0,39,64,20,8,4,185,10,2,0,129,6,194,12,3,89,5,1,87,9,89,7,0,12, + 16,212,60,236,252,60,236,49,0,16,228,244,212,60,236,50,48,1,51,17,33,21,33,17,35,17,33,53,33,1,168,176,1,111,254,145,176,254,145,1, + 111,5,213,254,92,153,251,163,4,93,153,0,0,1,0,57,255,59,3,199,5,213,0,19,0,62,64,32,18,6,185,0,16,8,185,10,4,0,2,14, + 10,12,129,2,194,20,15,0,89,17,13,1,87,9,5,89,11,7,3,20,16,212,60,60,236,50,252,60,60,236,50,49,0,16,228,244,196,50,16,196, + 50,16,238,50,16,238,50,48,37,33,17,35,17,33,53,33,17,33,53,33,17,51,17,33,21,33,17,33,3,199,254,145,176,254,145,1,111,254,145,1, + 111,176,1,111,254,145,1,111,223,254,92,1,164,154,2,31,153,1,164,254,92,153,253,225,0,1,1,51,1,209,3,133,4,33,0,11,0,18,183,9, + 199,3,12,6,92,0,12,16,212,236,49,0,16,212,236,48,1,52,54,51,50,22,21,20,6,35,34,38,1,51,173,126,124,171,172,125,125,172,2,250, + 124,171,171,124,125,172,172,0,0,1,1,51,1,129,3,213,4,113,0,2,0,0,1,17,1,1,51,2,162,1,129,2,240,254,136,0,0,1,0,236, + 0,0,1,193,0,254,0,3,0,17,179,1,25,0,4,16,212,236,49,0,178,0,131,2,47,236,48,55,51,21,35,236,213,213,254,254,0,2,0,236, + 0,0,4,107,0,254,0,3,0,7,0,26,182,0,25,1,5,25,4,8,16,212,252,212,236,49,0,180,4,0,131,6,2,47,60,236,50,48,37,51, + 21,35,37,51,21,35,3,150,213,213,253,86,213,213,254,254,254,254,0,0,0,3,0,236,0,0,7,20,0,254,0,3,0,7,0,11,0,35,64,17, + 8,4,0,131,10,6,2,4,25,5,0,25,1,9,25,8,12,16,212,252,212,236,212,236,49,0,47,60,60,236,50,50,48,37,51,21,35,37,51,21, + 35,37,51,21,35,3,150,212,212,2,169,213,213,250,173,213,213,254,254,254,254,254,254,0,0,1,0,220,2,107,1,175,3,105,0,3,0,0,19,51, + 21,35,220,211,211,3,105,254,0,7,0,113,255,227,10,76,5,240,0,11,0,23,0,35,0,39,0,51,0,63,0,75,0,174,64,68,36,15,37,38, + 37,38,15,39,36,39,66,64,0,146,12,46,146,30,141,40,146,24,70,6,146,52,12,141,58,38,18,140,36,24,145,76,37,73,67,39,49,43,67,13, + 61,9,13,15,14,3,13,21,49,13,27,61,14,73,13,21,55,43,13,27,14,33,11,76,16,252,228,236,212,196,236,228,16,238,16,238,246,238,16,238, + 17,18,57,17,18,57,49,0,16,228,50,244,60,60,228,50,236,50,16,238,246,238,16,238,50,48,75,83,88,7,16,5,237,7,16,5,237,89,34,1, + 75,176,20,84,75,176,9,84,91,75,176,11,84,91,75,176,12,84,91,75,176,13,84,91,75,176,14,84,91,88,189,0,76,0,64,0,1,0,76,0, + 76,255,192,56,17,55,56,89,1,34,6,21,20,22,51,50,54,53,52,38,39,50,22,21,20,6,35,34,38,53,52,54,1,50,22,21,20,6,35,34, + 38,53,52,54,33,51,1,35,19,34,6,21,20,22,51,50,54,53,52,38,1,50,22,21,20,6,35,34,38,53,52,54,23,34,6,21,20,22,51,50, + 54,53,52,38,8,244,87,100,100,87,85,99,99,85,158,186,187,157,160,186,187,249,116,158,188,187,159,159,185,186,4,37,160,252,90,160,31,86,99,98, + 87,87,99,100,3,178,158,186,187,157,160,186,187,159,87,99,99,87,85,99,99,2,145,148,132,130,149,149,130,131,149,127,220,187,187,219,219,187,188,219, + 2,224,219,187,189,218,219,188,186,220,249,243,5,142,149,130,132,148,148,132,129,150,253,159,220,187,187,219,219,187,188,219,127,148,132,130,149,149,130,131, + 149,0,0,0,0,9,0,113,255,227,13,114,5,240,0,11,0,22,0,34,0,45,0,55,0,59,0,69,0,80,0,92,0,0,1,34,6,21,20,22, + 51,50,54,53,52,38,39,50,22,16,6,35,34,38,53,52,54,5,34,6,21,20,22,51,50,54,53,52,38,39,50,22,16,6,35,34,38,53,52,54, + 0,32,22,21,20,6,32,38,53,52,37,51,1,35,18,34,6,21,20,22,50,54,53,52,1,50,22,16,6,35,34,38,53,52,54,23,34,6,21,20, + 22,51,50,54,53,52,38,12,26,87,100,100,87,85,99,99,85,158,186,187,157,160,186,187,253,121,87,100,100,87,85,99,99,85,158,186,187,157,160,186, + 187,248,214,1,60,188,187,254,194,185,4,223,160,252,90,160,117,172,99,98,174,99,3,78,158,186,187,157,160,186,187,159,87,99,99,87,85,99,99,2, + 145,148,132,130,149,149,130,131,149,127,220,254,138,219,219,187,188,219,127,148,132,130,149,149,130,131,149,127,220,254,138,219,219,187,188,219,2,224,219,187, + 189,218,219,188,186,220,249,243,5,142,149,130,132,148,148,132,129,254,53,220,254,138,219,219,187,188,219,127,148,132,130,149,149,130,131,149,0,1,0,40, + 4,96,1,160,5,213,0,3,0,0,27,1,51,1,40,173,203,254,223,4,96,1,117,254,139,0,0,0,255,255,0,40,4,96,2,204,5,213,16,38, + 11,16,0,0,16,7,11,16,1,44,0,0,255,255,0,40,4,96,3,248,5,213,16,39,11,16,1,44,0,0,16,38,11,16,0,0,16,7,11,16, + 2,88,0,0,0,1,0,40,4,96,1,160,5,213,0,3,0,0,1,35,1,51,1,160,87,254,223,203,4,96,1,117,255,255,0,40,4,96,2,204, + 5,213,16,38,11,19,0,0,16,7,11,19,1,44,0,0,255,255,0,40,4,96,3,248,5,213,16,38,11,19,0,0,16,39,11,19,2,88,0,0, + 16,7,11,19,1,44,0,0,0,1,0,11,254,29,2,171,255,195,0,5,0,0,1,35,39,7,35,1,2,171,148,187,188,149,1,82,254,29,249,249, + 1,166,0,0,0,1,0,158,0,141,2,115,4,35,0,6,0,71,64,37,3,232,4,5,4,2,232,1,2,5,5,4,2,232,3,2,6,0,6,1, + 232,0,6,66,2,4,231,0,166,7,2,3,0,111,5,110,7,16,252,236,50,57,49,0,16,244,236,57,48,75,83,88,7,4,237,7,16,8,237,7, + 16,8,237,7,16,4,237,89,34,1,21,9,1,21,1,53,2,115,254,211,1,45,254,43,4,35,191,254,244,254,244,191,1,162,82,0,0,1,0,193, + 0,141,2,150,4,35,0,6,0,73,64,38,5,232,6,5,2,3,2,4,232,3,3,2,6,232,0,1,0,5,232,4,5,1,1,0,66,5,3,231, + 0,166,7,5,1,111,3,0,112,7,16,252,60,236,57,49,0,16,244,236,57,48,75,83,88,7,16,8,237,7,16,4,237,7,16,4,237,7,16,8, + 237,89,34,19,1,21,1,53,9,1,193,1,213,254,43,1,45,254,211,4,35,254,94,82,254,94,191,1,12,1,12,0,255,255,0,195,0,4,5,235, + 5,204,18,38,0,153,0,75,16,39,0,17,255,232,2,78,16,39,0,17,2,22,0,4,16,39,0,17,4,61,2,78,16,7,0,17,2,22,4,206, + 255,255,0,147,0,0,3,79,5,213,16,39,0,4,255,94,0,0,16,7,0,4,1,79,0,0,0,0,0,3,0,147,0,0,3,176,5,240,0,23, + 0,27,0,36,0,0,1,35,17,6,7,6,7,53,62,1,51,50,22,21,20,6,15,1,14,1,7,14,1,21,3,51,21,35,19,17,55,62,1,53, + 52,39,38,2,76,191,31,32,90,97,94,193,103,184,223,72,90,88,47,39,8,6,6,197,203,203,197,45,57,51,65,37,1,145,3,173,8,13,35,67, + 188,57,56,194,159,76,137,86,86,47,53,25,21,60,52,254,242,254,5,66,254,82,45,53,94,49,89,55,31,0,0,0,255,255,255,236,5,124,4,20, + 6,11,16,7,0,66,0,0,7,95,0,0,0,1,255,167,254,27,6,199,255,133,0,13,0,37,179,4,15,10,14,16,196,212,196,179,7,0,15,14, + 17,18,57,57,49,64,7,11,3,10,4,7,0,14,0,16,212,220,220,60,204,50,48,1,50,36,55,21,6,4,35,34,36,39,53,22,4,3,54,231, + 1,197,229,235,254,58,224,223,254,60,236,230,1,194,254,181,104,104,126,118,118,117,119,126,105,103,0,0,0,1,255,167,6,4,6,199,7,110,0,13, + 0,37,179,4,15,10,14,16,196,212,196,179,7,0,15,14,17,18,57,57,49,64,7,10,4,11,3,0,7,14,0,16,212,220,220,60,204,50,48,1, + 50,4,23,21,38,36,35,34,4,7,53,54,36,3,54,224,1,198,235,229,254,59,231,231,254,62,230,236,1,196,7,110,118,118,126,104,104,103,105,126, + 119,117,0,0,0,1,255,170,254,29,2,73,1,213,0,7,0,0,1,51,9,1,35,11,1,35,1,231,98,254,226,1,30,98,237,237,99,1,213,254, + 36,254,36,1,138,254,118,0,255,255,0,61,255,197,7,195,6,131,16,39,0,13,0,0,253,123,16,39,0,13,4,0,253,123,16,7,0,13,2,0, + 0,147,0,0,0,1,0,221,2,129,3,51,3,95,0,3,0,0,19,33,21,33,221,2,86,253,170,3,95,222,0,0,0,1,254,137,255,227,2,205, + 5,240,0,3,0,43,64,19,0,15,1,2,1,2,15,3,0,3,66,2,140,0,145,4,1,3,4,16,212,204,49,0,16,228,228,48,75,83,88,7, + 16,5,237,7,16,5,237,89,34,1,51,1,35,2,45,160,252,92,160,5,240,249,243,0,0,1,0,176,254,242,2,88,6,20,0,11,0,0,1,17, + 51,21,33,17,33,21,35,17,51,21,1,104,240,254,88,1,168,240,240,2,94,253,35,143,7,34,143,253,35,74,0,0,0,1,0,176,254,242,2,88, + 6,20,0,11,0,0,19,53,51,17,35,53,33,17,33,53,51,17,176,240,240,1,168,254,88,240,2,94,74,2,221,143,248,222,143,2,221,0,0,0, + 255,255,0,74,0,0,7,23,5,240,16,38,0,34,183,0,16,7,0,34,3,103,0,0,255,255,0,147,0,0,5,74,5,240,16,38,0,34,0,0, + 16,7,0,4,3,74,0,0,255,255,0,147,0,0,5,74,5,240,16,39,0,4,255,94,0,0,16,7,0,34,1,154,0,0,0,0,0,1,0,100, + 255,5,3,150,4,93,0,11,0,55,183,5,6,7,8,4,4,0,12,16,220,212,23,57,49,0,64,10,66,11,8,169,2,4,0,188,6,12,16,204, + 244,60,196,236,50,48,75,83,88,183,8,17,5,7,17,6,5,6,7,5,16,236,16,236,89,19,22,51,50,55,7,1,35,1,6,32,39,100,154,234, + 251,179,8,254,224,152,1,8,117,254,195,200,4,93,16,16,128,251,40,4,174,15,15,0,0,1,0,236,255,59,4,135,5,213,0,13,0,0,1,50, + 4,21,20,6,7,17,35,17,35,17,35,17,2,172,215,1,4,235,215,142,190,141,5,213,232,190,184,221,17,252,178,6,31,249,225,6,154,0,0,0, + 0,2,0,216,1,194,3,40,4,18,0,3,0,11,0,0,1,51,17,7,43,1,34,38,53,52,54,51,2,121,175,175,118,2,125,172,173,126,4,18, + 253,177,1,172,125,124,171,0,0,2,0,216,1,194,3,40,4,18,0,3,0,11,0,0,1,39,17,59,1,50,22,21,20,6,43,1,1,135,175,175, + 118,126,173,172,125,2,1,194,1,2,79,171,124,125,172,0,255,255,0,61,255,197,3,195,3,107,18,7,0,13,0,0,253,123,0,0,0,2,1,29, + 255,18,2,66,4,35,0,3,0,9,0,0,1,21,35,53,19,21,19,35,3,53,1,240,211,211,82,129,164,4,35,254,254,252,219,172,254,192,1,64, + 172,0,0,0,255,255,255,167,254,27,6,199,7,110,16,38,11,29,0,0,16,6,11,30,0,0,0,0,255,255,0,61,255,242,3,195,7,111,18,39, + 0,13,0,0,253,168,16,7,0,13,0,0,1,127,0,0,255,255,0,145,255,66,3,67,5,213,16,39,0,18,0,145,0,0,16,39,0,17,1,142, + 0,0,16,7,0,17,255,217,4,72,0,0,0,1,0,100,1,211,7,156,3,49,0,29,0,0,1,21,14,1,35,34,39,38,39,38,39,38,35,34, + 6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,7,156,158,230,146,148,236,16,8,10,23,233,140,132,220,148,158,230,146,176,210,14,8,12, + 21,233,140,130,215,3,49,178,79,68,59,4,2,2,6,62,77,83,178,79,69,60,4,2,3,5,62,76,255,255,255,167,254,20,6,199,255,126,16,7, + 11,30,0,0,248,16,0,0,0,1,1,56,0,200,5,124,5,13,0,23,0,0,1,17,35,17,7,39,55,33,53,33,39,55,23,17,51,17,55,23, + 7,33,21,33,23,7,3,170,160,249,113,249,254,159,1,97,250,113,250,160,250,113,250,1,97,254,159,250,113,2,41,254,159,1,96,249,114,249,160,250, + 114,251,1,98,254,158,250,113,250,160,249,114,0,3,0,250,1,50,3,182,4,182,0,3,0,7,0,11,0,0,19,53,51,21,1,53,51,21,3,53, + 51,21,250,200,1,44,200,200,200,2,144,200,200,254,162,200,200,2,188,200,200,0,0,0,255,255,0,40,4,96,5,36,5,213,16,39,11,16,1,44, + 0,0,16,38,11,16,0,0,16,39,11,16,3,132,0,0,16,7,11,16,2,88,0,0,0,4,1,102,1,0,5,78,4,232,0,3,0,7,0,11, + 0,15,0,0,1,53,51,21,33,53,51,21,1,53,51,21,3,53,51,21,1,102,200,2,88,200,253,168,200,200,200,2,144,200,200,200,200,254,112,200, + 200,3,32,200,200,0,0,0,0,5,1,102,0,246,5,78,4,222,0,3,0,7,0,11,0,15,0,19,0,0,1,53,51,21,19,53,51,21,3,53, + 51,21,1,53,51,21,3,53,51,21,2,246,200,200,200,200,200,252,44,200,220,200,2,134,200,200,254,112,200,200,3,32,200,200,252,244,200,200,3,12, + 200,200,0,0,0,2,0,219,0,0,1,174,5,213,0,3,0,7,0,0,19,51,21,35,17,51,21,35,219,211,211,211,211,5,213,254,252,39,254,0, + 0,4,0,100,254,229,5,253,6,239,0,3,0,7,0,11,0,15,0,0,19,51,21,35,37,51,21,35,1,51,21,35,17,51,21,35,100,211,211,4, + 198,211,211,253,157,211,211,211,211,3,105,254,254,254,4,132,254,249,242,254,0,5,0,112,0,0,6,68,5,213,0,3,0,7,0,11,0,15,0,27, + 0,0,37,53,51,21,3,53,51,21,1,53,51,21,3,53,51,21,1,17,35,17,33,53,33,17,51,17,33,21,4,134,200,200,200,252,44,200,220,200, + 1,124,160,253,102,2,154,160,2,154,246,200,200,3,32,200,200,252,244,200,200,3,12,200,200,254,132,253,102,2,154,160,2,155,253,101,160,0,0,0, + 0,3,0,219,0,80,1,174,5,62,0,3,0,7,0,11,0,0,19,51,21,35,17,51,21,35,17,51,21,35,219,211,211,211,211,211,211,5,62,254, + 253,14,254,2,246,254,0,0,0,4,0,219,0,17,1,174,5,119,0,3,0,7,0,11,0,15,0,0,19,51,21,35,17,51,21,35,17,51,21,35, + 17,51,21,35,219,211,211,211,211,211,211,211,211,2,137,254,3,236,254,252,150,254,3,240,254,0,0,0,0,2,0,87,2,141,2,238,5,240,0,13, + 0,25,0,0,0,34,7,6,21,20,23,22,50,55,54,53,52,47,1,50,22,21,20,6,35,34,38,53,52,54,2,8,202,50,51,51,50,202,50,51, + 51,151,161,170,170,161,162,170,170,5,151,86,86,172,173,86,86,86,86,173,172,86,175,222,211,212,222,222,212,211,222,0,0,2,0,122,2,156,0,238, + 6,3,0,3,0,7,0,31,64,6,9,5,1,4,0,8,16,220,60,220,60,204,49,0,64,6,4,7,0,3,0,8,16,212,196,16,220,204,48,19, + 51,17,35,17,51,21,35,122,116,116,116,116,5,15,253,141,3,103,130,0,0,2,0,63,2,156,2,244,5,223,0,2,0,13,0,212,64,22,0,3, + 11,7,221,5,1,9,247,3,145,14,1,12,10,0,93,6,8,4,12,14,16,220,212,60,196,236,50,17,57,49,0,16,244,252,212,60,236,50,18,57, + 48,1,75,176,14,84,75,176,15,84,91,75,176,16,84,91,75,176,17,84,91,75,176,11,84,91,75,176,10,84,91,88,189,0,14,0,64,0,1,0, + 14,0,14,255,192,56,17,55,56,89,0,75,176,17,84,75,176,14,84,91,88,189,0,14,255,192,0,1,0,14,0,14,0,64,56,17,55,56,89,64, + 84,11,1,29,1,47,1,57,1,73,1,70,3,89,3,105,3,139,3,171,3,187,3,11,1,0,15,1,15,2,15,5,15,6,15,7,15,8,15,11, + 15,12,15,13,19,0,31,1,31,2,31,5,31,6,31,7,31,8,31,11,31,12,31,13,34,0,53,0,71,0,75,13,83,0,91,13,101,0,132,0, + 165,0,181,0,30,93,1,93,9,1,33,3,51,17,51,21,35,21,35,53,33,53,1,221,254,203,1,53,22,166,135,135,144,254,98,5,102,254,93,2, + 28,253,228,109,186,186,121,0,0,1,0,102,2,141,2,211,5,223,0,32,0,0,19,33,21,33,21,54,55,54,51,50,23,22,21,20,7,6,35,34, + 38,39,53,22,23,22,51,50,54,52,38,35,34,6,7,142,1,254,254,121,28,29,28,28,161,94,94,97,96,176,60,126,66,57,62,62,69,111,130,130, + 111,52,104,54,5,223,95,204,9,4,4,77,76,131,135,75,74,18,18,113,27,14,13,102,174,102,20,21,0,2,0,92,2,141,2,243,5,240,0,15, + 0,47,0,0,1,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38,19,21,38,39,38,35,34,7,6,7,54,55,54,51,50,23,22,21,20,7, + 6,35,34,38,53,52,55,54,51,50,23,22,1,179,88,51,51,51,51,88,87,51,51,51,51,171,49,50,50,49,128,68,68,10,38,57,58,68,145,84, + 84,88,87,145,167,176,108,108,182,49,50,50,4,109,52,53,91,90,52,53,53,52,90,91,53,52,1,98,103,20,10,11,75,76,153,49,26,26,76,77, + 132,127,79,78,222,212,198,117,118,8,9,0,0,1,0,108,2,156,2,213,5,223,0,6,0,0,19,33,21,1,35,1,33,108,2,105,254,164,136,1, + 72,254,51,5,223,48,252,237,2,228,0,0,0,3,0,89,2,141,2,236,5,240,0,12,0,42,0,58,0,0,0,34,7,6,21,20,22,51,50,55, + 54,52,39,37,38,39,38,53,52,54,32,23,22,21,20,7,6,7,22,23,22,21,20,7,6,35,34,39,38,53,52,55,54,55,20,23,22,51,50,55, + 54,53,52,39,38,35,34,7,6,2,0,186,53,53,106,93,92,54,53,53,254,236,84,46,47,164,1,30,82,81,46,47,83,90,56,53,85,86,158,159, + 85,86,53,54,45,47,46,85,81,49,48,48,47,83,83,48,47,4,42,44,43,75,76,86,44,43,150,43,93,18,49,50,72,100,116,58,58,100,74,48, + 49,18,18,58,55,80,121,65,65,65,65,121,78,57,56,198,63,38,37,37,36,65,63,38,37,37,36,0,0,2,0,83,2,141,2,233,5,240,0,31, + 0,46,0,0,19,53,22,23,22,51,50,55,54,55,6,7,6,35,34,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34,39,38,19,50,54,53, + 52,39,38,35,34,7,6,21,20,23,22,145,49,50,50,48,129,68,67,10,35,60,57,69,144,168,87,88,145,167,87,88,107,108,182,49,50,50,204,88, + 102,51,51,88,85,53,52,52,51,2,174,103,20,11,10,75,75,154,47,27,26,152,132,129,77,78,111,111,212,198,117,118,8,9,1,114,104,92,90,52, + 53,53,52,90,92,52,52,0,0,1,0,137,2,156,3,176,5,107,0,11,0,0,1,17,33,21,33,17,35,17,33,53,33,17,2,81,1,95,254,161, + 105,254,161,1,95,5,107,254,200,95,254,200,1,56,95,1,56,0,0,0,0,1,0,137,3,212,3,176,4,51,0,3,0,0,19,33,21,33,137,3, + 39,252,217,4,51,95,0,0,0,2,0,137,3,97,3,176,4,165,0,3,0,7,0,0,19,33,21,33,21,33,21,33,137,3,39,252,217,3,39,252, + 217,4,165,94,135,95,0,0,0,1,0,111,2,5,1,144,6,2,0,13,0,0,1,14,1,16,22,23,35,38,39,38,52,55,54,55,1,144,84,82, + 82,84,101,94,47,47,47,46,95,6,2,129,252,254,254,254,128,131,128,127,250,127,126,132,0,1,0,103,2,5,1,136,6,2,0,15,0,0,19,51, + 22,23,22,20,7,6,7,35,54,55,54,16,39,38,103,101,95,47,46,46,47,95,101,84,41,42,42,41,6,2,132,126,127,250,127,128,131,128,127,127, + 1,2,126,126,0,1,0,117,2,156,2,196,5,30,0,19,0,48,64,7,21,0,3,14,10,11,20,16,212,220,60,47,204,204,75,176,13,81,88,177, + 21,64,56,89,49,178,127,21,1,93,0,64,6,6,17,12,2,11,20,16,212,60,196,212,204,48,1,17,35,17,52,38,35,34,6,21,17,35,17,51, + 21,62,1,51,50,22,2,196,116,78,78,94,108,117,117,41,113,74,121,125,4,23,254,133,1,119,89,89,107,92,254,158,2,115,97,56,56,134,0,0, + 255,255,0,87,255,241,2,238,3,84,18,7,11,73,0,0,253,100,0,0,255,255,0,137,0,0,2,197,3,67,18,7,0,123,0,0,253,100,0,0, + 255,255,0,94,0,0,2,180,3,84,18,7,0,116,0,0,253,100,0,0,255,255,0,98,255,241,2,205,3,84,18,7,0,117,0,0,253,100,0,0, + 255,255,0,63,0,0,2,244,3,67,18,7,11,75,0,0,253,100,0,0,255,255,0,102,255,241,2,211,3,67,18,7,11,76,0,0,253,100,0,0, + 255,255,0,92,255,241,2,243,3,84,18,7,11,77,0,0,253,100,0,0,255,255,0,108,0,0,2,213,3,67,18,7,11,78,0,0,253,100,0,0, + 255,255,0,89,255,241,2,236,3,84,18,7,11,79,0,0,253,100,0,0,255,255,0,83,255,241,2,233,3,84,18,7,11,80,0,0,253,100,0,0, + 255,255,0,137,0,0,3,176,2,207,18,7,11,81,0,0,253,100,0,0,255,255,0,137,1,56,3,176,1,151,18,7,11,82,0,0,253,100,0,0, + 255,255,0,137,0,197,3,176,2,9,18,7,11,83,0,0,253,100,0,0,255,255,0,111,255,105,1,144,3,102,18,7,11,84,0,0,253,100,0,0, + 255,255,0,103,255,105,1,136,3,102,18,7,11,85,0,0,253,100,0,0,255,255,0,77,255,240,2,161,2,130,18,7,8,162,0,0,253,100,0,0, + 255,255,0,71,255,240,2,213,2,130,18,7,8,168,0,0,253,100,0,0,255,255,0,71,255,240,2,207,2,130,18,7,8,177,0,0,253,100,0,0, + 255,255,0,117,0,0,3,33,2,115,18,7,2,165,0,0,253,100,0,0,255,255,0,71,255,240,2,213,2,130,18,7,8,169,0,0,253,100,0,0, + 255,255,0,117,0,0,2,196,3,103,18,7,2,114,0,0,253,100,0,0,255,255,0,117,0,0,2,231,3,103,18,7,8,174,0,0,253,100,0,0, + 255,255,0,122,0,0,0,238,3,103,18,7,2,163,0,0,253,100,0,0,255,255,0,117,0,0,4,123,2,130,18,7,8,175,0,0,253,100,0,0, + 255,255,0,117,0,0,2,196,2,130,18,7,11,86,0,0,253,100,0,0,255,255,0,117,255,17,2,236,2,130,18,7,8,181,0,0,253,100,0,0, + 255,255,0,117,0,0,2,144,2,147,18,7,2,164,0,0,253,100,0,0,255,255,0,35,0,0,1,219,3,37,18,7,8,182,0,0,253,100,0,0, + 0,1,0,86,0,0,6,174,5,214,0,35,0,0,1,14,1,35,34,0,16,0,51,50,22,23,21,46,1,35,34,6,16,22,51,50,54,55,17,33, + 21,33,17,33,21,33,17,33,21,33,3,221,79,178,99,254,254,219,1,37,254,101,177,78,76,173,98,192,204,204,192,98,173,76,2,196,253,211,2,22, + 253,234,2,58,253,47,1,184,54,54,1,55,2,28,1,55,53,54,159,71,70,234,254,68,234,70,71,2,10,128,254,181,128,254,107,128,0,3,0,115, + 255,166,4,190,6,57,0,39,0,46,0,52,0,0,1,22,23,55,51,7,22,23,21,38,39,1,51,50,54,55,21,14,1,35,34,39,7,35,55,38, + 39,7,35,55,38,39,38,17,16,55,54,37,55,51,7,6,7,6,17,20,23,1,38,39,1,22,23,3,104,65,62,30,155,47,40,37,58,64,254,193, + 18,119,211,93,97,216,121,27,26,18,155,25,65,57,38,155,65,19,17,178,178,160,1,8,21,156,227,145,88,125,82,2,52,62,67,254,193,53,65,5, + 235,8,19,105,165,22,28,213,60,41,251,151,94,95,211,72,72,2,63,87,18,30,135,230,18,21,207,1,103,1,104,208,185,20,75,252,31,112,157,254, + 216,238,148,3,203,19,4,251,149,40,21,0,0,1,0,96,255,228,4,179,5,240,0,44,0,0,37,54,55,54,55,21,14,1,35,32,0,17,16,0, + 33,50,22,23,21,46,1,35,34,2,17,16,23,22,23,17,51,21,62,1,51,50,22,31,1,46,1,35,34,6,21,3,46,97,88,106,93,97,217,121, + 254,202,254,155,1,101,1,54,123,217,95,93,212,119,234,249,124,94,153,152,48,154,110,15,38,23,1,26,60,36,128,139,138,7,39,47,95,211,72,71, + 1,158,1,103,1,104,1,159,71,71,213,95,94,254,199,254,216,254,217,156,117,30,3,93,157,92,89,4,5,170,16,15,182,171,0,0,0,1,0,133, + 0,0,4,203,5,213,0,17,0,0,1,17,33,21,33,17,33,21,33,17,51,21,35,17,35,17,35,53,1,113,3,90,253,112,2,80,253,176,250,250, + 202,236,1,126,4,87,170,254,72,170,254,181,69,254,199,1,57,69,0,0,0,1,0,129,0,0,4,98,5,240,0,35,0,0,1,17,33,21,33,53, + 51,17,35,53,51,53,35,53,51,53,16,54,51,50,22,23,21,46,1,35,34,6,29,1,33,21,33,21,33,21,2,53,2,45,252,31,236,191,191,199, + 199,214,232,61,151,79,76,136,61,148,116,1,135,254,121,1,143,1,236,254,190,170,170,1,66,143,143,143,95,1,5,243,31,29,182,41,41,155,212,72, + 143,143,143,0,0,1,0,186,255,66,7,29,5,30,0,43,0,0,5,35,1,38,39,38,35,34,7,6,21,17,35,17,51,21,54,55,54,51,50,23, + 22,23,19,51,7,54,51,50,22,21,17,35,17,52,38,35,34,6,21,17,35,17,2,204,170,1,109,5,52,57,119,141,83,83,185,185,62,89,88,121, + 122,85,54,37,133,170,88,92,120,175,190,185,114,117,143,166,185,190,3,120,141,71,77,95,97,162,253,135,4,96,174,102,50,49,62,38,62,1,69,214, + 51,246,225,253,92,2,158,161,156,190,164,253,135,1,29,0,0,5,0,117,0,0,5,135,5,213,0,2,0,6,0,34,0,38,0,41,0,0,1,39, + 21,19,39,35,21,3,33,19,51,17,51,17,51,21,35,21,51,21,35,17,33,3,35,17,35,17,35,53,51,53,35,53,51,5,23,51,53,3,23,53, + 2,75,79,182,56,126,196,1,16,211,229,196,195,195,195,195,254,240,211,229,196,195,195,195,195,2,18,56,126,79,79,3,175,206,206,254,242,147,147,3, + 52,253,218,2,38,253,218,123,147,123,253,218,2,38,253,218,2,38,123,147,123,123,147,147,254,242,206,206,0,2,0,201,255,227,9,206,5,213,0,8, + 0,80,0,0,1,17,51,50,54,53,52,38,35,1,6,7,6,43,1,17,35,17,33,50,23,22,23,51,17,51,17,33,21,33,17,20,22,59,1,53, + 30,1,51,50,54,53,52,38,47,1,46,1,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,38,39,53, + 35,34,38,53,17,1,135,239,133,145,145,133,1,221,6,113,122,236,239,190,1,173,236,122,87,24,81,174,1,101,254,155,71,108,171,96,187,91,122,132, + 95,161,60,161,143,211,194,96,169,72,74,158,85,129,129,93,139,59,185,155,233,203,85,183,102,171,201,152,5,47,253,207,146,135,134,146,254,204,200,106, + 113,253,168,5,213,113,82,136,1,62,254,194,143,253,160,137,78,35,53,53,89,81,75,80,37,15,36,149,130,158,172,30,30,174,40,40,84,84,64,73, + 33,14,42,153,137,156,182,35,35,1,159,210,2,96,0,0,0,2,0,201,255,227,8,51,5,213,0,7,0,69,0,0,1,17,51,50,54,16,38,35, + 1,23,35,3,46,1,43,1,17,35,17,33,32,22,21,20,6,7,30,1,31,1,22,23,22,51,50,54,53,52,38,47,1,46,1,53,52,54,51,50, + 22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,39,38,1,147,254,146,149,149,146,2,191,4,217,191,74,139,120,220,202,1, + 200,1,0,252,131,125,65,123,62,91,98,96,99,97,130,140,101,171,64,171,152,224,206,102,180,76,78,168,90,137,137,98,148,63,196,165,247,216,90,97, + 44,5,47,253,238,135,1,6,133,250,216,7,1,127,150,98,253,137,5,213,214,216,141,186,36,22,144,126,180,51,25,27,89,81,75,80,37,15,36,149, + 130,158,172,30,30,174,40,40,84,84,64,73,33,14,42,153,137,156,182,18,8,0,0,0,0,6,0,59,0,0,7,174,5,213,0,31,0,34,0,38, + 0,41,0,45,0,49,0,0,19,39,35,53,51,39,51,23,33,55,51,23,33,55,51,7,51,21,35,7,51,21,35,3,35,3,35,3,35,3,35,53, + 5,27,1,1,23,33,55,1,27,2,7,51,39,33,23,33,55,182,30,93,58,49,204,48,2,19,48,227,48,2,19,48,205,49,57,93,29,122,158,225, + 254,218,195,220,254,224,159,4,192,165,165,254,117,29,1,145,29,251,32,165,165,229,29,125,28,253,76,29,1,145,29,4,15,117,143,194,194,194,194,194, + 194,143,117,143,252,128,3,128,252,128,3,128,143,143,253,103,2,153,1,4,117,117,254,252,253,103,2,153,1,4,117,117,117,117,0,0,0,2,0,95, + 255,227,5,241,5,213,0,13,0,27,0,0,19,37,32,0,25,1,35,17,52,38,35,33,17,35,41,1,34,0,25,1,51,17,20,22,51,33,3,51, + 95,2,7,0,255,1,6,184,157,176,254,177,184,5,142,253,253,255,254,250,184,157,176,1,83,4,184,5,210,3,254,214,254,220,254,145,1,86,240,211, + 250,178,1,42,1,36,1,111,254,170,240,211,5,78,0,0,255,255,0,113,254,192,4,244,6,20,16,38,0,211,0,0,16,7,2,143,0,138,0,0, + 0,1,0,0,255,227,4,143,5,240,0,49,1,28,64,58,32,18,211,34,16,43,7,211,9,25,161,26,174,22,149,29,1,161,0,174,4,149,47,145, + 29,140,41,9,50,43,34,33,41,35,38,18,16,10,3,13,9,17,8,44,32,38,19,7,17,8,17,13,28,25,0,38,42,33,47,60,212,196,50,252, + 196,196,18,57,57,18,57,57,17,18,57,17,23,57,18,57,57,17,57,57,49,0,16,196,50,228,244,236,244,236,16,238,246,238,16,238,50,221,60,238, + 50,48,1,75,176,9,84,75,176,12,84,91,75,176,13,84,91,75,176,15,84,91,75,176,23,84,91,75,176,24,84,91,88,189,0,50,255,192,0,1, + 0,50,0,50,0,64,56,17,55,56,89,64,122,14,0,14,1,11,2,11,49,84,20,105,12,108,14,110,15,111,16,111,17,111,18,111,19,105,20,107, + 31,111,32,111,33,111,34,111,35,110,36,108,37,105,39,105,45,159,7,159,8,159,9,159,10,159,11,159,12,159,13,159,14,159,15,159,16,159,17,159, + 18,159,19,150,31,159,32,159,33,159,34,159,35,159,36,159,37,159,38,159,39,159,40,159,41,159,42,159,43,159,44,157,45,50,0,8,0,9,16,8, + 16,9,32,8,32,9,85,21,83,30,106,21,103,31,10,93,0,93,1,21,46,1,35,34,6,7,33,7,33,14,1,21,20,22,23,33,7,33,30,1, + 51,50,54,55,21,14,1,35,34,0,3,35,55,51,52,38,53,52,54,53,35,55,51,18,0,51,50,22,4,143,91,169,102,157,202,32,2,65,55,253, + 230,2,1,1,2,1,190,56,254,138,32,202,157,102,169,91,89,185,96,237,254,203,40,211,55,139,1,1,194,55,156,40,1,54,236,98,185,5,98,213, + 105,90,200,187,123,24,46,35,32,46,24,123,187,202,90,105,211,72,72,1,34,1,3,123,23,47,32,35,47,23,123,1,1,1,34,71,0,1,0,40, + 0,0,5,22,5,213,0,17,0,0,19,17,51,17,1,51,1,33,21,33,1,35,1,17,35,17,35,53,191,189,2,117,243,253,128,1,170,254,88,2, + 176,249,253,95,189,151,3,84,2,129,253,137,2,119,253,127,115,253,31,2,207,253,49,2,225,115,0,0,0,1,0,20,0,0,5,3,5,213,0,23, + 0,0,1,17,33,53,33,21,33,17,55,23,5,21,55,23,5,17,35,17,7,39,37,53,7,39,2,38,253,238,4,239,253,238,229,80,254,203,230,80, + 254,202,203,231,77,1,52,232,77,3,141,1,158,170,170,254,241,161,111,216,136,162,111,217,253,184,1,186,161,110,217,136,162,110,0,0,0,5,0,208, + 254,57,9,164,5,240,0,22,0,45,0,98,0,119,0,131,0,0,1,39,19,54,55,62,1,51,50,22,23,22,21,20,7,6,7,6,35,34,39,38, + 39,19,34,7,6,7,6,21,20,23,22,51,50,54,55,54,55,54,53,52,39,38,39,38,5,54,55,19,6,7,6,7,6,7,39,62,1,55,54,51, + 50,4,23,30,1,21,20,7,6,7,14,1,7,6,7,6,35,34,39,46,1,39,38,47,1,6,7,6,35,34,39,38,53,52,54,51,50,1,3,6, + 7,23,22,23,22,51,50,54,55,54,55,54,53,52,39,38,39,38,1,38,35,34,7,6,21,20,23,22,51,50,7,8,185,162,34,62,49,150,97,74, + 123,37,65,48,49,81,91,87,55,62,47,30,247,87,49,12,16,10,23,32,62,36,60,24,20,19,17,29,12,24,20,249,185,12,11,180,46,32,35,24, + 21,17,174,26,100,67,119,175,203,1,45,94,85,82,28,26,66,36,96,62,68,76,95,75,62,46,51,98,32,64,15,15,18,21,78,92,117,76,77,132, + 105,73,1,228,177,25,21,40,83,51,57,53,108,154,57,44,28,24,30,31,56,132,253,71,40,47,38,14,13,23,23,32,45,254,57,41,2,208,151,105, + 82,109,58,51,88,146,119,100,103,55,63,32,23,50,1,248,106,26,55,35,61,53,40,54,36,32,27,54,50,57,84,47,20,12,11,183,40,50,3,77, + 10,20,22,33,29,58,53,83,125,36,64,123,109,98,245,129,113,140,130,126,69,115,47,52,24,29,9,10,45,19,38,10,10,34,23,84,65,66,96,93, + 133,3,146,252,155,124,64,27,56,22,25,134,110,82,128,107,99,100,93,97,67,156,251,160,34,14,14,15,24,15,14,0,0,2,0,46,255,227,4,142, + 5,240,0,41,0,53,0,0,19,39,54,51,50,23,22,51,50,55,38,53,52,55,54,51,50,23,22,21,20,7,22,21,20,7,6,35,53,50,55,54, + 53,52,39,6,35,34,39,38,35,34,37,54,53,52,39,38,35,34,7,6,21,20,185,139,147,111,124,64,88,34,48,55,227,80,89,136,116,97,84,107, + 181,126,106,252,134,91,73,119,137,109,113,74,50,53,51,2,48,68,27,35,50,52,33,25,2,4,96,240,78,107,66,177,254,172,88,96,96,83,177,227, + 171,163,191,194,134,113,162,74,60,147,88,114,126,104,70,217,108,175,86,49,63,63,48,87,166,0,0,0,0,4,0,68,0,0,4,162,5,213,0,29, + 0,36,0,43,0,49,0,0,19,53,35,53,51,17,33,50,23,22,23,51,21,35,22,20,7,51,21,35,6,7,6,43,1,17,35,17,35,53,5,33, + 21,51,50,55,54,1,33,38,39,38,43,1,5,33,21,33,54,52,151,82,82,1,200,251,129,76,31,92,72,1,1,71,90,31,77,129,251,254,202,83, + 3,28,254,1,254,141,77,23,254,17,1,255,16,23,77,141,254,2,35,253,221,2,35,2,3,236,86,116,1,31,113,68,106,116,21,44,21,116,107,68, + 113,253,168,3,120,116,116,122,73,22,1,89,27,21,73,237,86,21,44,0,0,2,0,93,255,91,4,177,6,120,0,36,0,45,0,0,5,35,53,38, + 39,38,17,16,55,54,55,53,51,21,22,23,22,23,21,38,39,38,39,17,54,55,54,55,17,35,53,33,17,6,7,6,7,39,17,6,7,6,17,16, + 23,22,2,249,140,223,137,168,168,137,223,140,105,96,112,94,95,107,98,107,78,63,72,57,120,1,34,99,120,104,117,140,133,79,111,111,79,165,143,31, + 167,204,1,109,1,110,205,166,31,143,137,4,31,36,70,215,95,48,44,4,251,63,2,17,18,39,1,145,166,253,127,83,42,37,5,178,4,167,32,108, + 153,254,209,254,210,153,108,0,0,3,0,16,0,0,5,5,5,213,0,23,0,27,0,30,0,0,19,53,33,19,51,19,33,21,33,23,51,21,35,19, + 35,3,33,3,35,19,35,53,51,55,51,7,33,47,1,51,3,51,1,49,181,229,181,1,48,254,251,71,190,147,181,210,170,254,6,170,213,181,146,189, + 73,193,67,1,169,68,250,210,105,3,82,123,2,8,253,248,123,207,123,253,248,2,8,253,248,2,8,123,207,207,207,123,1,65,0,0,0,1,0,117, + 255,227,5,188,5,240,0,54,0,0,1,54,55,54,55,33,53,33,54,55,54,53,52,38,35,34,6,7,53,62,1,51,50,4,21,20,7,51,21,33, + 6,15,1,33,21,33,6,21,20,22,51,50,54,55,21,14,1,35,32,36,53,52,55,35,53,1,92,4,22,74,128,254,53,3,146,12,13,59,179,165, + 95,204,115,114,218,105,245,1,23,25,175,254,253,103,216,67,2,133,252,83,49,188,173,114,236,123,128,239,106,254,231,254,221,18,168,2,161,7,22,74, + 44,123,8,9,43,107,118,128,54,55,197,38,38,228,198,85,66,123,92,42,13,123,59,94,126,136,70,69,208,47,48,224,217,75,63,123,0,2,0,165, + 254,211,4,114,6,20,0,31,0,42,0,0,1,21,46,1,35,17,50,54,55,21,6,7,6,7,17,35,17,38,39,38,19,53,16,55,54,55,53,51, + 21,22,23,22,1,3,6,7,6,7,6,23,22,23,22,4,114,92,168,101,101,168,92,90,92,88,91,100,185,116,212,1,212,121,178,101,93,88,92,254, + 139,1,91,67,118,15,14,14,25,108,67,4,164,213,105,90,251,241,90,105,211,72,36,34,2,254,240,1,21,22,118,214,1,57,17,1,66,203,116,23, + 232,226,2,34,36,251,164,3,249,22,67,117,170,161,102,180,108,67,0,0,0,2,0,20,0,0,5,3,5,213,0,3,0,11,0,0,19,33,21,33, + 21,33,21,33,17,35,17,33,20,4,239,251,17,4,239,253,238,203,253,238,5,213,170,120,170,251,247,4,9,0,0,0,0,1,0,106,0,0,4,175, + 5,213,0,38,0,0,19,55,33,7,33,22,23,33,7,35,6,7,6,7,22,23,22,23,19,35,3,38,39,38,43,1,53,51,50,55,54,55,33,55, + 33,38,39,38,35,106,55,4,14,55,254,158,79,21,1,53,55,246,5,61,65,125,65,61,59,65,205,217,191,75,68,70,120,220,254,146,74,68,6,253, + 190,55,2,0,18,45,74,146,5,90,123,123,78,129,123,126,85,93,36,22,72,68,130,254,104,1,127,151,48,49,166,67,62,114,123,67,52,88,0,0, + 0,1,0,10,0,5,5,50,5,218,0,27,0,0,1,16,7,6,33,35,17,7,39,37,53,7,39,37,17,51,17,55,23,5,21,55,23,5,17,32, + 0,17,5,50,204,204,254,80,172,230,78,1,52,232,76,1,52,202,230,80,254,202,232,80,254,200,1,53,1,31,2,241,254,126,181,181,2,30,161,110, + 216,137,162,110,217,1,228,254,170,162,111,217,136,163,111,218,253,251,1,24,1,46,0,0,0,1,252,18,5,21,255,203,6,20,0,5,0,0,1,19, + 51,7,33,21,252,18,218,126,132,2,229,5,21,0,255,155,100,0,0,0,0,1,252,61,5,21,255,246,6,20,0,5,0,0,3,33,53,33,39,51, + 10,252,71,2,229,132,126,5,21,100,155,0,0,1,252,61,4,122,255,203,6,20,0,8,0,0,3,33,23,35,39,55,51,7,33,53,253,27,132,126, + 175,175,126,132,2,229,5,21,155,205,205,155,0,1,252,61,4,122,255,203,6,20,0,8,0,0,1,53,33,39,51,23,7,35,55,252,61,2,229,132, + 126,175,175,126,132,5,21,100,155,205,205,155,0,4,252,19,4,123,255,236,6,16,0,3,0,7,0,11,0,12,0,0,1,51,21,35,37,51,21,35, + 37,51,21,35,23,252,19,203,203,3,14,203,203,254,121,203,203,102,6,16,202,202,202,202,202,203,0,0,0,5,251,80,4,123,0,176,6,16,0,3, + 0,7,0,11,0,15,0,16,0,0,3,51,21,35,37,51,21,35,37,51,21,35,37,51,21,35,5,27,203,203,251,107,203,203,3,14,203,203,254,121, + 203,203,1,41,6,16,202,202,202,202,202,202,202,203,0,0,0,1,252,61,4,122,255,203,6,20,0,13,0,0,1,23,35,39,55,51,7,33,39,51, + 23,7,35,55,252,230,132,126,175,175,126,132,2,60,132,126,175,175,126,132,5,21,155,205,205,155,155,205,205,155,0,0,0,4,0,67,255,207,7,216, + 6,4,0,10,0,36,0,40,0,66,0,0,1,34,6,21,20,22,51,50,54,61,1,55,17,35,53,14,1,35,34,38,53,52,54,51,23,52,38,35, + 34,6,7,53,62,1,51,50,22,37,51,1,35,1,21,46,1,35,34,6,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,51,50,22,2, + 15,160,112,83,72,102,127,188,188,3,153,109,141,166,205,198,169,111,103,68,129,99,92,148,71,194,193,2,176,216,252,68,216,5,169,94,111,56,121,137, + 137,121,56,111,94,73,130,73,202,236,238,209,67,128,3,246,66,82,67,73,148,130,10,77,254,13,62,5,79,158,129,150,155,6,87,92,32,55,178,36, + 30,202,250,249,203,3,132,178,52,30,156,148,147,157,31,52,177,34,27,250,209,212,249,27,0,4,0,67,255,207,7,254,6,4,0,32,0,43,0,69, + 0,73,0,0,1,46,1,52,54,4,23,21,39,38,35,34,21,20,22,31,1,30,1,20,6,35,38,39,53,23,22,51,50,53,52,38,39,1,34,6, + 21,20,22,51,50,54,61,1,55,17,35,53,14,1,35,34,38,53,52,54,51,23,52,38,35,34,6,7,53,62,1,51,50,22,37,51,1,35,6,86, + 135,127,185,1,78,122,36,112,129,180,59,105,48,153,137,202,170,175,145,37,147,139,177,61,123,251,137,160,112,83,72,102,127,188,188,3,153,109,141,166, + 205,198,169,111,103,68,129,99,92,148,71,194,193,2,176,216,252,68,216,1,125,28,124,239,142,1,52,188,18,57,100,36,44,24,10,33,127,243,149,6, + 53,202,19,76,102,44,49,27,2,132,66,82,67,73,148,130,10,77,254,13,62,5,79,158,129,150,155,6,87,92,32,55,178,36,30,202,250,249,203,0, + 0,2,0,115,255,227,5,39,5,240,0,24,0,33,0,0,1,21,46,1,35,34,7,17,22,51,50,54,55,21,14,1,35,32,0,17,16,0,33,50, + 22,1,17,6,7,6,17,16,23,22,5,39,89,232,151,163,121,121,163,151,232,89,106,237,132,254,173,254,122,1,134,1,83,134,237,253,11,35,31,157, + 157,31,5,98,118,65,90,52,251,45,52,90,66,117,72,72,1,159,1,103,1,104,1,159,71,251,19,4,91,27,33,172,254,186,254,187,172,33,0,0, + 255,255,0,195,255,227,8,109,5,240,16,38,0,114,0,0,16,7,0,38,3,70,0,0,0,2,255,214,0,0,5,24,5,213,0,8,0,43,0,153, + 184,0,44,47,184,0,45,47,184,0,21,220,184,0,0,220,184,0,44,16,184,0,40,208,184,0,40,47,184,0,4,220,65,27,0,22,0,4,0,38, + 0,4,0,54,0,4,0,70,0,4,0,86,0,4,0,102,0,4,0,118,0,4,0,134,0,4,0,150,0,4,0,166,0,4,0,182,0,4,0,198, + 0,4,0,214,0,4,0,13,93,65,5,0,229,0,4,0,245,0,4,0,2,93,184,0,0,16,184,0,9,208,184,0,21,16,184,0,11,208,184,0, + 21,16,184,0,31,208,184,0,0,16,184,0,35,208,0,184,0,10,47,186,0,33,0,34,0,3,43,184,0,33,16,48,49,1,6,7,6,21,20,23, + 22,23,17,53,51,21,22,23,22,23,21,38,39,38,39,17,54,55,54,55,21,6,7,6,7,21,33,21,33,53,38,39,38,17,16,55,54,1,119,73, + 51,99,99,51,73,202,56,54,81,76,78,78,55,56,56,55,78,78,77,82,52,56,2,215,252,95,161,107,149,151,105,4,179,29,58,114,205,205,113,59, + 29,3,212,122,110,4,11,18,35,172,43,22,15,4,252,164,4,16,21,43,170,36,18,11,4,42,170,222,32,114,159,1,14,1,18,157,110,0,0,0, + 0,4,0,60,255,207,7,229,6,4,0,25,0,29,0,40,0,50,0,0,1,21,46,1,35,34,6,21,20,22,51,50,54,55,21,14,1,35,34,38, + 53,52,54,51,50,22,37,51,1,35,1,34,6,21,20,22,51,50,54,16,38,36,32,22,21,20,6,32,38,53,52,3,6,94,111,56,121,137,137,121, + 56,111,94,73,130,73,202,236,238,209,67,128,2,221,216,252,68,216,4,107,97,118,118,97,96,119,119,254,223,1,130,218,218,254,126,217,5,151,178,52, + 30,156,148,147,157,31,52,177,34,29,252,209,212,249,27,75,249,203,3,4,158,146,145,159,160,1,32,160,157,248,213,212,248,248,212,213,0,3,0,60, + 255,207,8,77,6,4,0,19,0,45,0,49,0,0,1,17,51,17,20,22,51,50,54,53,17,51,17,35,53,14,1,35,34,38,1,21,46,1,35,34, + 6,21,20,22,51,50,54,55,21,14,1,35,34,38,53,52,54,51,50,22,37,51,1,35,5,92,188,81,80,99,117,188,188,6,144,96,158,161,253,170, + 94,111,56,121,137,137,121,56,111,94,73,130,73,202,236,238,209,67,128,2,221,216,252,68,216,1,76,2,16,253,245,114,105,129,117,1,240,252,144,68, + 9,80,193,4,255,178,52,30,156,148,147,157,31,52,177,34,29,252,209,212,249,27,75,249,203,0,0,0,255,255,0,164,255,227,4,123,5,240,16,6, + 1,82,0,0,255,255,0,111,254,214,5,35,4,227,16,7,3,193,0,0,254,243,0,0,255,255,0,195,0,0,7,38,5,240,16,38,0,114,0,0, + 16,7,0,41,3,3,0,0,0,1,0,73,255,227,7,140,5,251,0,111,0,0,1,15,1,17,33,54,55,54,55,54,51,50,23,22,21,20,7,6, + 35,34,39,38,35,34,7,6,7,6,7,6,17,20,23,22,23,22,51,50,55,54,55,23,6,7,6,35,34,39,38,39,38,53,52,55,33,20,7,6, + 7,6,35,34,39,38,53,52,54,51,50,23,22,23,22,23,22,51,50,55,54,55,54,25,1,34,7,6,7,6,21,20,23,22,31,1,20,7,6,35, + 34,39,38,39,38,53,52,55,54,55,54,51,50,22,3,191,2,108,1,248,40,57,66,75,99,123,61,20,38,27,37,20,22,29,37,48,51,33,40,26, + 22,26,40,26,33,44,22,55,29,51,57,31,37,55,29,96,108,71,59,55,29,28,13,254,19,50,53,93,173,185,104,66,52,44,39,53,15,18,11,22, + 9,39,66,91,81,70,36,37,136,93,99,39,71,9,2,9,9,18,37,33,24,29,20,9,8,125,75,114,126,147,44,167,5,234,31,49,253,188,209,140, + 152,73,103,20,41,29,42,26,33,28,38,33,40,68,59,119,214,254,189,165,130,125,44,22,55,53,59,33,95,39,93,55,58,121,125,169,91,180,207,158, + 163,92,174,64,52,62,35,44,15,18,33,44,11,39,81,70,170,167,0,255,2,106,22,26,40,74,71,31,52,16,36,36,44,16,42,29,18,41,47,57, + 132,121,75,35,37,6,0,0,0,1,0,2,254,249,5,139,5,217,0,80,0,0,5,55,22,51,50,55,54,55,54,55,54,53,52,39,38,39,38,35, + 34,6,7,22,23,22,7,2,7,38,39,38,34,7,39,54,51,50,23,54,53,52,39,38,39,38,53,52,55,54,55,22,23,22,55,54,55,21,14,2, + 35,34,39,38,39,6,7,6,21,20,23,54,55,50,23,22,21,16,7,0,35,34,3,42,105,40,88,37,31,35,27,26,18,13,27,28,49,70,130,83, + 176,69,47,11,13,24,203,79,46,53,53,70,117,22,189,80,85,91,81,70,91,48,48,114,108,211,126,156,27,34,5,145,75,73,125,33,59,73,70,115, + 59,31,31,110,161,237,242,157,59,95,254,233,84,94,205,140,81,31,31,55,57,125,119,178,150,94,108,46,71,137,121,114,92,91,52,254,250,79,57,37, + 35,105,35,222,94,77,88,59,128,165,121,118,64,99,141,132,147,125,7,1,26,2,101,46,73,68,92,26,22,55,73,59,62,50,86,231,167,137,117,211, + 176,254,162,211,254,254,0,0,0,3,0,201,0,0,6,3,5,213,0,3,0,7,0,19,0,0,1,17,51,17,33,17,51,17,37,33,17,33,17,33, + 17,33,17,33,17,33,4,213,202,251,142,202,254,210,1,146,2,22,1,146,254,110,253,234,254,110,5,113,250,243,5,13,250,243,5,13,100,253,136,2, + 120,250,43,2,219,253,37,0,0,1,0,72,0,0,4,135,6,20,0,25,0,0,1,3,35,19,62,1,53,52,38,35,34,6,7,3,35,1,51,3, + 62,1,51,50,22,21,20,6,4,117,131,185,131,9,10,106,95,148,217,32,121,184,1,47,184,119,70,218,120,148,163,9,2,164,253,92,2,157,47,72, + 21,84,94,200,166,253,147,6,20,253,156,94,109,160,145,36,82,0,0,0,0,1,0,90,0,0,4,135,6,20,0,25,0,0,1,51,7,37,23,5, + 3,54,51,50,22,7,3,35,19,18,35,34,6,7,3,35,19,7,39,55,1,136,185,45,1,141,14,254,80,52,170,231,193,151,45,131,184,130,62,248, + 149,209,32,123,185,223,209,14,245,6,20,234,124,97,136,254,245,201,239,232,253,92,2,158,1,61,190,164,253,135,4,127,66,99,76,0,0,1,0,59, + 255,225,3,116,5,240,0,57,0,0,1,15,1,17,16,7,6,35,34,39,38,53,52,55,54,51,50,23,22,23,22,23,22,51,50,55,54,55,54,53, + 17,34,7,6,7,6,21,20,23,20,22,21,20,7,6,35,34,39,38,53,52,55,54,55,54,51,50,22,3,116,30,104,193,130,143,110,60,55,16,26, + 35,27,31,8,11,11,27,20,59,75,81,62,33,31,124,90,97,44,52,6,20,31,22,24,26,22,40,88,77,139,149,181,33,125,5,227,44,22,252,254, + 254,134,194,130,60,55,68,57,15,27,35,7,55,46,27,19,77,61,134,132,190,3,17,26,29,46,49,63,27,22,4,64,9,39,31,18,22,40,77,127, + 88,73,40,39,13,0,0,0,0,2,0,106,255,227,5,70,5,240,0,33,0,50,0,0,63,1,54,51,50,23,22,51,50,55,54,53,52,39,38,53, + 52,63,1,6,21,20,23,22,21,20,7,6,35,34,39,38,35,34,19,54,51,50,23,22,51,50,55,7,6,35,34,38,35,34,7,106,140,111,117,57, + 132,144,33,121,100,71,62,80,80,213,80,80,53,202,186,242,54,129,133,56,94,110,109,141,123,127,122,128,125,125,200,139,111,143,214,143,122,128,90,165, + 39,80,86,137,97,75,126,112,146,109,100,160,140,139,121,107,148,98,188,94,242,222,79,80,5,54,56,49,47,58,170,58,98,58,0,0,0,1,0,68, + 255,227,5,110,5,242,0,74,0,0,1,5,22,23,22,51,50,55,54,53,52,39,55,22,21,20,7,6,35,34,39,38,39,36,35,53,34,7,6,7, + 39,52,55,54,55,54,55,54,19,54,55,54,55,54,51,50,23,22,21,20,7,6,35,34,39,38,39,38,39,38,35,34,7,14,1,7,6,7,6,7, + 6,7,23,51,50,1,219,1,2,110,90,83,60,103,86,66,9,44,24,110,121,121,52,102,88,143,254,251,82,68,55,53,13,53,73,26,49,37,48,55, + 11,5,35,33,64,99,209,114,71,66,14,41,31,44,29,13,11,7,41,51,57,75,46,35,36,4,4,20,22,38,55,66,3,15,62,1,95,110,48,24, + 25,86,66,154,82,30,14,132,14,228,110,121,35,31,72,137,8,66,63,132,24,193,88,33,36,24,57,66,1,127,169,132,128,77,119,62,55,108,26,16, + 46,27,11,59,55,37,44,59,40,211,167,189,117,121,44,68,48,3,0,0,0,2,255,228,255,227,2,210,5,240,0,28,0,38,0,0,1,22,51,50, + 55,51,6,7,6,35,34,39,7,35,54,55,38,53,52,55,18,55,54,51,50,21,6,7,2,1,18,19,54,53,52,35,6,3,6,1,48,41,87,58, + 75,133,60,70,76,70,156,63,75,156,108,80,10,31,117,104,72,123,125,1,18,72,254,184,187,57,30,25,109,97,27,1,12,200,115,102,53,57,139,110, + 147,137,78,85,152,152,2,59,117,81,173,78,93,254,131,254,247,1,92,1,22,147,38,69,87,253,250,145,0,2,0,32,255,227,6,27,6,20,0,31, + 0,39,0,0,19,51,21,51,53,51,21,33,21,33,17,62,1,51,50,0,16,2,35,34,38,39,21,35,17,35,17,35,17,35,53,51,0,16,38,32, + 6,16,22,32,193,184,184,185,2,177,253,79,58,177,123,204,0,255,255,204,123,177,58,185,184,184,161,161,4,155,167,254,220,167,167,1,36,6,20,147, + 147,147,125,254,178,100,97,254,188,253,240,254,188,97,100,168,5,4,250,252,5,4,125,251,227,1,150,231,231,254,106,231,0,2,0,198,0,0,5,162, + 5,213,0,3,0,13,0,0,37,1,35,9,1,33,1,17,51,17,33,1,17,35,5,32,253,22,238,2,234,252,148,1,168,2,208,100,254,88,253,48, + 100,100,5,13,250,243,5,113,251,31,4,225,250,43,4,225,251,31,0,0,0,4,0,54,0,0,7,193,5,213,0,19,0,31,0,43,0,47,2,22, + 177,146,151,66,176,147,176,152,66,0,176,0,47,179,14,15,44,47,176,4,23,60,177,1,149,237,176,0,176,45,221,176,46,60,176,45,176,29,222,176, + 35,205,16,16,177,4,129,63,177,5,10,176,2,23,60,177,11,149,237,176,35,17,176,11,18,176,23,57,176,23,32,70,104,72,176,23,16,176,41,176, + 35,176,29,35,73,105,59,177,128,2,66,177,129,0,66,61,176,29,176,23,35,73,176,128,98,105,176,29,70,96,176,20,70,97,176,146,67,176,1,96, + 35,66,176,146,67,176,1,96,67,176,0,85,88,176,20,176,146,67,176,1,96,67,56,89,176,20,16,178,26,38,32,176,3,23,60,177,128,0,66,177, + 129,0,66,24,48,1,176,48,16,177,3,4,254,176,4,60,176,0,196,176,3,177,17,28,253,176,16,60,16,176,3,177,13,54,252,176,14,60,176,13, + 177,6,28,253,176,7,60,176,15,57,176,15,32,70,104,72,16,176,13,176,10,176,0,176,3,35,73,104,59,176,11,60,16,176,13,176,20,214,176,20, + 176,32,221,176,44,57,176,44,32,70,104,72,176,32,176,38,214,176,38,176,26,176,20,176,32,35,73,105,59,176,47,176,44,176,20,35,73,104,58,16, + 16,16,16,16,176,26,176,49,35,73,176,146,67,176,1,96,35,66,176,146,67,176,1,96,67,176,0,80,88,181,38,26,20,32,44,47,176,146,67,176, + 1,96,67,176,6,23,56,75,176,10,82,88,176,13,176,20,35,73,176,146,67,176,1,96,35,66,176,146,67,176,1,96,67,176,64,80,88,176,146,67, + 176,1,96,67,176,64,97,176,146,67,176,1,96,35,66,180,6,7,13,14,15,176,146,67,176,1,96,67,176,5,23,56,89,89,89,177,128,2,66,177, + 129,0,66,61,176,20,176,26,35,73,176,128,98,105,176,20,70,96,176,23,70,97,176,146,67,176,1,96,35,66,176,146,67,176,1,96,67,176,0,85, + 88,176,23,176,146,67,176,1,96,67,56,89,176,23,16,178,29,35,41,176,3,23,60,177,128,0,66,177,129,0,66,24,49,176,4,176,7,35,73,176, + 0,82,88,12,177,16,15,7,176,15,16,177,6,17,237,176,16,16,177,5,17,253,10,12,2,13,177,5,6,8,176,4,16,176,5,60,11,10,12,3, + 13,177,5,6,8,176,7,16,176,6,60,11,10,89,51,53,50,53,17,33,1,17,52,54,51,21,34,21,17,33,1,17,20,6,1,52,54,51,50,22, + 21,20,6,35,34,38,55,20,22,51,50,54,53,52,38,35,34,6,3,53,33,21,54,147,1,16,2,150,157,186,147,254,240,253,106,157,4,227,144,103, + 103,144,144,103,103,144,140,57,50,50,57,57,50,50,57,140,1,238,170,107,4,192,251,31,3,204,128,149,170,107,251,64,4,225,252,52,128,149,2,110, + 138,191,191,138,138,191,191,138,78,103,103,78,78,103,103,253,68,123,123,0,0,4,1,27,0,0,6,229,5,202,0,12,0,25,0,34,0,45,0,0, + 1,22,17,16,0,33,32,0,3,16,0,33,32,6,33,32,0,17,18,0,33,32,0,17,16,39,5,17,51,50,54,53,52,38,35,37,33,50,22,21, + 20,6,43,1,17,35,6,11,218,254,74,254,209,254,207,254,82,6,1,180,1,49,1,50,41,254,247,254,250,254,134,5,1,117,1,6,1,7,1,121, + 187,253,211,178,99,107,107,99,254,193,1,63,176,180,180,176,178,141,4,241,219,254,206,254,208,254,76,1,180,1,48,1,48,1,182,101,254,133,254,249, + 254,251,254,135,1,121,1,5,1,9,187,119,254,175,88,81,80,88,100,137,131,133,135,254,152,0,0,0,0,2,0,110,254,59,5,67,3,246,0,48, + 0,60,0,0,1,6,21,20,23,54,55,54,51,50,23,22,21,20,7,6,35,34,39,54,55,22,51,50,55,54,53,52,39,38,35,34,1,18,21,20, + 7,6,35,34,39,38,53,16,55,38,53,52,55,3,6,21,20,23,22,23,50,55,54,53,52,2,53,136,31,91,171,219,132,131,70,73,156,121,174,101, + 76,18,9,41,113,122,93,69,38,32,74,189,254,159,135,69,89,131,113,58,63,223,46,232,148,129,31,48,46,65,28,32,3,198,130,190,77,107,101,148, + 189,76,80,171,218,215,167,60,43,29,40,140,104,195,124,72,61,254,121,254,222,124,157,110,142,61,66,134,1,11,252,158,127,238,164,252,239,198,123,117, + 46,70,1,47,52,95,78,0,0,4,0,200,0,0,5,84,5,213,0,3,0,11,0,22,0,31,0,0,1,17,51,17,51,17,33,50,55,17,38,35, + 37,33,50,4,21,20,4,43,1,17,33,1,17,54,55,54,53,52,39,38,1,44,202,100,1,46,24,23,23,24,253,64,2,145,250,1,1,254,255,251, + 254,254,110,3,88,60,45,93,92,44,5,113,250,243,5,13,253,106,2,2,146,2,100,219,211,213,218,253,136,5,90,253,153,22,41,86,159,158,86,41, + 0,4,0,115,254,248,5,217,5,240,0,17,0,25,0,33,0,41,0,0,37,1,35,39,7,6,35,32,0,17,16,0,33,32,0,17,16,2,37,22, + 32,55,17,38,32,7,3,17,6,7,6,16,23,22,1,17,54,55,54,16,39,38,4,66,1,10,244,221,51,17,16,254,197,254,135,1,121,1,59,1, + 58,1,120,209,253,43,108,1,16,108,108,254,240,108,105,36,32,155,155,32,2,222,35,31,155,155,31,27,254,221,239,3,1,1,165,1,97,1,98,1, + 165,254,91,254,158,254,252,254,142,11,50,50,4,215,50,50,251,106,4,84,29,37,182,253,156,181,37,4,53,251,175,29,36,182,2,99,182,36,0,0, + 0,2,0,66,255,238,6,28,6,50,0,12,0,95,0,0,1,17,22,51,50,55,54,53,52,39,38,39,38,19,3,39,6,7,6,7,6,35,34,39, + 38,53,52,55,54,51,50,23,22,23,22,23,22,51,50,55,54,55,54,53,17,34,7,6,21,20,23,30,1,21,20,7,6,34,39,38,53,52,55,54, + 33,54,63,1,21,50,23,22,23,22,21,20,7,6,7,23,22,23,22,51,50,55,54,55,23,6,7,6,35,34,39,38,3,66,31,61,143,93,105,83, + 27,92,90,151,206,86,31,51,48,70,159,185,110,55,59,26,25,35,26,22,27,17,22,16,26,70,102,83,57,33,33,231,129,60,9,2,16,29,35,53, + 29,44,104,189,1,34,29,59,60,182,137,132,50,88,110,103,154,90,82,123,26,44,29,31,35,17,31,35,57,62,59,75,33,81,5,161,253,73,7,97, + 103,194,163,83,27,20,15,251,22,1,230,9,192,136,137,68,163,53,64,55,42,26,24,22,26,31,39,16,26,83,58,121,125,158,3,42,130,55,72,25, + 48,9,53,15,35,33,31,24,44,73,145,108,187,13,29,28,64,28,31,51,88,167,191,110,104,48,222,205,123,31,31,40,50,24,114,58,61,31,79,0, + 0,2,0,83,255,227,6,108,5,241,0,73,0,88,0,0,5,38,53,52,39,38,35,34,15,1,21,20,7,6,35,34,39,38,53,22,23,20,23,22, + 50,55,54,53,17,52,39,38,35,34,7,6,20,23,22,51,23,34,39,38,53,52,55,54,51,50,23,22,23,55,54,51,50,23,22,21,20,7,6,7, + 50,23,22,23,22,21,20,23,55,23,1,22,21,17,55,54,55,54,53,52,39,38,35,34,7,5,2,82,22,40,79,42,92,120,103,103,140,141,102,103, + 45,46,64,64,144,63,64,64,63,92,81,65,64,64,64,83,54,151,102,103,103,102,151,162,101,30,16,211,187,112,47,36,126,65,66,125,58,49,36,27, + 32,45,144,42,252,164,21,154,144,77,74,74,24,31,64,102,29,183,159,140,91,166,43,56,199,206,118,117,117,118,176,12,12,122,86,87,87,87,150,2, + 155,149,88,87,87,86,202,86,87,92,117,118,156,157,117,117,117,35,32,98,87,14,49,177,87,123,124,94,49,36,104,123,131,128,118,67,91,4,83,75, + 92,254,149,71,67,104,102,121,151,32,10,47,0,5,0,200,0,0,6,50,5,213,0,9,0,30,0,38,0,46,0,50,0,0,1,38,39,38,43,1, + 22,23,19,51,1,30,1,23,19,33,3,46,1,43,1,17,33,17,33,32,22,21,20,7,6,1,17,33,50,55,17,38,35,23,17,54,55,54,16,39, + 38,37,17,51,17,4,251,76,68,69,120,45,77,101,143,199,254,248,53,113,62,205,254,72,191,74,139,120,20,254,110,2,167,1,0,252,117,49,253,149, + 1,69,24,23,23,24,152,65,43,90,89,42,252,178,202,1,127,151,48,49,47,201,254,229,2,79,25,132,126,254,104,1,127,150,98,253,137,5,213,214, + 216,208,98,41,2,165,253,106,2,2,146,2,23,253,153,22,41,86,1,62,85,41,45,250,243,5,13,0,0,2,0,169,0,0,6,131,5,213,0,8, + 0,31,0,167,184,0,32,47,184,0,33,47,184,0,32,16,184,0,14,208,184,0,14,47,184,0,13,220,184,0,0,208,184,0,33,16,184,0,19,220, + 184,0,5,220,65,5,0,234,0,5,0,250,0,5,0,2,93,65,27,0,25,0,5,0,41,0,5,0,57,0,5,0,73,0,5,0,89,0,5,0, + 105,0,5,0,121,0,5,0,137,0,5,0,153,0,5,0,169,0,5,0,185,0,5,0,201,0,5,0,217,0,5,0,13,93,184,0,9,208,184,0, + 9,47,186,0,30,0,14,0,19,17,18,57,0,184,0,13,47,184,0,26,47,184,0,29,47,186,0,15,0,0,0,3,43,184,0,15,16,186,0,2, + 0,11,0,3,43,184,0,2,16,48,49,1,17,51,50,54,53,52,38,35,1,6,43,1,17,35,17,33,50,4,21,20,7,23,55,51,9,1,35,11, + 1,35,1,1,115,254,141,154,154,141,1,32,115,173,254,202,1,200,251,1,1,78,174,190,232,254,205,1,67,233,207,212,232,1,73,5,47,253,207,146, + 135,134,146,253,95,54,253,168,5,213,227,219,172,107,219,234,254,134,254,107,1,4,254,252,1,149,0,0,0,4,0,201,255,37,5,84,6,199,0,5, + 0,36,0,43,0,46,0,0,1,17,51,19,38,35,19,22,23,22,23,19,35,3,38,39,38,39,1,39,55,35,17,33,50,23,55,37,55,5,7,22, + 23,22,21,20,6,11,1,54,55,54,53,52,1,19,35,1,147,209,200,63,92,252,65,62,58,65,205,217,191,75,69,54,84,254,174,111,70,94,1,200, + 126,95,11,254,186,44,1,182,56,27,23,126,131,124,167,84,51,74,253,219,143,143,5,47,253,238,1,248,26,253,141,22,72,68,130,254,104,1,127,151, + 48,38,9,252,176,44,175,5,213,26,27,130,111,174,140,16,19,107,216,141,186,1,231,254,93,15,45,68,131,98,252,135,1,103,0,0,0,2,1,3, + 3,139,6,40,5,216,0,39,0,52,0,0,1,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53, + 52,38,47,1,46,1,53,52,54,51,50,22,55,51,27,1,51,17,35,17,3,35,3,17,35,2,230,85,87,39,65,71,47,69,56,112,105,144,140,52, + 115,71,91,100,47,69,75,55,63,56,112,99,138,124,51,105,208,184,161,162,184,138,140,135,141,137,5,183,89,34,19,42,47,40,32,11,9,18,86,65, + 79,91,19,21,96,42,24,44,50,44,42,10,9,18,77,61,72,92,15,5,254,172,1,84,253,200,1,148,254,216,1,40,254,108,0,0,0,3,255,252, + 0,0,8,48,4,96,0,7,0,19,0,25,0,0,3,33,21,33,17,35,17,33,5,33,21,33,17,33,21,33,17,33,21,33,1,51,17,33,21,33, + 4,3,179,254,114,152,254,115,2,224,2,111,254,22,1,213,254,43,1,246,253,133,2,239,133,1,224,253,155,4,96,128,252,32,3,224,96,102,254,247, + 102,254,187,102,3,128,252,230,102,0,0,0,0,2,1,39,3,147,6,70,5,213,0,12,0,20,0,62,64,33,1,6,7,16,10,4,18,14,9,3, + 6,201,13,2,0,129,21,1,9,5,98,3,9,98,11,13,99,15,98,19,99,17,21,16,212,228,252,228,212,236,212,236,17,57,49,0,16,244,60,60, + 236,23,50,212,60,60,196,17,57,48,1,27,1,51,17,35,17,3,35,3,17,35,17,35,21,35,17,35,17,35,53,4,74,174,164,170,113,195,55,203, + 114,113,203,114,201,5,213,255,0,1,0,253,190,1,228,254,209,1,47,254,28,2,66,94,254,28,1,228,94,0,0,0,0,1,0,16,255,34,5,104, + 6,196,0,16,0,0,9,1,37,55,5,1,19,1,51,1,35,11,1,39,9,1,51,1,215,1,1,254,186,44,1,182,254,162,166,1,218,210,253,199, + 229,158,253,111,1,45,254,163,211,3,77,2,134,130,111,174,252,144,254,70,4,233,250,43,1,158,253,132,44,2,245,3,146,0,0,0,0,2,0,92, + 0,0,5,153,5,213,0,3,0,13,0,0,37,1,35,1,3,33,21,1,33,21,33,53,1,33,1,200,3,56,234,252,200,107,5,15,252,200,3,79, + 250,195,3,56,252,223,100,5,13,250,243,5,113,100,250,243,100,100,5,13,0,1,0,88,254,76,4,47,6,20,0,31,0,0,23,22,32,54,53,52, + 38,35,33,53,1,33,53,1,33,53,33,21,1,33,21,1,50,30,1,21,16,7,6,33,34,39,88,170,1,163,193,185,165,254,240,1,247,254,9,1, + 247,253,196,3,36,254,39,1,217,254,39,172,223,166,141,185,254,254,187,212,167,99,163,204,134,147,166,1,101,147,1,101,147,168,254,176,168,254,176,97, + 212,138,254,211,102,134,74,0,255,255,0,78,0,0,5,207,5,231,16,6,3,61,0,0,255,255,0,78,255,227,5,207,5,202,16,6,1,115,0,0, + 0,1,0,24,254,206,4,149,6,68,0,85,0,0,1,55,54,55,54,53,52,39,38,35,34,7,6,35,34,39,38,53,55,51,6,23,22,51,50,55, + 50,54,51,50,22,23,22,21,20,7,6,7,23,54,51,50,23,22,21,16,3,6,33,34,39,52,39,38,39,38,35,34,7,39,54,55,54,51,50,23, + 22,21,20,23,22,51,50,55,54,55,54,53,52,39,38,39,38,35,34,7,1,142,95,125,121,106,35,49,81,24,128,150,26,92,36,24,152,35,35,35, + 35,130,44,84,17,71,17,71,92,24,60,130,132,108,2,71,50,251,101,36,176,242,254,215,115,97,2,4,16,24,35,48,69,24,75,88,81,60,77,17, + 11,25,30,64,152,117,74,38,39,17,20,33,103,176,108,93,2,168,138,9,121,106,141,46,35,46,11,11,35,25,33,211,60,35,33,5,6,22,24,59, + 71,163,129,132,66,3,14,152,119,128,254,235,254,250,200,24,135,28,44,16,24,60,36,61,44,35,35,22,119,85,25,30,116,75,121,121,152,86,63,64, + 33,106,46,0,0,1,0,68,0,0,2,10,4,96,0,13,0,0,33,17,52,39,38,43,1,53,51,50,23,22,21,17,1,78,34,36,108,88,110,182, + 80,82,2,213,145,46,48,156,96,98,212,253,54,0,0,0,255,255,0,201,0,0,5,106,5,213,16,6,0,46,0,0,255,255,0,16,0,0,5,104, + 7,109,16,6,0,135,0,0,0,3,0,92,0,0,5,223,6,46,0,50,0,63,0,82,0,0,1,23,50,23,22,21,20,7,6,41,1,55,50,55, + 54,55,54,53,17,34,7,6,21,20,23,20,22,21,20,7,6,35,34,39,38,53,52,55,54,37,55,23,50,23,22,23,22,21,20,7,6,5,50,55, + 54,53,52,39,38,39,38,35,17,20,1,5,50,55,54,55,54,53,52,39,38,39,38,35,34,7,6,7,6,4,113,7,169,95,95,121,220,254,179,253, + 115,59,150,134,57,29,31,185,130,77,11,13,19,33,44,25,17,38,113,160,1,8,152,9,198,145,143,48,73,103,75,254,138,204,113,83,70,42,101,108, + 134,254,232,1,92,136,108,104,48,88,86,46,84,77,118,75,73,31,46,88,3,84,16,97,94,128,174,125,218,117,134,59,139,132,211,2,131,130,73,77, + 11,61,5,44,13,51,19,33,22,35,86,134,116,159,39,73,64,28,31,51,72,108,154,104,74,51,112,82,129,117,70,42,27,24,253,194,29,253,40,2, + 26,29,48,88,185,114,86,44,24,24,6,236,110,206,0,0,0,1,0,130,255,232,5,55,5,240,0,61,0,0,1,23,54,37,30,1,23,22,23,22, + 55,21,6,7,38,39,6,7,6,21,20,23,22,23,30,1,21,20,7,6,7,39,54,55,54,53,52,39,38,55,34,7,6,21,16,23,22,45,1,21, + 6,7,6,36,39,38,39,38,53,52,55,54,2,75,71,152,1,47,11,40,11,17,16,22,105,140,104,59,117,41,29,24,11,3,15,15,15,70,115,198, + 26,90,73,35,46,33,19,125,73,105,176,222,1,107,1,1,215,101,192,254,143,130,93,46,48,94,192,5,53,35,108,114,28,119,31,40,15,22,33,46, + 68,14,36,187,13,34,28,57,66,71,22,51,50,75,37,141,70,110,31,35,22,73,35,116,51,185,116,82,93,134,218,254,185,176,225,38,127,57,136,75, + 40,86,130,92,143,145,181,209,189,147,0,0,0,2,0,125,255,231,6,89,5,45,0,26,0,41,0,0,37,22,23,22,32,55,54,55,51,6,7,6, + 32,36,2,53,52,18,36,51,50,4,18,21,33,34,21,53,20,51,33,50,53,17,38,39,38,35,34,7,6,7,1,144,67,93,150,1,74,152,106,77, + 111,95,142,179,254,122,254,155,198,201,1,103,190,189,1,103,202,251,74,19,19,3,144,20,70,95,152,159,160,152,95,68,228,77,51,84,84,60,96,120, + 71,90,179,1,65,175,176,1,69,174,174,254,187,176,19,73,19,19,1,112,80,51,82,81,52,79,0,0,0,2,0,87,255,227,4,96,4,68,0,28, + 0,37,0,0,1,6,21,20,23,22,51,50,55,54,55,51,6,7,6,32,39,38,53,52,55,54,0,51,32,17,20,7,6,55,54,53,52,35,34,6, + 3,32,1,44,4,34,59,158,116,57,102,24,135,40,149,104,254,100,111,78,15,49,1,82,240,1,135,205,209,107,112,227,134,186,57,1,65,1,152,38, + 34,94,62,110,35,63,81,127,89,62,153,107,155,68,77,253,1,52,254,235,199,103,105,224,77,113,171,204,254,237,0,0,0,1,0,162,255,227,4,134, + 5,240,0,69,0,0,1,23,6,7,6,35,34,39,38,39,38,53,52,55,54,63,1,38,39,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34, + 39,38,53,52,55,54,53,52,39,38,35,34,7,6,21,20,23,22,23,22,51,21,34,7,6,7,6,21,20,23,22,51,50,55,54,55,4,39,95,31, + 16,178,251,143,105,108,69,95,134,109,178,2,108,61,79,99,123,241,136,84,51,45,50,34,41,23,13,28,26,37,43,102,97,64,97,80,47,90,95,124, + 171,123,119,58,109,97,90,194,129,117,62,13,1,73,104,65,17,172,34,37,64,95,169,174,138,108,24,21,36,61,80,148,139,99,122,83,50,86,78,45, + 50,22,14,33,28,36,43,31,37,36,43,64,101,151,125,78,48,23,26,54,30,29,57,110,153,166,97,91,117,62,95,0,0,1,0,84,255,223,6,17, + 6,11,0,77,0,0,1,23,7,6,35,34,39,38,39,17,33,7,35,21,20,7,6,7,6,33,34,39,38,53,52,55,54,51,50,23,22,23,22,23, + 22,51,50,55,54,55,54,61,1,33,55,33,17,38,35,34,7,6,21,20,31,1,20,7,6,35,34,39,38,53,52,55,54,33,50,23,55,21,22,23, + 22,51,50,55,5,238,35,88,39,58,39,55,225,63,1,60,61,255,42,42,77,198,254,244,128,95,52,30,27,46,31,13,18,22,19,27,66,94,108,123, + 62,29,33,254,151,39,1,66,97,62,193,110,71,7,20,25,35,26,38,35,31,119,167,1,52,36,66,154,187,143,48,22,48,33,5,242,19,163,75,20, + 61,25,253,220,68,99,152,132,128,75,202,95,52,66,40,31,26,11,20,48,51,26,66,123,62,99,101,130,185,68,2,73,24,110,70,84,61,31,73,44, + 26,31,31,31,70,180,119,167,8,55,75,46,22,9,48,0,0,1,0,201,0,0,4,35,5,213,0,9,0,0,41,1,53,33,17,33,53,33,17,51, + 4,35,252,166,2,144,253,176,2,80,202,170,1,184,170,2,201,0,0,0,0,1,0,57,255,199,8,66,6,2,0,107,0,0,1,17,20,23,22,23, + 22,51,50,55,54,55,23,6,7,6,34,39,38,39,38,17,52,2,55,6,3,2,3,7,39,2,3,38,39,38,39,17,20,7,6,7,6,35,34,39, + 38,53,52,55,54,51,50,23,22,51,50,54,55,54,53,17,38,35,34,7,6,15,1,54,55,54,55,54,51,50,23,51,22,19,18,19,23,18,55,18, + 55,54,51,50,23,22,21,20,7,6,35,34,39,38,39,38,39,38,35,34,7,6,6,215,22,22,44,27,28,53,40,46,39,42,39,69,96,159,57,55, + 18,6,7,5,174,121,123,55,97,20,59,102,55,59,62,70,51,46,94,80,101,77,68,42,29,24,35,55,29,28,64,44,106,33,28,72,104,72,60,61, + 20,46,15,24,27,37,95,121,143,105,7,165,112,112,51,11,84,125,128,156,152,178,66,39,29,18,30,44,36,8,22,7,11,4,25,26,29,26,42,5, + 29,253,53,220,128,129,47,22,44,44,64,33,59,68,97,57,55,158,84,2,1,30,1,145,31,179,254,196,254,201,254,86,77,15,1,230,1,59,169,110, + 119,70,254,15,237,187,179,94,79,63,47,44,37,33,24,59,62,106,121,116,159,2,214,88,60,59,125,3,102,63,69,39,95,110,165,254,250,254,244,254, + 177,11,1,72,244,1,2,151,152,39,29,29,39,16,35,9,22,13,29,4,24,22,46,0,0,2,0,104,255,231,3,74,3,41,0,11,0,23,0,0, + 1,52,38,35,34,2,21,20,22,51,50,18,3,50,22,21,20,2,35,34,38,53,52,18,2,169,87,79,109,141,86,80,109,141,194,152,203,221,162,152, + 203,221,1,247,116,125,254,254,207,116,123,1,4,1,253,216,163,198,254,255,216,163,198,1,1,0,0,0,0,1,0,103,255,227,5,178,5,240,0,52, + 0,0,9,1,22,21,20,7,52,39,1,7,6,31,1,22,20,7,6,43,1,53,54,53,52,47,1,38,52,63,1,39,38,53,52,55,20,23,9,1, + 39,38,53,52,55,20,31,1,22,21,20,7,52,47,1,3,196,1,139,99,144,50,252,251,155,62,66,172,100,61,86,69,245,196,47,98,53,140,154,241, + 99,144,50,2,108,1,25,116,99,144,50,182,99,144,50,18,2,208,254,117,99,49,130,76,83,50,3,5,156,63,66,172,100,214,44,62,56,63,93,29, + 47,99,54,188,141,155,241,99,49,130,76,83,50,253,150,1,25,116,99,49,130,76,83,50,182,99,49,130,76,83,50,18,0,1,255,251,255,227,5,57, + 5,241,0,48,0,0,1,17,51,22,21,20,15,1,14,1,35,33,34,46,1,53,52,63,1,62,1,51,33,17,52,39,46,1,35,33,34,46,3,53, + 52,62,1,51,50,23,30,2,51,33,50,22,4,190,79,44,30,135,17,20,34,251,244,22,24,24,34,133,17,20,36,3,132,20,20,37,64,253,127,59, + 53,72,29,22,4,16,20,25,12,12,42,31,28,2,214,89,91,4,182,252,35,4,36,20,27,135,18,6,2,20,18,16,34,134,16,6,3,120,50,13, + 16,6,4,24,49,91,71,40,32,20,32,30,31,4,87,0,0,1,0,27,255,184,3,65,5,240,0,44,0,0,1,33,50,23,22,20,14,1,7,30, + 1,18,16,7,6,35,34,38,47,1,14,1,35,33,34,53,52,63,1,62,1,51,33,17,33,34,38,53,52,54,50,23,22,23,22,1,84,1,80,108, + 30,19,12,48,37,2,2,61,10,24,45,22,18,6,14,100,18,44,254,109,70,34,133,17,20,36,1,133,254,186,109,71,20,45,12,23,46,16,5,143, + 55,35,42,40,47,10,26,130,253,36,254,251,34,83,30,31,97,101,14,40,16,33,135,16,6,3,205,113,126,66,25,30,59,6,2,0,0,1,0,86, + 255,184,4,186,5,240,0,38,0,0,1,33,34,38,53,52,62,1,51,50,23,30,2,51,33,50,30,2,21,20,14,1,7,30,1,23,18,21,20,7, + 6,35,34,38,39,38,53,4,10,253,0,109,71,4,16,20,25,12,12,42,31,28,3,10,53,71,26,6,12,48,37,2,2,4,57,10,23,46,24,17, + 12,12,4,166,113,126,40,31,20,31,30,32,4,31,48,26,11,16,40,47,10,26,130,38,253,74,147,115,33,83,39,68,81,73,0,0,0,2,0,70, + 0,0,2,215,6,20,0,11,0,21,0,0,19,52,54,51,50,22,21,20,6,35,34,38,1,51,21,33,53,51,17,35,53,33,188,112,81,79,111,111, + 79,81,112,1,131,152,253,111,151,151,1,249,5,84,81,111,111,81,79,111,110,251,117,121,121,3,53,121,0,2,0,90,255,213,7,82,5,59,0,9, + 0,27,0,0,18,16,0,33,32,0,16,0,33,32,5,1,21,7,30,1,21,16,0,33,32,0,17,16,0,33,32,4,254,1,72,1,27,1,26,1, + 72,254,184,254,230,254,229,3,233,1,35,239,2,2,254,91,254,159,254,158,254,91,1,165,1,98,1,4,1,114,3,101,254,72,254,253,1,3,1,184, + 1,1,194,1,10,244,221,33,35,16,254,197,254,135,1,121,1,59,1,58,1,120,209,0,0,4,0,151,0,0,9,76,4,96,0,9,0,12,0,20, + 0,32,0,0,19,33,21,33,17,33,21,33,17,35,1,3,33,1,51,1,35,39,33,7,35,1,51,27,1,51,9,1,35,9,1,35,1,151,2,131, + 254,20,1,188,254,68,151,3,131,181,1,106,255,0,151,1,119,138,90,254,68,90,140,3,214,143,245,246,144,254,195,1,82,144,254,235,254,233,144,1, + 96,4,96,128,254,182,127,253,233,3,8,254,67,2,53,252,128,230,230,3,128,254,179,1,77,254,82,254,46,1,125,254,131,1,222,0,0,3,0,36, + 255,240,5,122,4,96,0,15,0,45,0,49,0,0,37,53,34,39,38,39,38,53,17,35,17,20,22,23,22,50,3,22,51,50,55,21,6,35,34,39, + 38,53,17,35,17,33,17,35,34,6,21,35,52,54,51,33,21,35,17,20,1,51,17,35,5,22,137,44,26,9,14,134,23,20,57,225,89,8,108,40, + 72,116,132,253,42,21,167,254,178,61,90,50,100,114,165,4,15,182,253,33,134,134,90,52,64,39,33,56,162,2,12,253,214,166,122,25,69,1,66,175, + 10,241,16,202,98,253,1,227,252,4,3,252,76,115,168,123,100,254,18,89,254,175,3,152,0,2,0,0,254,115,5,90,4,123,0,8,0,29,0,0, + 1,22,19,18,17,51,16,3,2,3,16,3,2,35,34,7,35,52,55,54,51,32,19,18,19,51,2,3,2,17,1,215,174,85,69,130,69,108,52,70, + 140,197,169,24,100,71,81,245,1,180,137,110,160,130,203,67,70,4,29,193,254,92,254,167,254,120,1,159,1,66,1,253,250,190,2,27,1,42,2,87, + 159,98,79,90,253,61,1,154,1,14,254,143,254,201,254,190,253,253,0,0,0,2,0,200,0,0,5,48,5,213,0,3,0,9,0,0,1,17,51,17, + 37,21,33,17,33,17,1,44,202,3,58,253,42,254,110,5,113,250,243,5,13,100,100,250,143,5,213,0,0,3,0,201,0,0,6,1,5,213,0,3, + 0,7,0,15,0,0,1,17,51,17,33,17,51,17,1,33,17,33,17,33,17,33,4,211,202,251,144,202,4,10,254,110,253,236,254,110,5,56,5,113, + 250,243,5,13,250,243,5,13,250,143,5,113,250,143,5,213,0,2,0,25,254,119,6,83,5,193,0,5,0,17,0,0,9,2,33,9,2,21,33,9, + 1,33,21,33,53,9,1,53,1,166,3,16,253,6,254,252,2,250,252,240,5,151,252,25,2,250,252,240,4,23,249,198,3,7,253,23,254,218,3,89, + 3,42,252,214,252,167,6,231,100,252,214,252,167,99,99,3,83,3,21,127,0,1,0,163,255,227,5,187,5,240,0,29,0,0,1,17,33,21,33,17, + 54,36,51,32,0,17,16,0,33,34,36,39,53,30,1,51,32,0,17,16,0,33,34,6,1,107,1,74,253,238,117,1,26,160,1,94,1,139,254,117, + 254,162,146,254,249,111,112,252,139,1,18,1,19,254,237,254,238,107,168,4,254,254,111,166,2,129,83,85,254,103,254,147,254,146,254,103,72,70,215,95, + 96,1,50,1,47,1,46,1,50,37,0,0,0,1,0,8,0,0,3,169,5,213,0,5,0,23,181,2,28,0,58,3,6,16,220,252,236,49,0,180, + 3,149,4,129,1,47,244,236,48,33,35,17,33,53,33,3,169,202,253,41,3,161,5,43,170,0,0,0,0,1,0,7,0,0,3,168,5,213,0,5, + 0,23,181,4,28,1,58,3,6,16,220,252,236,49,0,180,3,149,0,129,2,47,228,236,48,1,17,33,53,33,17,3,168,252,95,2,215,5,213,250, + 43,170,5,43,0,1,255,252,0,0,4,231,5,213,0,8,0,0,33,35,9,1,35,1,17,51,17,4,231,217,254,98,254,101,217,2,16,203,2,102, + 253,154,3,14,2,199,253,57,0,4,0,87,0,0,6,74,5,213,0,11,0,19,0,23,0,34,0,0,1,32,23,22,21,20,7,2,0,41,1,1, + 5,3,51,50,55,19,38,35,33,3,51,19,5,3,54,55,54,19,54,53,52,39,38,3,124,1,178,168,116,23,75,254,34,254,80,253,253,1,34,1, + 127,251,99,245,173,226,147,246,254,111,251,202,251,2,175,205,27,25,208,65,20,102,18,5,213,181,124,223,99,118,254,126,254,150,5,213,100,250,243,65, + 4,139,65,250,243,5,13,120,251,227,16,19,157,1,80,102,85,194,109,19,0,4,0,90,255,227,5,173,6,20,0,10,0,31,0,35,0,50,0,0, + 19,6,21,20,23,22,23,19,6,7,6,1,33,55,6,7,6,35,34,2,53,52,55,54,0,51,50,23,22,23,19,33,7,1,51,9,1,3,22,51, + 50,55,54,55,54,53,52,39,38,35,34,231,31,42,32,54,175,66,56,119,3,120,254,178,33,78,98,98,124,203,158,34,35,1,62,203,124,79,79,39, + 118,1,78,254,254,247,134,1,9,253,50,189,24,26,165,119,120,31,31,56,55,165,26,2,116,158,75,115,79,61,32,3,134,32,61,130,252,237,168,100, + 48,49,1,12,148,80,178,178,1,68,49,48,100,2,94,100,250,172,5,84,254,100,252,54,3,130,130,159,158,74,116,104,105,0,0,0,0,3,0,91, + 255,227,4,147,4,123,0,10,0,40,0,50,0,0,19,6,21,20,23,22,23,19,6,7,6,19,22,51,50,55,54,55,7,6,7,6,35,32,39,38, + 53,52,55,18,55,54,51,50,23,22,21,20,15,1,33,55,33,54,53,52,39,38,35,34,7,218,12,78,22,30,161,38,35,160,168,71,95,121,127,90, + 92,23,107,108,109,107,254,244,125,90,15,53,181,179,252,228,102,70,16,18,253,143,20,2,1,10,57,78,169,74,67,2,48,60,55,141,104,29,22,3, + 58,21,28,130,253,74,21,31,22,40,117,42,22,22,156,111,166,68,77,1,19,162,161,145,99,147,70,80,90,100,56,50,118,82,115,17,0,3,0,79, + 0,0,2,129,6,20,0,3,0,7,0,11,0,0,1,51,7,35,3,51,19,35,19,33,19,33,1,201,184,46,184,212,134,178,134,36,254,178,218,1, + 78,6,20,233,251,57,3,152,252,4,4,96,0,3,255,22,254,86,2,129,6,20,0,3,0,12,0,26,0,0,1,51,7,35,3,19,35,3,6,7, + 54,55,54,5,35,55,51,50,55,54,55,19,33,3,6,7,6,1,201,184,46,184,102,202,134,208,35,53,72,50,75,254,220,220,20,49,105,48,47,29, + 233,1,78,222,41,100,101,6,20,233,250,191,4,18,251,208,181,84,15,48,72,244,100,48,49,153,4,172,251,140,214,96,96,0,0,0,0,2,0,59, + 255,227,5,184,5,240,0,38,0,48,0,0,9,1,14,1,21,35,52,18,55,1,51,23,62,1,51,50,0,21,20,6,7,30,1,21,20,6,35,34, + 38,39,53,30,1,51,50,54,53,52,38,55,62,1,53,52,38,35,34,6,7,3,186,254,4,59,72,186,116,93,254,233,252,143,104,228,131,241,1,50, + 134,134,48,50,222,184,83,165,85,87,158,68,105,131,59,50,91,85,212,160,95,166,73,2,64,2,8,89,203,114,132,1,2,126,1,31,149,89,87,254, + 237,215,128,225,99,63,125,60,162,197,36,36,182,47,49,111,88,51,103,206,81,161,88,146,194,63,64,0,0,1,0,81,0,0,3,136,4,96,0,9, + 0,36,64,9,5,9,8,11,70,0,6,2,10,16,196,196,212,236,236,50,49,0,64,8,7,135,6,3,135,0,188,2,47,228,236,212,236,48,1,17, + 33,53,33,17,33,53,33,17,3,136,252,201,2,127,254,7,1,249,4,96,251,160,147,1,111,147,1,203,255,255,0,137,255,227,7,96,5,240,16,39, + 11,34,3,53,0,0,16,38,0,123,0,0,16,7,11,78,4,139,253,100,255,255,0,137,255,227,7,116,5,240,16,39,11,34,3,53,0,0,16,38, + 0,123,0,0,16,7,11,80,4,139,253,100,255,255,0,137,255,227,10,174,5,240,16,39,11,34,3,53,0,0,16,38,0,123,0,0,16,39,0,123, + 4,139,253,100,16,7,11,73,7,192,253,100,255,255,0,137,255,227,7,88,5,240,16,38,0,123,0,0,16,39,11,34,3,53,0,0,16,7,0,117, + 4,139,253,100,255,255,0,94,255,227,7,88,5,240,16,38,0,116,0,0,16,39,11,34,3,53,0,0,16,7,0,117,4,139,253,100,255,255,0,137, + 255,227,7,94,5,240,16,38,0,123,0,0,16,39,11,34,3,53,0,0,16,7,11,76,4,139,253,100,255,255,0,94,255,227,7,94,5,240,16,38, + 0,116,0,0,16,39,11,34,3,53,0,0,16,7,11,76,4,139,253,100,255,255,0,98,255,227,7,94,5,240,16,38,0,117,0,0,16,39,11,34, + 3,53,0,0,16,7,11,76,4,139,253,100,255,255,0,63,255,227,7,94,5,240,16,38,11,75,0,0,16,39,11,34,3,53,0,0,16,7,11,76, + 4,139,253,100,255,255,0,137,255,227,7,126,5,240,16,38,0,123,0,0,16,39,11,34,3,53,0,0,16,7,11,77,4,139,253,100,255,255,0,102, + 255,227,7,126,5,240,16,38,11,76,0,0,16,39,11,34,3,53,0,0,16,7,11,77,4,139,253,100,255,255,0,137,255,227,7,119,5,240,16,38, + 0,123,0,0,16,39,11,34,3,53,0,0,16,7,11,79,4,139,253,100,255,255,0,98,255,227,7,119,5,240,16,38,0,117,0,0,16,39,11,34, + 3,53,0,0,16,7,11,79,4,139,253,100,255,255,0,102,255,227,7,119,5,240,16,38,11,76,0,0,16,39,11,34,3,53,0,0,16,7,11,79, + 4,139,253,100,255,255,0,108,255,227,7,119,5,240,16,38,11,78,0,0,16,39,11,34,3,53,0,0,16,7,11,79,4,139,253,100,255,255,0,137, + 255,227,6,2,5,240,16,38,0,123,0,0,16,7,11,34,3,53,0,0,255,255,0,201,0,0,1,147,5,213,16,6,0,44,0,0,255,255,0,201, + 0,0,3,39,5,213,16,38,0,44,0,0,16,7,0,44,1,148,0,0,255,255,0,201,0,0,4,187,5,213,16,38,0,44,0,0,16,39,0,44, + 1,148,0,0,16,7,0,44,3,40,0,0,255,255,0,201,0,0,7,81,5,213,16,38,0,44,0,0,16,7,0,57,1,233,0,0,255,255,0,16, + 0,0,5,104,5,213,16,6,0,57,0,0,255,255,0,16,0,0,6,152,5,213,16,38,0,57,0,0,16,7,0,44,5,5,0,0,255,255,0,16, + 0,0,8,44,5,213,16,38,0,57,0,0,16,39,0,44,5,5,0,0,16,7,0,44,6,153,0,0,255,255,0,16,0,0,9,192,5,213,16,38, + 0,57,0,0,16,39,0,44,5,5,0,0,16,39,0,44,6,153,0,0,16,7,0,44,8,45,0,0,255,255,0,201,0,0,7,23,5,213,16,38, + 0,44,0,0,16,7,0,59,1,220,0,0,255,255,0,61,0,0,5,59,5,213,16,6,0,59,0,0,255,255,0,61,0,0,6,174,5,213,16,38, + 0,59,0,0,16,7,0,44,5,27,0,0,255,255,0,61,0,0,8,66,5,213,16,38,0,59,0,0,16,39,0,44,5,27,0,0,16,7,0,44, + 6,175,0,0,255,255,0,201,0,0,4,106,5,213,16,6,0,47,0,0,255,255,0,115,255,227,5,39,5,240,16,6,0,38,0,0,255,255,0,201, + 0,0,5,176,5,213,16,6,0,39,0,0,255,255,0,201,0,0,6,31,5,213,16,6,0,48,0,0,255,255,0,193,0,0,1,121,6,20,16,6, + 0,76,0,0,255,255,0,193,0,0,2,233,6,20,16,38,0,76,0,0,16,7,0,76,1,112,0,0,255,255,0,193,0,0,4,89,6,20,16,38, + 0,76,0,0,16,39,0,76,1,112,0,0,16,7,0,76,2,224,0,0,255,255,0,193,0,0,6,65,6,20,16,38,0,76,0,0,16,7,0,89, + 1,194,0,0,255,255,0,61,0,0,4,127,4,96,16,6,0,89,0,0,255,255,0,61,0,0,5,189,6,20,16,38,0,89,0,0,16,7,0,76, + 4,68,0,0,255,255,0,61,0,0,7,45,6,20,16,38,0,89,0,0,16,39,0,76,4,68,0,0,16,7,0,76,5,180,0,0,255,255,0,61, + 0,0,8,157,6,20,16,38,0,89,0,0,16,39,0,76,4,68,0,0,16,39,0,76,5,180,0,0,16,7,0,76,7,36,0,0,255,255,0,193, + 0,0,6,74,6,20,16,38,0,76,0,0,16,7,0,91,1,209,0,0,255,255,0,59,0,0,4,121,4,96,16,6,0,91,0,0,255,255,0,59, + 0,0,5,212,6,20,16,38,0,91,0,0,16,7,0,76,4,91,0,0,255,255,0,59,0,0,7,68,6,20,16,38,0,91,0,0,16,39,0,76, + 4,91,0,0,16,7,0,76,5,203,0,0,255,255,0,193,0,0,1,121,6,20,16,6,0,79,0,0,255,255,0,113,255,227,3,231,4,123,16,6, + 0,70,0,0,255,255,0,113,255,227,4,90,6,20,16,6,0,71,0,0,255,255,0,186,0,0,7,29,4,123,16,6,0,80,0,0,0,3,0,121, + 0,0,9,125,5,213,0,13,0,22,0,31,0,0,1,32,0,17,16,0,41,1,32,0,17,16,0,33,1,51,32,0,17,16,0,33,35,3,17,35, + 32,0,17,16,0,33,6,53,1,178,1,150,254,104,254,80,253,140,254,80,254,104,1,150,1,178,1,159,244,1,53,1,31,254,225,254,203,244,202,244, + 254,203,254,225,1,31,1,53,5,213,254,151,254,128,254,126,254,150,1,106,1,130,1,128,1,105,250,209,1,24,1,46,1,44,1,23,251,119,4,137, + 254,233,254,212,254,210,254,232,0,3,0,201,0,0,5,176,5,213,0,17,0,26,0,35,0,251,186,0,9,0,27,0,3,43,184,0,9,16,186,0, + 14,0,23,0,3,43,184,0,14,16,186,0,31,0,5,0,3,43,184,0,31,16,184,0,9,16,184,0,0,208,65,5,0,234,0,5,0,250,0,5, + 0,2,93,65,27,0,25,0,5,0,41,0,5,0,57,0,5,0,73,0,5,0,89,0,5,0,105,0,5,0,121,0,5,0,137,0,5,0,153,0, + 5,0,169,0,5,0,185,0,5,0,201,0,5,0,217,0,5,0,13,93,184,0,9,16,184,0,18,208,65,5,0,234,0,23,0,250,0,23,0,2, + 93,65,27,0,25,0,23,0,41,0,23,0,57,0,23,0,73,0,23,0,89,0,23,0,105,0,23,0,121,0,23,0,137,0,23,0,153,0,23,0, + 169,0,23,0,185,0,23,0,201,0,23,0,217,0,23,0,13,93,184,0,31,16,184,0,37,220,0,186,0,2,0,34,0,3,43,184,0,2,16,186, + 0,28,0,8,0,3,43,184,0,28,16,186,0,19,0,0,0,3,43,184,0,19,16,186,0,10,0,18,0,3,43,184,0,10,16,48,49,1,21,51, + 32,0,17,16,0,33,35,21,51,32,22,21,20,6,35,3,17,51,50,54,53,52,38,35,1,33,32,0,17,16,0,41,1,1,147,244,1,53,1,31, + 254,225,254,203,244,72,1,0,240,241,255,72,78,159,147,147,159,254,232,1,159,1,178,1,150,254,104,254,80,254,97,1,89,179,1,24,1,46,1,44, + 1,23,178,194,207,208,195,2,158,253,232,129,140,138,129,1,222,254,151,254,128,254,126,254,150,0,0,0,0,5,0,121,0,0,9,125,5,213,0,17, + 0,26,0,40,0,49,0,67,0,0,1,21,51,32,22,21,20,6,43,1,21,51,32,0,17,16,0,33,3,51,50,54,53,52,38,43,1,19,33,32, + 0,17,16,0,41,1,32,0,17,16,0,1,17,35,34,6,21,20,22,51,19,53,35,32,0,17,16,0,33,51,53,35,34,38,53,52,54,33,5,96, + 72,1,0,240,241,255,72,244,1,53,1,31,254,225,254,203,244,78,159,147,147,159,78,213,253,140,254,80,254,104,1,150,1,178,2,116,1,178,1,150, + 254,104,252,177,78,159,147,147,159,78,244,254,203,254,225,1,31,1,53,244,72,255,241,240,1,0,5,47,178,194,207,208,195,179,1,24,1,46,1,44, + 1,23,252,176,129,140,138,129,252,9,1,106,1,130,1,128,1,105,254,151,254,128,254,126,254,150,1,223,2,24,129,138,140,129,2,158,178,254,233,254, + 212,254,210,254,232,179,195,208,207,194,0,0,255,255,0,115,255,227,5,39,5,240,16,6,1,72,0,0,255,255,0,127,255,227,3,245,4,123,16,6, + 2,22,0,0,0,1,0,115,254,86,5,39,5,240,0,28,0,0,1,21,46,1,35,32,0,17,16,0,33,50,54,55,17,35,17,6,7,6,35,32, + 0,17,16,0,33,50,22,5,39,102,231,130,255,0,254,240,1,16,1,0,130,231,102,201,12,12,118,132,254,173,254,122,1,134,1,83,134,237,5,98, + 213,95,94,254,199,254,216,254,217,254,199,94,95,253,16,1,185,4,4,36,1,159,1,103,1,104,1,159,71,0,0,0,255,255,0,87,255,227,7,88, + 5,240,16,39,11,34,3,53,0,0,16,39,0,117,4,139,253,100,16,6,11,73,0,0,0,1,0,100,0,204,6,63,4,56,0,9,0,129,180,2, + 9,6,0,10,16,212,212,204,50,64,9,64,2,64,9,48,2,48,9,4,93,49,64,10,2,5,9,1,0,6,5,156,6,10,0,16,212,236,17,57, + 57,204,16,204,48,64,12,8,9,9,0,8,7,8,7,156,0,9,0,7,5,16,252,60,8,6,16,60,64,12,3,2,2,1,3,4,3,4,156,1, + 2,1,7,5,16,252,60,8,6,16,60,176,16,75,83,88,0,179,3,2,8,9,16,60,16,60,180,8,156,9,9,0,7,5,16,236,180,3,156,2, + 2,1,7,5,16,236,89,19,53,1,23,7,33,21,33,23,7,100,1,137,120,233,4,195,251,61,233,120,2,85,90,1,137,120,233,170,233,120,0,0, + 0,1,1,163,0,0,5,15,5,220,0,9,0,129,64,10,2,5,9,1,0,6,5,156,6,10,16,212,236,17,57,57,204,16,204,49,0,180,2,9, + 6,0,10,16,212,212,204,50,64,9,79,2,79,9,63,2,63,9,4,93,48,64,12,8,9,9,0,8,7,8,7,156,0,9,0,7,4,16,252,60, + 8,6,16,60,64,12,3,2,2,1,3,4,3,4,156,1,2,1,7,4,16,252,60,8,6,16,60,176,16,75,83,88,1,179,3,2,8,9,16,60, + 16,60,180,8,156,9,9,0,7,4,16,236,180,3,156,2,2,1,7,4,16,236,89,1,51,1,7,39,17,35,17,7,39,3,45,90,1,136,120,232, + 170,234,120,5,220,254,118,120,234,251,60,4,196,234,120,0,0,1,0,117,0,204,6,80,4,56,0,9,0,129,180,2,9,0,6,10,16,212,212,204, + 50,64,9,79,2,79,9,95,2,95,9,4,93,49,64,10,9,6,2,1,0,5,6,156,5,10,0,16,212,236,17,57,57,204,16,204,48,64,12,8, + 9,9,0,8,7,8,7,156,0,9,0,7,5,16,252,60,8,6,16,60,64,12,3,2,2,1,3,4,3,4,156,1,2,1,7,5,16,252,60,8, + 6,16,60,176,16,75,83,88,0,179,3,2,8,9,16,60,16,60,180,8,156,9,9,0,7,5,16,236,180,3,156,2,2,1,7,5,16,236,89,1, + 21,1,39,55,33,53,33,39,55,6,80,254,119,120,233,251,61,4,195,233,120,2,175,90,254,119,120,233,170,233,120,0,0,1,1,163,255,249,5,15, + 5,213,0,9,0,129,64,10,9,6,2,1,0,5,6,156,5,10,16,212,236,17,57,57,204,16,204,49,0,180,2,9,0,6,10,16,212,212,204,50, + 64,9,64,2,64,9,80,2,80,9,4,93,48,64,12,8,9,9,0,8,7,8,7,156,0,9,0,7,4,16,252,60,8,6,16,60,64,12,3,2, + 2,1,3,4,3,4,156,1,2,1,7,4,16,252,60,8,6,16,60,176,16,75,83,88,1,179,3,2,8,9,16,60,16,60,180,8,156,9,9,0, + 7,4,16,236,180,3,156,2,2,1,7,4,16,236,89,5,35,1,55,23,17,51,17,55,23,3,135,90,254,118,120,234,170,232,120,7,1,138,120,234, + 4,196,251,60,234,120,0,0,0,1,0,100,0,204,6,80,4,56,0,15,0,218,182,7,10,9,2,15,0,16,16,212,204,50,212,204,50,64,13,80, + 2,80,15,95,10,95,7,79,10,79,7,6,93,49,0,64,15,7,2,4,10,15,0,1,8,9,4,13,4,156,13,16,16,212,236,17,23,57,204,50, + 16,204,50,48,64,12,14,15,15,0,14,13,14,13,156,0,15,0,7,5,16,252,60,8,6,16,60,64,12,3,2,2,1,3,4,3,4,156,1,2, + 1,7,5,16,252,60,8,6,16,60,64,12,11,10,10,9,11,12,11,12,156,9,9,10,7,5,16,252,60,8,6,16,60,64,12,6,7,7,8,6, + 5,6,5,156,8,7,8,7,5,16,252,60,8,6,16,60,176,16,75,83,88,0,183,11,10,6,7,3,2,14,15,16,60,16,60,16,60,16,60,180, + 14,156,15,15,0,7,5,16,236,180,3,156,2,2,1,7,5,16,236,180,11,156,10,10,9,7,5,16,236,180,6,156,7,7,8,7,5,16,236,89, + 19,53,1,23,7,33,39,55,1,21,1,39,55,33,23,7,100,1,137,120,233,3,188,233,120,1,137,254,119,120,233,252,68,233,120,2,85,90,1,137, + 120,233,233,120,254,119,90,254,119,120,233,233,120,0,0,0,0,1,1,163,255,239,5,15,5,220,0,15,0,222,64,15,7,2,4,10,15,0,1,8, + 9,4,13,4,156,13,16,16,212,236,17,23,57,204,50,16,204,50,49,0,182,7,10,9,2,15,0,16,16,212,204,50,212,204,50,64,17,95,2,95, + 15,80,10,80,7,79,2,79,15,64,10,64,7,8,93,48,64,12,14,15,15,0,14,13,14,13,156,0,15,0,7,4,16,252,60,8,6,16,60,64, + 12,3,2,2,1,3,4,3,4,156,1,2,1,7,4,16,252,60,8,6,16,60,64,12,11,10,10,9,11,12,11,12,156,9,9,10,7,4,16,252, + 60,8,6,16,60,64,12,6,7,7,8,6,5,6,5,156,8,7,8,7,4,16,252,60,8,6,16,60,176,16,75,83,88,1,183,11,10,6,7,3, + 2,14,15,16,60,16,60,16,60,16,60,180,14,156,15,15,0,7,4,16,236,180,3,156,2,2,1,7,4,16,236,180,11,156,10,10,9,7,4,16, + 236,180,6,156,7,7,8,7,4,16,236,89,1,51,1,7,39,17,55,23,1,35,1,55,23,17,7,39,3,45,90,1,136,120,232,232,120,254,120,90, + 254,118,120,234,234,120,5,220,254,118,120,234,252,67,234,120,254,118,1,138,120,234,3,189,234,120,0,0,0,1,1,32,0,52,5,159,4,179,0,9, + 0,0,1,55,33,21,33,1,7,1,17,35,1,32,63,2,44,254,182,3,94,120,252,162,169,4,116,63,169,252,162,120,3,94,254,182,0,1,1,32, + 0,52,5,159,4,179,0,9,0,0,1,23,17,35,17,1,39,1,33,53,5,96,63,169,252,162,120,3,94,254,182,4,179,63,253,212,1,74,252,162, + 120,3,94,169,0,1,1,32,0,52,5,159,4,179,0,9,0,0,37,7,33,53,33,1,55,1,17,51,5,159,63,253,212,1,74,252,162,120,3,94, + 169,115,63,169,3,94,120,252,162,1,74,0,0,1,1,32,0,52,5,159,4,179,0,9,0,0,37,39,17,51,17,1,23,1,33,21,1,95,63,169, + 3,94,120,252,162,1,74,52,63,2,44,254,182,3,94,120,252,162,169,0,0,1,0,100,0,204,6,63,4,56,0,17,0,0,1,3,39,19,33,23, + 7,1,53,1,23,7,33,19,23,3,33,21,4,66,200,148,151,253,255,233,120,254,119,1,137,120,233,2,100,200,148,151,1,154,2,45,254,165,85,1, + 6,233,120,1,137,90,1,137,120,233,1,91,85,254,250,170,0,1,0,117,0,204,6,80,4,56,0,17,0,0,1,19,23,3,33,39,55,1,21,1, + 39,55,33,3,39,19,33,53,2,114,200,148,151,2,1,233,120,1,137,254,119,120,233,253,156,200,148,151,254,102,2,215,1,91,85,254,250,233,120,254, + 119,90,254,119,120,233,254,165,85,1,6,170,0,1,0,44,0,211,6,158,3,80,0,52,0,0,1,22,23,22,51,50,55,62,1,55,54,55,54,55, + 54,51,50,23,22,23,22,23,7,38,39,38,39,38,35,34,7,6,7,6,7,6,7,6,7,6,35,34,39,38,47,1,17,35,17,55,33,21,5,1, + 237,35,47,41,56,53,44,48,70,21,34,60,59,78,74,88,91,71,82,55,60,34,157,21,35,33,50,41,56,53,44,47,36,35,21,31,63,50,87,71, + 91,88,74,78,59,160,169,63,2,44,254,182,1,244,33,21,19,19,21,70,48,79,60,58,34,32,32,37,55,60,79,65,48,35,33,23,19,19,20,36, + 35,48,73,66,53,39,32,32,34,58,160,254,182,2,44,63,169,1,0,0,0,1,0,22,0,211,6,136,3,80,0,52,0,0,1,55,37,53,33,23, + 17,35,17,7,6,7,6,35,34,39,38,39,38,39,38,39,38,39,38,35,34,7,6,7,6,7,39,54,55,54,55,54,51,50,23,22,23,22,23,30, + 1,23,22,51,50,55,54,4,199,160,254,182,2,44,63,169,160,59,78,74,88,91,71,87,50,63,31,21,35,36,47,44,53,56,41,50,33,35,21,157, + 34,60,55,82,71,91,88,74,78,59,60,34,21,70,48,44,53,56,41,47,1,244,160,1,169,63,253,212,1,74,160,58,34,32,32,39,53,66,73,48, + 35,36,20,19,19,23,33,35,48,65,79,60,55,37,32,32,34,58,60,79,48,70,21,19,19,21,0,0,0,1,0,100,0,204,6,63,4,56,0,17, + 0,0,19,1,23,7,51,1,23,7,33,21,33,23,7,1,35,23,7,1,100,1,137,120,233,240,1,97,120,233,2,227,253,29,233,120,254,159,240,233, + 120,254,119,2,175,1,137,120,233,1,97,120,233,170,233,120,1,97,233,120,1,137,0,0,0,1,1,165,0,0,5,17,5,220,0,17,0,0,9,1, + 7,39,21,1,7,39,17,35,17,7,39,1,53,7,39,1,3,135,1,138,120,234,1,98,120,234,170,232,120,1,96,232,120,1,136,5,220,254,118,120, + 234,240,254,158,120,234,253,28,2,228,234,120,1,98,240,234,120,1,138,0,0,1,0,117,0,204,6,80,4,56,0,17,0,0,9,1,39,55,35,1, + 39,55,33,53,33,39,55,1,51,39,55,1,6,80,254,119,120,233,240,254,159,120,233,253,29,2,227,233,120,1,97,240,233,120,1,137,2,85,254,119, + 120,233,254,159,120,233,170,233,120,254,159,233,120,254,119,0,0,1,1,165,255,249,5,17,5,213,0,17,0,0,5,1,55,23,53,1,55,23,17,51, + 17,55,23,1,21,55,23,1,3,47,254,118,120,234,254,158,120,234,170,232,120,254,160,232,120,254,120,7,1,138,120,234,240,1,98,120,234,2,228,253, + 28,234,120,254,158,240,234,120,254,118,0,0,0,1,0,100,0,204,6,63,4,56,0,14,0,0,19,53,1,23,7,33,1,23,9,1,7,1,33,23, + 7,100,1,137,120,233,2,234,1,97,120,254,194,1,62,120,254,159,253,22,233,120,2,85,90,1,137,120,233,1,97,120,254,194,254,194,120,1,97,233, + 120,0,0,0,0,1,0,117,0,204,6,80,4,56,0,14,0,0,9,1,39,55,33,1,39,9,1,55,1,33,39,55,1,6,80,254,119,120,233,253, + 22,254,159,120,1,62,254,194,120,1,97,2,234,233,120,1,137,2,85,254,119,120,233,254,159,120,1,62,1,62,120,254,159,233,120,254,119,0,0,0, + 0,1,0,100,0,204,6,63,4,56,0,13,0,0,1,33,23,7,1,53,1,23,7,33,17,51,17,35,5,149,251,231,233,120,254,119,1,137,120,233, + 4,25,170,170,2,45,233,120,1,137,90,1,137,120,233,1,89,252,164,0,0,1,1,165,0,0,5,15,5,220,0,13,0,0,37,17,7,39,1,51, + 1,7,39,17,33,21,33,53,3,5,232,120,1,136,90,1,136,120,232,1,90,252,164,170,4,26,234,120,1,138,254,118,120,234,251,230,170,170,0,0, + 0,1,0,117,0,204,6,80,4,56,0,13,0,134,183,12,9,10,6,2,156,4,14,16,212,236,50,212,204,50,64,9,79,9,79,12,95,9,95,12, + 4,93,49,64,10,9,5,11,10,6,156,12,3,1,14,0,16,212,204,204,252,57,57,204,204,48,64,12,8,9,9,10,8,7,8,7,156,10,9,10, + 7,5,16,252,60,8,6,16,60,64,12,13,12,12,11,13,0,13,0,156,11,12,11,7,5,16,252,60,8,6,16,60,176,16,75,83,88,0,179,13, + 12,8,9,16,60,16,60,180,8,156,9,9,10,7,5,16,236,180,13,156,12,12,11,7,5,16,236,89,1,33,17,35,17,51,17,33,39,55,1,21, + 1,39,5,56,251,231,170,170,4,25,233,120,1,137,254,119,120,2,45,254,167,3,92,254,167,233,120,254,119,90,254,119,120,0,0,0,0,1,1,165, + 255,249,5,15,5,213,0,13,0,0,1,33,53,33,21,33,17,55,23,1,35,1,55,23,3,5,254,168,3,92,254,166,232,120,254,120,90,254,120,120, + 232,5,43,170,170,251,230,234,120,254,118,1,138,120,234,0,0,1,1,165,0,0,5,15,5,220,0,19,0,0,1,55,23,1,33,21,33,53,33,1, + 55,23,17,7,39,1,51,1,7,39,3,175,232,120,254,120,1,130,252,164,1,128,254,120,120,232,232,120,1,136,90,1,136,120,232,1,194,234,120,254, + 118,170,170,1,138,120,234,3,2,234,120,1,138,254,118,120,234,0,0,0,0,1,0,100,0,204,6,62,4,134,0,37,0,0,1,53,50,23,22,23, + 30,1,21,20,6,7,6,7,6,35,33,23,7,1,53,1,23,7,33,32,55,54,55,62,1,53,52,38,39,38,39,38,5,19,62,52,50,47,43,45, + 43,45,39,58,49,32,252,72,233,120,254,119,1,137,120,233,1,217,1,217,22,24,19,18,20,19,19,19,24,22,3,220,170,22,21,45,41,111,61,60, + 106,46,40,26,22,233,120,1,137,90,1,137,120,233,10,10,18,17,49,26,27,46,20,18,10,10,0,0,0,1,0,118,0,204,6,80,4,134,0,41, + 0,0,1,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,51,33,39,55,1,21,1,39,55,33,34,39,38,39,38,39,38,53,52,55,54,55, + 54,55,54,51,1,161,27,22,24,19,18,10,10,10,12,16,19,24,22,27,3,151,233,120,1,137,254,119,120,233,252,105,65,49,58,39,45,21,22,22, + 23,43,47,50,52,62,3,220,10,10,18,17,26,23,27,26,23,28,15,18,10,10,233,120,254,119,90,254,119,120,233,22,26,40,46,52,54,60,61,54, + 57,41,45,21,22,0,0,0,0,2,0,100,0,204,6,62,4,134,0,24,0,62,0,0,1,51,50,55,54,55,54,55,54,53,52,39,38,39,38,39, + 38,34,7,6,7,6,7,6,21,7,53,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,43,1,21,35,53,33, + 23,7,1,53,1,23,7,4,145,130,27,22,24,19,18,10,10,10,10,18,19,24,22,54,22,24,19,16,12,10,169,22,23,43,47,50,52,62,65,49, + 58,39,45,21,22,22,23,43,47,50,52,62,130,169,253,148,233,120,254,119,1,137,120,233,2,215,10,10,18,17,26,23,26,27,23,26,17,18,10,10, + 10,10,18,15,28,23,27,130,130,61,54,57,41,45,21,22,22,26,40,46,52,54,61,60,54,57,41,45,21,22,220,220,233,120,1,137,90,1,137,120, + 233,0,0,0,0,2,0,118,0,204,6,80,4,134,0,24,0,62,0,0,1,53,52,39,38,39,38,39,38,34,7,6,7,6,7,6,21,20,23,22, + 23,22,23,22,51,41,1,39,55,1,21,1,39,55,33,21,35,53,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,22, + 23,22,21,2,35,10,12,16,19,24,22,54,22,24,19,18,10,10,10,10,18,19,24,22,27,1,43,2,108,233,120,1,137,254,119,120,233,253,148,169, + 130,62,52,50,47,43,23,22,22,21,45,39,58,49,65,62,52,50,47,43,23,22,2,215,130,27,23,28,15,18,10,10,10,10,18,17,26,23,27,26, + 23,26,17,18,10,10,233,120,254,119,90,254,119,120,233,220,220,22,21,45,41,57,54,60,61,54,52,46,40,26,22,22,21,45,41,57,54,61,0,0, + 0,1,0,100,0,204,6,80,4,56,0,88,0,0,1,35,23,7,1,53,1,23,7,51,50,23,22,23,30,1,50,54,55,54,55,54,55,54,55,54, + 51,50,23,22,23,22,23,22,23,30,1,50,54,55,54,55,54,59,1,39,55,1,21,1,39,55,35,34,7,6,7,6,7,6,34,39,38,39,38,39, + 38,39,38,39,38,34,7,6,7,6,7,6,7,6,7,6,34,39,38,39,38,39,38,1,134,10,233,120,254,119,1,137,120,233,10,48,36,35,36,10, + 24,27,24,10,10,5,16,32,34,37,39,45,48,36,39,32,33,15,5,10,10,24,27,24,10,39,32,39,45,10,233,120,1,137,254,119,120,233,10,14, + 11,13,10,31,40,39,90,38,40,31,34,15,4,10,10,13,11,28,11,13,10,9,5,15,34,31,40,38,90,39,40,31,10,13,11,2,45,233,120,1, + 137,90,1,137,120,233,18,18,36,10,12,12,10,12,13,45,35,37,17,18,18,20,34,38,42,13,12,10,12,12,10,39,15,18,233,120,254,119,90,254, + 119,120,233,6,6,10,34,20,18,18,20,34,38,42,13,12,10,6,6,6,6,10,9,16,42,38,34,20,18,18,20,34,10,6,6,0,0,1,0,100, + 0,190,6,80,4,70,0,23,0,0,37,39,19,33,23,7,1,53,1,23,7,33,19,23,3,33,39,55,1,21,1,39,55,33,3,16,160,112,254,156, + 233,120,254,119,1,137,120,233,1,162,134,160,112,1,100,233,120,1,137,254,119,120,233,254,94,190,58,1,53,233,120,1,137,90,1,137,120,233,1,111, + 58,254,203,233,120,254,119,90,254,119,120,233,0,1,1,42,255,252,5,157,5,216,0,13,0,0,9,1,19,23,3,1,3,37,23,1,39,1,55,19, + 4,9,253,33,157,167,94,2,223,193,1,13,98,254,57,89,254,193,139,190,4,8,254,88,3,120,29,253,238,1,168,251,184,190,139,254,192,16,1,200, + 98,254,241,0,0,1,1,90,0,0,5,9,5,242,0,11,0,0,1,17,35,17,33,23,7,1,53,1,23,7,5,9,170,254,19,233,120,254,119,1, + 137,120,233,4,145,251,111,3,231,233,120,1,137,90,1,137,120,233,0,0,0,1,1,172,0,0,5,91,5,242,0,11,0,0,1,33,39,55,1,21, + 1,39,55,33,17,35,1,172,2,151,233,120,1,137,254,119,120,233,254,19,170,4,145,233,120,254,119,90,254,119,120,233,252,25,0,0,0,1,1,90, + 255,227,5,9,5,213,0,11,0,0,1,33,23,7,1,53,1,23,7,33,17,51,5,9,253,105,233,120,254,119,1,137,120,233,1,237,170,1,68,233, + 120,1,137,90,1,137,120,233,3,231,0,0,0,1,1,172,255,227,5,91,5,213,0,11,0,0,1,17,51,17,33,39,55,1,21,1,39,55,1,172, + 170,1,237,233,120,1,137,254,119,120,233,1,68,4,145,252,25,233,120,254,119,90,254,119,120,233,0,0,0,1,1,221,255,249,6,20,4,212,0,11, + 0,0,1,17,55,23,1,35,1,55,23,17,33,53,4,179,233,120,254,119,90,254,119,120,233,253,212,4,212,252,61,233,120,254,119,1,137,120,233,3, + 25,170,0,0,0,1,0,100,0,204,5,63,5,3,0,11,0,0,1,33,23,7,1,53,1,23,7,33,17,51,5,63,252,61,233,120,254,119,1,137, + 120,233,3,25,170,2,45,233,120,1,137,90,1,137,120,233,2,44,0,0,0,1,0,45,1,160,6,101,5,88,0,38,0,0,1,55,23,1,35,1, + 55,23,53,52,55,54,55,54,55,54,32,23,22,23,22,23,22,21,35,52,38,39,38,39,38,34,7,6,7,6,7,6,21,2,57,232,120,254,120,90, + 254,118,120,234,46,45,92,90,110,108,1,0,108,110,90,92,45,46,170,66,66,60,86,74,190,78,82,64,64,35,33,2,184,234,120,254,118,1,138,120, + 234,50,127,112,107,95,86,49,46,46,49,86,95,107,112,127,93,162,66,59,39,33,33,35,63,64,83,81,93,0,0,0,0,1,0,79,1,160,6,135, + 5,88,0,38,0,0,1,53,52,39,38,39,38,39,38,34,7,6,7,14,1,21,35,52,55,54,55,54,55,54,32,23,22,23,22,23,22,29,1,55, + 23,1,35,1,55,4,123,33,35,64,64,82,78,190,74,86,60,66,66,170,46,45,92,90,110,108,1,0,108,110,90,92,45,46,234,120,254,118,90,254, + 120,120,2,184,50,93,81,83,64,63,35,33,33,39,59,66,162,93,127,112,107,95,86,49,46,46,49,86,95,107,112,127,50,234,120,254,118,1,138,120, + 0,2,0,222,0,52,6,77,5,213,0,3,0,13,0,0,19,53,33,21,5,55,33,21,33,1,7,1,17,35,222,5,111,250,211,63,2,44,254,182, + 3,94,120,252,162,169,5,114,99,99,254,63,169,252,162,120,3,94,254,182,0,2,0,112,255,161,6,68,5,99,0,13,0,27,0,0,19,53,33,39, + 55,1,17,51,17,35,17,1,39,55,1,33,23,7,1,17,35,17,51,17,1,23,7,33,112,4,18,234,120,1,138,170,170,254,118,120,234,1,194,251, + 238,234,120,254,118,170,170,1,138,120,234,4,18,1,1,170,232,120,254,120,1,78,253,8,1,80,254,120,120,232,2,88,232,120,1,136,254,176,2,248, + 254,178,1,136,120,232,0,0,0,1,0,211,0,127,6,25,5,112,0,54,0,0,1,6,7,6,21,20,22,23,22,23,22,50,55,54,55,62,1,53, + 52,39,38,47,1,17,35,17,55,33,21,33,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55,2,2,68, + 32,33,66,66,60,86,74,190,78,82,64,66,66,33,34,66,35,170,64,2,44,254,182,35,90,47,46,46,48,89,84,116,103,133,128,108,112,88,89,48, + 46,46,45,92,4,43,66,81,81,93,90,162,66,59,39,33,33,35,63,66,162,90,93,81,81,66,35,254,182,2,44,64,170,35,90,112,112,127,124,112, + 113,89,83,52,46,46,48,87,89,113,112,124,127,112,107,95,0,1,0,157,0,127,5,227,5,112,0,54,0,0,1,55,22,23,22,21,20,7,6,7, + 6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,63,1,33,53,33,23,17,35,17,7,6,7,6,21,20,22,23,22,23,22,50,55,54,55,62, + 1,53,52,39,38,4,180,120,92,45,46,46,48,89,88,112,108,128,133,103,116,84,89,48,46,46,47,90,35,254,182,2,44,64,170,35,66,34,33,66, + 66,64,82,78,190,74,86,60,66,66,33,32,4,43,120,95,107,112,127,124,112,113,89,87,48,46,46,52,83,89,113,112,124,127,112,112,90,35,170,64, + 253,212,1,74,35,66,81,81,93,90,162,66,63,35,33,33,39,59,66,162,90,93,81,81,0,1,0,100,2,45,6,63,4,56,0,6,0,75,179,2, + 6,0,7,16,212,204,204,180,64,5,80,5,2,93,49,181,2,1,5,156,6,7,0,16,212,252,57,204,48,64,12,3,2,2,1,3,4,3,4,156, + 1,2,1,7,5,16,252,60,8,6,16,60,176,16,75,83,88,0,182,3,156,2,2,1,3,2,16,60,7,5,16,236,89,19,53,1,23,7,33,21, + 100,1,137,120,233,4,195,2,45,130,1,137,120,233,170,0,0,1,0,100,0,204,6,63,2,215,0,6,0,75,179,5,2,0,7,16,212,204,204,180, + 64,5,80,5,2,93,49,181,5,6,1,156,2,7,0,16,212,236,57,204,48,64,12,4,5,5,6,4,3,4,3,156,6,5,6,7,5,16,252,60, + 8,6,16,60,176,16,75,83,88,0,182,4,156,5,5,6,4,5,16,60,7,5,16,236,89,19,33,21,33,23,7,1,100,5,219,251,61,233,120,254, + 119,2,215,170,233,120,1,137,0,1,3,5,0,0,5,15,5,220,0,6,0,0,1,51,1,7,39,17,35,3,5,130,1,136,120,232,170,5,220,254, + 118,120,234,251,60,0,0,0,0,1,1,163,0,0,3,175,5,220,0,6,0,0,1,17,35,17,7,39,1,3,175,170,234,120,1,138,5,220,250,36, + 4,196,234,120,1,138,0,0,0,1,0,117,2,45,6,80,4,56,0,6,0,75,179,5,6,2,7,16,212,212,204,180,79,5,95,5,2,93,49,181, + 5,6,2,156,1,7,0,16,212,252,57,204,48,64,12,4,5,5,6,4,3,4,3,156,6,5,6,7,5,16,252,60,8,6,16,60,176,16,75,83, + 88,0,182,4,156,5,5,6,4,5,16,60,7,5,16,236,89,1,33,53,33,39,55,1,6,80,250,37,4,195,233,120,1,137,2,45,170,233,120,254, + 119,0,0,0,0,1,0,117,0,204,6,80,2,215,0,6,0,75,179,2,0,6,7,16,212,212,204,180,79,5,95,5,2,93,49,181,2,1,6,156, + 5,7,0,16,212,236,57,204,48,64,12,3,2,2,1,3,4,3,4,156,1,2,1,7,5,16,252,60,9,7,16,60,176,16,75,83,88,0,182,3, + 156,2,2,1,3,2,16,60,7,5,16,236,89,1,21,1,39,55,33,53,6,80,254,119,120,233,251,61,2,215,130,254,119,120,233,170,0,1,3,5, + 0,0,5,15,5,220,0,6,0,0,33,17,51,17,55,23,1,3,5,170,232,120,254,120,5,220,251,60,234,120,254,118,0,1,1,163,0,0,3,175, + 5,220,0,6,0,0,33,35,1,55,23,17,51,3,175,130,254,118,120,234,170,1,138,120,234,4,196,0,255,255,0,100,255,160,6,80,5,100,16,39, + 12,21,0,0,254,212,16,7,12,23,0,0,1,44,0,0,255,255,0,119,255,249,6,59,5,220,16,39,12,24,1,44,0,0,16,7,12,22,254,212, + 0,0,0,0,255,255,0,100,255,160,6,80,5,100,16,39,12,23,0,0,254,212,16,7,12,21,0,0,1,44,0,0,0,1,0,100,255,160,6,63, + 5,100,0,17,0,0,1,3,53,1,23,7,33,21,33,23,7,33,21,33,23,7,1,53,1,99,255,1,137,120,233,4,195,251,61,215,215,4,195,251, + 61,233,120,254,119,2,130,0,255,90,1,137,120,233,170,215,215,170,233,120,1,137,90,0,0,1,0,120,0,0,6,60,5,220,0,17,0,0,1,19, + 51,1,7,39,17,35,17,7,39,17,35,17,7,39,1,51,3,90,254,90,1,138,120,234,170,214,216,170,232,120,1,136,90,4,220,1,0,254,118,120, + 234,251,60,4,196,216,216,251,60,4,196,234,120,1,138,0,0,1,0,118,255,160,6,81,5,100,0,17,0,0,1,5,21,1,39,55,33,53,33,39, + 55,33,53,33,39,55,1,21,5,82,0,255,254,119,120,233,251,61,4,195,215,215,251,61,4,195,233,120,1,137,2,130,255,90,254,119,120,233,170,215, + 215,170,233,120,254,119,90,0,0,1,0,120,255,249,6,60,5,213,0,17,0,0,37,1,35,1,55,23,17,51,17,55,23,17,51,17,55,23,1,35, + 3,90,255,0,90,254,120,120,232,170,216,214,170,234,120,254,118,90,249,255,0,1,138,120,234,4,196,251,60,216,216,4,196,251,60,234,120,254,118,0, + 255,255,0,100,0,14,6,80,4,246,16,39,12,70,0,0,255,66,16,7,12,65,0,0,0,190,0,0,255,255,0,100,0,14,6,80,4,246,16,39, + 12,66,0,0,255,66,16,7,12,69,0,0,0,190,0,0,0,2,0,100,0,204,6,63,4,56,0,4,0,26,0,0,1,33,7,23,33,37,7,33, + 21,33,7,39,55,33,23,7,1,53,1,23,7,33,55,23,7,33,21,3,247,253,153,105,105,1,238,1,38,121,2,20,253,167,117,130,73,254,208,93, + 120,254,119,1,137,120,93,2,52,117,130,73,1,85,2,235,105,105,210,210,120,202,75,127,93,120,1,137,90,1,137,120,93,202,75,127,120,0,0,0, + 0,3,0,100,0,193,6,80,4,67,0,23,0,28,0,33,0,0,37,39,55,35,23,7,1,53,1,23,7,33,55,23,7,51,39,55,1,21,1,39, + 55,33,19,7,33,55,39,41,1,7,23,33,3,7,141,62,176,93,120,254,119,1,137,120,93,1,84,81,141,62,176,93,120,1,137,254,119,120,93,254, + 172,120,76,1,160,105,105,254,12,254,96,105,105,1,84,193,52,172,93,120,1,137,90,1,137,120,93,224,52,172,93,120,254,119,90,254,119,120,93,1, + 74,210,105,105,105,105,0,0,0,2,0,117,0,204,6,80,4,56,0,4,0,26,0,0,1,33,55,39,33,5,55,33,53,33,55,23,7,33,39,55, + 1,21,1,39,55,33,7,39,55,33,53,2,189,2,103,105,105,254,18,254,218,121,253,236,2,89,117,130,73,1,48,93,120,1,137,254,119,120,93,253, + 204,117,130,73,254,171,2,25,105,105,210,210,120,202,75,127,93,120,254,119,90,254,119,120,93,202,75,127,120,0,0,0,0,1,0,100,0,204,6,63, + 4,56,0,14,0,0,1,33,21,33,23,7,1,53,1,23,7,33,21,33,7,1,144,4,175,251,201,93,120,254,119,1,137,120,93,4,55,251,81,105, + 2,25,120,93,120,1,137,90,1,137,120,93,120,105,0,0,0,1,1,165,0,0,5,17,5,220,0,14,0,0,1,17,35,17,7,39,1,51,1,7, + 39,17,35,17,39,2,241,120,92,120,1,136,90,1,138,120,94,120,104,4,176,251,80,4,56,94,120,1,138,254,118,120,94,251,200,4,176,104,0,0, + 0,1,0,117,0,204,6,80,4,56,0,14,0,0,1,55,39,33,53,33,39,55,1,21,1,39,55,33,53,5,36,105,105,251,81,4,55,93,120,1, + 137,254,119,120,93,251,201,2,25,105,105,120,93,120,254,119,90,254,119,120,93,120,0,0,0,1,1,165,255,249,5,17,5,213,0,14,0,0,1,23, + 55,17,51,17,55,23,1,35,1,55,23,17,51,2,241,106,104,120,94,120,254,118,90,254,120,120,92,120,1,37,104,104,4,176,251,200,94,120,254,118, + 1,138,120,94,4,56,0,0,0,2,0,100,0,204,6,80,4,56,0,5,0,21,0,0,1,33,55,39,33,7,5,33,23,7,1,53,1,23,7,33, + 39,55,1,21,1,39,1,144,3,148,105,105,252,108,105,3,133,253,92,93,120,254,119,1,137,120,93,2,164,93,120,1,137,254,119,120,2,25,105,105, + 105,225,93,120,1,137,90,1,137,120,93,93,120,254,119,90,254,119,120,0,0,2,1,164,255,240,5,16,5,220,0,5,0,21,0,0,1,17,23,55, + 17,39,3,17,7,39,1,51,1,7,39,17,55,23,1,35,1,55,2,241,105,105,105,225,93,120,1,137,90,1,137,120,93,93,120,254,119,90,254,119, + 120,4,176,252,108,105,105,3,148,105,252,123,2,164,93,120,1,137,254,119,120,93,253,92,93,120,254,119,1,137,120,0,0,1,1,32,255,209,6,3, + 4,179,0,14,0,0,9,1,7,1,21,35,17,55,33,21,35,1,7,1,35,1,201,3,80,85,253,5,169,63,2,44,131,2,251,85,252,176,149,3, + 118,252,176,85,2,251,132,2,44,63,169,253,5,85,3,80,0,1,0,188,255,209,5,159,4,179,0,14,0,0,1,53,35,1,39,1,35,53,33,23, + 17,35,53,1,39,4,246,149,252,176,85,2,251,131,2,44,63,169,253,5,85,3,118,148,252,176,85,2,251,169,63,253,212,132,253,5,85,0,0,0, + 0,1,0,188,0,52,5,159,5,22,0,14,0,0,9,1,55,1,53,51,17,7,33,53,51,1,55,1,51,4,246,252,176,85,2,251,169,63,253,212, + 131,253,5,85,3,80,149,1,113,3,80,85,253,5,132,253,212,63,169,2,251,85,252,176,0,1,1,32,0,52,6,3,5,22,0,14,0,0,1,21, + 51,1,23,1,51,21,33,39,17,51,21,1,23,1,201,149,3,80,85,253,5,131,253,212,63,169,2,251,85,1,113,148,3,80,85,253,5,169,63,2, + 44,132,2,251,85,0,0,0,0,1,0,100,0,204,6,63,4,56,0,15,0,0,1,33,21,33,23,33,21,33,7,1,53,1,23,33,21,33,1,99, + 4,220,251,36,138,4,82,252,38,120,254,119,1,137,120,3,218,251,174,2,190,120,138,120,120,1,137,90,1,137,120,120,0,1,0,117,0,204,6,80, + 4,56,0,15,0,0,1,33,53,33,39,33,53,33,55,1,21,1,39,33,53,33,5,81,251,36,4,220,138,251,174,3,218,120,1,137,254,119,120,252, + 38,4,82,2,70,120,138,120,120,254,119,90,254,119,120,120,0,1,0,100,0,204,6,63,4,56,0,24,0,0,1,35,39,7,39,7,39,7,39,35, + 23,7,1,53,1,23,7,51,23,55,23,55,23,55,23,6,63,40,70,180,180,180,180,180,110,99,233,120,254,119,1,137,120,233,139,70,180,180,180,180, + 180,110,2,45,70,180,180,180,180,180,110,233,120,1,137,90,1,137,120,233,70,180,180,180,180,180,110,0,0,1,0,117,0,204,6,80,4,56,0,24, + 0,0,19,53,55,23,55,23,55,23,55,51,39,55,1,21,1,39,55,35,7,39,7,39,7,39,7,117,110,180,180,180,180,180,70,139,233,120,1,137, + 254,119,120,233,99,110,180,180,180,180,180,70,2,45,170,110,180,180,180,180,180,70,233,120,254,119,90,254,119,120,233,110,180,180,180,180,180,70,0,0, + 0,1,1,163,0,0,5,15,5,220,0,25,0,0,1,51,1,7,39,17,33,21,33,21,33,21,33,17,35,17,33,53,33,53,33,53,33,17,7,39, + 3,45,90,1,136,120,232,1,40,254,216,1,40,254,216,170,254,218,1,38,254,218,1,38,234,120,5,220,254,118,120,234,254,142,170,170,170,254,172,1, + 84,170,170,170,1,114,234,120,0,1,1,163,255,249,5,15,5,213,0,25,0,0,5,35,1,55,23,17,33,53,33,53,33,53,33,17,51,17,33,21, + 33,21,33,21,33,17,55,23,3,133,90,254,120,120,232,254,216,1,40,254,216,1,40,170,1,38,254,218,1,38,254,218,234,120,7,1,138,120,234,1, + 114,170,170,170,1,84,254,172,170,170,170,254,142,234,120,0,0,3,0,100,0,204,6,63,4,56,0,9,0,13,0,17,0,0,19,53,1,23,7,33, + 21,33,23,7,1,53,33,21,51,53,33,21,100,1,137,120,233,1,113,254,143,233,120,1,170,0,255,170,0,255,2,85,90,1,137,120,233,170,233,120, + 1,97,170,170,170,170,0,0,0,3,1,163,0,0,5,17,5,220,0,9,0,13,0,17,0,0,1,51,1,7,39,17,35,17,7,39,1,51,21,35, + 21,51,17,35,3,45,90,1,138,120,234,170,234,120,1,98,170,170,170,170,5,220,254,118,120,234,254,142,1,114,234,120,254,86,254,170,255,0,0,0, + 0,3,0,117,0,204,6,80,4,56,0,9,0,13,0,17,0,0,9,1,39,55,33,53,33,39,55,1,37,33,21,35,39,21,35,53,6,80,254,119, + 120,233,254,143,1,113,233,120,1,137,251,206,0,255,255,170,255,2,85,254,119,120,233,170,233,120,254,119,40,170,170,170,170,0,0,0,0,3,1,163, + 255,249,5,17,5,213,0,9,0,13,0,17,0,0,5,1,55,23,17,51,17,55,23,1,3,53,51,21,3,17,51,17,3,45,254,118,120,234,170,234, + 120,254,118,130,170,170,170,7,1,138,120,234,1,114,254,142,234,120,254,118,3,52,254,254,1,168,1,0,255,0,0,0,0,1,0,107,0,203,6,63, + 4,57,0,13,0,0,1,21,33,23,7,1,17,35,17,51,17,1,23,7,6,63,251,238,234,120,254,118,170,170,1,138,120,234,2,215,170,234,120,1, + 138,254,126,3,92,254,128,1,138,120,234,0,0,1,0,117,0,203,6,73,4,57,0,13,0,0,19,33,39,55,1,17,51,17,35,17,1,39,55,33, + 117,4,18,234,120,1,138,170,170,254,118,120,234,251,238,2,215,234,120,254,118,1,128,252,164,1,130,254,118,120,234,0,0,2,0,55,0,134,6,63, + 4,126,0,6,0,13,0,0,9,2,53,33,17,33,19,9,1,17,33,17,33,1,207,254,246,1,10,4,12,251,244,100,254,4,1,252,4,12,251,244, + 3,140,254,246,254,246,131,1,14,253,125,1,252,1,252,254,239,254,42,0,0,2,1,94,0,0,5,86,6,8,0,6,0,13,0,0,9,2,51,17, + 33,17,5,9,1,33,17,33,17,4,100,254,246,254,246,131,1,14,253,125,1,252,1,252,254,239,254,42,4,112,1,10,254,246,251,244,4,12,100,1, + 252,254,4,251,244,4,12,0,0,2,0,72,0,134,6,80,4,126,0,6,0,13,0,0,1,21,33,17,33,21,9,1,17,33,17,33,17,1,4,184, + 251,244,4,12,1,10,254,146,251,244,4,12,1,252,3,140,131,254,242,131,1,10,254,4,1,17,1,214,1,17,254,4,0,2,1,94,255,205,5,86, + 5,213,0,6,0,13,0,0,1,35,17,33,17,35,9,1,33,17,33,17,33,1,4,100,131,254,242,131,1,10,254,4,1,17,1,214,1,17,254,4, + 1,101,4,12,251,244,254,246,1,110,4,12,251,244,254,4,0,4,1,94,0,0,5,86,6,8,0,6,0,13,0,17,0,21,0,0,1,33,17,33, + 9,1,33,3,17,51,9,1,51,17,1,17,33,17,5,33,21,33,4,69,254,42,254,239,1,252,1,252,254,239,100,131,254,246,254,246,131,1,114,254, + 42,1,114,254,242,1,14,2,36,1,232,1,252,254,4,254,124,1,232,1,10,254,246,254,24,254,212,254,164,1,92,100,148,0,0,0,0,2,1,94, + 0,0,5,86,6,8,0,10,0,21,0,0,41,1,17,51,17,33,9,1,33,17,51,5,35,21,33,53,35,17,51,9,1,51,5,13,252,154,200,254, + 239,1,252,1,252,254,239,200,253,198,200,2,158,200,131,254,246,254,246,131,1,92,2,176,1,252,254,4,253,80,100,148,148,3,120,1,10,254,246,0, + 0,3,1,64,0,0,5,116,6,8,0,11,0,22,0,25,0,0,37,35,21,33,53,35,17,51,39,33,7,51,1,33,17,51,17,33,9,1,33,17, + 51,1,51,39,2,211,200,2,158,200,161,100,254,120,100,161,2,58,252,154,200,254,209,2,26,2,26,254,209,200,253,217,232,116,248,148,148,3,90,100, + 100,251,174,1,92,2,146,2,26,253,230,253,110,3,170,116,0,3,1,94,0,0,5,86,6,8,0,6,0,17,0,24,0,0,37,35,21,33,17,7, + 51,1,33,17,51,17,33,9,1,33,17,51,1,17,33,53,35,17,51,2,196,185,1,29,216,116,2,73,252,154,185,254,254,1,252,1,252,254,254,185, + 254,127,1,29,185,116,248,148,4,228,216,251,144,1,92,2,176,1,252,254,4,253,80,3,236,251,28,148,3,120,0,0,0,3,1,94,0,0,5,86, + 6,8,0,6,0,17,0,23,0,0,37,17,51,9,1,51,17,5,33,17,33,1,33,9,1,33,1,33,3,51,9,1,51,55,3,225,131,254,246,254, + 246,131,1,114,254,42,254,239,1,24,254,232,1,252,1,252,254,232,1,24,254,239,107,138,254,246,254,246,138,128,100,2,244,1,10,254,246,253,12,100, + 2,244,1,24,1,252,254,4,254,232,1,124,1,10,254,246,128,0,0,0,0,3,1,94,0,0,5,86,6,8,0,10,0,25,0,31,0,0,37,35, + 21,33,53,35,17,51,9,1,51,1,33,17,51,17,33,1,33,9,1,33,1,33,17,51,1,51,9,1,51,55,2,211,200,2,158,200,131,254,246,254, + 246,131,2,58,252,154,200,254,239,1,24,254,232,1,252,1,252,254,232,1,24,254,239,200,254,205,138,254,246,254,246,138,128,248,148,148,2,96,1,10, + 254,246,252,168,1,92,1,152,1,24,1,252,254,4,254,232,254,104,3,20,1,10,254,246,128,0,0,0,0,2,0,117,0,134,6,125,4,126,0,10, + 0,21,0,0,55,17,33,21,33,17,9,1,17,33,21,3,53,35,17,51,53,33,21,9,1,21,117,1,92,2,176,1,252,254,4,253,80,100,148,148, + 3,120,1,10,254,246,207,3,102,200,1,17,254,4,254,4,1,17,200,2,58,200,253,98,200,131,1,10,1,10,131,0,0,2,0,122,0,0,6,77, + 5,213,0,5,0,15,0,0,1,21,33,17,35,17,1,55,33,21,33,1,7,1,17,35,6,77,250,144,99,1,34,63,2,44,254,182,3,94,120,252, + 162,169,5,213,99,250,142,5,213,254,159,63,169,252,162,120,3,94,254,182,0,2,0,122,0,0,6,77,5,213,0,5,0,15,0,0,51,53,33,17, + 51,17,1,7,33,53,33,1,55,1,17,51,122,5,112,99,254,222,63,253,212,1,74,252,162,120,3,94,169,99,5,114,250,43,1,97,63,169,3,94, + 120,252,162,1,74,0,0,0,0,2,1,94,255,205,5,86,6,8,0,9,0,19,0,0,1,17,51,9,1,51,17,35,9,1,39,33,9,1,33,17, + 33,9,1,33,3,225,131,254,246,254,246,131,131,1,10,1,10,31,1,17,254,4,254,4,1,17,254,239,1,252,1,252,254,239,1,101,3,11,1,10, + 254,246,252,245,254,246,1,10,100,254,4,1,252,2,67,1,252,254,4,0,0,3,0,117,0,204,6,80,4,56,0,41,0,53,0,65,0,0,9,1, + 39,55,33,6,7,6,7,6,7,6,34,39,38,39,38,39,38,39,35,53,51,54,55,54,55,54,55,54,50,23,22,23,22,23,22,23,33,39,55,1, + 36,34,7,6,7,6,7,33,38,39,38,39,19,33,22,23,22,23,22,50,55,54,55,54,6,80,254,119,120,233,254,161,6,10,27,50,49,64,61,147, + 58,67,46,50,27,10,6,190,190,6,10,27,50,49,64,61,147,58,67,46,50,27,10,6,1,95,233,120,1,137,252,95,82,35,41,24,26,15,1,108, + 17,24,29,36,104,254,152,14,25,29,36,35,82,35,36,29,25,2,85,254,119,120,233,24,24,64,50,49,27,26,26,30,46,50,64,24,24,170,26,25, + 64,50,49,27,26,26,30,46,50,64,25,26,233,120,254,119,157,15,18,26,28,30,35,23,28,16,254,240,29,26,28,16,15,15,16,28,26,0,0,0, + 255,255,0,119,255,249,6,59,5,220,16,39,12,22,1,44,0,0,16,7,12,24,254,212,0,0,0,0,0,1,0,117,254,116,6,80,6,144,0,25, + 0,0,1,7,5,21,1,39,55,33,53,33,39,55,33,53,33,39,55,33,53,33,39,55,1,21,7,5,6,80,255,0,255,254,119,120,233,251,61,4, + 195,215,215,251,61,4,195,215,215,251,61,4,195,233,120,1,137,255,0,255,2,85,255,255,90,254,119,120,233,170,215,215,170,215,215,170,233,120,254,119, + 90,255,255,0,0,1,0,100,0,192,6,63,4,68,0,17,0,0,19,53,1,23,7,33,17,51,17,33,21,33,17,35,17,33,23,7,100,1,137,120, + 233,2,51,170,1,230,254,26,170,253,205,233,120,2,85,90,1,137,120,233,1,109,254,147,170,254,147,1,109,233,120,0,0,1,0,117,0,192,6,80, + 4,68,0,17,0,0,9,1,39,55,33,17,35,17,33,53,33,17,51,17,33,39,55,1,6,80,254,119,120,233,253,205,170,254,26,1,230,170,2,51, + 233,120,1,137,2,85,254,119,120,233,254,147,1,109,170,1,109,254,147,233,120,254,119,0,0,1,0,100,0,192,6,80,4,68,0,23,0,0,1,17, + 51,17,33,39,55,1,21,1,39,55,33,17,35,17,33,23,7,1,53,1,23,7,3,5,170,1,137,233,120,1,137,254,119,120,233,254,119,170,254,119, + 233,120,254,119,1,137,120,233,2,215,1,109,254,147,233,120,254,119,90,254,119,120,233,254,147,1,109,233,120,1,137,90,1,137,120,233,0,1,0,100, + 0,192,6,63,4,68,0,25,0,0,19,53,1,23,7,33,17,51,17,51,17,51,17,33,21,33,17,35,17,35,17,35,17,33,23,7,100,1,137,120, + 233,1,167,170,170,170,1,30,254,226,170,170,170,254,89,233,120,2,85,90,1,137,120,233,1,109,254,147,1,109,254,147,170,254,147,1,109,254,147,1, + 109,233,120,0,0,1,0,117,0,192,6,80,4,68,0,25,0,0,9,1,39,55,33,17,35,17,35,17,35,17,33,53,33,17,51,17,51,17,51,17, + 33,39,55,1,6,80,254,119,120,233,254,89,170,170,170,254,226,1,30,170,170,170,1,167,233,120,1,137,2,85,254,119,120,233,254,147,1,109,254,147, + 1,109,170,1,109,254,147,1,109,254,147,233,120,254,119,0,0,1,0,100,0,192,6,80,4,68,0,31,0,0,1,17,51,17,51,17,51,17,33,39, + 55,1,21,1,39,55,33,17,35,17,35,17,35,17,33,23,7,1,53,1,23,7,2,156,140,100,140,1,32,233,120,1,137,254,119,120,233,254,224,140, + 100,140,254,224,233,120,254,119,1,137,120,233,2,215,1,109,254,147,1,109,254,147,233,120,254,119,90,254,119,120,233,254,147,1,109,254,147,1,109,233, + 120,1,137,90,1,137,120,233,0,2,0,55,0,196,6,63,4,64,0,2,0,9,0,0,1,17,7,5,17,9,1,17,33,21,1,165,250,1,74,254, + 66,1,190,4,74,1,136,1,244,250,65,254,131,1,190,1,190,254,131,130,0,2,0,117,0,196,6,125,4,64,0,2,0,9,0,0,1,55,39,3, + 33,53,33,17,9,1,5,15,250,250,80,251,182,4,74,1,190,254,66,1,136,250,250,254,197,130,1,125,254,66,254,66,0,3,0,55,0,196,6,125, + 4,64,0,2,0,5,0,15,0,0,1,55,39,1,17,7,5,33,17,9,1,17,33,17,9,1,5,15,250,250,252,150,250,4,20,253,54,254,66,1, + 190,2,202,1,190,254,66,1,136,250,250,254,12,1,244,250,65,254,131,1,190,1,190,254,131,1,125,254,66,254,66,0,0,2,0,16,0,0,5,104, + 5,213,0,2,0,10,0,0,37,1,33,19,1,51,19,33,19,51,1,2,188,1,19,253,219,160,253,198,213,136,2,161,136,210,253,199,199,2,231,252, + 82,5,213,254,129,1,127,250,43,0,0,0,0,1,0,135,255,227,4,110,5,240,0,29,0,109,186,0,15,0,0,0,3,43,184,0,15,16,65,27, + 0,22,0,15,0,38,0,15,0,54,0,15,0,70,0,15,0,86,0,15,0,102,0,15,0,118,0,15,0,134,0,15,0,150,0,15,0,166,0,15, + 0,182,0,15,0,198,0,15,0,214,0,15,0,13,93,65,5,0,229,0,15,0,245,0,15,0,2,93,0,186,0,18,0,27,0,3,43,184,0,18, + 16,186,0,3,0,12,0,3,43,184,0,3,16,48,49,19,16,0,51,50,23,22,23,35,38,39,38,35,34,2,17,16,18,51,50,55,54,55,51,6, + 7,6,35,34,0,135,1,9,251,251,133,66,33,202,18,27,79,157,156,157,157,156,157,79,27,18,202,33,66,133,251,251,254,247,2,233,1,122,1,141, + 198,99,144,73,55,153,254,205,254,204,254,204,254,205,153,55,73,144,99,197,1,140,0,0,0,2,0,95,255,227,3,196,5,76,0,32,0,48,0,0, + 5,34,39,38,53,52,55,54,51,50,23,22,23,54,53,52,39,38,35,34,7,53,54,51,32,23,22,21,20,7,2,7,6,1,20,23,22,51,50,55, + 54,55,54,55,38,35,34,7,6,1,181,141,92,109,96,99,178,117,92,54,37,13,32,71,188,71,110,116,104,1,12,114,53,25,63,163,128,254,193,44, + 47,72,64,51,72,53,44,22,89,154,132,58,36,29,85,101,183,190,148,152,73,43,72,81,92,135,78,173,44,168,31,246,116,173,113,131,254,184,156,122, + 1,83,100,54,57,45,62,101,83,89,215,174,108,0,0,0,0,1,0,201,0,0,4,139,5,213,0,11,0,0,1,17,33,53,33,17,33,53,33,17, + 33,53,4,139,252,62,2,248,253,8,2,248,253,8,5,213,250,43,170,1,236,170,1,235,170,0,0,0,0,3,0,201,255,162,4,139,6,53,0,19, + 0,23,0,27,0,0,1,17,33,7,35,55,35,53,51,19,33,53,33,19,33,53,33,55,51,15,1,3,51,17,1,3,33,17,4,139,253,75,29,170, + 29,99,152,152,254,208,1,100,152,254,4,2,48,30,170,30,52,152,234,254,226,152,1,182,5,213,250,43,94,94,170,1,236,170,1,235,170,96,96,170, + 254,21,1,235,253,107,254,20,1,236,0,0,0,3,0,155,255,236,6,93,5,174,0,27,0,40,0,54,0,0,1,55,51,7,22,23,22,16,2,4, + 35,34,39,38,39,7,35,55,38,39,38,16,18,36,51,50,23,22,9,1,39,38,35,34,4,7,6,7,22,23,22,9,1,22,23,22,51,50,36,55, + 54,55,38,39,38,5,8,89,106,128,105,69,100,200,254,160,185,187,176,56,48,126,105,170,63,47,99,198,1,96,187,185,176,18,252,201,2,244,14,145, + 153,154,254,221,82,81,1,1,81,36,3,103,253,5,39,45,145,154,153,1,34,83,82,1,1,82,58,5,59,110,157,83,122,178,254,128,254,157,190,95, + 30,39,156,210,66,84,177,1,128,1,99,190,95,10,251,233,3,165,8,78,157,147,145,155,155,145,64,3,68,252,82,31,24,79,157,147,145,155,155,145, + 103,0,0,0,0,2,255,250,0,0,5,96,5,193,0,2,0,6,0,56,64,15,0,3,1,3,5,4,3,2,1,0,5,7,5,6,7,16,212,204, + 17,23,57,49,0,47,196,204,17,57,48,64,20,99,1,109,2,112,1,120,2,127,2,121,5,118,6,7,110,0,127,0,2,93,1,93,9,1,33,1, + 51,1,33,2,172,254,94,3,68,253,239,224,2,67,250,154,4,238,251,196,5,15,250,63,0,2,255,250,0,0,5,96,5,193,0,2,0,6,0,0, + 37,1,33,9,1,33,1,2,172,1,162,252,188,1,51,253,189,5,102,253,189,211,4,60,250,241,5,193,250,63,0,0,0,1,0,175,255,236,6,73, + 5,174,0,28,0,0,1,22,23,22,23,22,23,33,21,33,34,36,2,53,52,18,36,51,33,21,33,6,7,6,7,6,7,33,21,1,87,7,63,74, + 140,137,148,2,185,253,71,192,254,157,190,190,1,99,192,2,185,253,71,148,137,139,75,64,9,4,245,2,115,74,120,139,78,76,1,159,198,1,96,187, + 185,1,96,200,159,1,77,79,138,120,93,160,0,3,0,175,254,229,6,73,6,175,0,30,0,38,0,47,0,0,1,23,7,33,21,33,3,33,21,33, + 3,22,51,33,21,33,34,39,3,39,19,38,39,38,2,53,52,18,36,59,1,1,20,23,22,23,22,23,19,55,19,35,34,7,6,7,6,21,4,216, + 150,73,1,36,254,162,185,2,23,253,175,176,36,36,2,185,253,71,65,63,100,150,96,44,44,177,190,190,1,99,192,234,252,221,70,85,129,29,29,160, + 59,184,176,147,138,125,89,73,6,175,55,202,159,254,4,160,254,29,5,159,11,254,238,55,1,8,19,24,99,1,96,187,185,1,96,200,252,197,74,120, + 145,72,16,13,1,184,160,1,252,78,71,146,120,93,0,0,0,1,0,217,0,155,4,229,4,103,0,22,0,0,37,32,36,53,52,36,41,1,21,5, + 6,7,6,7,33,21,33,22,23,22,51,33,21,3,43,254,216,254,214,1,42,1,40,1,186,254,70,232,105,78,29,3,118,252,138,37,70,114,223,1, + 186,155,246,240,240,246,142,1,1,79,58,133,142,145,48,81,142,0,0,0,0,1,0,175,255,236,6,73,5,174,0,28,0,0,1,38,39,38,39,38, + 39,33,53,33,50,4,18,21,20,2,4,35,33,53,33,54,55,54,55,54,55,33,53,5,161,7,63,74,140,137,148,253,71,2,185,192,1,99,190,190, + 254,157,192,253,71,2,185,148,137,139,75,64,9,251,11,3,39,74,120,139,78,76,1,159,198,254,160,187,185,254,160,200,159,1,77,79,138,120,93,160, + 0,3,0,175,254,229,6,73,6,175,0,30,0,38,0,47,0,0,1,39,55,33,53,33,19,33,53,33,19,38,35,33,53,33,50,23,19,23,3,22, + 23,22,18,21,20,2,4,43,1,1,52,39,38,39,38,39,3,7,3,51,50,55,54,55,54,53,2,32,150,73,254,220,1,94,185,253,233,2,81,176, + 36,36,253,71,2,185,65,63,100,150,96,44,44,177,190,190,254,157,192,234,3,35,70,84,130,29,29,160,59,184,176,147,138,125,89,73,254,229,55,202, + 159,1,252,160,1,227,5,159,11,1,18,55,254,248,19,24,99,254,160,187,185,254,160,200,3,59,74,120,145,72,16,13,254,72,160,254,4,78,71,146, + 120,93,0,0,0,1,0,217,0,155,4,229,4,103,0,22,0,0,1,32,4,21,20,4,41,1,53,37,50,55,54,55,33,53,5,38,39,38,7,33, + 53,2,147,1,40,1,42,254,214,254,216,254,70,1,186,232,105,78,29,252,138,3,118,37,70,116,221,254,70,4,103,246,241,239,246,142,1,80,58,133, + 142,1,145,49,82,1,142,0,0,1,1,44,0,0,3,235,3,226,0,3,0,11,0,184,0,1,47,184,0,0,47,48,49,33,17,33,17,1,44,2, + 191,3,226,252,30,0,0,0,0,1,0,156,254,119,5,113,5,193,0,7,0,30,64,15,6,2,215,4,214,0,175,8,3,103,1,5,103,0,8,16, + 212,236,212,236,49,0,16,252,236,236,50,48,19,33,17,35,17,33,17,35,156,4,213,240,253,10,239,5,193,248,182,6,125,249,131,0,0,1,0,156, + 254,119,5,113,5,193,0,7,0,30,64,15,3,214,7,215,5,1,175,8,5,103,7,3,103,1,8,16,212,236,212,236,49,0,16,252,60,252,252,48, + 19,17,51,17,33,17,51,17,156,239,2,246,240,254,119,7,74,249,131,6,125,248,182,0,0,1,0,25,254,119,5,59,5,193,0,11,0,93,64,20, + 10,4,12,2,5,7,2,0,7,12,10,5,4,3,1,0,6,6,8,12,16,212,196,23,57,49,0,16,196,212,204,16,206,17,18,57,57,48,64,48, + 81,3,86,5,80,5,90,10,115,3,112,3,118,4,117,5,112,5,122,10,128,3,128,5,12,90,9,127,2,127,3,112,5,112,6,123,9,116,11,143, + 2,143,3,128,5,128,6,11,93,1,93,19,33,21,33,9,1,33,21,33,53,9,1,55,4,234,252,65,2,160,253,74,3,239,250,222,2,213,253,73, + 5,193,193,253,51,253,4,192,149,3,33,2,227,0,0,0,0,1,0,217,2,45,5,219,2,215,0,3,0,17,182,0,156,2,4,1,0,4,16,212, + 196,49,0,16,212,236,48,19,33,21,33,217,5,2,250,254,2,215,170,0,0,2,0,217,0,0,5,219,5,4,0,11,0,15,0,0,33,35,17,33, + 53,33,17,51,17,33,21,33,1,53,33,21,3,174,168,253,211,2,45,168,2,45,253,211,253,43,5,2,1,131,170,1,131,254,125,170,2,215,170,170, + 0,2,0,217,0,0,5,219,5,213,0,11,0,15,0,87,186,0,5,0,6,0,3,43,184,0,5,16,184,0,0,208,184,0,6,16,184,0,10,208, + 184,0,6,16,184,0,12,208,184,0,5,16,184,0,13,208,0,184,0,5,47,186,0,13,0,14,0,3,43,184,0,13,16,186,0,2,0,3,0,3, + 43,184,0,2,16,184,0,3,16,184,0,7,208,184,0,2,16,184,0,9,208,48,49,1,17,33,21,33,17,35,17,33,53,33,25,1,51,21,35,3, + 174,2,45,253,211,168,253,211,2,45,168,168,4,160,254,5,170,254,5,1,251,170,1,251,1,53,204,0,255,255,0,0,255,66,2,178,5,213,16,6, + 0,18,0,0,255,255,1,138,255,146,4,60,6,37,16,7,0,63,1,138,0,80,0,0,0,1,1,5,0,0,5,175,5,4,0,17,0,0,1,37, + 55,5,17,51,17,37,23,13,1,7,37,17,35,17,5,39,2,177,254,84,85,1,172,168,1,172,85,254,84,1,172,85,254,84,168,254,84,85,2,130, + 247,147,247,1,239,254,17,247,147,247,247,147,247,254,17,1,239,247,147,0,255,255,1,68,1,71,3,190,3,194,16,7,0,114,0,129,253,210,0,0, + 255,255,1,88,1,89,3,170,3,169,16,6,11,0,37,136,0,1,0,61,255,215,5,25,6,125,0,10,0,42,64,24,10,9,8,7,6,5,11,2, + 4,2,0,11,10,9,7,6,5,4,3,0,8,1,8,11,16,212,204,23,57,49,0,16,212,204,196,17,18,23,57,48,1,51,21,35,1,35,1,7, + 39,37,1,4,92,189,115,253,174,66,254,193,125,25,1,27,1,0,6,125,96,249,186,3,115,45,80,98,253,59,0,0,255,255,0,61,255,215,5,25, + 7,118,18,38,12,159,0,0,16,7,0,117,0,115,1,134,255,255,0,61,255,215,5,25,7,101,18,38,12,159,0,0,16,7,11,75,0,115,1,134, + 0,2,0,220,0,229,4,219,3,229,0,11,0,49,0,0,1,50,55,2,35,34,7,6,21,20,23,22,5,21,35,34,39,38,39,38,39,6,7,6, + 35,34,39,38,53,52,55,54,51,50,23,22,23,22,23,54,55,54,59,1,21,35,34,7,18,51,2,15,165,99,127,137,100,51,54,54,56,3,43,77, + 73,54,54,52,31,49,67,59,73,116,135,89,94,94,83,143,73,54,63,43,40,40,67,59,73,116,75,64,148,116,127,137,1,107,240,1,6,72,77,102, + 112,69,70,2,132,30,27,63,36,84,120,53,64,101,106,175,168,114,101,30,33,57,51,69,120,53,64,131,240,254,250,0,0,3,0,220,0,229,5,206, + 3,229,0,35,0,47,0,59,0,0,1,38,39,6,7,6,35,34,39,38,53,52,55,54,51,50,23,22,23,22,23,54,55,54,51,50,23,22,21,20, + 7,6,35,34,39,38,37,50,55,2,35,34,7,6,21,20,23,22,1,34,7,18,51,50,55,54,53,52,39,38,3,165,31,49,67,59,74,115,135,89, + 94,94,84,142,73,54,63,43,40,40,67,59,74,115,135,89,94,94,84,142,73,54,54,254,54,165,99,127,137,100,51,55,55,56,2,235,149,115,126,138, + 100,51,55,55,56,1,93,36,84,120,53,64,101,106,175,168,114,101,30,33,57,51,69,120,53,64,101,106,175,168,114,101,30,27,77,240,1,6,72,77, + 102,112,69,70,1,244,240,254,250,72,77,102,112,69,70,0,0,1,1,27,0,203,5,153,5,73,0,5,0,0,37,33,17,51,17,33,5,153,251,130, + 170,3,212,203,4,126,252,44,0,1,0,175,0,0,6,73,5,213,0,5,0,0,37,21,33,1,51,1,6,73,250,102,3,185,242,252,203,202,202,5, + 213,250,245,0,0,2,0,175,255,148,6,73,5,213,0,5,0,27,0,65,0,184,0,7,47,184,0,18,47,186,0,14,0,15,0,3,43,184,0,14, + 16,184,0,0,208,186,0,4,0,18,0,7,17,18,57,186,0,5,0,18,0,7,17,18,57,184,0,15,16,184,0,21,208,186,0,22,0,18,0,7, + 17,18,57,48,49,37,38,39,38,39,1,19,1,51,1,22,23,22,23,33,21,33,22,21,35,52,39,33,1,38,39,55,22,4,96,39,74,65,87,254, + 206,227,1,96,242,254,76,113,82,93,43,1,88,254,201,4,140,5,252,42,2,13,30,31,80,29,202,139,134,115,94,254,30,2,227,2,40,253,82,115, + 147,167,176,202,53,55,55,53,3,54,21,20,117,19,0,0,0,2,0,237,255,250,5,220,5,209,0,23,0,29,0,53,186,0,13,0,28,0,3,43, + 184,0,13,16,0,184,0,9,47,184,0,18,47,186,0,5,0,18,0,9,17,18,57,186,0,22,0,18,0,9,17,18,57,186,0,25,0,18,0,9, + 17,18,57,48,49,9,1,55,1,38,39,55,22,23,37,21,5,22,7,21,6,7,5,21,37,6,7,39,54,19,9,1,54,55,54,3,114,253,123,2, + 2,142,25,29,139,29,25,1,212,254,138,69,6,7,71,1,133,254,37,28,30,134,31,121,253,221,2,26,52,4,7,1,52,1,82,192,1,87,33,30, + 76,33,36,238,210,190,179,198,9,161,147,191,210,241,38,33,76,32,2,233,254,231,254,240,123,129,158,0,0,1,1,176,254,74,2,80,6,43,0,3, + 0,0,1,51,17,35,1,176,160,160,6,43,248,31,0,0,0,1,0,102,254,74,3,155,6,43,0,11,0,55,186,0,6,0,0,0,3,43,184,0, + 6,16,184,0,2,208,184,0,0,16,184,0,8,208,0,184,0,1,47,184,0,7,47,186,0,3,0,7,0,1,17,18,57,186,0,9,0,7,0,1, + 17,18,57,48,49,1,17,51,17,55,23,5,17,35,17,7,39,1,176,160,251,80,254,181,160,253,77,2,86,3,213,252,156,176,111,231,252,41,3,103, + 177,110,0,0,0,2,1,16,254,74,2,240,6,43,0,3,0,7,0,0,1,51,17,35,1,51,17,35,1,16,160,160,1,64,160,160,6,43,248,31, + 7,225,248,31,0,1,0,102,254,74,3,155,6,43,0,19,0,123,184,0,20,47,184,0,21,47,184,0,20,16,184,0,0,208,184,0,0,47,184,0, + 14,220,184,0,2,208,184,0,21,16,184,0,10,220,184,0,4,220,184,0,10,16,184,0,6,208,184,0,4,16,184,0,12,208,184,0,0,16,184,0, + 16,208,0,184,0,1,47,184,0,5,47,184,0,11,47,184,0,15,47,186,0,3,0,11,0,1,17,18,57,186,0,7,0,11,0,1,17,18,57,186, + 0,13,0,11,0,1,17,18,57,186,0,17,0,11,0,1,17,18,57,48,49,1,17,51,17,55,17,51,17,55,23,7,17,35,17,7,17,35,17,7, + 39,1,16,160,160,160,91,80,171,160,160,160,93,77,1,230,4,69,252,43,113,3,100,253,12,64,111,120,251,186,3,215,112,252,153,2,247,65,110,0, + 0,1,1,8,0,0,4,211,4,162,0,6,0,0,33,1,51,1,35,9,1,1,8,1,105,250,1,104,195,254,222,254,221,4,162,251,94,3,172,252, + 84,0,0,0,0,1,1,8,0,0,4,211,4,162,0,6,0,0,1,51,9,1,51,1,35,1,8,195,1,35,1,34,195,254,152,250,4,162,252,84, + 3,172,251,94,0,1,1,8,0,0,4,211,4,162,0,17,0,0,1,16,18,51,50,18,25,1,35,17,52,38,35,34,6,21,17,35,1,8,245,241, + 240,245,172,148,165,166,148,172,2,80,1,40,1,42,254,214,254,216,253,176,2,55,244,211,211,244,253,201,0,1,1,8,0,0,4,211,4,162,0,17, + 0,0,1,17,51,17,20,22,51,50,54,53,17,51,17,16,2,35,34,2,1,8,172,148,166,165,148,172,245,240,241,245,2,82,2,80,253,201,244,211, + 211,244,2,55,253,176,254,216,254,214,1,42,0,1,0,117,254,77,3,182,6,14,0,21,0,0,1,62,1,50,22,23,7,38,35,34,7,3,14,1, + 34,38,39,55,22,51,50,55,1,227,8,162,151,126,20,148,17,57,71,8,65,8,162,151,126,20,148,17,57,71,8,4,226,167,133,125,140,15,130,175, + 250,176,167,133,125,140,15,130,175,0,0,0,255,255,0,117,254,77,5,219,6,14,16,38,12,176,0,0,16,7,12,176,2,37,0,0,255,255,0,117, + 254,77,8,0,6,14,16,38,12,176,0,0,16,39,12,176,2,37,0,0,16,7,12,176,4,74,0,0,0,3,0,117,254,77,3,182,6,14,0,45, + 0,54,0,63,0,0,1,54,55,54,51,50,23,22,23,7,38,35,34,7,3,22,23,22,21,20,7,6,7,3,6,7,6,35,34,39,38,39,55,22, + 51,50,55,19,38,39,38,53,52,55,54,55,19,54,55,54,53,52,39,38,39,3,19,6,7,6,21,20,23,22,1,227,8,83,79,74,77,71,55,20, + 148,17,57,71,8,14,99,66,110,110,86,115,15,8,83,79,74,77,71,55,20,148,17,57,71,8,15,93,73,110,111,83,117,138,61,44,69,71,37,44, + 189,22,61,44,72,75,37,4,226,167,68,65,70,55,140,15,130,175,254,214,24,75,124,146,156,111,85,19,254,190,167,68,65,70,55,140,15,130,175,1, + 49,24,73,111,155,156,115,86,19,253,155,16,47,72,103,106,71,36,18,254,52,1,214,17,46,74,104,103,72,36,0,0,0,4,0,117,254,77,5,219, + 6,14,0,77,0,81,0,90,0,99,0,0,1,54,55,54,51,50,23,22,23,7,38,35,34,7,3,33,19,54,55,54,51,50,23,22,23,7,38,35, + 34,7,3,22,23,22,21,20,7,6,7,3,6,7,6,35,34,39,38,39,55,22,51,50,55,19,33,3,6,7,6,35,34,39,38,39,55,22,51,50, + 55,19,38,39,38,53,52,55,54,55,19,33,19,33,3,19,6,7,6,21,20,23,22,1,3,54,55,54,53,52,39,38,1,227,8,83,79,74,77,71, + 55,20,148,17,57,71,8,14,1,126,15,8,83,79,74,77,71,55,20,148,17,57,71,8,14,99,66,110,110,86,115,15,8,83,79,74,77,71,55,20, + 148,17,57,71,8,14,254,130,15,8,83,79,74,77,71,55,20,148,17,57,71,8,15,93,73,110,111,83,117,137,1,126,24,254,130,190,22,61,44,72, + 75,37,3,13,22,61,44,69,71,37,4,226,167,68,65,70,55,140,15,130,175,254,226,1,55,167,68,65,70,55,140,15,130,175,254,214,24,75,124,146, + 156,111,85,19,254,190,167,68,65,70,55,140,15,130,175,1,36,254,195,167,68,65,70,55,140,15,130,175,1,48,25,73,111,155,156,115,86,19,253,146, + 1,241,254,33,1,214,17,46,74,104,103,72,36,1,186,254,43,16,47,72,103,106,71,36,0,5,0,117,254,77,8,0,6,14,0,109,0,113,0,117, + 0,126,0,135,0,0,1,54,55,54,51,50,23,22,23,7,38,35,34,7,3,33,19,54,55,54,51,50,23,22,23,7,38,35,34,7,3,33,19,54, + 55,54,51,50,23,22,23,7,38,35,34,7,3,22,23,22,21,20,7,6,7,3,6,7,6,35,34,39,38,39,55,22,51,50,55,19,33,3,6,7, + 6,35,34,39,38,39,55,22,51,50,55,19,33,3,6,7,6,35,34,39,38,39,55,22,51,50,55,19,38,39,38,53,52,55,54,55,1,19,33,3, + 41,1,19,33,3,19,6,7,6,21,20,23,22,1,3,54,55,54,53,52,39,38,1,227,8,83,79,74,77,71,55,20,148,17,57,71,8,14,1,126, + 15,8,83,79,74,77,71,55,20,148,17,57,71,8,14,1,126,15,8,83,79,74,77,71,55,20,148,17,57,71,8,14,99,66,110,110,86,115,15,8, + 83,79,74,77,71,55,20,148,17,57,71,8,14,254,130,15,8,83,79,74,77,71,55,20,148,17,57,71,8,14,254,130,15,8,83,79,74,77,71,55, + 20,148,17,57,71,8,15,93,73,110,111,83,117,4,44,24,254,130,24,253,219,1,126,24,254,130,190,22,61,44,72,75,37,5,50,22,61,44,69,71, + 37,4,226,167,68,65,70,55,140,15,130,175,254,226,1,55,167,68,65,70,55,140,15,130,175,254,226,1,55,167,68,65,70,55,140,15,130,175,254,214, + 24,75,124,146,156,111,85,19,254,190,167,68,65,70,55,140,15,130,175,1,36,254,195,167,68,65,70,55,140,15,130,175,1,36,254,195,167,68,65,70, + 55,140,15,130,175,1,48,25,73,111,155,156,115,86,19,253,146,1,241,254,15,1,241,254,33,1,214,17,46,74,104,103,72,36,1,186,254,43,16,47, + 72,103,106,71,36,0,0,0,0,1,0,117,254,76,4,46,6,15,0,51,0,0,1,38,35,34,7,3,22,23,22,29,1,55,23,7,35,39,55,23, + 53,52,39,38,39,3,14,1,35,34,38,39,55,22,51,50,55,19,6,7,6,21,35,52,55,54,55,19,62,1,51,50,22,23,3,34,17,59,69,8, + 16,89,63,119,94,72,190,54,188,72,92,79,51,44,44,8,160,72,79,128,20,148,17,59,69,8,43,64,47,86,102,109,86,109,17,8,160,72,79,128, + 20,4,246,130,175,254,179,24,63,117,156,30,93,72,189,189,72,93,30,115,77,51,11,252,103,165,135,122,143,15,130,175,3,136,16,46,86,114,155,109, + 86,17,1,95,165,135,122,143,0,3,0,117,254,77,4,29,6,14,0,8,0,17,0,60,0,0,1,19,6,7,6,21,20,23,22,37,52,39,3,62, + 1,55,39,55,19,38,35,34,7,3,22,23,22,21,55,23,7,6,7,6,7,3,14,1,34,38,39,55,22,51,50,55,19,38,39,38,53,52,55,54, + 55,19,62,1,50,22,23,1,183,22,61,44,72,75,37,1,128,152,22,61,81,9,135,72,108,17,59,69,8,14,89,76,109,72,72,167,26,60,86,115, + 15,8,159,152,128,20,148,17,59,69,8,15,93,73,110,111,83,117,15,8,159,152,128,20,1,74,1,214,17,46,74,103,104,72,36,230,153,59,254,43, + 16,101,19,136,72,2,93,130,175,254,214,22,77,111,124,72,72,167,67,63,90,19,254,190,165,135,122,143,15,130,175,1,49,24,73,111,155,156,115,86, + 19,1,60,164,136,122,143,0,0,3,0,117,254,77,4,31,6,14,0,8,0,18,0,59,0,0,1,19,6,7,6,21,20,23,22,1,46,1,39,3, + 62,1,55,7,39,19,38,35,34,7,3,30,1,31,1,7,39,20,6,7,3,14,1,34,38,39,55,22,51,50,55,19,38,39,38,53,52,55,54,55, + 19,62,1,50,22,23,1,183,22,61,44,72,75,37,1,109,35,54,44,22,61,105,7,83,72,178,17,59,69,8,14,99,139,18,164,72,75,194,115,15, + 8,159,152,128,20,148,17,59,69,8,15,93,73,110,111,83,117,15,8,159,152,128,20,1,74,1,214,17,46,74,103,104,72,36,1,54,66,48,18,254, + 43,16,130,64,84,72,2,239,130,175,254,214,24,157,63,164,72,75,124,192,19,254,190,165,135,122,143,15,130,175,1,49,24,73,111,155,156,115,86,19, + 1,60,164,136,122,143,0,0,255,255,0,121,0,205,4,158,4,213,16,39,13,74,255,158,254,133,16,39,13,74,2,240,254,133,16,7,13,74,1,71, + 1,143,0,0,255,255,0,121,0,205,4,158,4,213,16,39,13,74,1,71,254,133,16,39,13,74,2,240,1,143,16,7,13,74,255,158,1,143,0,0, + 255,255,0,161,0,205,1,116,4,214,16,39,13,74,255,198,1,144,16,7,13,74,255,198,254,133,0,0,255,255,0,121,0,205,4,158,4,213,16,39, + 13,74,2,240,1,143,16,39,13,74,255,158,1,143,16,39,13,74,2,240,254,133,16,7,13,74,255,158,254,133,0,0,255,255,0,217,2,45,5,219, + 4,106,16,39,13,74,2,20,1,36,16,6,12,151,0,0,0,3,0,217,0,159,5,220,4,106,0,3,0,7,0,11,0,0,1,51,21,35,19,51, + 21,35,5,33,21,33,5,8,211,211,1,211,211,251,208,3,88,252,168,1,157,254,3,203,254,149,170,0,255,255,0,216,0,159,5,220,4,106,16,38, + 12,151,0,0,16,39,13,74,255,253,254,87,16,39,13,74,255,254,1,36,16,39,13,74,4,45,254,87,16,7,13,74,4,46,1,36,255,255,0,217, + 0,159,5,219,4,106,16,38,12,193,0,0,16,39,13,74,2,19,254,87,16,7,13,74,2,20,1,36,0,1,0,217,1,211,5,219,3,50,0,29, + 0,0,1,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,5,219,105,179,97,110,146,10, + 7,6,15,155,94,88,172,98,105,179,97,110,147,11,5,6,15,155,94,86,169,3,50,179,78,69,59,4,3,2,6,61,76,84,179,78,69,59,5,2, + 2,6,61,75,0,1,0,217,1,211,5,219,3,50,0,29,0,0,19,30,1,51,50,55,54,55,54,55,54,51,50,22,23,21,46,1,35,34,7,6, + 7,6,7,6,35,34,38,39,217,103,169,86,94,155,15,6,5,11,147,110,97,179,105,98,172,88,94,155,15,6,7,10,146,110,97,179,105,3,50,85, + 75,61,6,2,2,5,59,69,78,179,84,76,61,6,2,3,4,59,69,78,0,1,0,162,1,49,6,18,3,212,0,41,0,0,1,46,1,35,34,6, + 21,30,1,51,7,34,46,1,53,52,62,1,51,50,22,23,30,1,51,50,54,53,46,1,35,55,50,30,1,21,20,14,1,35,34,38,3,58,81,159, + 72,82,100,2,104,78,1,105,156,92,100,142,110,120,194,62,64,176,72,82,100,2,104,78,1,105,156,92,100,142,110,120,196,2,46,116,116,108,72,61, + 89,155,79,154,72,76,162,92,125,88,91,141,108,72,61,89,155,79,154,72,76,162,92,125,0,1,0,217,0,87,5,219,4,173,0,17,0,0,1,2, + 35,34,3,2,39,34,3,35,18,51,50,19,18,23,50,19,5,219,123,251,230,100,102,102,116,88,170,123,251,230,100,102,102,116,88,2,215,253,128,1, + 214,1,220,1,254,35,2,128,254,42,254,36,1,1,221,0,0,1,0,208,0,0,2,48,5,2,0,29,0,0,33,35,46,1,53,52,55,54,55,54, + 55,54,53,52,38,39,51,30,1,21,20,7,6,7,6,7,6,21,20,22,2,48,180,78,68,58,4,4,2,6,60,76,84,180,78,68,58,6,2,2, + 6,60,74,104,180,96,110,146,10,8,6,14,156,94,88,172,98,106,178,98,110,146,12,4,6,16,154,94,86,170,0,0,0,1,0,217,0,157,5,219, + 4,108,0,27,0,0,1,38,35,34,6,7,53,62,1,51,50,23,19,23,3,22,51,50,54,55,21,14,1,35,34,39,3,39,2,230,99,68,88,172, + 98,105,179,97,93,121,172,155,168,101,69,86,169,103,105,179,97,96,121,171,155,2,83,32,76,84,179,78,69,43,1,126,70,254,140,32,75,85,179,78, + 69,44,254,133,70,0,0,0,0,2,0,217,1,16,5,219,3,162,0,28,0,32,0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53, + 62,1,51,50,23,22,23,22,23,22,51,50,54,1,33,21,33,5,219,105,179,97,110,146,17,6,15,155,94,88,172,98,105,179,97,110,147,11,5,6, + 15,155,94,86,169,251,101,5,2,250,254,2,111,179,78,69,59,7,2,6,61,76,84,179,78,69,59,5,2,2,6,61,75,1,136,168,0,2,0,217, + 1,96,5,219,3,244,0,26,0,30,0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,1,33, + 21,33,5,219,105,179,97,110,146,17,6,15,155,94,88,172,98,105,179,97,110,147,15,22,155,94,86,169,251,101,5,2,250,254,3,244,178,79,69,59, + 7,2,6,61,76,83,178,78,69,59,6,9,61,75,254,107,170,0,0,0,0,2,0,217,0,98,5,219,4,211,0,37,0,38,0,0,1,3,22,51, + 50,55,54,55,21,14,1,35,34,39,7,33,21,33,7,39,55,33,53,33,55,38,35,34,6,7,53,62,1,51,50,31,1,19,1,5,3,203,31,37, + 72,92,175,12,105,179,97,66,80,144,2,159,252,239,185,137,108,254,229,1,153,184,145,90,88,172,98,105,179,97,110,147,51,239,253,125,4,111,254,233, + 11,45,88,34,178,79,69,22,186,170,254,100,154,170,243,56,76,83,178,78,69,59,22,1,73,252,141,0,0,3,0,217,0,184,5,219,4,193,0,26, + 0,30,0,34,0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,1,33,21,33,21,33,21,33, + 5,219,105,179,97,110,146,17,6,15,155,94,88,172,98,105,179,97,110,147,15,22,155,94,86,169,251,101,5,2,250,254,5,2,250,254,4,193,178,79, + 69,59,7,2,6,61,76,83,178,78,69,59,6,7,63,75,254,107,170,203,170,0,0,0,0,2,0,217,0,24,5,219,4,193,0,26,0,46,0,0, + 1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,1,35,53,33,55,33,53,33,55,23,7,33,21,33, + 7,33,21,33,7,39,5,219,105,179,97,110,146,17,6,15,155,94,88,172,98,105,179,97,110,147,15,22,155,94,86,169,252,76,231,1,149,209,253,154, + 3,25,140,111,19,1,1,254,75,208,2,133,252,201,166,111,4,193,178,79,69,59,7,2,6,61,76,83,178,78,69,59,6,7,63,75,252,76,170,203, + 170,138,115,23,170,203,170,160,115,0,0,0,0,1,0,217,255,246,5,219,5,66,0,46,0,0,1,22,51,50,55,54,55,21,14,1,35,34,39,7, + 33,21,33,7,33,21,33,7,39,55,35,53,33,55,33,53,33,55,39,38,35,34,6,7,53,62,1,51,50,31,1,55,23,4,98,10,9,75,96,74, + 113,105,179,97,39,43,92,2,43,253,122,108,2,242,252,179,104,146,62,249,1,84,109,254,63,2,28,117,50,155,94,88,172,98,105,179,97,110,147,99, + 134,146,4,34,1,37,30,93,178,79,69,7,171,170,203,170,194,78,116,170,203,170,218,20,61,76,83,178,78,69,59,37,250,78,0,0,0,2,0,217, + 1,16,5,219,3,244,0,29,0,59,0,63,64,31,46,31,57,42,0,45,34,19,1,16,27,12,30,42,156,49,57,156,34,4,156,27,12,156,19,60, + 30,0,45,15,60,16,212,60,196,50,49,0,16,212,236,212,236,220,252,212,236,192,17,18,57,57,17,18,57,57,17,18,57,57,48,1,21,14,1,35, + 34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,19,21,14,1,35,34,39,38,39,38,39,38,35,34,6, + 7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,5,219,105,179,97,110,146,10,7,6,15,155,94,88,172,98,105,179,97,110,147,11,5,6,15, + 155,94,86,169,103,105,179,97,110,146,10,7,6,15,155,94,88,172,98,105,179,97,110,147,10,5,7,15,155,94,86,169,2,111,179,78,69,59,4,3, + 2,6,61,76,84,179,78,69,59,5,2,2,6,61,75,1,218,178,79,69,59,4,3,2,6,61,76,83,178,78,69,59,4,2,3,6,61,75,0,0, + 0,1,0,217,0,5,5,219,4,255,0,52,0,0,1,22,51,50,54,55,21,14,1,35,34,39,7,22,51,50,54,55,21,14,1,35,34,47,1,3, + 39,19,38,35,34,6,7,53,62,1,51,50,23,55,38,35,34,6,7,53,62,1,50,31,1,19,23,4,17,57,43,86,169,103,105,179,97,64,76,74, + 147,90,86,169,103,105,179,97,131,125,19,141,164,137,57,43,88,172,98,105,179,97,64,77,72,146,90,88,172,98,105,179,194,160,18,141,164,3,97,13, + 75,85,178,79,69,20,187,56,75,85,179,78,69,59,9,254,152,64,1,94,13,76,84,179,78,69,20,187,56,76,83,178,78,69,59,7,1,102,64,0, + 0,3,0,217,0,184,5,219,4,201,0,26,0,53,0,57,0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2, + 22,51,50,54,19,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,1,33,21,33,5,219,105,179,97,110, + 146,17,6,15,155,94,88,172,98,105,179,97,110,147,15,22,155,94,86,169,103,105,179,97,113,143,17,6,15,155,94,88,172,98,105,179,97,110,147,15, + 22,198,51,86,169,251,101,5,2,250,254,3,76,178,79,69,59,7,2,6,61,76,83,178,78,69,59,6,7,63,75,1,210,178,79,69,59,7,2,6, + 61,76,83,178,78,69,59,6,7,63,75,252,238,170,0,0,0,3,0,217,0,121,5,219,4,209,0,26,0,53,0,80,0,0,1,21,14,1,35,34, + 47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,19,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50, + 31,2,22,51,50,54,19,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,5,219,105,179,97,110,146,17, + 6,15,155,94,88,172,98,105,179,97,110,147,15,22,155,94,86,169,103,105,179,97,110,146,17,6,15,155,94,88,172,98,105,179,97,110,147,15,22,155, + 94,86,169,103,105,179,97,113,143,17,6,15,155,94,88,172,98,105,179,97,110,147,15,22,198,51,86,169,1,215,178,79,69,59,7,2,6,61,76,83, + 178,78,69,59,6,7,63,75,1,210,178,79,69,59,7,2,6,61,76,83,178,78,69,59,6,7,63,75,1,210,178,79,69,59,7,2,6,61,76,83, + 178,78,69,59,6,7,63,75,0,3,0,217,0,184,5,219,4,193,0,26,0,30,0,34,0,0,19,30,1,51,50,63,2,54,51,50,22,23,21,46, + 1,35,34,7,6,15,1,6,35,34,38,39,1,21,33,53,1,21,33,53,217,103,169,86,94,155,22,15,147,110,97,179,105,98,172,88,94,155,15,6, + 17,146,110,97,179,105,5,2,250,254,5,2,250,254,4,193,85,75,63,7,6,59,69,78,178,83,76,61,6,2,7,59,69,79,254,200,170,170,254,139, + 170,170,0,0,0,2,0,216,0,215,5,219,4,43,0,9,0,19,0,0,1,32,37,53,4,5,32,37,21,4,5,32,5,21,36,37,4,5,53,36, + 3,91,254,225,254,156,1,103,1,28,1,38,1,89,254,162,254,224,1,37,1,90,254,163,254,222,254,224,254,157,1,104,2,211,166,178,149,17,166,178, + 151,179,166,178,151,15,2,164,178,151,0,0,0,2,0,217,0,54,5,219,4,206,0,28,0,57,0,0,37,54,55,54,55,54,55,33,21,33,6,7, + 6,7,6,34,39,38,39,38,39,33,53,33,22,23,22,23,22,19,6,7,6,7,6,7,33,53,33,54,55,54,55,54,50,23,22,23,22,23,33,21, + 33,38,39,38,39,38,3,91,67,45,56,30,27,4,1,155,254,246,14,28,55,86,89,206,89,87,54,30,12,254,246,1,156,4,27,30,56,46,67,67, + 46,56,30,27,4,254,100,1,10,12,30,54,87,89,206,89,86,55,28,14,1,10,254,101,4,27,30,56,45,217,4,30,44,67,69,91,168,60,48,91, + 50,51,51,50,91,51,57,168,92,68,68,43,30,3,78,4,30,43,68,68,92,168,57,51,91,50,51,51,50,91,48,60,168,91,69,67,44,30,0,0, + 0,2,0,217,1,96,5,219,4,206,0,28,0,32,0,0,1,6,7,6,7,6,7,33,53,33,54,55,54,55,54,50,23,22,23,22,23,33,21,33, + 38,39,38,39,38,1,33,21,33,3,91,67,46,56,30,27,4,254,100,1,10,12,30,54,87,89,206,89,86,55,28,14,1,10,254,101,4,27,30,56, + 45,253,59,5,2,250,254,4,43,4,30,43,68,68,92,168,57,51,91,50,51,51,50,91,48,60,168,91,69,67,44,30,253,227,170,0,255,255,0,217, + 1,96,5,219,4,255,16,39,13,74,2,21,1,185,16,6,0,32,0,0,255,255,0,217,0,2,5,219,4,255,16,39,13,74,2,19,253,186,16,38, + 0,32,0,0,16,7,13,74,2,20,1,185,255,255,0,217,0,5,5,222,4,255,16,39,13,74,255,254,1,185,16,38,0,32,0,0,16,7,13,74, + 4,48,253,189,255,255,0,217,0,5,5,221,4,255,16,39,13,74,255,254,253,189,16,38,0,32,2,0,16,7,13,74,4,46,1,185,255,255,0,207, + 1,54,7,50,3,207,16,39,13,74,255,244,254,238,16,39,13,74,255,244,0,137,16,7,0,32,1,87,0,0,0,0,255,255,0,205,1,54,7,51, + 3,204,16,38,0,32,244,0,16,39,13,74,5,133,0,134,16,7,13,74,5,133,254,238,0,2,0,217,1,96,5,219,3,162,0,9,0,27,0,0, + 1,6,21,20,23,51,54,53,52,39,23,33,21,33,53,33,38,53,52,55,33,53,33,21,33,22,23,20,2,230,52,52,242,51,52,141,1,119,250,254, + 1,126,25,27,254,128,5,2,254,137,26,1,2,250,48,73,71,48,48,71,71,50,240,170,170,63,56,62,59,168,168,26,95,56,0,0,0,4,0,217, + 1,96,5,219,6,21,0,3,0,7,0,17,0,32,0,0,19,33,21,33,21,33,21,33,1,34,6,21,20,22,50,54,52,38,39,50,22,23,30,1, + 21,20,6,35,34,38,53,52,54,217,5,2,250,254,5,2,250,254,2,133,72,100,100,145,100,101,72,59,107,39,42,42,168,122,123,164,167,3,162,168, + 240,170,4,68,98,70,69,96,96,139,98,113,43,40,40,100,58,115,161,158,118,118,163,0,0,3,0,217,1,96,5,219,5,75,0,3,0,7,0,17, + 0,0,19,33,21,33,21,33,21,33,1,32,23,21,38,33,6,7,53,54,217,5,2,250,254,5,2,250,254,2,130,1,0,225,224,254,255,254,230,233, + 3,162,168,240,170,3,235,151,178,151,2,149,178,151,0,0,0,3,0,217,1,96,5,219,6,127,0,3,0,7,0,14,0,0,19,33,21,33,21,33, + 21,33,9,1,51,1,35,11,1,217,5,2,250,254,5,2,250,254,1,36,1,4,180,1,3,159,190,184,3,162,168,240,170,2,130,2,157,253,99,1, + 217,254,39,0,0,3,0,217,1,96,5,219,6,127,0,3,0,7,0,14,0,0,19,33,21,33,21,33,21,33,1,51,27,1,51,1,35,217,5,2, + 250,254,5,2,250,254,1,36,166,184,190,159,254,253,180,3,162,168,240,170,5,31,254,39,1,217,253,99,0,3,0,217,1,96,5,219,6,202,0,3, + 0,7,0,17,0,0,19,33,21,33,21,33,21,33,19,33,27,1,33,7,19,39,7,19,217,5,2,250,254,5,2,250,254,250,1,43,93,94,1,42, + 242,94,244,243,93,3,162,168,240,170,4,78,1,28,254,228,176,254,228,176,176,1,28,0,0,4,0,217,1,96,5,219,6,212,0,3,0,7,0,10, + 0,14,0,0,19,33,21,33,21,33,21,33,1,3,33,3,51,1,33,217,5,2,250,254,5,2,250,254,2,130,166,1,78,223,112,1,33,253,78,3, + 162,168,240,170,4,192,254,78,2,102,253,31,0,7,0,217,1,96,5,219,6,28,0,3,0,7,0,27,0,48,0,55,0,71,0,79,0,0,19,33, + 21,33,21,33,21,33,1,21,35,34,6,29,1,51,21,35,17,35,17,35,53,51,53,52,54,51,3,21,33,20,22,51,50,54,55,21,14,1,35,34, + 38,53,52,54,51,50,22,7,52,38,35,34,6,21,39,53,51,17,35,53,14,1,35,34,38,52,54,51,50,22,6,20,22,50,54,52,38,34,217,5, + 2,250,254,5,2,250,254,4,164,63,36,27,109,109,67,63,63,63,68,237,254,207,78,66,38,72,35,36,74,39,96,113,107,91,81,95,67,60,49,55, + 72,198,66,66,21,64,44,73,92,92,73,44,64,205,60,105,61,61,105,3,162,168,240,170,4,188,55,30,36,36,51,254,160,1,96,51,28,68,61,254, + 170,32,68,72,19,18,62,15,16,112,96,99,116,105,71,54,66,63,57,105,218,253,208,61,36,35,116,190,117,35,103,147,83,83,147,83,0,3,0,217, + 1,96,5,219,6,20,0,3,0,7,0,42,0,0,19,33,21,33,21,33,21,33,1,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21,17,35, + 17,52,38,35,34,6,21,17,35,17,51,21,62,1,51,50,22,217,5,2,250,254,5,2,250,254,2,159,33,93,63,85,92,90,55,57,69,80,90,55, + 58,68,80,90,90,30,86,58,59,83,3,162,168,240,170,4,61,61,58,120,111,254,181,1,72,79,77,93,81,254,202,1,72,80,76,94,80,254,202,2, + 37,85,50,48,61,0,0,0,0,4,0,217,1,96,5,219,6,218,0,3,0,7,0,11,0,44,0,0,19,33,21,33,21,33,21,33,1,51,21,35, + 55,35,53,52,54,63,1,62,1,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,15,1,14,1,7,14,1,21,217,5,2,250,254,5,2, + 250,254,2,52,101,101,98,95,28,45,45,28,26,66,54,39,90,48,47,96,52,92,111,36,45,44,23,20,4,3,3,3,162,168,240,170,3,1,127,200, + 78,50,65,43,44,27,47,24,45,55,35,33,94,28,28,97,79,38,69,43,43,23,27,13,10,30,26,0,0,1,0,217,0,39,5,219,4,221,0,19, + 0,62,64,34,13,12,10,3,2,207,4,0,156,6,12,207,14,10,156,18,6,16,8,20,18,14,13,12,8,4,3,2,8,9,5,15,0,20,16,220, + 60,196,50,23,57,49,0,16,212,60,204,50,252,60,236,16,254,60,236,57,17,18,57,48,19,33,1,23,7,33,21,33,7,33,21,33,1,39,55,33, + 53,33,55,33,217,3,4,1,0,125,174,1,47,254,72,195,2,123,252,250,254,254,125,174,254,213,1,182,195,253,135,3,162,1,59,102,213,168,240,170, + 254,199,102,211,170,240,0,0,0,3,0,217,0,184,5,219,4,76,0,3,0,7,0,11,0,33,64,14,4,6,0,2,8,10,12,10,6,2,8,4, + 0,12,16,220,60,60,220,60,60,49,0,16,212,220,220,220,220,220,48,19,33,21,33,17,33,21,33,17,33,21,33,217,5,2,250,254,5,2,250,254, + 5,2,250,254,2,215,170,2,31,170,253,192,170,0,0,0,0,1,0,217,255,206,5,219,5,52,0,27,0,0,1,33,53,33,55,23,7,33,21,33, + 7,33,21,33,7,33,21,33,7,39,55,33,53,33,55,33,53,33,3,149,253,68,3,24,128,153,81,1,34,254,129,114,1,241,253,181,110,2,185,252, + 233,129,153,82,254,221,1,129,111,254,16,2,76,3,162,170,232,84,148,170,203,170,203,170,234,84,150,170,203,170,0,0,0,4,0,217,0,0,5,219, + 5,9,0,3,0,7,0,11,0,15,0,41,64,20,4,6,0,2,12,14,8,10,16,14,10,6,3,2,12,8,4,3,0,16,16,220,23,60,220,23, + 60,49,0,16,212,220,220,220,220,220,220,220,48,19,33,21,33,17,33,21,33,17,33,21,33,17,33,21,33,217,5,2,250,254,5,2,250,254,5,2, + 250,254,5,2,250,254,3,148,170,2,31,170,252,75,170,2,31,170,0,0,0,2,0,217,0,0,5,219,4,168,0,6,0,10,0,84,64,46,2,156, + 3,4,3,1,156,0,1,4,4,3,1,156,2,1,5,6,5,0,156,6,5,66,5,4,2,1,0,5,3,209,6,167,7,156,9,1,8,2,0,36, + 7,4,35,11,16,252,60,236,50,50,57,49,0,47,236,244,236,23,57,48,75,83,88,7,4,237,7,16,8,237,7,16,8,237,7,16,4,237,89,34, + 9,2,21,1,53,9,1,33,21,33,5,219,252,64,3,192,250,254,5,2,250,254,5,2,250,254,3,248,254,235,254,238,178,1,112,170,1,111,252,2, + 170,0,0,0,0,2,0,217,0,0,5,219,4,168,0,6,0,10,0,86,64,47,6,156,0,6,3,4,3,5,156,4,4,3,0,156,1,2,1,6, + 156,5,6,2,2,1,66,6,5,3,2,0,5,4,209,1,167,7,156,8,6,7,2,36,9,4,0,35,11,16,252,60,60,236,50,57,49,0,47,236, + 244,236,23,57,48,75,83,88,7,16,8,237,7,16,4,237,7,16,4,237,7,16,8,237,89,34,19,53,1,21,1,53,9,1,21,33,53,217,5,2, + 250,254,3,193,1,65,250,254,3,248,176,254,145,170,254,144,178,1,18,253,199,170,170,0,0,3,0,218,255,86,5,220,5,27,0,3,0,10,0,14, + 0,0,51,33,21,33,9,2,21,1,53,9,1,33,21,33,218,5,2,250,254,5,2,252,64,3,192,250,254,5,2,250,254,5,2,250,254,170,5,21, + 254,235,254,238,178,1,112,170,1,111,252,2,170,0,0,0,0,3,0,218,255,86,5,220,5,27,0,3,0,10,0,14,0,0,33,21,33,53,17,53, + 1,21,1,53,9,1,21,33,53,5,220,250,254,5,2,250,254,3,192,1,66,250,254,170,170,4,107,176,254,145,170,254,144,178,1,18,253,199,170,170, + 0,2,0,218,254,177,5,220,5,27,0,19,0,26,0,0,5,33,53,33,55,33,53,33,55,23,7,33,21,33,7,33,21,33,7,39,9,2,21,1, + 53,1,2,39,254,179,1,218,96,253,198,2,200,137,138,41,1,80,254,34,95,2,61,253,54,138,138,3,222,252,64,3,192,250,254,5,2,170,170,115, + 170,164,115,49,170,115,170,165,116,5,70,254,235,254,238,178,1,112,170,1,111,0,0,0,0,2,0,218,254,177,5,220,5,27,0,19,0,26,0,0, + 5,33,53,33,55,33,53,33,55,23,7,33,21,33,7,33,21,33,7,39,1,53,1,21,1,53,1,2,39,254,179,1,218,96,253,198,2,200,137,138, + 41,1,80,254,34,95,2,61,253,54,138,138,254,220,5,2,250,254,3,192,170,170,115,170,164,115,49,170,115,170,165,116,5,70,176,254,145,170,254,144, + 178,1,18,0,0,2,0,148,0,46,7,204,4,223,0,6,0,13,0,0,9,2,21,1,53,1,5,9,1,21,1,53,1,7,204,252,198,3,58,251, + 202,4,54,252,254,252,198,3,58,251,202,4,54,4,17,254,112,254,114,197,2,8,159,2,10,206,254,112,254,114,197,2,8,159,2,10,0,2,0,148, + 0,46,7,204,4,223,0,6,0,13,0,0,19,53,1,21,1,53,1,3,53,1,21,1,53,1,148,4,54,251,202,3,58,56,4,54,251,202,3,58, + 4,17,206,253,246,159,253,248,197,1,142,1,144,206,253,246,159,253,248,197,1,142,0,0,0,2,0,176,254,242,3,6,6,18,0,25,0,39,0,0, + 1,6,7,22,23,22,21,20,7,6,7,22,23,33,54,55,38,39,38,53,52,55,54,55,38,39,19,54,55,54,16,39,38,39,6,7,6,16,23,22, + 2,123,41,35,89,52,74,74,52,89,35,41,254,192,41,35,89,52,74,74,52,89,35,41,160,22,17,65,65,17,22,22,17,65,65,17,6,18,71,70, + 163,158,226,223,224,227,158,162,71,71,71,71,162,158,227,224,223,226,158,163,70,71,250,50,59,59,226,1,206,225,59,60,60,59,225,254,50,226,59,0, + 0,1,0,216,0,26,5,220,4,232,0,27,0,0,1,6,7,53,36,63,1,36,37,53,4,37,19,23,7,54,55,21,4,15,1,4,5,21,36,5, + 3,39,2,87,180,201,1,9,223,101,254,246,254,187,1,178,1,0,196,148,135,183,200,254,251,228,100,1,16,1,63,254,78,255,0,196,148,1,93,41, + 93,178,111,38,182,14,151,178,175,10,1,98,82,244,41,96,178,113,37,181,13,152,178,175,11,254,159,82,0,2,0,217,0,5,5,219,5,100,0,15, + 0,18,0,0,1,5,21,37,3,39,19,37,53,1,19,23,7,37,21,5,7,13,1,3,157,2,62,253,122,153,135,147,254,17,3,27,173,136,109,1, + 31,254,122,200,254,70,1,60,1,223,203,182,234,254,189,64,1,54,180,166,1,32,1,111,64,230,104,182,139,71,157,112,0,2,0,217,255,160,5,219, + 4,255,0,15,0,18,0,0,1,37,53,5,19,23,3,5,21,1,3,39,55,5,53,37,55,45,1,3,23,253,194,2,134,153,135,147,1,239,252,229, + 173,136,109,254,225,1,134,200,1,186,254,196,3,37,203,182,234,1,67,64,254,202,180,166,254,224,254,145,64,230,104,182,139,71,157,112,0,2,0,217, + 255,47,5,219,5,86,0,2,0,26,0,0,1,13,1,3,33,53,33,19,37,53,37,19,23,7,37,21,5,3,5,21,37,3,33,21,33,7,39,3, + 146,254,137,1,47,244,254,131,1,189,120,253,203,3,3,118,164,72,1,45,254,137,114,1,233,253,219,102,2,139,253,53,76,164,3,79,108,85,253,114, + 170,1,67,162,170,221,1,64,61,199,86,176,108,254,209,140,178,158,254,237,170,209,61,0,0,2,0,217,255,47,5,219,5,86,0,2,0,26,0,0, + 1,37,39,1,33,53,33,55,5,53,37,55,37,53,5,19,23,3,5,21,5,3,33,21,33,7,39,3,145,1,9,214,254,29,254,248,1,71,87,254, + 98,1,232,91,253,189,2,127,132,164,127,1,218,253,109,109,3,0,252,193,78,164,2,151,76,62,252,223,170,236,119,178,139,245,167,176,183,1,101,61, + 254,168,136,170,189,254,216,170,209,61,0,0,0,2,0,217,255,144,5,220,4,168,0,29,0,36,0,0,37,21,14,1,35,34,39,38,39,38,39,38, + 35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,19,9,1,21,1,53,1,5,220,106,178,98,110,146,10,6,6,16,154,94,88,172, + 98,104,180,96,110,148,10,6,6,14,156,94,86,168,103,252,64,3,192,250,254,5,2,240,180,78,68,58,4,4,2,6,60,76,84,180,78,68,58,6, + 2,2,6,60,74,3,94,254,235,254,238,178,1,112,170,1,111,0,0,0,0,2,0,218,255,176,5,220,4,168,0,27,0,34,0,0,1,21,14,1, + 35,34,39,46,1,39,38,35,34,6,7,53,62,1,51,50,23,30,1,23,22,51,50,54,1,53,1,21,1,53,1,5,220,106,178,98,110,146,10,12, + 16,154,94,88,172,98,104,180,96,110,148,10,12,14,156,94,86,168,251,102,5,2,250,254,3,193,1,14,178,78,70,60,4,4,6,62,76,84,178,78, + 70,60,4,4,6,62,76,3,62,176,254,145,170,254,144,178,1,18,0,0,0,2,0,217,255,41,5,220,5,80,0,49,0,52,0,0,37,38,35,34, + 6,7,53,62,1,51,50,23,19,37,53,37,19,23,7,37,21,5,3,5,21,37,3,23,22,23,22,23,22,51,50,54,55,21,14,1,35,34,39,38, + 39,38,47,1,7,39,1,13,1,2,107,30,13,88,172,98,104,180,96,39,43,107,253,198,3,8,117,165,69,1,37,254,143,115,1,228,253,225,107,7, + 10,6,6,14,156,94,86,168,104,106,178,98,110,146,10,6,6,16,34,80,165,1,118,254,132,1,49,45,3,76,84,180,78,68,7,1,29,163,170,222, + 1,57,65,187,84,176,106,254,205,138,178,156,254,227,2,6,2,2,6,60,74,86,180,78,68,58,4,4,2,6,13,216,60,3,236,110,87,0,0,0, + 0,2,0,217,255,47,5,220,5,86,0,49,0,52,0,0,1,5,21,5,7,22,23,22,23,22,23,22,51,50,54,55,21,14,1,35,34,39,38,39, + 38,39,38,39,3,39,55,6,7,6,7,53,54,55,54,63,1,5,53,37,55,37,53,5,19,23,3,37,39,4,8,1,211,253,117,94,48,54,10,6, + 6,14,156,94,86,168,104,106,178,98,110,146,10,6,6,16,71,59,104,164,86,56,54,86,98,104,90,77,83,60,254,97,1,233,94,253,185,2,131,128, + 164,232,1,2,206,3,191,134,170,187,247,13,22,4,2,2,6,62,76,84,178,78,70,60,4,2,2,6,29,15,254,241,61,223,9,24,38,84,178,78, + 35,30,4,161,119,178,139,244,168,176,184,1,102,61,253,128,74,59,0,0,0,2,0,208,255,78,5,220,5,125,0,6,0,13,0,0,19,53,1,21, + 1,53,9,3,21,1,53,1,218,5,2,250,254,3,192,1,56,252,64,3,192,250,254,5,2,2,39,176,254,145,170,254,144,178,1,18,3,187,254,235, + 254,238,178,1,112,170,1,111,0,2,0,208,255,78,5,220,5,125,0,6,0,13,0,0,9,2,21,1,53,9,1,53,1,21,1,53,1,5,210,252, + 64,3,192,250,254,5,2,251,8,5,2,250,254,3,192,2,39,254,235,254,238,178,1,112,170,1,111,1,246,176,254,145,170,254,144,178,1,18,0,0, + 0,3,0,208,254,109,5,220,6,96,0,2,0,30,0,33,0,0,45,2,3,37,53,37,19,23,3,37,21,5,3,5,21,37,7,5,21,5,3,39, + 19,5,53,37,19,37,53,5,19,13,1,3,77,1,77,254,220,96,253,186,2,194,90,166,68,1,132,254,79,65,1,242,253,232,30,2,64,253,70,90, + 166,68,254,116,1,184,64,254,8,2,31,109,254,172,1,42,179,95,84,1,87,167,170,202,1,136,38,254,212,111,176,125,254,228,142,178,154,129,165,170, + 200,254,119,38,1,45,114,178,126,1,24,145,176,155,1,222,98,85,0,0,0,3,0,208,254,109,5,220,6,96,0,2,0,5,0,33,0,0,1,7, + 23,1,55,47,1,37,53,5,19,23,3,5,21,5,7,37,21,5,7,5,21,37,3,39,19,37,53,37,55,5,53,37,2,192,174,152,1,74,166,146, + 164,253,118,2,177,97,166,100,1,174,253,236,34,2,44,253,169,44,2,131,253,86,96,166,98,254,76,2,28,34,253,204,2,95,1,68,50,44,2,163, + 47,42,47,188,176,197,1,168,38,254,79,123,170,152,148,159,176,173,194,184,178,196,254,91,38,1,174,125,170,154,148,162,178,173,0,0,0,1,0,217, + 255,178,5,219,5,80,0,10,0,0,1,0,5,4,1,21,0,37,53,36,1,5,219,254,114,253,243,2,9,1,146,254,111,252,143,3,115,1,143,4, + 97,254,129,97,94,254,126,239,2,0,124,166,124,2,0,0,0,1,0,217,255,178,5,219,5,80,0,10,0,0,19,53,0,5,21,4,1,53,0,37, + 36,217,1,143,3,115,252,143,254,111,1,146,2,9,253,243,4,97,239,254,0,124,166,124,254,0,239,1,130,94,97,0,0,2,0,217,255,41,5,219, + 5,87,0,5,0,16,0,0,33,21,0,37,53,4,1,0,5,4,1,21,0,37,53,36,1,5,219,254,103,252,151,3,86,1,172,254,129,254,36,1, + 220,1,127,254,129,252,125,3,131,1,127,215,1,190,145,174,133,2,223,254,229,93,93,254,229,215,1,120,132,166,124,1,128,0,0,0,0,2,0,217, + 255,41,5,219,5,87,0,5,0,16,0,0,51,0,37,21,4,1,17,53,0,5,21,4,1,53,0,37,36,217,1,172,3,86,252,151,254,103,1,127, + 3,131,252,125,254,129,1,127,1,220,254,36,1,161,133,174,145,254,66,5,87,215,254,128,124,166,132,254,136,215,1,27,93,93,0,0,0,2,0,217, + 255,82,5,219,5,87,0,29,0,40,0,0,37,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51, + 50,54,19,0,5,4,1,21,0,37,53,36,1,5,219,105,179,97,110,146,10,7,6,15,155,94,88,172,98,105,179,97,110,147,11,5,6,15,155,94, + 86,169,103,254,129,254,36,1,220,1,127,254,129,252,125,3,131,1,127,177,179,78,69,59,4,3,2,6,61,76,84,179,78,69,59,5,2,2,6,61, + 75,4,36,254,229,93,93,254,229,215,1,120,132,166,124,1,128,0,0,0,0,2,0,217,255,82,5,219,5,87,0,29,0,40,0,0,37,21,14,1, + 35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,1,53,0,5,21,4,1,53,0,37,36,5,219,105, + 179,97,110,146,10,7,6,15,155,94,88,172,98,105,179,97,110,147,11,5,6,15,155,94,86,169,251,101,1,127,3,131,252,125,254,129,1,127,1,220, + 254,36,177,179,78,69,59,4,3,2,6,61,76,84,179,78,69,59,5,2,2,6,61,75,4,36,215,254,128,124,166,132,254,136,215,1,27,93,93,0, + 0,2,0,217,255,131,5,219,6,29,0,21,0,26,0,0,1,38,37,53,36,37,1,23,3,54,55,21,6,7,3,4,23,21,2,37,3,39,1,6, + 7,22,23,2,238,240,254,219,1,195,1,69,1,30,131,185,158,116,186,214,139,1,36,247,227,254,130,235,130,1,107,151,161,125,117,1,176,85,41,166, + 63,165,2,101,75,254,116,117,149,239,179,117,254,212,127,237,239,1,34,166,254,9,75,3,10,57,30,23,39,0,0,0,0,2,0,217,254,229,5,219, + 5,127,0,21,0,26,0,0,1,22,5,21,4,5,1,39,19,6,7,53,54,55,19,36,39,53,18,5,19,23,1,54,55,38,39,3,198,240,1,37, + 254,61,254,187,254,226,131,185,158,116,186,214,139,254,220,247,227,1,126,235,130,254,149,151,161,125,117,3,82,85,41,166,63,165,253,155,75,1,140,117, + 149,239,179,117,1,44,127,237,239,254,222,166,1,247,75,252,246,57,30,23,39,0,0,0,0,1,0,204,0,163,5,232,4,95,0,19,0,0,37,33, + 34,0,53,52,55,54,51,33,21,33,34,6,21,20,23,22,51,33,5,232,252,194,202,254,236,138,138,200,3,64,252,192,136,190,94,96,136,3,64,163, + 1,22,200,198,141,139,150,192,136,138,94,96,0,1,0,204,0,163,5,232,4,95,0,19,0,0,55,53,33,50,55,54,53,52,38,35,33,53,33,50, + 23,22,21,20,0,35,204,3,64,136,96,94,190,136,252,192,3,64,200,138,138,254,236,202,163,150,96,94,138,136,192,150,139,141,198,200,254,234,0,0, + 0,2,0,204,255,59,5,232,5,207,0,9,0,30,0,0,1,35,34,6,21,20,23,22,59,1,27,1,51,3,33,21,33,3,33,21,33,3,35,19, + 34,0,53,52,55,54,51,3,162,250,136,190,94,96,136,48,248,114,170,114,1,110,254,100,202,2,102,253,108,112,170,112,200,254,234,138,138,200,3,201, + 192,136,138,94,96,3,38,1,112,254,144,150,253,112,150,254,152,1,104,1,22,200,198,141,139,0,0,0,0,2,0,204,255,51,5,232,5,199,0,9, + 0,30,0,0,1,51,50,54,53,52,39,38,43,1,11,1,35,19,33,53,33,19,33,53,33,19,51,3,50,0,21,20,7,6,35,3,18,250,136,190, + 94,96,136,48,248,114,170,114,254,146,1,156,202,253,154,2,148,112,170,112,200,1,22,138,138,200,1,57,192,136,138,94,96,252,218,254,144,1,112,150, + 2,144,150,1,104,254,152,254,234,200,198,141,139,0,0,0,0,2,0,190,0,0,5,219,4,232,0,3,0,24,0,0,55,33,21,33,1,33,34,39, + 38,53,52,55,54,51,33,21,33,34,6,21,20,23,22,51,33,242,4,233,251,23,4,233,252,193,201,138,139,139,138,200,3,64,252,192,137,190,95,96, + 136,3,64,150,150,1,44,139,139,200,198,141,139,150,192,136,138,94,96,0,0,2,0,217,0,0,5,246,4,232,0,3,0,24,0,0,55,33,21,33, + 17,53,33,50,55,54,53,52,38,35,33,53,33,50,23,22,21,20,7,6,35,217,4,233,251,23,3,64,136,96,95,190,137,252,192,3,64,200,138,139, + 139,138,201,150,150,1,44,150,96,94,138,136,192,150,139,141,198,200,139,139,0,2,0,190,255,19,5,219,5,215,0,9,0,39,0,0,1,33,34,6, + 21,20,23,22,59,2,33,21,33,7,33,21,33,7,39,55,33,53,33,55,38,39,38,53,52,55,54,51,33,55,23,7,33,21,33,3,209,254,202,137, + 190,95,96,136,39,156,2,125,253,69,61,2,248,252,201,97,134,76,254,233,1,84,62,185,130,139,139,138,200,1,115,99,134,76,1,48,254,146,4,82, + 192,136,138,94,96,150,150,150,237,53,184,150,150,8,131,139,200,198,141,139,239,55,184,150,0,2,0,217,255,19,5,246,5,215,0,9,0,39,0,0, + 1,51,50,55,54,53,52,39,38,47,1,33,53,33,55,23,7,22,23,22,21,20,7,6,43,1,7,33,21,33,7,39,55,33,53,33,55,33,53,33, + 3,94,187,136,96,95,95,66,86,153,253,9,3,53,99,134,84,112,88,139,139,138,201,247,63,2,224,252,227,98,134,76,254,208,1,109,62,254,85,1, + 233,1,194,96,94,138,136,96,67,20,9,150,239,55,203,32,88,141,198,200,139,139,150,150,237,53,184,150,150,150,0,0,0,2,0,190,255,106,5,219, + 4,233,0,11,0,32,0,0,41,1,53,33,55,23,7,33,21,33,7,39,1,33,34,39,38,53,52,55,54,51,33,21,33,34,6,21,20,23,22,51, + 33,2,196,254,46,2,66,113,120,45,1,235,253,165,113,120,3,68,252,193,201,138,139,139,138,200,3,64,252,192,137,190,95,96,136,3,64,150,150,90, + 60,150,150,90,1,105,139,139,200,198,141,139,150,192,136,138,94,96,0,0,0,2,0,190,255,106,5,219,4,233,0,11,0,32,0,0,41,1,53,33, + 55,23,7,33,21,33,7,39,1,53,33,50,55,54,53,52,38,35,33,53,33,50,23,22,21,20,7,6,35,2,196,254,46,2,66,113,120,45,1,235, + 253,165,113,120,254,39,3,64,136,96,95,190,137,252,192,3,64,200,138,139,139,138,201,150,150,90,60,150,150,90,1,105,150,96,94,138,136,192,150,139, + 141,198,200,139,139,0,0,0,0,2,1,8,0,0,4,211,4,162,0,17,0,27,0,0,1,17,51,17,20,22,51,50,54,53,17,51,17,16,2,35, + 34,2,55,53,55,23,7,33,21,33,23,7,1,8,172,148,166,165,148,172,245,240,241,245,238,196,60,116,1,99,254,157,116,60,2,82,2,80,253,201, + 244,211,211,244,2,55,253,176,254,216,254,214,1,42,202,45,197,60,117,85,116,60,0,0,255,255,1,8,0,0,4,211,4,162,16,38,12,175,0,0, + 16,7,13,74,1,169,255,51,0,2,1,8,0,5,4,211,4,167,0,17,0,29,0,0,1,17,51,17,20,22,51,50,54,53,17,51,17,16,2,35, + 34,2,1,21,51,21,35,21,35,53,35,53,51,53,1,8,172,148,166,165,148,172,245,240,241,245,2,24,170,170,101,170,170,2,87,2,80,253,201,244, + 211,211,244,2,55,253,176,254,216,254,214,1,42,1,225,171,100,171,171,100,171,0,0,0,0,1,0,217,0,0,5,219,4,139,0,7,0,27,64,5, + 1,5,3,7,8,16,220,220,220,60,49,0,64,5,1,3,5,7,8,16,212,220,220,220,48,19,33,21,33,17,33,21,33,217,5,2,251,168,4,88, + 250,254,4,139,170,252,201,170,0,1,0,217,0,0,5,219,4,139,0,7,0,27,64,5,1,5,3,7,8,16,220,60,220,220,49,0,64,5,7,5, + 3,1,8,16,212,220,220,220,48,1,17,33,53,33,17,33,53,5,219,250,254,4,88,251,168,4,139,251,117,170,3,55,170,0,0,0,0,2,0,217, + 255,86,5,219,5,11,0,7,0,11,0,0,19,33,21,33,17,33,21,33,21,33,21,33,217,5,2,251,168,4,88,250,254,5,2,250,254,5,11,170, + 252,201,170,128,170,0,0,0,0,2,0,217,255,86,5,219,5,11,0,7,0,11,0,0,1,17,33,53,33,17,33,53,1,21,33,53,5,219,250,254, + 4,88,251,168,5,2,250,254,5,11,251,117,170,3,55,170,250,245,170,170,0,1,0,217,0,0,5,101,5,2,0,7,0,0,1,17,35,17,33,17, + 35,17,5,101,170,252,200,170,5,2,250,254,4,88,251,168,5,2,0,0,0,1,0,217,0,0,5,101,5,2,0,7,0,0,51,17,51,17,33,17, + 51,17,217,170,3,56,170,5,2,251,168,4,88,250,254,0,0,3,0,187,255,227,5,249,5,36,0,25,0,51,0,63,0,0,0,34,7,6,7,14, + 1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,36,32,22,23,22,23,22,21,20,7,6,7,14,1,32,38,39,38,39,38, + 53,52,55,54,55,54,5,17,33,21,33,17,35,17,33,53,33,17,3,197,214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77,76,76,77,76, + 92,254,174,1,20,238,98,99,49,49,49,49,99,98,238,254,236,238,98,99,49,49,49,49,99,98,1,205,1,100,254,156,170,254,156,1,100,4,142,39, + 39,76,77,184,109,106,184,77,76,39,39,39,39,76,77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99,118,119, + 137,140,118,119,99,98,132,254,155,170,254,155,1,101,170,1,101,0,0,0,0,3,0,187,255,227,5,249,5,36,0,3,0,29,0,55,0,0,1,33, + 21,33,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,36,32,22,23,22,23,22,21,20,7,6,7, + 14,1,32,38,39,38,39,38,53,52,55,54,55,54,1,161,3,114,252,142,2,36,214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77,76,76, + 77,76,92,254,174,1,20,238,98,99,49,49,49,49,99,98,238,254,236,238,98,99,49,49,49,49,99,98,2,215,170,2,97,39,39,76,77,184,109,106, + 184,77,76,39,39,39,39,76,77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99,118,119,137,140,118,119,99,98, + 0,3,0,187,255,227,5,249,5,36,0,25,0,51,0,63,0,0,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52, + 38,39,38,39,36,32,22,23,22,23,22,21,20,7,6,7,14,1,32,38,39,38,39,38,53,52,55,54,55,54,1,7,23,7,39,7,39,55,39,55, + 23,55,3,197,214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77,76,76,77,76,92,254,174,1,20,238,98,99,49,49,49,49,99,98,238,254, + 236,238,98,99,49,49,49,49,99,98,2,237,253,252,120,252,252,121,253,252,120,252,252,4,142,39,39,76,77,184,109,106,184,77,76,39,39,39,39,76, + 77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99,118,119,137,140,118,119,99,98,254,190,252,252,120,252,253,121, + 252,252,120,252,253,0,0,0,0,3,0,187,255,227,5,249,5,36,0,3,0,29,0,55,0,0,9,1,23,1,0,34,7,6,7,14,1,21,20,22, + 23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,36,32,22,23,22,23,22,21,20,7,6,7,14,1,32,38,39,38,39,38,53,52,55,54, + 55,54,1,230,2,112,120,253,144,1,103,214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77,76,76,77,76,92,254,174,1,20,238,98,99,49, + 49,49,49,99,98,238,254,236,238,98,99,49,49,49,49,99,98,1,134,2,112,120,253,144,3,128,39,39,76,77,184,109,106,184,77,76,39,39,39,39, + 76,77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99,118,119,137,140,118,119,99,98,0,0,0,0,3,0,187, + 255,227,5,249,5,36,0,3,0,29,0,55,0,0,1,51,21,35,18,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52, + 38,39,38,39,36,32,22,23,22,23,22,21,20,7,6,7,14,1,32,38,39,38,39,38,53,52,55,54,55,54,2,240,212,212,213,214,93,92,76,77, + 76,76,77,76,92,93,214,93,92,76,77,76,76,77,76,92,254,174,1,20,238,98,99,49,49,49,49,99,98,238,254,236,238,98,99,49,49,49,49,99, + 98,3,1,254,2,139,39,39,76,77,184,109,106,184,77,76,39,39,39,39,76,77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99, + 98,100,100,98,99,118,119,137,140,118,119,99,98,0,0,0,0,4,0,187,255,227,5,249,5,36,0,9,0,24,0,50,0,76,0,0,1,34,6,21, + 20,22,50,54,52,38,39,50,22,23,30,1,21,20,6,35,34,38,53,52,62,1,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62, + 1,53,52,38,39,38,39,36,32,22,23,22,23,22,21,20,7,6,7,14,1,32,38,39,38,39,38,53,52,55,54,55,54,3,90,80,110,110,160,110, + 111,79,64,118,43,46,46,185,134,135,180,184,240,214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77,76,76,77,76,92,254,174,1,20,238,98, + 99,49,49,49,49,99,98,238,254,236,238,98,99,49,49,49,49,99,98,3,65,111,80,79,109,109,158,112,129,49,46,45,114,66,132,183,180,135,134,186, + 204,39,39,76,77,184,109,106,184,77,76,39,39,39,39,76,77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99, + 118,119,137,140,118,119,99,98,0,3,0,187,255,227,5,249,5,36,0,17,0,43,0,69,0,0,1,13,1,7,37,17,35,17,5,39,45,1,55,5, + 17,51,17,37,2,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,36,32,22,23,22,23,22,21,20,7, + 6,7,14,1,32,38,39,38,39,38,53,52,55,54,55,54,4,240,254,189,1,67,52,254,209,102,254,209,52,1,67,254,189,52,1,47,102,1,47,247, + 214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77,76,76,77,76,92,254,174,1,20,238,98,99,49,49,49,49,99,98,238,254,236,238,98,99, + 49,49,49,49,99,98,3,49,175,176,88,183,254,173,1,83,183,88,176,175,89,183,1,83,254,173,183,1,4,39,39,76,77,184,109,106,184,77,76,39, + 39,39,39,76,77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99,118,119,137,140,118,119,99,98,0,4,0,187, + 255,227,5,249,5,36,0,3,0,7,0,33,0,59,0,0,1,33,21,33,21,33,21,33,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55, + 54,55,62,1,53,52,38,39,38,39,36,32,22,23,22,23,22,21,20,7,6,7,14,1,32,38,39,38,39,38,53,52,55,54,55,54,2,26,2,128, + 253,128,2,128,253,128,1,171,214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77,76,76,77,76,92,254,174,1,20,238,98,99,49,49,49,49, + 99,98,238,254,236,238,98,99,49,49,49,49,99,98,3,106,136,192,136,2,244,39,39,76,77,184,109,106,184,77,76,39,39,39,39,76,77,184,106,109, + 184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99,118,119,137,140,118,119,99,98,0,3,0,187,255,227,5,249,5,36,0,25, + 0,51,0,55,0,0,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,36,32,22,23,22,23,22,21, + 20,7,6,7,14,1,32,38,39,38,39,38,53,52,55,54,55,54,19,33,21,33,3,197,214,93,92,76,77,76,76,77,76,92,93,214,93,92,76,77, + 76,76,77,76,92,254,174,1,20,238,98,99,49,49,49,49,99,98,238,254,236,238,98,99,49,49,49,49,99,98,56,2,128,253,128,4,142,39,39,76, + 77,184,109,106,184,77,76,39,39,39,39,76,77,184,106,109,184,77,76,39,189,100,98,99,119,118,140,137,119,118,99,98,100,100,98,99,118,119,137,140, + 118,119,99,98,254,23,170,0,0,3,0,187,255,227,5,249,5,36,0,3,0,7,0,19,0,0,1,17,33,17,37,33,17,33,1,17,33,21,33,17, + 35,17,33,53,33,17,1,81,4,18,251,88,5,62,250,194,2,244,1,100,254,156,170,254,156,1,100,4,137,251,240,4,16,155,250,191,4,89,254,155, + 170,254,155,1,101,170,1,101,0,3,0,187,255,227,5,249,5,36,0,3,0,7,0,11,0,0,1,33,21,33,3,17,33,17,37,33,17,33,1,161, + 3,114,252,142,80,4,18,251,88,5,62,250,194,2,215,170,2,92,251,240,4,16,155,250,191,0,0,0,0,3,0,187,255,227,5,249,5,36,0,11, + 0,15,0,19,0,0,9,2,7,9,1,39,9,1,55,9,1,37,17,33,17,37,33,17,33,5,61,254,149,1,107,121,254,150,254,150,121,1,107,254, + 149,121,1,106,1,106,252,141,4,18,251,88,5,62,250,194,3,236,254,150,254,150,120,1,106,254,149,121,1,106,1,106,121,254,149,1,107,36,251,240, + 4,16,155,250,191,0,0,0,0,3,0,187,255,227,5,249,5,36,0,3,0,7,0,11,0,0,1,51,21,35,1,17,33,17,37,33,17,33,2,240, + 212,212,254,97,4,18,251,88,5,62,250,194,3,1,254,2,134,251,240,4,16,155,250,191,0,1,0,175,0,0,6,74,5,154,0,7,0,25,64,10, + 2,4,6,0,8,4,6,2,0,8,16,220,220,60,220,49,0,16,60,220,220,220,48,51,17,51,17,33,21,33,17,175,127,5,28,250,228,5,154,253, + 117,127,253,112,0,1,0,175,0,0,6,74,5,154,0,7,0,0,33,35,17,33,53,33,17,51,6,74,127,250,228,5,28,127,2,144,127,2,139,0, + 0,1,0,175,0,0,6,73,5,154,0,7,0,0,1,21,33,17,35,17,33,53,6,73,253,115,128,253,115,5,154,127,250,229,5,27,127,0,0,0, + 0,1,0,175,0,0,6,73,5,154,0,7,0,0,51,53,33,17,51,17,33,21,175,2,141,128,2,141,127,5,27,250,229,127,0,0,0,1,0,175, + 0,0,3,124,5,154,0,7,0,0,51,17,51,17,33,21,33,17,175,127,2,78,253,178,5,154,253,117,127,253,112,0,0,1,0,175,0,0,3,124, + 5,154,0,11,0,0,33,35,17,51,17,33,21,33,21,33,21,33,1,46,127,127,2,78,253,178,2,78,253,178,5,154,254,36,127,228,127,0,0,0, + 0,1,0,175,0,0,6,74,5,154,0,11,0,0,33,35,17,51,17,33,21,33,21,33,21,33,1,46,127,127,5,28,250,228,5,28,250,228,5,154, + 254,36,127,228,127,0,0,0,0,2,0,175,0,0,6,74,5,154,0,7,0,11,0,0,33,17,51,17,33,21,33,17,33,35,17,51,2,18,127,3, + 185,252,71,254,157,127,127,5,154,253,117,127,253,112,5,154,0,3,0,175,0,0,6,74,5,154,0,3,0,11,0,15,0,0,33,35,17,51,1,17, + 51,17,33,21,33,17,33,35,17,51,1,46,127,127,2,71,127,2,86,253,170,254,157,127,127,5,154,250,102,5,154,253,117,127,253,112,5,154,0,0, + 0,2,0,175,0,0,6,74,5,154,0,3,0,15,0,0,33,35,17,51,1,35,17,51,17,33,21,33,21,33,21,33,1,46,127,127,1,99,127,127, + 3,185,252,71,3,185,252,71,5,154,250,102,5,154,254,36,127,228,127,0,0,1,0,175,255,175,6,74,5,235,0,15,0,0,51,17,51,17,33,1, + 23,1,33,21,33,1,39,1,33,17,175,127,2,39,1,83,115,254,197,2,106,253,92,254,170,115,1,61,254,20,5,154,253,117,2,220,53,253,89,127, + 253,31,54,2,171,253,112,0,0,2,0,175,255,175,6,74,5,235,0,19,0,23,0,0,1,23,3,33,21,33,7,33,21,33,1,39,19,33,17,35, + 17,51,17,33,3,55,33,21,4,168,115,234,2,25,253,173,106,2,189,253,8,254,254,115,233,254,104,127,127,2,120,165,106,253,195,5,235,53,254,8, + 127,228,127,253,211,54,1,247,254,36,5,154,254,36,254,157,228,228,0,0,0,2,0,175,255,175,6,74,5,235,0,15,0,19,0,0,1,23,1,33, + 21,33,1,39,1,33,17,35,17,51,17,33,1,35,17,51,5,130,115,254,197,1,144,254,54,254,170,115,1,61,254,157,127,127,1,158,252,255,127,127, + 5,235,53,253,89,127,253,31,54,2,171,253,112,5,154,253,117,252,241,5,154,0,0,0,0,3,0,175,255,175,6,74,5,235,0,19,0,23,0,27, + 0,0,33,35,17,51,17,33,1,23,3,33,21,33,7,33,21,33,1,39,19,33,1,35,17,51,1,55,33,21,2,145,127,127,1,244,1,2,115,234, + 1,58,254,140,106,1,222,253,231,254,254,115,233,254,236,254,157,127,127,2,178,106,254,71,5,154,254,36,2,45,53,254,8,127,228,127,253,211,54,1, + 247,254,36,5,154,252,193,228,228,0,0,0,0,1,0,217,255,167,5,203,5,93,0,42,0,0,19,53,36,37,54,55,54,53,52,38,35,34,7,39, + 54,51,50,22,21,20,7,6,5,4,23,22,21,20,6,35,34,39,55,22,51,50,54,53,52,39,38,39,36,217,1,155,1,64,200,101,61,77,62,80, + 55,115,90,160,136,176,148,227,254,137,1,119,227,148,176,136,160,90,115,55,80,62,77,61,101,200,254,192,2,46,168,40,89,55,79,48,60,48,58,62, + 126,106,160,121,159,91,140,60,60,140,91,159,121,160,106,126,62,58,48,60,48,79,55,89,0,1,0,217,255,167,5,203,5,93,0,42,0,0,1,4, + 5,6,7,6,21,20,22,51,50,55,23,6,35,34,38,53,52,55,54,37,36,39,38,53,52,54,51,50,23,7,38,35,34,6,21,20,23,22,23,4, + 5,5,203,254,101,254,192,200,101,61,77,62,80,55,115,90,160,136,176,148,227,1,119,254,137,227,148,176,136,160,90,115,55,80,62,77,61,101,200,1, + 64,1,155,2,46,40,89,55,79,48,60,48,58,62,126,106,160,121,159,91,140,60,60,140,91,159,121,160,106,126,62,58,48,60,48,79,55,89,40,0, + 0,2,0,217,0,30,5,219,4,230,0,2,0,6,0,0,1,17,9,2,53,1,5,49,252,162,4,8,250,254,5,2,1,32,2,196,254,158,253,156, + 2,17,166,2,17,0,0,0,0,2,0,217,0,30,5,219,4,230,0,2,0,6,0,0,9,2,3,17,1,21,1,131,3,94,252,162,170,5,2,1, + 32,1,98,1,98,252,58,4,200,253,239,166,0,3,0,217,255,158,5,219,5,100,0,3,0,6,0,10,0,0,23,53,33,21,3,17,9,2,53,1, + 217,5,2,170,252,162,4,8,250,254,5,2,98,170,170,2,0,2,196,254,158,253,156,2,17,166,2,17,0,3,0,217,255,158,5,219,5,100,0,3, + 0,6,0,10,0,0,23,53,33,21,9,2,3,17,1,21,217,5,2,251,168,3,94,252,162,170,5,2,98,170,170,2,0,1,98,1,98,252,58,4, + 200,253,239,166,0,2,0,121,1,103,7,135,3,162,0,23,0,31,0,0,1,54,50,22,20,6,34,39,38,39,33,6,7,6,34,38,52,54,50,23, + 22,23,33,54,4,34,6,20,22,50,54,52,5,159,83,235,170,167,242,81,51,19,253,81,20,51,84,242,162,166,235,87,52,19,2,175,20,252,100,114, + 79,79,115,79,3,79,83,168,239,164,81,51,67,66,51,82,162,242,167,85,52,67,68,14,80,114,79,79,113,0,0,0,0,2,0,121,1,103,7,135, + 3,162,0,23,0,31,0,0,1,6,34,38,52,54,50,23,22,23,33,54,55,54,50,22,20,6,34,39,38,39,33,6,36,50,54,52,38,34,6,20, + 2,97,83,235,170,167,242,81,51,19,2,175,20,51,84,242,162,166,235,87,52,19,253,81,20,3,156,114,79,79,115,79,1,186,83,168,239,164,81,51, + 67,66,51,82,162,242,167,85,52,67,68,14,80,114,79,79,113,0,0,0,0,2,0,98,1,103,6,82,3,162,0,13,0,21,0,0,19,55,33,54, + 55,54,50,22,20,6,34,39,38,39,36,38,34,6,20,22,50,54,98,1,3,192,19,49,91,235,165,162,242,83,52,19,1,154,79,115,80,79,116,79, + 2,46,168,68,47,89,167,242,162,82,51,66,142,80,81,113,79,79,0,0,0,4,0,121,255,160,6,59,5,100,0,3,0,7,0,11,0,15,0,0, + 1,51,17,35,5,33,21,33,3,35,17,51,37,33,53,33,3,6,168,168,1,40,2,13,253,243,128,168,168,254,216,253,243,2,13,5,100,253,243,128, + 170,253,115,2,13,128,170,0,0,1,0,238,0,0,3,60,5,155,0,7,0,0,33,35,17,35,53,33,21,35,2,84,126,232,2,78,232,5,28,127, + 127,0,0,0,0,2,0,200,0,0,5,19,5,236,0,3,0,10,0,0,51,53,33,21,1,51,9,1,51,1,35,200,4,75,251,245,195,1,35,1, + 34,195,254,152,250,170,170,5,236,252,84,3,172,251,94,0,0,2,0,200,0,0,5,19,5,236,0,3,0,10,0,0,19,33,21,33,19,1,51,1, + 35,9,1,200,4,75,251,181,64,1,105,250,1,104,195,254,222,254,221,5,236,170,250,190,4,162,251,94,3,172,252,84,0,2,0,200,0,0,5,19, + 5,236,0,3,0,10,0,0,19,33,21,33,23,51,9,1,51,1,35,200,4,75,251,181,64,195,1,35,1,34,195,254,152,250,5,236,170,160,252,84, + 3,172,251,94,0,2,1,27,0,0,5,153,4,126,0,12,0,21,0,0,41,1,17,51,17,22,23,30,1,23,22,23,33,1,17,33,38,39,46,1, + 39,38,5,153,251,130,170,90,86,165,238,70,37,18,1,20,252,44,2,69,15,27,61,206,143,63,4,126,254,235,18,37,70,238,164,86,90,2,68,253, + 188,65,63,143,206,61,27,0,0,2,1,27,0,0,5,153,4,126,0,2,0,7,0,0,9,1,33,5,53,1,51,17,4,239,252,214,3,42,252,44, + 3,212,170,3,212,252,214,170,170,3,212,251,130,0,0,0,0,1,255,250,254,119,6,150,5,193,0,6,0,0,9,1,35,9,1,35,1,3,183,2, + 223,203,253,125,253,125,203,2,221,5,193,248,182,6,119,249,137,7,74,0,0,1,255,250,254,119,6,150,5,193,0,6,0,0,9,1,51,9,1,51, + 1,2,217,253,33,203,2,131,2,131,203,253,35,254,119,7,74,249,137,6,119,248,182,0,0,1,0,140,254,119,6,4,5,193,0,16,0,29,64,6, + 12,14,18,5,3,17,16,220,220,16,220,220,49,0,64,5,13,18,8,0,17,16,220,204,16,204,48,1,34,4,21,17,35,17,16,0,32,0,25,1, + 35,17,52,36,3,72,219,254,204,173,1,189,1,254,1,189,173,254,207,5,29,227,252,251,57,4,224,1,66,1,40,254,216,254,190,251,32,4,199,250, + 229,0,0,0,0,1,0,140,254,119,6,4,5,193,0,16,0,29,64,6,12,14,17,5,3,18,16,220,220,16,220,220,49,0,64,5,13,18,8,0, + 17,16,220,204,16,204,48,5,50,36,53,17,51,17,16,0,32,0,25,1,51,17,20,4,3,72,219,1,52,173,254,67,254,2,254,67,173,1,49,229, + 227,252,4,199,251,32,254,190,254,216,1,40,1,66,4,224,251,57,250,229,255,255,0,6,254,35,3,238,6,117,18,6,14,156,0,0,0,1,0,219, + 2,72,1,174,3,70,0,3,0,18,183,2,131,0,4,1,25,0,4,16,212,236,49,0,16,212,236,48,19,51,21,35,219,211,211,3,70,254,0,0, + 0,1,0,249,1,49,4,9,4,25,0,9,0,0,19,33,27,1,33,7,19,39,7,19,249,1,43,93,94,1,42,242,94,244,243,93,2,253,1,28, + 254,228,176,254,228,176,176,1,28,0,0,0,0,3,0,217,0,30,5,219,4,231,0,3,0,7,0,25,0,0,1,51,21,35,17,51,21,35,3,33, + 53,33,1,55,9,1,23,1,33,21,33,1,7,9,1,39,2,223,246,246,246,246,82,254,76,1,180,254,139,120,1,202,1,202,120,254,139,1,180,254, + 76,1,117,120,254,54,254,54,120,1,19,245,4,201,246,254,60,170,1,117,120,254,54,1,202,120,254,139,170,254,139,120,1,202,254,54,120,0,0,0, + 0,3,0,217,255,194,7,39,5,66,0,5,0,8,0,11,0,0,23,17,9,1,17,1,39,1,17,9,1,17,217,3,39,3,39,252,217,155,254,30, + 3,24,1,226,62,5,128,253,176,2,80,250,128,2,78,113,1,94,253,68,1,94,254,162,2,198,0,0,0,2,0,217,255,194,7,39,5,66,0,8, + 0,11,0,0,37,21,9,1,17,9,1,21,1,33,1,17,7,39,252,217,252,217,3,39,3,39,253,116,254,202,254,30,162,224,2,78,253,178,5,128, + 253,176,2,80,221,254,28,1,94,253,68,0,0,2,0,217,255,194,7,39,5,66,0,8,0,11,0,0,19,53,9,1,17,9,1,53,1,33,1,17, + 217,3,39,3,39,252,217,252,217,2,140,1,54,1,226,4,98,224,253,178,2,78,250,128,2,80,253,176,221,1,228,254,162,2,188,0,0,1,0,217, + 255,194,7,39,5,66,0,7,0,0,23,53,9,1,53,1,21,1,217,2,140,253,116,6,78,252,217,62,224,1,225,1,226,221,251,93,221,2,80,0, + 0,1,0,217,255,194,7,39,5,66,0,7,0,0,5,9,1,53,1,21,9,1,7,39,252,217,252,217,6,78,253,116,2,140,62,2,80,253,176,221, + 4,163,221,254,30,254,31,0,0,2,0,217,1,96,5,219,3,244,0,26,0,30,0,0,19,30,1,51,50,63,2,54,51,50,22,23,21,46,1,35, + 34,7,6,15,1,6,35,34,38,39,1,21,33,53,217,103,169,86,94,155,22,15,147,110,97,179,105,98,172,88,94,155,15,6,17,146,110,97,179,105, + 5,2,250,254,3,244,85,75,61,9,6,59,69,78,178,83,76,61,6,2,7,59,69,79,254,200,170,170,0,1,0,99,0,0,5,121,4,162,0,10, + 0,0,19,51,0,19,18,1,51,0,3,35,2,99,215,1,117,63,73,1,107,215,254,56,102,186,102,4,162,254,144,254,37,1,218,1,113,254,129,252, + 221,3,35,0,0,1,0,99,0,0,5,121,4,162,0,10,0,0,51,0,19,51,18,1,35,0,3,2,1,99,1,200,102,186,102,1,200,215,254,149, + 73,63,254,139,1,127,3,35,252,221,254,129,1,113,1,218,254,37,254,144,0,2,0,190,255,250,5,219,5,10,0,19,0,41,0,0,1,33,34,7, + 6,21,20,22,51,33,21,33,34,39,38,53,52,54,51,33,17,33,32,39,38,17,16,55,54,41,1,21,33,34,7,6,21,20,23,22,51,33,5,219, + 253,107,58,40,40,80,58,2,149,253,106,128,90,89,178,129,2,150,253,107,254,241,188,189,189,186,1,15,2,151,253,106,200,138,139,139,138,201,2,149, + 3,12,40,41,57,58,80,170,90,88,130,128,180,252,68,189,190,1,13,1,12,191,189,170,139,141,198,200,139,139,0,0,0,2,0,217,255,250,5,246, + 5,10,0,19,0,41,0,0,19,53,33,50,22,21,20,7,6,35,33,53,33,50,54,53,52,39,38,35,1,53,33,50,55,54,53,52,39,38,35,33, + 53,33,32,23,22,17,16,7,6,33,217,2,150,129,178,89,90,128,253,106,2,149,58,80,40,40,58,253,107,2,149,201,138,139,139,138,200,253,106,2, + 151,1,15,186,189,189,188,254,241,3,12,170,180,128,130,88,90,170,80,58,57,41,40,252,238,170,139,139,200,198,141,139,170,189,191,254,244,254,243,190, + 189,0,0,0,0,2,0,210,0,0,5,226,5,78,0,17,0,36,0,0,33,17,52,38,34,6,21,17,35,17,52,55,54,51,50,22,21,17,33,17, + 16,0,32,23,22,25,1,35,17,52,39,38,32,7,6,21,17,3,228,80,116,80,170,90,88,130,128,180,252,68,1,124,2,24,192,188,170,138,140,254, + 112,138,140,2,198,58,80,80,58,253,58,2,200,128,90,88,178,128,253,56,2,198,1,16,1,120,188,186,254,240,253,56,2,200,200,138,138,138,138,202, + 253,58,0,0,0,2,0,210,255,227,5,226,5,49,0,17,0,36,0,0,1,17,20,22,50,54,53,17,51,17,20,7,6,35,34,38,53,17,33,17, + 16,0,32,39,38,25,1,51,17,20,23,22,32,55,54,53,17,2,208,80,116,80,170,90,88,130,128,180,3,188,254,132,253,232,192,188,170,138,140,1, + 144,138,140,5,49,253,58,58,80,80,58,2,198,253,56,128,90,88,178,128,2,200,253,58,254,240,254,136,188,186,1,16,2,200,253,56,200,138,138,138, + 138,202,2,198,0,1,1,124,0,0,5,56,5,213,0,27,0,0,1,52,39,38,39,17,35,17,6,7,6,21,17,35,17,52,55,54,55,17,51,17, + 22,23,22,21,17,35,4,142,90,58,75,170,75,58,90,170,140,108,145,170,147,108,138,170,2,159,128,89,58,20,252,58,3,198,19,58,90,128,253,97, + 2,157,200,140,108,23,1,97,254,159,23,108,138,200,253,97,0,2,0,217,255,52,5,219,5,213,0,27,0,31,0,0,5,35,17,35,17,35,17,33, + 53,33,53,33,53,33,17,51,17,51,17,51,17,33,21,33,21,33,21,33,39,53,35,21,4,89,170,170,170,254,126,1,130,254,126,1,130,170,170,170, + 1,130,254,126,1,130,254,126,170,170,204,2,44,253,212,2,44,170,240,168,2,51,253,205,2,51,253,205,168,240,170,170,240,240,0,0,0,2,0,217, + 0,94,5,219,4,166,0,3,0,10,0,0,1,51,21,35,9,2,21,1,53,1,4,164,211,211,1,55,251,248,4,8,250,254,5,2,3,0,254,1, + 238,254,145,254,147,182,1,209,166,1,209,0,0,2,0,217,0,94,5,219,4,166,0,3,0,10,0,0,1,51,21,35,3,53,1,21,1,53,1,1, + 61,211,211,100,5,2,250,254,4,6,3,0,254,1,238,182,254,47,166,254,47,182,1,109,0,3,0,148,0,46,10,204,4,223,0,6,0,13,0,20, + 0,0,9,2,21,1,53,1,5,9,1,21,1,53,1,5,9,1,21,1,53,1,10,204,252,198,3,58,251,202,4,54,253,0,252,198,3,58,251,202, + 4,54,252,254,252,198,3,58,251,202,4,54,4,17,254,112,254,114,197,2,8,159,2,10,206,254,112,254,114,197,2,8,159,2,10,206,254,112,254,114, + 197,2,8,159,2,10,0,0,0,3,0,148,0,46,10,204,4,223,0,6,0,13,0,20,0,0,19,53,1,21,1,53,1,3,53,1,21,1,53,1, + 3,53,1,21,1,53,1,148,4,54,251,202,3,58,56,4,54,251,202,3,58,58,4,54,251,202,3,58,4,17,206,253,246,159,253,248,197,1,142,1, + 144,206,253,246,159,253,248,197,1,142,1,144,206,253,246,159,253,248,197,1,142,0,0,0,0,3,0,217,254,46,5,219,6,212,0,6,0,10,0,17, + 0,0,19,9,1,53,1,21,9,1,33,53,33,17,9,1,21,1,53,1,217,3,193,252,63,5,2,250,254,5,2,250,254,5,2,252,64,3,192,250, + 254,5,2,254,222,1,21,1,18,178,254,144,170,254,145,3,254,170,3,78,254,235,254,238,178,1,112,170,1,111,0,0,0,3,0,217,254,46,5,219, + 6,212,0,6,0,10,0,17,0,0,1,21,1,53,1,21,9,1,53,33,21,1,53,1,21,1,53,1,5,219,250,254,5,2,252,63,254,191,5,2, + 250,254,5,2,250,254,3,192,254,222,176,1,111,170,1,112,178,254,238,2,57,170,170,3,248,176,254,145,170,254,144,178,1,18,0,0,0,2,0,217, + 0,0,5,219,4,168,0,6,0,10,0,0,37,21,1,53,1,21,9,1,53,33,21,5,219,250,254,5,2,252,64,254,190,5,2,176,176,1,111,170, + 1,112,178,254,238,2,57,170,170,0,0,0,0,2,0,217,0,0,5,219,4,168,0,6,0,10,0,0,55,9,1,53,1,21,9,1,33,53,33,217, + 3,193,252,63,5,2,250,254,5,2,250,254,5,2,176,1,21,1,18,178,254,144,170,254,145,3,254,170,0,2,0,217,255,41,5,219,5,87,0,5, + 0,16,0,0,1,0,5,53,36,1,17,21,0,37,53,36,1,21,0,5,4,5,219,254,84,252,170,3,105,1,153,254,129,252,125,3,131,1,127,254, + 129,254,36,1,220,4,128,254,95,133,174,145,1,190,250,169,215,1,128,124,166,132,1,120,215,254,229,93,93,0,0,0,0,2,0,217,255,41,5,219, + 5,87,0,5,0,16,0,0,19,53,0,5,21,36,1,0,37,36,1,53,0,5,21,4,1,217,1,153,3,105,252,170,254,84,1,127,1,220,254,36, + 254,129,1,127,3,131,252,125,254,129,4,128,215,254,66,145,174,133,253,33,1,27,93,93,1,27,215,254,136,132,166,124,254,128,0,0,0,2,0,217, + 254,147,5,219,6,29,0,33,0,38,0,0,33,21,0,37,1,39,1,38,39,53,4,23,55,38,37,53,36,37,19,23,3,54,55,21,6,15,1,4, + 23,21,38,37,7,4,1,55,6,7,22,5,219,254,243,254,42,254,227,130,1,15,186,213,0,255,218,63,240,254,216,1,181,1,59,246,131,166,189,130, + 200,226,105,1,29,246,218,254,128,64,1,154,254,93,48,113,119,94,215,1,37,164,253,161,75,2,65,54,35,174,40,65,135,70,43,166,60,122,2,12, + 75,254,159,100,130,215,148,96,223,103,182,215,214,135,136,148,1,226,102,35,23,18,0,0,0,2,0,217,254,147,5,219,6,29,0,33,0,38,0,0, + 19,53,22,5,1,23,1,22,23,21,4,5,7,36,37,21,4,5,3,39,19,6,7,53,54,63,1,4,7,53,36,37,55,36,5,7,54,55,38,217, + 250,1,216,1,20,131,254,252,191,222,254,184,254,252,88,1,39,1,125,254,56,254,182,238,130,143,154,117,166,230,99,254,204,187,1,18,1,66,56,254, + 158,1,246,13,35,37,30,4,128,215,251,140,2,77,75,253,214,46,31,166,48,81,189,116,59,174,76,158,254,5,75,1,49,103,127,215,162,118,213,125, + 183,215,203,105,119,105,144,27,8,7,6,0,0,2,0,217,254,223,5,219,6,35,0,23,0,27,0,0,1,23,7,33,21,33,3,33,21,33,7,33, + 21,33,3,39,55,33,53,33,55,33,17,33,1,19,33,17,4,77,160,88,1,70,254,125,221,2,96,253,99,46,2,203,252,248,109,160,88,254,187,1, + 130,46,254,80,3,7,254,230,221,253,224,6,35,58,245,170,253,152,170,128,170,254,209,58,245,170,128,3,188,252,238,2,104,253,152,0,0,2,0,217, + 254,223,5,219,6,35,0,23,0,27,0,0,1,23,7,33,17,33,7,33,21,33,3,39,55,33,53,33,55,33,53,33,19,33,53,33,23,3,33,17, + 4,77,160,88,1,70,253,99,46,2,203,252,248,109,160,88,254,187,1,130,46,254,80,1,237,221,253,54,3,7,120,221,1,182,6,35,58,245,252,68, + 128,170,254,209,58,245,170,128,170,2,104,170,170,253,152,2,104,0,0,0,0,1,0,217,255,63,5,219,4,244,0,20,0,0,19,33,21,33,17,33, + 21,33,23,7,33,21,33,7,39,55,33,53,33,55,33,217,5,2,251,168,4,88,254,85,27,77,1,221,253,171,146,139,77,254,35,2,85,90,253,81, + 4,244,170,253,152,170,19,109,170,207,98,109,170,128,0,0,0,1,0,217,255,63,5,219,4,244,0,20,0,0,37,21,33,7,39,55,33,53,33,55, + 33,53,33,17,33,53,33,17,33,23,7,5,219,253,171,146,139,77,254,35,2,85,90,253,81,4,88,251,168,5,2,254,85,27,77,184,170,207,98,109, + 170,128,170,2,104,170,252,68,19,109,0,0,0,2,0,217,254,229,5,220,4,168,0,27,0,34,0,0,37,38,35,34,6,7,53,62,1,51,50,23, + 55,23,7,22,51,50,54,55,21,14,1,35,34,39,7,39,9,2,21,1,53,1,2,230,99,67,88,172,98,104,180,96,94,120,110,155,105,101,69,86, + 168,104,106,178,98,95,122,108,155,3,93,252,64,3,192,250,254,5,2,17,31,76,84,180,78,68,42,243,70,233,32,74,86,180,78,68,43,240,70,4, + 205,254,235,254,238,178,1,112,170,1,111,0,0,2,0,217,254,229,5,220,4,168,0,27,0,34,0,0,37,38,35,34,6,7,53,62,1,51,50,23, + 55,23,7,22,51,50,54,55,21,14,1,35,34,39,7,39,1,53,1,21,1,53,1,2,230,99,67,88,172,98,104,180,96,94,120,110,155,105,101,69, + 86,168,104,106,178,98,95,122,108,155,254,91,5,2,250,254,3,192,17,31,76,84,180,78,68,42,243,70,233,32,74,86,180,78,68,43,240,70,4,205, + 176,254,145,170,254,144,178,1,18,0,0,0,0,2,0,217,254,166,5,219,5,87,0,27,0,38,0,0,5,38,35,34,6,7,53,62,1,51,50,23, + 55,23,7,22,51,50,54,55,21,14,1,35,34,39,7,39,1,0,5,4,1,21,0,37,53,36,1,2,230,99,68,88,172,98,105,179,97,93,121,109, + 155,105,101,69,86,169,103,105,179,97,96,121,108,155,3,93,254,129,254,36,1,220,1,127,254,129,252,125,3,131,1,127,46,32,76,84,179,78,69,43, + 243,70,233,32,75,85,179,78,69,44,241,70,5,148,254,229,93,93,254,229,215,1,120,132,166,124,1,128,0,2,0,225,254,162,5,227,5,87,0,27, + 0,38,0,0,5,38,35,34,6,7,53,62,1,51,50,23,55,23,7,22,51,50,54,55,21,14,1,35,34,39,7,39,1,53,0,5,21,4,1,53, + 0,37,36,2,238,99,68,88,172,98,105,179,97,93,121,109,155,105,101,69,86,169,103,105,179,97,96,121,108,155,254,91,1,127,3,131,252,125,254,129, + 1,127,1,220,254,36,51,32,76,84,179,78,69,43,244,70,234,32,75,85,179,78,69,44,240,70,5,152,215,254,128,124,166,132,254,136,215,1,27,93, + 93,0,0,0,0,3,0,217,254,246,5,219,6,12,0,11,0,15,0,18,0,0,1,23,3,55,17,37,3,39,19,37,53,9,1,17,7,3,39,19, + 5,4,231,158,131,217,253,185,219,158,220,253,226,3,76,1,12,139,208,158,145,254,10,6,12,64,254,193,89,251,56,240,253,232,64,2,25,224,166,1, + 92,252,239,2,196,57,254,4,64,1,97,206,0,3,0,217,254,246,5,219,6,12,0,11,0,15,0,18,0,0,1,39,19,7,17,5,19,23,3,5, + 21,9,1,17,55,19,23,3,37,1,205,158,131,217,2,71,219,158,220,2,30,252,180,254,244,139,208,158,145,1,246,254,246,64,1,63,89,4,200,240, + 2,24,64,253,231,224,166,254,164,3,17,253,60,57,1,252,64,254,159,206,0,3,0,217,254,125,5,219,6,133,0,3,0,23,0,26,0,0,1,17, + 7,3,1,53,33,19,37,53,1,19,23,3,55,17,37,3,33,21,33,3,39,55,1,19,5,5,49,142,207,253,5,1,124,160,253,228,3,73,193,158, + 129,219,253,183,133,2,206,252,236,118,158,92,1,39,144,254,13,1,158,2,196,58,254,5,253,113,170,1,134,223,166,1,91,1,215,64,254,197,90,251, + 56,241,254,187,170,254,223,64,225,2,208,1,95,205,0,0,0,3,0,213,254,125,5,215,6,133,0,19,0,23,0,26,0,0,55,17,1,19,23,3, + 5,21,1,3,33,21,33,3,39,55,35,53,33,55,1,37,17,37,1,3,37,213,2,165,233,158,233,1,191,253,57,131,3,74,252,112,118,158,92,186, + 1,0,93,1,7,254,70,1,16,1,71,106,1,113,156,4,200,254,233,2,56,64,253,199,185,166,254,219,254,192,170,254,223,64,225,170,228,2,129,181, + 253,60,112,1,94,254,252,152,255,255,3,150,255,66,4,105,5,184,16,39,13,74,2,187,252,250,16,39,13,74,2,187,2,114,16,7,13,74,2,187, + 255,182,0,0,255,255,0,236,1,254,7,19,2,252,16,38,13,74,17,182,16,39,13,74,2,187,255,182,16,7,13,74,5,101,255,182,255,255,0,236, + 255,66,7,19,5,184,16,39,13,74,0,17,252,250,16,39,13,74,5,101,2,114,16,7,13,74,2,187,255,182,0,0,255,255,0,236,255,66,7,19, + 5,184,16,39,13,74,5,101,252,250,16,39,13,74,0,17,2,114,16,7,13,74,2,187,255,182,0,0,0,1,0,88,255,236,7,168,5,174,0,33, + 0,0,1,33,53,33,54,55,54,36,51,33,21,33,6,7,6,7,6,7,33,21,33,22,23,22,23,22,23,33,21,33,34,36,39,38,2,20,254,68, + 1,186,15,77,94,1,100,192,2,184,253,71,147,138,138,75,65,8,4,244,251,14,7,64,74,139,138,147,2,185,253,72,192,254,156,94,72,2,115,160, + 148,143,176,200,159,1,77,79,138,120,93,160,74,120,139,78,76,1,159,198,176,133,0,0,0,1,0,175,255,236,6,73,5,174,0,27,0,0,1,22, + 18,4,23,33,21,33,34,36,2,16,18,36,51,33,21,33,6,4,2,7,33,17,51,17,35,17,1,87,7,137,1,22,147,2,185,253,71,192,254,157, + 190,190,1,99,192,2,185,253,71,147,254,235,139,9,4,85,160,160,2,115,74,254,253,154,1,159,198,1,96,1,116,1,96,200,159,1,156,254,254,93, + 1,16,253,64,1,16,0,0,0,1,0,217,0,155,4,229,4,103,0,25,0,0,37,32,36,16,36,41,1,21,33,34,7,6,7,33,53,51,17,35, + 53,33,22,23,22,51,33,21,3,43,254,216,254,214,1,42,1,40,1,186,254,70,230,107,78,29,2,232,142,142,253,24,37,70,114,223,1,186,155,246, + 1,224,246,142,81,59,132,172,254,26,172,145,48,81,142,0,255,255,0,175,255,236,6,73,7,72,16,38,12,141,0,0,16,7,13,74,2,56,4,2, + 0,2,0,175,255,236,6,73,6,210,0,28,0,32,0,0,1,22,23,22,23,22,23,33,21,33,34,36,2,53,52,18,36,51,33,21,33,6,7,6, + 7,6,7,33,21,17,33,53,33,1,87,7,63,74,140,137,148,2,185,253,71,192,254,157,190,190,1,99,192,2,185,253,71,148,137,139,75,64,9,4, + 245,250,165,5,91,2,115,74,120,139,78,76,1,159,198,1,96,187,185,1,96,200,159,1,77,79,138,120,93,160,3,191,160,0,0,0,0,2,0,217, + 0,155,4,229,5,125,0,22,0,26,0,0,37,32,36,53,52,36,41,1,21,5,6,7,6,7,33,21,33,22,23,22,51,33,21,17,33,53,33,3, + 43,254,216,254,214,1,42,1,40,1,186,254,70,232,105,78,29,3,118,252,138,37,70,114,223,1,186,252,27,3,229,155,246,240,240,246,142,1,1,79, + 58,133,142,145,48,81,142,4,86,140,0,0,0,2,0,175,254,218,6,73,5,174,0,28,0,32,0,0,1,22,23,22,23,22,23,33,21,33,34,36, + 2,53,52,18,36,51,33,21,33,6,7,6,7,6,7,33,21,17,33,53,33,1,87,7,63,74,140,137,148,2,185,253,71,192,254,157,190,190,1,99, + 192,2,185,253,71,148,137,139,75,64,9,4,245,250,165,5,91,2,115,74,120,139,78,76,1,159,198,1,96,187,185,1,96,200,159,1,77,79,138,120, + 93,160,252,103,160,0,0,0,0,1,0,175,255,236,6,73,5,174,0,31,0,0,1,33,21,33,23,22,23,22,23,33,21,33,34,36,2,53,52,18, + 36,51,33,21,33,6,7,6,7,6,7,33,21,33,1,87,4,242,251,67,17,74,140,138,147,2,185,253,71,192,254,157,190,190,1,99,192,2,185,253, + 71,147,138,139,75,14,12,4,198,251,14,2,115,160,34,139,78,76,1,159,198,1,96,187,185,1,96,200,159,1,77,79,138,27,26,160,0,1,0,88, + 255,236,7,168,5,174,0,33,0,0,1,33,21,33,6,7,6,4,35,33,53,33,54,55,54,55,54,55,33,53,33,38,39,38,39,38,39,33,53,33, + 50,4,23,22,5,236,1,188,254,70,15,77,94,254,156,192,253,72,2,185,147,138,138,75,65,8,251,12,4,242,7,64,74,139,138,147,253,71,2,184, + 192,1,100,94,72,3,39,160,148,143,176,200,159,1,77,79,138,120,93,160,74,120,139,78,76,1,159,198,176,133,0,0,0,1,0,175,255,236,6,73, + 5,174,0,27,0,0,1,38,2,36,39,33,53,33,50,4,18,16,2,4,35,33,53,33,54,36,18,55,33,17,35,17,51,17,5,161,7,137,254,234, + 147,253,71,2,185,192,1,99,190,190,254,157,192,253,71,2,185,147,1,21,139,9,251,171,160,160,3,39,74,1,3,154,1,159,198,254,160,254,140,254, + 160,200,159,1,156,1,2,93,254,240,2,192,254,240,0,0,0,1,0,217,0,155,4,229,4,103,0,25,0,0,1,32,4,16,4,41,1,53,33,50, + 55,54,55,33,21,35,17,51,21,33,38,39,38,35,37,53,2,147,1,40,1,42,254,214,254,216,254,70,1,186,230,107,78,29,253,24,142,142,2,232, + 37,70,114,223,254,70,4,103,246,254,32,246,142,81,58,133,172,1,230,172,145,48,80,1,142,0,0,0,0,2,0,175,255,236,6,73,6,210,0,28, + 0,32,0,0,1,38,39,38,39,38,39,33,53,33,50,4,18,21,20,2,4,35,33,53,33,54,55,54,55,54,55,33,53,1,33,53,33,5,161,7, + 63,74,140,137,148,253,71,2,185,192,1,99,190,190,254,157,192,253,71,2,185,148,137,139,75,64,9,251,11,5,91,250,165,5,91,3,39,74,120,139, + 78,76,1,159,198,254,160,187,185,254,160,200,159,1,77,79,138,120,93,160,3,11,160,0,0,2,0,217,0,155,4,229,5,125,0,22,0,26,0,0, + 1,32,4,21,20,4,41,1,53,37,50,55,54,55,33,53,5,38,39,38,7,33,53,37,33,53,33,2,147,1,40,1,42,254,214,254,216,254,70,1, + 186,232,105,78,29,252,138,3,118,37,70,116,221,254,70,3,229,252,27,3,229,4,103,246,241,239,246,142,1,80,58,133,142,1,145,49,82,1,142,138, + 140,0,0,0,0,1,0,217,0,0,6,31,5,194,0,11,0,0,1,33,17,33,21,33,17,33,21,33,17,33,6,31,251,100,4,156,250,186,5,70, + 251,100,4,156,2,130,254,40,170,5,194,170,254,20,0,0,0,3,0,74,255,220,4,137,4,28,0,19,0,27,0,35,0,0,1,50,23,55,23,7, + 22,21,20,0,35,34,39,7,39,55,38,53,52,0,5,38,35,34,6,21,20,31,1,22,51,50,54,53,52,39,2,104,186,143,117,99,118,110,254,196, + 221,184,141,118,99,117,111,1,60,1,192,100,128,162,233,71,99,99,126,163,233,69,4,23,113,118,99,118,141,186,221,254,196,111,118,99,118,141,186,223, + 1,60,213,72,233,165,128,99,98,71,233,163,128,98,0,0,0,1,0,114,1,76,4,82,3,140,0,7,0,0,1,17,1,53,5,17,1,21,2,162, + 253,208,1,176,2,48,2,122,254,210,1,74,194,250,1,46,254,182,194,0,0,2,0,146,0,0,4,130,4,196,0,4,0,9,0,0,51,17,9,1, + 17,37,33,17,9,1,146,1,248,1,248,252,182,2,164,254,174,254,174,2,160,2,36,253,220,253,96,170,1,213,1,121,254,135,0,0,0,1,1,163, + 3,218,5,15,5,220,0,7,0,0,9,1,39,1,51,1,7,1,3,45,254,238,120,1,138,90,1,136,120,254,240,4,234,254,240,120,1,138,254,118, + 120,1,16,0,0,1,1,163,0,0,5,15,2,2,0,7,0,0,37,51,1,23,1,35,1,55,3,45,90,1,16,120,254,120,90,254,118,120,242,1, + 16,120,254,118,1,138,120,0,255,255,1,163,0,0,5,15,3,63,16,38,23,23,0,0,16,7,13,136,0,0,252,38,255,255,1,163,0,0,5,15, + 4,27,16,39,23,23,0,0,0,220,16,38,23,23,0,215,16,7,13,136,0,0,252,38,0,1,1,59,255,197,2,173,6,78,0,25,0,0,1,23, + 6,20,23,22,20,7,6,20,23,22,20,7,39,54,52,39,38,52,55,54,52,39,38,52,1,183,122,76,76,124,124,76,76,124,124,122,76,76,124,124, + 76,76,124,6,78,118,79,112,80,129,248,129,80,111,80,129,249,129,118,79,112,80,129,248,129,80,112,80,129,248,0,0,0,1,0,176,254,242,2,88, + 6,20,0,5,0,0,19,33,21,35,17,35,176,1,168,240,184,6,20,143,249,109,0,0,0,1,0,199,254,242,2,111,6,20,0,5,0,0,1,17, + 35,17,35,53,2,111,184,240,6,20,248,222,6,147,143,0,0,1,0,176,254,242,2,88,6,20,0,5,0,0,19,17,51,17,51,21,176,184,240,254, + 242,7,34,249,109,143,0,0,0,1,0,199,254,242,2,111,6,20,0,5,0,0,1,33,53,51,17,51,2,111,254,88,240,184,254,242,143,6,147,0, + 0,2,2,244,255,98,6,19,2,130,0,3,0,7,0,0,1,51,17,35,19,53,33,21,2,244,144,144,200,2,87,1,186,253,168,2,144,144,144,0, + 0,2,0,100,255,98,3,132,2,130,0,3,0,7,0,0,1,21,33,53,5,51,17,35,2,188,253,168,2,144,144,144,2,130,144,144,200,253,168,0, + 0,2,2,244,1,242,6,19,5,18,0,3,0,7,0,0,1,53,33,21,37,35,17,51,3,188,2,87,253,113,144,144,1,242,144,144,200,2,88,0, + 0,2,0,100,1,242,3,132,5,18,0,3,0,7,0,0,1,21,33,53,37,35,17,51,2,188,253,168,3,32,144,144,2,130,144,144,56,2,88,0, + 0,1,0,217,1,31,5,219,3,94,0,5,0,0,1,21,33,17,35,17,5,219,251,166,168,3,94,170,254,107,2,63,0,2,0,6,1,2,4,21, + 5,18,0,7,0,15,0,0,19,36,5,2,19,4,37,18,1,18,3,4,37,2,19,36,140,1,129,1,129,137,137,254,127,254,127,137,254,241,184,184, + 2,7,2,8,184,184,253,248,1,138,137,137,1,128,1,130,138,138,254,126,253,248,1,244,2,28,177,177,254,12,253,229,177,0,0,0,0,6,0,247, + 0,1,7,9,6,19,0,3,0,49,0,59,0,70,0,79,0,89,0,0,1,33,17,33,17,21,20,6,32,38,53,52,54,59,1,17,35,34,38,53, + 52,54,32,22,29,1,33,53,52,54,51,50,22,21,20,6,43,1,17,51,50,22,21,20,6,35,34,38,61,1,1,53,52,38,35,34,6,20,22,51, + 19,35,34,6,21,20,22,51,50,54,53,1,51,50,54,52,38,34,6,21,17,21,20,22,50,54,53,52,38,35,3,108,1,40,254,216,185,254,252,184, + 184,127,170,170,127,184,184,1,4,185,1,40,185,130,131,183,183,128,170,170,128,183,183,131,130,185,254,68,98,69,68,98,98,69,166,166,69,98,98,69, + 68,98,2,80,167,68,98,97,138,98,98,138,97,98,68,2,118,1,40,254,68,170,128,183,184,131,128,186,1,40,186,129,130,184,183,128,170,170,128,183, + 184,130,129,186,254,216,186,128,131,184,183,128,170,2,80,167,69,97,97,138,98,253,176,98,68,69,98,98,68,2,247,98,138,97,97,69,253,9,167,68, + 98,98,69,68,98,0,0,0,0,1,0,217,1,31,5,219,3,94,0,5,0,0,1,33,17,51,17,33,5,219,250,254,168,4,90,1,31,2,63,254, + 107,0,0,0,0,1,0,176,3,103,3,58,6,20,0,5,0,0,1,33,17,35,17,33,3,58,254,6,144,2,138,5,132,253,227,2,173,0,0,0, + 0,1,0,134,3,103,3,16,6,20,0,5,0,0,19,53,33,17,35,17,134,2,138,144,5,132,144,253,83,2,29,0,0,1,0,176,255,112,3,58, + 2,29,0,5,0,0,33,21,33,17,51,17,3,58,253,118,144,144,2,173,253,227,0,0,0,1,0,134,255,112,3,16,2,29,0,5,0,0,51,33, + 17,51,17,33,134,1,250,144,253,118,2,29,253,83,0,0,0,1,1,175,254,0,3,250,7,108,0,25,0,0,1,17,52,55,26,1,51,50,22,21, + 20,6,35,34,39,38,39,46,1,35,34,3,2,21,48,17,1,175,3,12,190,202,80,100,64,55,43,28,24,15,6,9,16,104,17,8,254,0,5,8, + 36,129,2,3,1,188,84,65,54,63,19,16,38,15,72,253,149,254,211,2,250,152,0,0,0,1,0,42,254,26,2,117,7,137,0,25,0,0,1,17, + 20,7,10,1,35,34,38,53,52,54,51,50,23,22,23,30,1,51,50,19,18,53,48,17,2,117,3,12,190,202,80,100,64,55,43,28,24,15,6,9, + 16,104,17,8,7,137,250,245,36,129,253,253,254,68,84,65,54,63,19,16,38,15,72,2,107,1,45,2,5,107,0,0,0,3,0,156,1,208,8,156, + 4,154,0,7,0,11,0,15,0,0,9,1,39,1,51,1,7,1,37,33,53,41,2,21,33,4,111,254,38,120,2,82,90,2,80,120,254,40,254,141, + 253,70,2,186,2,138,2,188,253,68,3,168,254,40,120,2,82,253,174,120,1,216,72,170,170,0,0,0,0,2,0,156,0,0,8,156,4,154,0,7, + 0,11,0,0,19,33,1,33,21,33,1,33,37,33,21,33,156,2,186,2,228,2,98,253,70,253,28,253,158,5,68,2,188,253,68,4,154,252,16,170, + 3,240,170,170,0,5,0,156,0,0,11,79,6,20,0,4,0,9,0,12,0,15,0,21,0,0,51,17,33,9,2,17,51,9,1,41,1,9,1,33, + 9,3,51,9,1,156,7,169,3,10,252,246,248,235,141,2,118,253,138,4,237,251,230,2,13,253,243,4,26,253,243,2,221,253,138,2,118,142,2,118, + 253,138,6,20,252,246,252,246,5,128,251,20,2,118,2,118,253,243,253,33,2,13,2,223,253,138,253,138,2,116,2,120,0,5,0,156,0,0,8,156, + 6,20,0,3,0,8,0,11,0,14,0,19,0,0,51,17,33,17,1,17,51,9,1,41,1,9,1,33,9,3,51,17,156,8,0,248,148,141,2,118, + 253,138,4,237,251,230,2,13,253,243,4,26,253,243,2,221,253,138,2,118,142,6,20,249,236,5,128,251,20,2,118,2,118,253,243,253,33,2,13,2, + 223,253,138,253,138,4,236,0,0,43,0,120,0,0,11,20,5,213,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,95,0,107,0,119,0,131, + 0,143,0,155,0,167,0,179,0,191,0,203,0,215,0,227,0,239,0,251,1,7,1,19,1,31,1,43,1,55,1,67,1,79,1,91,1,103,1,115, + 1,127,1,139,1,151,1,163,1,175,1,187,1,199,1,211,1,228,1,240,1,252,2,8,0,0,1,33,50,21,17,20,35,33,34,53,17,52,23,17, + 20,51,33,50,53,17,52,35,33,34,1,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,37,21,20,43,1,34, + 61,1,52,59,1,50,5,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,5,21,20,43,1,34,61,1,52,59, + 1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21, + 20,43,1,34,61,1,52,59,1,50,5,21,20,43,1,34,61,1,52,59,1,50,37,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34, + 61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59, + 1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,39,21, + 20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34, + 61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59,1,50,7,21,20,43,1,34,61,1,52,59, + 1,50,7,21,20,43,1,34,61,1,52,59,1,50,39,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21, + 20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34, + 61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,23,21,20,43,1,34,61,1,52,59, + 1,50,5,21,20,43,1,34,61,1,52,59,1,50,7,50,21,17,20,43,1,34,61,1,52,35,34,61,1,52,51,19,21,20,43,1,34,61,1,52, + 59,1,50,23,21,20,43,1,34,61,1,52,59,1,50,5,34,61,1,52,51,33,50,29,1,20,35,1,85,8,226,221,221,247,30,221,147,74,8,226, + 73,73,247,30,74,1,3,37,74,37,37,74,37,223,37,75,36,36,75,37,1,74,37,74,37,37,74,37,254,70,37,74,37,37,74,37,221,37,74,37, + 37,74,37,1,185,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,1, + 142,37,251,37,37,251,37,248,67,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,220,37,74,37,37,74,37,221,37,74,37, + 37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,36,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37, + 74,37,37,74,37,221,37,74,37,37,74,37,220,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37, + 36,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,220,37,74,37,37,74,37,221,37,74,37,37, + 74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,221,37,74,37,37,74,37,1,30,37,139,37,37,139,37,37,37,37,246,42,36,37,37,148, + 37,74,37,37,74,37,223,37,75,36,36,75,37,249,165,37,37,4,4,37,37,5,213,221,251,229,221,221,4,27,221,221,251,229,74,74,4,27,74,252, + 28,73,37,37,73,38,37,74,37,37,74,37,183,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37, + 74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,183,74,37,37,74,37,37,74,37,37,74,37,37,74, + 37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,183,74,37,37,74,37, + 37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37, + 74,37,180,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74, + 37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,37,74,37,219,37,254,222,37,37,149,32,37,73,37,253,72,74,37,37,74,37, + 37,74,37,37,74,37,148,37,74,37,37,74,37,0,0,0,0,5,0,1,0,0,10,180,6,20,0,4,0,9,0,12,0,15,0,21,0,0,41,1, + 9,1,33,7,35,9,1,51,9,2,17,9,1,3,35,9,1,51,1,10,180,248,87,252,246,3,10,7,169,148,141,253,138,2,118,141,250,134,2,13, + 2,13,253,243,253,243,208,142,253,138,2,118,142,2,118,3,10,3,10,148,253,138,253,138,4,236,253,243,2,13,251,20,2,13,253,243,4,236,253,136, + 253,140,2,118,0,5,0,150,255,70,6,102,5,252,0,5,0,11,0,15,0,19,0,23,0,0,9,2,17,9,1,3,17,9,1,17,1,3,55,1, + 7,17,23,1,39,1,51,17,35,1,8,2,118,2,118,253,138,253,138,114,2,232,2,232,253,24,38,57,1,222,57,57,254,34,57,254,34,114,114,1, + 53,254,149,1,107,2,216,1,107,254,149,252,230,3,92,1,173,254,83,252,164,254,83,5,65,99,254,236,99,254,92,99,254,236,99,2,250,253,216,0, + 255,255,0,166,0,0,2,110,4,96,16,6,3,77,0,0,255,255,0,186,254,86,4,164,4,123,16,6,3,85,0,0,255,255,0,135,255,227,6,39, + 4,96,16,6,3,93,0,0,255,255,0,113,255,231,4,228,4,121,16,6,3,69,0,0,0,1,0,26,254,46,5,245,0,208,0,11,0,0,1,33, + 17,33,21,35,17,33,17,35,53,33,1,184,2,160,1,157,245,252,16,246,1,158,254,216,1,248,170,254,8,1,248,170,0,2,0,156,0,0,8,197, + 5,251,0,13,0,17,0,0,1,33,39,55,1,21,1,39,55,33,1,33,53,33,5,53,33,21,5,226,1,203,233,120,1,137,254,119,120,233,254,141, + 253,28,253,70,2,98,2,226,2,188,4,154,233,120,254,119,90,254,119,120,233,252,16,170,170,170,170,0,0,2,0,35,0,0,6,217,5,208,0,5, + 0,11,0,0,37,33,9,1,33,9,3,33,9,1,2,18,2,216,1,108,254,148,253,40,254,148,1,43,254,82,1,173,3,91,1,174,254,83,114,2, + 118,2,118,253,138,253,24,2,232,2,232,253,24,253,24,0,0,1,0,176,253,252,3,80,7,146,0,11,0,0,1,35,53,16,19,18,19,51,0,3, + 2,17,1,115,195,160,186,166,160,254,252,90,127,253,252,234,3,151,1,226,2,48,1,3,253,243,254,134,253,238,252,237,0,1,0,176,253,252,1,115, + 7,137,0,3,0,0,19,51,17,35,176,195,195,7,137,246,115,0,0,0,0,1,0,176,254,20,3,80,7,137,0,11,0,0,1,21,16,19,18,19, + 35,2,3,2,17,53,1,115,127,147,203,160,208,144,160,7,137,234,252,165,254,87,254,20,254,101,1,69,1,238,2,38,3,50,234,0,0,1,0,176, + 253,252,3,80,7,146,0,11,0,0,1,53,16,3,2,1,51,18,19,18,17,21,2,141,127,90,254,252,160,166,186,160,253,252,234,3,19,2,18,1, + 121,2,14,254,253,253,208,254,30,252,105,234,0,1,2,141,253,252,3,80,7,137,0,4,0,0,1,17,35,17,48,3,80,195,7,137,246,115,9,141, + 0,1,0,176,254,20,3,80,7,137,0,11,0,0,1,51,21,16,3,2,3,35,18,19,18,17,2,141,195,160,144,208,160,203,147,127,7,137,234,252, + 205,253,219,254,18,254,187,1,155,1,236,1,169,3,91,0,0,1,0,176,253,252,3,80,7,109,0,5,0,0,1,35,17,33,21,33,1,115,195,2, + 160,254,35,253,252,9,113,195,0,1,0,176,253,252,1,115,7,137,0,3,0,0,19,51,17,35,176,195,195,7,137,246,115,0,0,0,0,1,0,176, + 254,20,3,80,7,137,0,5,0,0,1,17,33,21,33,17,1,115,1,221,253,96,7,137,247,78,195,9,117,0,0,0,0,1,0,176,253,252,3,80, + 7,109,0,5,0,0,1,17,33,53,33,17,2,141,254,35,2,160,253,252,8,174,195,246,143,0,0,0,0,1,2,141,253,252,3,80,7,122,0,3, + 0,0,1,51,17,35,2,141,195,195,7,122,246,130,0,0,0,1,0,176,254,20,3,80,7,122,0,5,0,0,1,51,17,33,53,33,2,141,195,253, + 96,1,221,7,122,246,154,195,0,1,2,163,253,234,5,88,7,109,0,13,0,0,1,35,17,52,55,54,51,33,21,33,34,7,6,21,3,93,186,111, + 121,186,1,19,254,231,101,68,57,253,234,7,117,223,145,158,176,102,87,153,0,1,0,168,253,252,3,93,7,134,0,24,0,0,1,22,23,22,25,1, + 35,17,16,39,38,37,39,53,51,32,55,54,25,1,51,17,16,7,6,2,148,58,42,101,186,110,75,254,251,61,61,1,3,77,110,186,101,40,2,193, + 32,61,147,254,67,253,232,2,12,1,183,95,65,4,1,187,69,99,1,179,2,12,253,232,254,72,152,60,0,1,2,163,254,20,5,88,7,134,0,13, + 0,0,1,17,20,23,22,51,33,21,33,34,39,38,53,17,3,93,57,68,101,1,25,254,237,184,123,111,7,134,248,148,154,86,102,176,158,143,225,7, + 100,0,0,0,0,1,2,163,253,244,3,93,7,140,0,3,0,0,1,35,17,51,3,93,186,186,253,244,9,152,0,0,0,1,0,168,253,234,3,93, + 7,109,0,13,0,0,1,17,52,39,38,35,33,53,33,50,23,22,21,17,2,163,57,68,101,254,231,1,19,186,121,111,253,234,7,125,153,87,102,176, + 158,145,223,248,139,0,0,0,0,1,2,163,253,252,5,88,7,134,0,24,0,0,1,38,39,38,25,1,51,17,16,23,22,33,51,21,7,4,7,6, + 25,1,35,17,16,55,54,3,108,60,40,101,186,110,77,1,3,61,61,254,251,75,110,186,101,42,2,193,33,60,152,1,184,2,24,253,244,254,77,99, + 69,187,1,4,65,95,254,73,253,244,2,24,1,189,147,61,0,1,0,168,254,20,3,93,7,134,0,13,0,0,1,51,17,20,7,6,35,33,53,33, + 50,55,54,53,2,163,186,111,123,184,254,237,1,25,101,68,57,7,134,248,156,225,143,158,176,102,86,154,0,1,1,175,254,0,2,117,7,137,0,3, + 0,0,1,17,51,17,1,175,198,254,0,9,137,246,119,0,0,2,0,55,0,134,6,64,5,213,0,8,0,17,0,0,37,9,1,17,33,17,33,3, + 33,3,53,9,1,53,33,19,33,3,2,51,254,4,1,252,2,55,1,214,1,251,244,100,254,246,1,10,4,12,1,254,242,1,134,1,252,1,252,254, + 239,2,104,251,194,1,114,131,254,246,254,246,131,3,118,253,152,0,0,0,0,2,0,186,0,0,6,213,4,196,0,2,0,6,0,0,1,33,9,1, + 33,17,33,6,213,249,229,3,13,3,14,249,229,6,27,2,160,2,36,251,60,1,248,0,0,4,0,150,255,70,6,102,5,252,0,5,0,11,0,31, + 0,43,0,0,9,2,17,9,1,3,17,9,1,17,1,0,20,23,22,23,22,50,55,54,55,54,52,39,38,39,38,34,7,6,7,2,16,62,1,32, + 30,1,16,14,1,32,38,1,8,2,118,2,118,253,138,253,138,114,2,232,2,232,253,24,254,110,54,54,92,93,218,93,92,54,54,54,54,92,93,218, + 93,92,54,168,138,238,1,24,238,138,138,238,254,232,238,1,53,254,149,1,107,2,216,1,107,254,149,252,230,3,92,1,173,254,83,252,164,254,83,3, + 200,218,93,92,54,54,54,54,92,93,218,93,92,54,54,54,54,92,254,170,1,24,238,138,138,238,254,232,238,138,138,0,255,255,0,6,0,154,6,33, + 3,142,16,6,14,131,0,0,0,3,0,89,254,247,4,207,2,90,0,13,0,25,0,32,0,0,0,34,7,6,21,20,23,22,50,55,54,53,52,47, + 1,50,22,21,20,6,35,34,38,53,52,54,1,17,7,53,55,51,17,3,233,202,50,51,51,50,202,50,51,51,151,161,170,170,161,162,170,170,254,86, + 223,230,137,2,1,86,86,172,173,86,86,86,86,173,172,86,175,222,211,212,222,222,212,211,222,252,172,2,209,41,116,39,252,189,0,0,0,2,255,130, + 255,227,4,164,6,20,0,23,0,31,0,0,1,62,1,51,50,0,16,2,35,34,38,39,21,35,17,5,39,37,53,51,21,37,23,5,0,16,38,32, + 6,16,22,32,1,115,58,177,123,204,0,255,255,204,123,177,58,185,254,233,33,1,56,185,1,35,33,254,188,2,114,167,254,220,167,167,1,36,3,182, + 100,97,254,188,253,240,254,188,97,100,168,4,230,93,99,104,192,131,97,97,109,252,64,1,150,231,231,254,106,231,0,0,0,1,0,146,254,46,4,130, + 0,208,0,7,0,0,1,33,17,51,17,33,17,51,1,58,2,160,168,252,16,168,254,216,1,248,253,94,2,162,0,0,0,3,0,152,255,236,6,148, + 5,232,0,13,0,27,0,38,0,219,186,0,14,0,6,0,3,43,184,0,14,16,186,0,35,0,29,0,3,43,184,0,35,16,186,0,0,0,20,0, + 3,43,184,0,0,16,65,27,0,22,0,14,0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14, + 0,150,0,14,0,166,0,14,0,182,0,14,0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,65,5,0,234, + 0,20,0,250,0,20,0,2,93,65,27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0, + 137,0,20,0,153,0,20,0,169,0,20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,0,186,0,17,0,3,0,3,43,184,0,17,16,186, + 0,10,0,24,0,3,43,184,0,10,16,186,0,36,0,37,0,3,43,184,0,36,16,184,0,28,208,48,49,1,16,0,33,32,0,17,52,18,36,51, + 50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,1,51,17,7,53,37,51,17,51,21,33,6,148,254,63,254,194,254,196,254,63,206,1, + 113,190,193,1,113,205,250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,1,124,217,236,1,1,161,218,253,151,2,234,254,193,254,65, + 1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112,1,144,1,28,179,1,71,177,177,254,185,253,255,2,126,43,152,47,252,230,142,0,0,0, + 0,3,0,152,255,236,6,148,5,232,0,13,0,27,0,56,1,63,186,0,14,0,6,0,3,43,184,0,14,16,186,0,51,0,38,0,3,43,184,0, + 51,16,186,0,0,0,20,0,3,43,184,0,0,16,65,27,0,22,0,14,0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14, + 0,118,0,14,0,134,0,14,0,150,0,14,0,166,0,14,0,182,0,14,0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0, + 14,0,2,93,65,5,0,234,0,20,0,250,0,20,0,2,93,65,27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0, + 105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0,169,0,20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,184,0,51,16,184,0, + 29,208,184,0,29,47,65,5,0,234,0,38,0,250,0,38,0,2,93,65,27,0,25,0,38,0,41,0,38,0,57,0,38,0,73,0,38,0,89,0, + 38,0,105,0,38,0,121,0,38,0,137,0,38,0,153,0,38,0,169,0,38,0,185,0,38,0,201,0,38,0,217,0,38,0,13,93,186,0,44,0, + 6,0,0,17,18,57,0,186,0,17,0,3,0,3,43,184,0,17,16,186,0,10,0,24,0,3,43,184,0,10,16,186,0,29,0,30,0,3,43,184, + 0,29,16,186,0,48,0,41,0,3,43,184,0,48,16,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,5,16,0,33,32,0,17,52,2, + 36,35,34,4,2,1,33,21,33,53,54,36,55,62,1,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,7,14,1,6,148,254,63,254,194, + 254,196,254,63,206,1,113,190,193,1,113,205,250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,2,79,1,180,253,92,82,1,6,33, + 62,47,95,78,59,132,115,97,145,61,163,197,48,62,17,178,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112,1,144, + 1,28,179,1,71,177,177,254,185,253,255,142,129,77,241,34,63,85,40,63,78,38,58,171,36,31,151,125,58,105,70,18,167,0,0,0,0,3,0,152, + 255,236,6,148,5,232,0,13,0,27,0,68,1,181,186,0,14,0,6,0,3,43,184,0,14,16,186,0,66,0,53,0,3,43,184,0,66,16,186,0, + 0,0,20,0,3,43,184,0,0,16,65,27,0,22,0,14,0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14, + 0,134,0,14,0,150,0,14,0,166,0,14,0,182,0,14,0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93, + 65,5,0,234,0,20,0,250,0,20,0,2,93,65,27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0, + 121,0,20,0,137,0,20,0,153,0,20,0,169,0,20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,65,5,0,234,0,53,0,250,0,53, + 0,2,93,65,27,0,25,0,53,0,41,0,53,0,57,0,53,0,73,0,53,0,89,0,53,0,105,0,53,0,121,0,53,0,137,0,53,0,153,0, + 53,0,169,0,53,0,185,0,53,0,201,0,53,0,217,0,53,0,13,93,186,0,28,0,53,0,66,17,18,57,186,0,44,0,53,0,66,17,18,57, + 184,0,44,47,65,5,0,234,0,44,0,250,0,44,0,2,93,65,27,0,25,0,44,0,41,0,44,0,57,0,44,0,73,0,44,0,89,0,44,0, + 105,0,44,0,121,0,44,0,137,0,44,0,153,0,44,0,169,0,44,0,185,0,44,0,201,0,44,0,217,0,44,0,13,93,184,0,31,220,186,0, + 38,0,6,0,0,17,18,57,186,0,59,0,6,0,0,17,18,57,0,186,0,17,0,3,0,3,43,184,0,17,16,186,0,10,0,24,0,3,43,184, + 0,10,16,186,0,41,0,34,0,3,43,184,0,41,16,186,0,63,0,56,0,3,43,184,0,63,16,186,0,50,0,47,0,3,43,184,0,50,16,186, + 0,28,0,47,0,50,17,18,57,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,5, + 30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6, + 6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,3,185,13,118, + 216,195,64,136,88,91,125,68,117,115,107,99,140,145,90,88,92,91,52,121,107,95,136,61,161,193,104,2,234,254,193,254,65,1,191,1,63,198,1,114, + 198,198,254,144,200,254,228,254,112,1,144,1,28,179,1,71,177,177,254,185,150,3,129,93,141,156,23,27,168,48,28,79,76,71,78,140,60,58,60,63, + 21,32,151,24,20,137,115,81,114,0,0,0,0,4,0,152,255,236,6,148,5,232,0,13,0,27,0,30,0,41,0,243,186,0,14,0,6,0,3,43, + 184,0,14,16,186,0,32,0,28,0,3,43,184,0,32,16,186,0,0,0,20,0,3,43,184,0,0,16,65,27,0,22,0,14,0,38,0,14,0,54, + 0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14,0,150,0,14,0,166,0,14,0,182,0,14,0,198,0,14,0,214, + 0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,65,5,0,234,0,20,0,250,0,20,0,2,93,65,27,0,25,0,20,0,41,0, + 20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0,169,0,20,0,185,0,20,0,201,0, + 20,0,217,0,20,0,13,93,184,0,32,16,184,0,36,208,184,0,28,16,184,0,38,208,0,186,0,17,0,3,0,3,43,184,0,17,16,186,0,10, + 0,24,0,3,43,184,0,10,16,186,0,34,0,35,0,3,43,184,0,34,16,184,0,29,208,184,0,35,16,184,0,39,208,48,49,1,16,0,33,32, + 0,17,52,18,36,51,50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,37,1,33,3,51,17,51,21,35,21,35,53,33,53,6,148,254, + 63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,2,191,254,243,1,13,24, + 206,141,141,182,254,67,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112,1,144,1,28,179,1,71,177,177,254,185,79, + 254,130,2,72,253,184,141,211,211,142,0,0,0,3,0,152,255,236,6,148,5,232,0,13,0,27,0,57,1,75,186,0,14,0,6,0,3,43,184,0, + 14,16,186,0,31,0,28,0,3,43,184,0,31,16,186,0,38,0,51,0,3,43,184,0,38,16,186,0,0,0,20,0,3,43,184,0,0,16,65,27, + 0,22,0,14,0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14,0,150,0,14,0,166,0,14, + 0,182,0,14,0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,65,5,0,234,0,20,0,250,0,20,0,2, + 93,65,27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0, + 169,0,20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,186,0,45,0,6,0,0,17,18,57,65,5,0,234,0,51,0,250,0,51,0,2, + 93,65,27,0,25,0,51,0,41,0,51,0,57,0,51,0,73,0,51,0,89,0,51,0,105,0,51,0,121,0,51,0,137,0,51,0,153,0,51,0, + 169,0,51,0,185,0,51,0,201,0,51,0,217,0,51,0,13,93,0,186,0,17,0,3,0,3,43,184,0,17,16,186,0,10,0,24,0,3,43,184, + 0,10,16,186,0,48,0,41,0,3,43,184,0,48,16,186,0,29,0,30,0,3,43,184,0,29,16,186,0,35,0,54,0,3,43,184,0,35,16,48, + 49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,1,33,21,33,21,6,54,51,50,22,21, + 20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,35,34,6,7,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,250,87,1, + 143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,1,152,2,61,254,111,3,63,31,176,207,213,190,64,133,88,95,119,68,104,118,118,104,50,101, + 89,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112,1,144,1,28,179,1,71,177,177,254,185,1,25,142,171,1,10, + 176,149,152,172,20,24,172,47,27,97,85,86,97,20,37,0,0,4,0,152,255,236,6,148,5,232,0,13,0,27,0,39,0,64,1,145,186,0,14,0, + 6,0,3,43,184,0,14,16,186,0,31,0,59,0,3,43,184,0,31,16,186,0,53,0,37,0,3,43,184,0,53,16,186,0,0,0,20,0,3,43, + 184,0,0,16,65,27,0,22,0,14,0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14,0,150, + 0,14,0,166,0,14,0,182,0,14,0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,65,5,0,234,0,20, + 0,250,0,20,0,2,93,65,27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0, + 20,0,153,0,20,0,169,0,20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,65,27,0,22,0,31,0,38,0,31,0,54,0,31,0,70, + 0,31,0,86,0,31,0,102,0,31,0,118,0,31,0,134,0,31,0,150,0,31,0,166,0,31,0,182,0,31,0,198,0,31,0,214,0,31,0,13, + 93,65,5,0,229,0,31,0,245,0,31,0,2,93,65,5,0,234,0,37,0,250,0,37,0,2,93,65,27,0,25,0,37,0,41,0,37,0,57,0, + 37,0,73,0,37,0,89,0,37,0,105,0,37,0,121,0,37,0,137,0,37,0,153,0,37,0,169,0,37,0,185,0,37,0,201,0,37,0,217,0, + 37,0,13,93,186,0,41,0,37,0,53,17,18,57,0,186,0,17,0,3,0,3,43,184,0,17,16,186,0,10,0,24,0,3,43,184,0,10,16,186, + 0,34,0,56,0,3,43,184,0,34,16,186,0,62,0,44,0,3,43,184,0,62,16,186,0,50,0,28,0,3,43,184,0,50,16,48,49,1,16,0, + 33,32,0,17,52,18,36,51,50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,5,34,6,21,20,22,51,50,54,53,52,38,19,21,46, + 1,35,34,6,7,6,54,51,50,22,21,20,6,35,34,38,53,52,18,51,50,22,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205, + 250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,2,161,78,92,92,78,78,92,92,212,84,97,47,119,127,5,9,128,78,160,186,194, + 160,185,192,234,200,53,106,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112,1,144,1,28,179,1,71,177,177,254,185, + 159,98,91,90,98,98,90,91,98,1,157,156,35,22,148,80,11,61,177,148,145,179,253,231,218,1,11,19,0,3,0,152,255,236,6,148,5,232,0,13, + 0,27,0,34,0,235,184,0,35,47,184,0,36,47,184,0,0,220,184,0,35,16,184,0,6,208,184,0,6,47,184,0,14,220,65,27,0,22,0,14, + 0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14,0,150,0,14,0,166,0,14,0,182,0,14, + 0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,184,0,0,16,184,0,20,220,65,5,0,234,0,20,0,250, + 0,20,0,2,93,65,27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0, + 153,0,20,0,169,0,20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,186,0,32,0,6,0,0,17,18,57,186,0,33,0,6,0,0,17, + 18,57,0,186,0,17,0,3,0,3,43,184,0,17,16,186,0,10,0,24,0,3,43,184,0,10,16,186,0,29,0,33,0,3,43,184,0,29,16,48, + 49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,1,33,21,1,35,1,33,6,148,254,63, + 254,194,254,196,254,63,206,1,113,190,193,1,113,205,250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,1,107,2,171,254,148,193,1, + 81,254,49,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112,1,144,1,28,179,1,71,177,177,254,185,1,25,75,252, + 163,3,26,0,0,5,0,152,255,236,6,148,5,232,0,13,0,27,0,39,0,63,0,75,2,13,186,0,14,0,6,0,3,43,184,0,14,16,186,0, + 31,0,61,0,3,43,184,0,31,16,186,0,49,0,70,0,3,43,184,0,49,16,186,0,0,0,20,0,3,43,184,0,0,16,65,27,0,22,0,14, + 0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14,0,150,0,14,0,166,0,14,0,182,0,14, + 0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,65,5,0,234,0,20,0,250,0,20,0,2,93,65,27,0, + 25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0,169,0,20,0, + 185,0,20,0,201,0,20,0,217,0,20,0,13,93,65,27,0,22,0,31,0,38,0,31,0,54,0,31,0,70,0,31,0,86,0,31,0,102,0,31, + 0,118,0,31,0,134,0,31,0,150,0,31,0,166,0,31,0,182,0,31,0,198,0,31,0,214,0,31,0,13,93,65,5,0,229,0,31,0,245,0, + 31,0,2,93,65,5,0,234,0,70,0,250,0,70,0,2,93,65,27,0,25,0,70,0,41,0,70,0,57,0,70,0,73,0,70,0,89,0,70,0, + 105,0,70,0,121,0,70,0,137,0,70,0,153,0,70,0,169,0,70,0,185,0,70,0,201,0,70,0,217,0,70,0,13,93,186,0,37,0,70,0, + 49,17,18,57,184,0,37,47,65,5,0,234,0,37,0,250,0,37,0,2,93,65,27,0,25,0,37,0,41,0,37,0,57,0,37,0,73,0,37,0, + 89,0,37,0,105,0,37,0,121,0,37,0,137,0,37,0,153,0,37,0,169,0,37,0,185,0,37,0,201,0,37,0,217,0,37,0,13,93,186,0, + 43,0,61,0,31,17,18,57,184,0,43,47,186,0,52,0,70,0,49,17,18,57,184,0,37,16,184,0,55,220,184,0,43,16,184,0,64,220,0,186, + 0,17,0,3,0,3,43,184,0,17,16,186,0,10,0,24,0,3,43,184,0,10,16,186,0,34,0,58,0,3,43,184,0,34,16,186,0,46,0,73, + 0,3,43,184,0,46,16,186,0,67,0,28,0,3,43,184,0,67,16,186,0,52,0,28,0,67,17,18,57,48,49,1,16,0,33,32,0,17,52,18, + 36,51,50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,5,34,6,21,20,22,51,50,54,53,52,38,37,46,1,53,52,54,51,50,22, + 21,20,6,7,30,1,21,20,6,35,34,38,53,52,54,55,20,22,51,50,54,53,52,38,35,34,6,6,148,254,63,254,194,254,196,254,63,206,1,113, + 190,193,1,113,205,250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,2,175,84,95,95,84,84,95,95,254,198,4,106,183,157,157,182, + 105,4,15,118,190,173,173,190,118,87,81,77,75,82,82,75,77,81,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112, + 1,144,1,28,179,1,71,177,177,254,185,230,80,73,73,80,81,72,73,80,73,1,118,83,116,136,136,116,83,118,1,3,131,92,138,151,151,138,92,131, + 193,61,66,66,61,62,66,66,0,4,0,152,255,236,6,148,5,232,0,13,0,27,0,52,0,64,1,145,186,0,14,0,6,0,3,43,184,0,14,16, + 186,0,62,0,41,0,3,43,184,0,62,16,186,0,0,0,20,0,3,43,184,0,0,16,186,0,47,0,56,0,3,43,184,0,47,16,65,27,0,22, + 0,14,0,38,0,14,0,54,0,14,0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14,0,150,0,14,0,166,0,14,0,182, + 0,14,0,198,0,14,0,214,0,14,0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,65,5,0,234,0,20,0,250,0,20,0,2,93,65, + 27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0,169,0, + 20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,65,27,0,22,0,62,0,38,0,62,0,54,0,62,0,70,0,62,0,86,0,62,0,102, + 0,62,0,118,0,62,0,134,0,62,0,150,0,62,0,166,0,62,0,182,0,62,0,198,0,62,0,214,0,62,0,13,93,65,5,0,229,0,62,0, + 245,0,62,0,2,93,186,0,29,0,41,0,62,17,18,57,65,5,0,234,0,56,0,250,0,56,0,2,93,65,27,0,25,0,56,0,41,0,56,0, + 57,0,56,0,73,0,56,0,89,0,56,0,105,0,56,0,121,0,56,0,137,0,56,0,153,0,56,0,169,0,56,0,185,0,56,0,201,0,56,0, + 217,0,56,0,13,93,0,186,0,17,0,3,0,3,43,184,0,17,16,186,0,10,0,24,0,3,43,184,0,10,16,186,0,32,0,50,0,3,43,184, + 0,32,16,186,0,44,0,59,0,3,43,184,0,44,16,186,0,53,0,38,0,3,43,184,0,53,16,48,49,1,16,0,33,32,0,17,52,18,36,51, + 50,4,18,5,16,0,33,32,0,17,52,2,36,35,34,4,2,1,53,30,1,51,50,54,55,54,6,35,34,38,53,52,54,51,50,22,21,20,2,35, + 34,38,19,50,54,53,52,38,35,34,6,21,20,22,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,250,87,1,143,1,28,1,28, + 1,143,182,254,184,173,173,254,184,182,1,144,85,97,46,119,127,5,10,128,79,159,186,194,160,185,191,233,200,53,107,217,78,91,91,78,78,92,92,2, + 234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254,228,254,112,1,144,1,28,179,1,71,177,177,254,185,253,139,156,36,21,147,79,13, + 60,175,148,145,180,253,232,218,254,246,19,1,180,98,91,91,98,98,91,91,98,0,0,0,0,5,0,152,255,236,6,148,5,232,0,13,0,27,0,38, + 0,50,0,62,1,155,186,0,14,0,6,0,3,43,184,0,14,16,186,0,35,0,29,0,3,43,184,0,35,16,186,0,42,0,60,0,3,43,184,0, + 42,16,186,0,54,0,48,0,3,43,184,0,54,16,186,0,0,0,20,0,3,43,184,0,0,16,65,27,0,22,0,14,0,38,0,14,0,54,0,14, + 0,70,0,14,0,86,0,14,0,102,0,14,0,118,0,14,0,134,0,14,0,150,0,14,0,166,0,14,0,182,0,14,0,198,0,14,0,214,0,14, + 0,13,93,65,5,0,229,0,14,0,245,0,14,0,2,93,65,5,0,234,0,20,0,250,0,20,0,2,93,65,27,0,25,0,20,0,41,0,20,0, + 57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0,169,0,20,0,185,0,20,0,201,0,20,0, + 217,0,20,0,13,93,65,5,0,234,0,48,0,250,0,48,0,2,93,65,27,0,25,0,48,0,41,0,48,0,57,0,48,0,73,0,48,0,89,0, + 48,0,105,0,48,0,121,0,48,0,137,0,48,0,153,0,48,0,169,0,48,0,185,0,48,0,201,0,48,0,217,0,48,0,13,93,65,5,0,234, + 0,60,0,250,0,60,0,2,93,65,27,0,25,0,60,0,41,0,60,0,57,0,60,0,73,0,60,0,89,0,60,0,105,0,60,0,121,0,60,0, + 137,0,60,0,153,0,60,0,169,0,60,0,185,0,60,0,201,0,60,0,217,0,60,0,13,93,0,186,0,17,0,3,0,3,43,184,0,17,16,186, + 0,10,0,24,0,3,43,184,0,10,16,186,0,45,0,57,0,3,43,184,0,45,16,186,0,36,0,37,0,3,43,184,0,36,16,186,0,51,0,39, + 0,3,43,184,0,51,16,184,0,36,16,184,0,28,208,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,5,16,0,33,32,0,17,52,2, + 36,35,34,4,2,19,51,17,7,53,55,51,17,51,21,33,1,34,6,21,20,22,51,50,54,53,52,38,39,50,22,21,20,6,35,34,38,53,52,54, + 6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,250,87,1,143,1,28,1,28,1,143,182,254,184,173,173,254,184,182,205,158,172,188, + 117,159,254,62,3,4,64,69,69,64,63,70,70,63,130,136,136,130,131,136,136,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,200,254, + 228,254,112,1,144,1,28,179,1,71,177,177,254,185,254,62,2,62,39,137,42,253,54,128,2,222,151,163,162,151,151,162,163,151,123,228,209,208,228,228, + 208,209,228,0,0,1,255,236,1,240,4,229,2,156,0,3,0,0,3,53,33,21,20,4,249,1,240,172,172,0,0,0,0,1,255,236,1,154,4,229, + 2,242,0,3,0,0,3,17,33,17,20,4,249,1,154,1,88,254,168,0,0,1,2,24,253,150,2,184,7,200,0,3,0,0,1,17,51,17,2,24, + 160,253,150,10,50,245,206,0,0,1,1,200,253,150,3,8,7,200,0,3,0,0,1,17,33,17,1,200,1,64,253,150,10,50,245,206,0,3,255,236, + 1,240,4,229,2,156,0,3,0,7,0,11,0,0,1,53,33,21,33,53,33,21,33,53,33,21,3,177,1,52,252,239,1,41,252,239,1,52,1,240, + 172,172,172,172,172,172,0,0,0,3,255,236,1,154,4,229,2,242,0,3,0,7,0,11,0,0,1,17,33,17,33,17,33,17,33,17,33,17,3,177, + 1,52,252,239,1,41,252,239,1,52,1,154,1,88,254,168,1,88,254,168,1,88,254,168,0,3,2,24,253,150,2,184,7,200,0,3,0,7,0,11, + 0,0,1,17,51,17,3,17,51,17,3,17,51,17,2,24,160,160,160,160,160,253,150,3,12,252,244,3,192,2,178,253,78,3,102,3,12,252,244,0, + 0,3,1,200,253,150,3,8,7,200,0,3,0,7,0,11,0,0,1,17,33,17,1,17,33,17,1,17,33,17,1,200,1,64,254,192,1,64,254,192, + 1,64,253,150,3,12,252,244,3,192,2,178,253,78,3,102,3,12,252,244,0,4,255,235,1,240,4,229,2,156,0,3,0,7,0,11,0,15,0,0, + 3,53,51,21,51,53,51,21,51,53,51,21,51,53,51,21,21,188,180,179,180,178,180,189,1,240,172,172,172,172,172,172,172,172,0,0,0,4,255,236, + 1,154,4,230,2,242,0,3,0,7,0,11,0,15,0,0,3,17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,20,188,180,179,180,178,180,189, + 1,154,1,88,254,168,1,88,254,168,1,88,254,168,1,88,254,168,0,0,0,4,2,24,253,150,2,184,7,200,0,3,0,7,0,11,0,15,0,0, + 1,17,51,17,3,17,51,17,3,17,51,17,3,17,51,17,2,24,160,160,160,160,160,160,160,5,150,2,50,253,206,248,0,2,50,253,206,5,115,1, + 217,254,39,253,115,1,217,254,39,0,0,0,0,4,1,200,253,150,3,8,7,200,0,3,0,7,0,11,0,15,0,0,1,17,33,17,1,17,33,17, + 1,17,33,17,1,17,33,17,1,200,1,64,254,192,1,64,254,192,1,64,254,192,1,64,5,150,2,50,253,206,248,0,2,50,253,206,5,115,1,217, + 254,39,253,115,1,217,254,39,0,1,2,24,253,150,4,229,2,156,0,5,0,0,1,17,33,21,33,17,2,24,2,205,253,211,253,150,5,6,172,251, + 166,0,0,0,0,1,2,24,253,150,4,229,2,242,0,5,0,0,1,17,33,17,33,17,2,24,2,205,253,211,253,150,5,92,254,168,251,252,0,0, + 0,1,1,200,253,150,4,229,2,156,0,5,0,0,1,17,33,21,33,17,1,200,3,29,254,35,253,150,5,6,172,251,166,0,0,0,0,1,1,200, + 253,150,4,229,2,242,0,5,0,0,1,17,33,17,33,17,1,200,3,29,254,35,253,150,5,92,254,168,251,252,0,0,0,1,255,236,253,150,2,184, + 2,156,0,5,0,0,1,17,33,53,33,17,2,24,253,212,2,204,253,150,4,90,172,250,250,0,0,0,0,1,255,236,253,150,2,184,2,242,0,5, + 0,0,1,17,33,17,33,17,2,24,253,212,2,204,253,150,4,4,1,88,250,164,0,0,0,1,255,236,253,150,3,8,2,156,0,5,0,0,1,17, + 33,53,33,17,1,200,254,36,3,28,253,150,4,90,172,250,250,0,0,0,0,1,255,236,253,150,3,8,2,242,0,5,0,0,1,17,33,17,33,17, + 1,200,254,36,3,28,253,150,4,4,1,88,250,164,0,0,0,1,2,24,1,240,4,229,7,200,0,5,0,0,1,17,51,17,33,21,2,24,160,2, + 45,1,240,5,216,250,212,172,0,1,2,24,1,154,4,229,7,200,0,5,0,0,1,17,51,17,33,17,2,24,160,2,45,1,154,6,46,251,42,254, + 168,0,0,0,0,1,1,200,1,240,4,229,7,200,0,5,0,0,1,17,33,17,33,21,1,200,1,64,1,221,1,240,5,216,250,212,172,0,0,0, + 0,1,1,200,1,154,4,229,7,200,0,5,0,0,1,17,33,17,33,17,1,200,1,64,1,221,1,154,6,46,251,42,254,168,0,0,0,1,255,236, + 1,240,2,184,7,200,0,5,0,0,3,53,33,17,51,17,20,2,44,160,1,240,172,5,44,250,40,0,0,1,255,236,1,154,2,184,7,200,0,5, + 0,0,3,17,33,17,51,17,20,2,44,160,1,154,1,88,4,214,249,210,0,1,255,236,1,240,3,8,7,200,0,5,0,0,3,53,33,17,33,17, + 20,1,220,1,64,1,240,172,5,44,250,40,0,1,255,236,1,154,3,8,7,200,0,5,0,0,3,17,33,17,33,17,20,1,220,1,64,1,154,1, + 88,4,214,249,210,0,0,0,0,1,2,24,253,150,4,229,7,200,0,7,0,0,1,17,51,17,33,21,33,17,2,24,160,2,45,253,211,253,150,10, + 50,250,212,172,251,166,0,0,0,1,2,24,253,150,4,229,7,200,0,7,0,0,1,17,51,17,33,17,33,17,2,24,160,2,45,253,211,253,150,10, + 50,251,42,254,168,251,252,0,0,1,1,200,253,150,4,229,7,200,0,9,0,0,1,17,35,17,33,17,33,21,33,17,2,24,80,1,64,1,221,253, + 211,253,150,4,90,5,216,250,212,172,251,166,0,1,1,200,253,150,4,229,7,200,0,9,0,0,1,17,51,17,51,17,33,21,33,17,1,200,80,160, + 2,45,254,35,253,150,5,6,5,44,250,212,172,251,166,0,0,1,1,200,253,150,4,229,7,200,0,7,0,0,1,17,33,17,33,21,33,17,1,200, + 1,64,1,221,254,35,253,150,10,50,250,212,172,251,166,0,0,1,1,200,253,150,4,229,7,200,0,9,0,0,1,17,35,17,33,17,33,17,33,17, + 2,24,80,1,64,1,221,253,211,253,150,4,4,6,46,251,42,254,168,251,252,0,0,0,0,1,1,200,253,150,4,229,7,200,0,9,0,0,1,17, + 51,17,51,17,33,17,33,17,1,200,80,160,2,45,254,35,253,150,5,92,4,214,251,42,254,168,251,252,0,1,1,200,253,150,4,229,7,200,0,7, + 0,0,1,17,33,17,33,17,33,17,1,200,1,64,1,221,254,35,253,150,10,50,251,42,254,168,251,252,0,1,255,236,253,150,2,184,7,200,0,7, + 0,0,1,17,33,53,33,17,51,17,2,24,253,212,2,44,160,253,150,4,90,172,5,44,245,206,0,0,0,1,255,236,253,150,2,184,7,200,0,7, + 0,0,1,17,33,17,33,17,51,17,2,24,253,212,2,44,160,253,150,4,4,1,88,4,214,245,206,0,0,1,255,236,253,150,3,8,7,200,0,9, + 0,0,1,17,33,53,33,17,33,17,35,17,2,24,253,212,1,220,1,64,80,253,150,4,90,172,5,44,250,40,251,166,0,1,255,236,253,150,3,8, + 7,200,0,9,0,0,1,17,33,53,33,17,51,17,51,17,1,200,254,36,2,44,160,80,253,150,4,90,172,5,44,250,212,250,250,0,0,1,255,236, + 253,150,3,8,7,200,0,7,0,0,1,17,33,53,33,17,33,17,1,200,254,36,1,220,1,64,253,150,4,90,172,5,44,245,206,0,0,1,255,236, + 253,150,3,8,7,200,0,9,0,0,1,17,33,17,33,17,33,17,35,17,2,24,253,212,1,220,1,64,80,253,150,4,4,1,88,4,214,249,210,251, + 252,0,0,0,0,1,255,236,253,150,3,8,7,200,0,9,0,0,1,17,33,17,33,17,51,17,51,17,1,200,254,36,2,44,160,80,253,150,4,4, + 1,88,4,214,251,42,250,164,0,1,255,236,253,150,3,8,7,200,0,7,0,0,1,17,33,17,33,17,33,17,1,200,254,36,1,220,1,64,253,150, + 4,4,1,88,4,214,245,206,0,1,255,236,253,150,4,229,2,156,0,7,0,0,1,17,33,53,33,21,33,17,2,24,253,212,4,249,253,211,253,150, + 4,90,172,172,251,166,0,0,0,1,255,236,253,150,4,229,2,242,0,9,0,0,1,17,33,17,33,21,33,21,33,17,2,24,253,212,2,204,2,45, + 253,211,253,150,4,4,1,88,86,172,251,166,0,1,255,236,253,150,4,229,2,242,0,9,0,0,1,17,33,53,33,53,33,17,33,17,2,24,253,212, + 2,44,2,205,253,211,253,150,4,90,172,86,254,168,251,252,0,1,255,236,253,150,4,229,2,242,0,7,0,0,1,17,33,17,33,17,33,17,2,24, + 253,212,4,249,253,211,253,150,4,4,1,88,254,168,251,252,0,1,255,236,253,150,4,229,2,156,0,7,0,0,1,17,33,53,33,21,33,17,1,200, + 254,36,4,249,254,35,253,150,4,90,172,172,251,166,0,0,0,1,255,236,253,150,4,229,2,242,0,9,0,0,1,17,33,17,33,21,33,21,33,17, + 1,200,254,36,3,28,1,221,254,35,253,150,4,4,1,88,86,172,251,166,0,1,255,236,253,150,4,229,2,242,0,9,0,0,1,17,33,53,33,53, + 33,17,33,17,1,200,254,36,1,220,3,29,254,35,253,150,4,90,172,86,254,168,251,252,0,1,255,236,253,150,4,229,2,242,0,7,0,0,1,17, + 33,17,33,17,33,17,1,200,254,36,4,249,254,35,253,150,4,4,1,88,254,168,251,252,0,1,255,236,1,240,4,229,7,200,0,7,0,0,3,53, + 33,17,51,17,33,21,20,2,44,160,2,45,1,240,172,5,44,250,212,172,0,1,255,236,1,154,4,229,7,200,0,9,0,0,3,17,33,17,51,17, + 33,21,33,21,20,2,44,160,2,45,253,211,1,154,1,88,4,214,250,212,172,86,0,0,0,1,255,236,1,154,4,229,7,200,0,9,0,0,3,53, + 33,17,51,17,33,17,33,53,20,2,44,160,2,45,253,51,1,240,172,5,44,251,42,254,168,86,0,0,0,1,255,236,1,154,4,229,7,200,0,7, + 0,0,3,17,33,17,51,17,33,17,20,2,44,160,2,45,1,154,1,88,4,214,251,42,254,168,0,0,0,1,255,236,1,240,4,229,7,200,0,7, + 0,0,3,53,33,17,33,17,33,21,20,1,220,1,64,1,221,1,240,172,5,44,250,212,172,0,0,0,0,1,255,236,1,154,4,229,7,200,0,9, + 0,0,3,17,33,17,33,17,33,21,33,21,20,1,220,1,64,1,221,254,35,1,154,1,88,4,214,250,212,172,86,0,0,1,255,236,1,154,4,229, + 7,200,0,9,0,0,3,53,33,17,33,17,33,17,33,53,20,1,220,1,64,1,221,252,227,1,240,172,5,44,251,42,254,168,86,0,0,1,255,236, + 1,154,4,229,7,200,0,7,0,0,3,17,33,17,33,17,33,17,20,1,220,1,64,1,221,1,154,1,88,4,214,251,42,254,168,0,0,1,255,236, + 253,150,4,229,7,200,0,11,0,0,1,17,35,17,33,53,33,17,51,17,33,21,2,184,160,253,212,2,44,160,2,45,1,240,251,166,4,90,172,5, + 44,250,212,172,0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17,33,17,33,17,51,17,33,21,33,17,2,24,253,212,2,44,160,2,45,253, + 211,253,150,4,4,1,88,4,214,250,212,172,251,166,0,0,0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17,33,53,33,17,51,17,33,17, + 33,17,2,24,253,212,2,44,160,2,45,253,211,253,150,4,90,172,5,44,251,42,254,168,251,252,0,0,0,1,255,236,253,150,4,229,7,200,0,11, + 0,0,1,17,33,17,33,17,51,17,33,17,33,17,2,24,253,212,2,44,160,2,45,253,211,253,150,4,4,1,88,4,214,251,42,254,168,251,252,0, + 0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17,33,53,33,17,33,17,33,21,33,17,2,24,253,212,1,220,1,64,1,221,253,211,253,150, + 4,90,172,5,44,250,212,172,251,166,0,0,0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17,33,53,33,17,51,17,33,21,33,17,1,200, + 254,36,2,44,160,2,45,254,35,253,150,4,90,172,5,44,250,212,172,251,166,0,0,0,0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17, + 33,53,33,17,33,17,33,21,33,17,1,200,254,36,1,220,1,64,1,221,254,35,253,150,4,90,172,5,44,250,212,172,251,166,0,0,0,1,255,236, + 253,150,4,229,7,200,0,13,0,0,1,17,33,17,33,17,33,17,33,21,33,21,35,17,2,24,253,212,1,220,1,64,1,221,254,35,80,253,150,4, + 4,1,88,4,214,250,212,172,86,251,252,0,0,1,255,236,253,150,4,229,7,200,0,13,0,0,1,17,35,53,33,53,33,17,33,17,33,17,33,17, + 2,24,80,254,36,1,220,1,64,1,221,253,211,253,150,4,4,86,172,5,44,251,42,254,168,251,252,0,0,1,255,236,253,150,4,229,7,200,0,13, + 0,0,1,17,33,17,33,17,51,17,51,21,33,21,33,17,1,200,254,36,2,44,160,80,1,221,254,35,253,150,4,4,1,88,4,214,251,42,86,172, + 251,166,0,0,0,1,255,236,253,150,4,229,7,200,0,13,0,0,1,17,33,53,33,53,51,17,51,17,33,17,33,17,1,200,254,36,1,220,80,160, + 2,45,254,35,253,150,4,90,172,86,4,214,251,42,254,168,251,252,0,0,0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17,33,17,33,17, + 33,17,33,17,33,17,2,24,253,212,1,220,1,64,1,221,253,211,253,150,4,4,1,88,4,214,251,42,254,168,251,252,0,1,255,236,253,150,4,229, + 7,200,0,11,0,0,1,17,33,17,33,17,51,17,33,17,33,17,1,200,254,36,2,44,160,2,45,254,35,253,150,4,4,1,88,4,214,251,42,254, + 168,251,252,0,0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17,33,17,33,17,33,17,33,21,33,17,1,200,254,36,1,220,1,64,1,221, + 254,35,253,150,4,4,1,88,4,214,250,212,172,251,166,0,0,1,255,236,253,150,4,229,7,200,0,11,0,0,1,17,33,53,33,17,33,17,33,17, + 33,17,1,200,254,36,1,220,1,64,1,221,254,35,253,150,4,90,172,5,44,251,42,254,168,251,252,0,0,1,255,236,253,150,4,229,7,200,0,11, + 0,0,1,17,33,17,33,17,33,17,33,17,33,17,1,200,254,36,1,220,1,64,1,221,254,35,253,150,4,4,1,88,4,214,251,42,254,168,251,252, + 0,2,255,236,1,240,4,229,2,156,0,3,0,7,0,0,3,53,33,21,51,53,33,21,20,2,44,160,2,45,1,240,172,172,172,172,0,2,255,236, + 1,154,4,229,2,242,0,3,0,7,0,0,1,17,33,17,33,17,33,17,2,184,2,45,251,7,2,44,1,154,1,88,254,168,1,88,254,168,0,0, + 0,2,2,24,253,150,2,184,7,200,0,3,0,7,0,0,1,17,51,17,3,17,51,17,2,24,160,160,160,2,242,4,214,251,42,250,164,4,4,251, + 252,0,0,0,0,2,1,200,253,150,3,8,7,200,0,3,0,7,0,0,1,17,33,17,1,17,33,17,1,200,1,64,254,192,1,64,2,242,4,214, + 251,42,250,164,4,4,251,252,0,2,255,236,1,68,4,229,3,72,0,3,0,7,0,0,3,53,33,21,1,53,33,21,20,4,249,251,7,4,249,2, + 156,172,172,254,168,172,172,0,0,2,1,120,253,150,3,88,7,200,0,3,0,7,0,0,1,17,51,17,51,17,51,17,1,120,160,160,160,253,150,10, + 50,245,206,10,50,245,206,0,0,1,2,24,253,150,4,229,3,72,0,9,0,0,1,17,33,21,33,21,33,21,33,17,2,24,2,205,253,211,2,45, + 253,211,253,150,5,178,172,172,172,252,82,0,0,1,1,120,253,150,4,229,2,156,0,9,0,0,1,17,33,21,33,17,35,17,35,17,1,120,3,109, + 254,115,160,160,253,150,5,6,172,251,166,4,90,251,166,0,0,2,1,120,253,150,4,229,3,72,0,5,0,11,0,0,1,17,33,21,33,17,51,17, + 33,21,33,17,1,120,3,109,253,51,160,2,45,254,115,253,150,5,178,172,250,250,4,90,172,252,82,0,0,1,255,236,253,150,2,184,3,72,0,9, + 0,0,1,17,33,53,33,53,33,53,33,17,2,24,253,212,2,44,253,212,2,204,253,150,3,174,172,172,172,250,78,0,0,1,255,236,253,150,3,88, + 2,156,0,9,0,0,3,53,33,17,35,17,35,17,35,17,20,3,108,160,160,160,1,240,172,250,250,4,90,251,166,4,90,0,0,0,0,2,255,236, + 253,150,3,88,3,72,0,5,0,11,0,0,1,17,33,53,33,17,33,17,33,53,33,17,2,184,253,52,3,108,254,32,254,116,2,44,253,150,5,6, + 172,250,78,3,174,172,251,166,0,1,2,24,1,68,4,229,7,200,0,9,0,0,1,17,51,17,33,21,33,21,33,21,2,24,160,2,45,253,211,2, + 45,1,68,6,132,251,128,172,172,172,0,0,0,1,1,120,1,240,4,229,7,200,0,9,0,0,1,17,51,17,51,17,51,17,33,21,1,120,160,160, + 160,1,141,1,240,5,216,250,212,5,44,250,212,172,0,0,0,2,1,120,1,68,4,229,7,200,0,5,0,11,0,0,1,17,51,17,33,21,1,17, + 51,17,33,21,2,184,160,1,141,252,147,160,2,205,2,156,5,44,251,128,172,254,168,6,132,250,40,172,0,1,255,236,1,68,2,184,7,200,0,9, + 0,0,3,53,33,53,33,53,33,17,51,17,20,2,44,253,212,2,44,160,1,68,172,172,172,4,128,249,124,0,0,0,0,1,255,236,1,240,3,88, + 7,200,0,9,0,0,3,53,33,17,51,17,51,17,51,17,20,1,140,160,160,160,1,240,172,5,44,250,212,5,44,250,40,0,0,0,0,2,255,236, + 1,68,3,88,7,200,0,5,0,11,0,0,3,53,33,17,51,17,1,53,33,17,51,17,20,1,140,160,253,212,2,204,160,2,156,172,4,128,250,212, + 254,168,172,5,216,249,124,0,0,1,2,24,253,150,4,229,7,200,0,11,0,0,1,17,51,17,33,21,33,21,33,21,33,17,2,24,160,2,45,253, + 211,2,45,253,211,253,150,10,50,251,128,172,172,172,252,82,0,2,1,120,253,150,4,229,7,200,0,3,0,11,0,0,1,17,51,17,51,17,51,17, + 33,21,33,17,1,120,160,160,160,1,141,254,115,253,150,10,50,245,206,10,50,250,212,172,251,166,0,0,0,3,1,120,253,150,4,229,7,200,0,5, + 0,9,0,15,0,0,1,17,51,17,33,21,1,17,51,17,51,17,33,21,33,17,2,184,160,1,141,252,147,160,160,2,45,254,115,2,156,5,44,251, + 128,172,250,250,10,50,245,206,4,90,172,252,82,0,0,0,0,1,255,236,253,150,2,184,7,200,0,11,0,0,1,17,33,53,33,53,33,53,33,17, + 51,17,2,24,253,212,2,44,253,212,2,44,160,253,150,3,174,172,172,172,4,128,245,206,0,2,255,236,253,150,3,88,7,200,0,7,0,11,0,0, + 1,17,33,53,33,17,51,17,51,17,51,17,1,120,254,116,1,140,160,160,160,253,150,4,90,172,5,44,245,206,10,50,245,206,0,0,0,3,255,236, + 253,150,3,88,7,200,0,5,0,11,0,15,0,0,3,53,33,17,51,17,3,17,33,53,33,17,51,17,51,17,20,1,140,160,160,254,116,2,44,160, + 160,2,156,172,4,128,250,212,250,250,3,174,172,251,166,10,50,245,206,0,0,2,255,236,253,150,4,229,3,72,0,7,0,11,0,0,1,17,33,53, + 33,21,33,17,1,53,33,21,2,24,253,212,4,249,253,211,253,52,4,249,253,150,3,174,172,172,252,82,5,6,172,172,0,1,255,236,253,150,4,229, + 2,156,0,11,0,0,3,53,33,21,33,17,35,17,35,17,35,17,20,4,249,254,115,160,160,160,1,240,172,172,251,166,4,90,251,166,4,90,0,0, + 0,3,255,236,253,150,4,229,3,72,0,3,0,9,0,15,0,0,3,53,33,21,1,17,33,53,33,17,51,17,33,21,33,17,20,4,249,252,147,254, + 116,2,44,160,2,45,254,115,2,156,172,172,250,250,3,174,172,251,166,4,90,172,252,82,0,2,255,236,1,68,4,229,7,200,0,3,0,11,0,0, + 3,53,33,21,1,53,33,17,51,17,33,21,20,4,249,251,7,2,44,160,2,45,1,68,172,172,1,88,172,4,128,251,128,172,0,0,0,1,255,236, + 1,240,4,229,7,200,0,11,0,0,3,53,33,17,51,17,51,17,51,17,33,21,20,1,140,160,160,160,1,141,1,240,172,5,44,250,212,5,44,250, + 212,172,0,0,0,3,255,236,1,68,4,229,7,200,0,3,0,9,0,15,0,0,3,53,33,21,1,53,33,17,51,17,51,17,51,17,33,21,20,4, + 249,251,7,1,140,160,160,160,1,141,1,68,172,172,1,88,172,4,128,250,212,5,44,251,128,172,0,0,0,1,255,236,253,150,4,229,7,200,0,19, + 0,0,1,17,33,53,33,53,33,53,33,17,51,17,33,21,33,21,33,21,33,17,2,24,253,212,2,44,253,212,2,44,160,2,45,253,211,2,45,253, + 211,253,150,3,174,172,172,172,4,128,251,128,172,172,172,252,82,0,0,0,0,1,255,236,253,150,4,229,7,200,0,19,0,0,3,53,33,17,51,17, + 51,17,51,17,33,21,33,17,35,17,35,17,35,17,20,1,140,160,160,160,1,141,254,115,160,160,160,1,240,172,5,44,250,212,5,44,250,212,172,251, + 166,4,90,251,166,4,90,0,0,4,255,236,253,150,4,229,7,200,0,5,0,11,0,17,0,23,0,0,1,17,33,21,33,17,33,17,33,53,33,17, + 1,53,33,17,51,17,51,17,51,17,33,21,2,184,2,45,254,115,254,32,254,116,2,44,253,212,1,140,160,160,160,1,141,253,150,4,90,172,252,82, + 3,174,172,251,166,5,6,172,4,128,250,212,5,44,251,128,172,0,0,0,0,1,2,24,253,150,4,229,2,156,0,12,0,0,1,17,52,55,54,51, + 33,21,33,34,6,21,17,2,24,81,91,168,1,121,254,135,89,91,253,150,3,96,161,127,134,172,126,124,252,160,0,0,0,1,255,236,253,150,2,184, + 2,156,0,13,0,0,1,17,52,39,38,35,33,53,33,50,23,22,21,17,2,24,46,45,89,254,136,1,120,168,91,81,253,150,3,96,126,61,63,172, + 134,120,168,252,160,0,0,0,0,1,255,236,1,240,2,184,7,200,0,12,0,0,3,53,33,50,54,53,17,51,17,20,7,6,35,20,1,120,89,91, + 160,81,91,168,1,240,172,126,124,4,50,251,206,168,120,134,0,1,2,24,1,240,4,229,7,200,0,12,0,0,1,33,34,39,38,53,17,51,17,20, + 22,51,33,4,229,254,135,168,91,81,160,91,89,1,121,1,240,134,120,168,4,50,251,206,124,126,0,0,0,1,255,147,253,150,5,62,7,200,0,3, + 0,0,3,1,51,1,109,4,249,178,251,7,253,150,10,50,245,206,0,0,0,1,255,147,253,150,5,62,7,200,0,3,0,0,1,35,1,51,5,62, + 178,251,7,178,253,150,10,50,0,1,255,147,253,150,5,62,7,200,0,11,0,0,1,35,9,1,35,9,1,51,9,1,51,1,5,62,178,253,220,253, + 221,178,2,125,253,131,178,2,35,2,36,178,253,132,253,150,4,99,251,157,5,25,5,25,251,157,4,99,250,231,0,0,0,1,255,236,1,240,2,124, + 2,156,0,3,0,0,3,53,33,21,20,2,144,1,240,172,172,0,0,0,0,1,2,24,2,70,2,184,7,200,0,3,0,0,1,17,51,17,2,24, + 160,2,70,5,130,250,126,0,0,1,2,124,1,240,4,229,2,156,0,3,0,0,1,53,33,21,2,124,2,105,1,240,172,172,0,0,0,1,2,24, + 253,150,2,184,2,70,0,3,0,0,1,17,51,17,2,24,160,253,150,4,176,251,80,0,0,1,255,236,1,154,2,124,2,242,0,3,0,0,3,17, + 33,17,20,2,144,1,154,1,88,254,168,0,0,1,1,200,2,70,3,8,7,200,0,3,0,0,1,17,33,17,1,200,1,64,2,70,5,130,250,126, + 0,1,2,124,1,154,4,229,2,242,0,3,0,0,1,17,33,17,2,124,2,105,1,154,1,88,254,168,0,1,1,200,253,150,3,8,2,70,0,3, + 0,0,1,17,33,17,1,200,1,64,253,150,4,176,251,80,0,1,255,236,1,154,4,229,2,242,0,7,0,0,3,53,33,53,33,17,33,53,20,2, + 144,2,105,253,151,1,240,172,86,254,168,86,0,1,1,200,253,150,3,8,7,200,0,7,0,0,1,17,51,17,51,17,51,17,1,200,80,160,80,253, + 150,4,176,5,130,250,126,251,80,0,0,0,0,1,255,236,1,154,4,229,2,242,0,7,0,0,3,17,33,21,33,21,33,21,20,2,144,2,105,253, + 151,1,154,1,88,86,172,86,0,1,1,200,253,150,3,8,7,200,0,7,0,0,1,17,35,17,33,17,35,17,2,24,80,1,64,80,253,150,4,176, + 5,130,250,126,251,80,0,0,255,255,255,236,2,20,6,59,6,40,16,7,14,86,0,0,4,20,0,0,0,1,255,236,254,0,6,59,255,5,0,3, + 0,0,3,17,33,17,20,6,79,254,0,1,5,254,251,0,0,1,255,236,254,0,6,59,255,246,0,3,0,0,3,17,33,17,20,6,79,254,0,1, + 246,254,10,0,0,1,255,236,254,0,6,59,1,15,0,3,0,0,3,17,33,17,20,6,79,254,0,3,15,252,241,0,0,1,255,236,254,0,6,59, + 2,20,0,3,0,0,3,17,33,17,20,6,79,254,0,4,20,251,236,0,0,1,255,236,254,0,6,59,3,25,0,3,0,0,3,17,33,17,20,6, + 79,254,0,5,25,250,231,0,0,1,255,236,254,0,6,59,4,30,0,3,0,0,3,17,33,17,20,6,79,254,0,6,30,249,226,0,0,1,255,236, + 254,0,6,59,5,35,0,3,0,0,3,17,33,17,20,6,79,254,0,7,35,248,221,0,0,1,255,236,254,0,6,59,6,40,0,3,0,0,3,17, + 33,17,20,6,79,254,0,8,40,247,216,0,0,1,255,236,254,0,5,113,6,40,0,3,0,0,3,17,33,17,20,5,133,254,0,8,40,247,216,0, + 0,1,255,236,254,0,4,167,6,40,0,3,0,0,3,17,33,17,20,4,187,254,0,8,40,247,216,0,0,1,255,236,254,0,3,221,6,40,0,3, + 0,0,3,17,33,17,20,3,241,254,0,8,40,247,216,0,0,1,255,236,254,0,3,19,6,40,0,3,0,0,3,17,33,17,20,3,39,254,0,8, + 40,247,216,0,0,1,255,236,254,0,2,73,6,40,0,3,0,0,3,17,33,17,20,2,93,254,0,8,40,247,216,0,0,1,255,236,254,0,1,127, + 6,40,0,3,0,0,3,17,33,17,20,1,147,254,0,8,40,247,216,0,0,1,255,236,254,0,0,181,6,40,0,3,0,0,3,17,51,17,20,201, + 254,0,8,40,247,216,0,0,255,255,3,19,254,0,6,58,6,40,16,7,14,94,3,39,0,0,0,0,0,12,255,236,254,0,5,113,6,40,0,3, + 0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,0,1,17,51,17,33,17,51,17,19,17,51,17,33,17,51,17, + 1,17,51,17,33,17,51,17,19,17,51,17,33,17,51,17,1,17,51,17,33,17,51,17,19,17,51,17,33,17,51,17,4,167,202,252,14,202,202,202, + 252,15,201,3,242,202,252,14,202,202,202,252,15,201,3,242,202,252,14,202,202,202,252,15,201,254,0,1,5,254,251,1,5,254,251,1,109,1,5,254, + 251,1,5,254,251,1,110,1,5,254,251,1,5,254,251,1,109,1,5,254,251,1,5,254,251,1,110,1,5,254,251,1,5,254,251,1,109,1,5,254, + 251,1,5,254,251,0,0,0,0,32,255,236,254,0,6,52,6,40,0,7,0,15,0,23,0,31,0,39,0,47,0,55,0,63,0,71,0,79,0,87, + 0,95,0,103,0,111,0,119,0,127,0,135,0,143,0,151,0,159,0,167,0,175,0,183,0,191,0,199,0,207,0,215,0,223,0,231,0,239,0,247, + 0,255,0,0,19,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,1,7,35,39, + 53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,1,7,35,39,53,55,51,23,5,7,35,39, + 53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,1,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39, + 53,55,51,23,5,7,35,39,53,55,51,23,1,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39, + 53,55,51,23,1,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,1,7,35,39, + 53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,1,7,35,39,53,55,51,23,5,7,35,39, + 53,55,51,23,5,7,35,39,53,55,51,23,5,7,35,39,53,55,51,23,181,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5, + 5,191,5,1,146,5,191,5,5,191,5,252,19,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5, + 5,191,5,250,129,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,252,19,5,191,5, + 5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,250,129,5,191,5,5,191,5,1,146,5,191,5, + 5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,252,19,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5, + 5,191,5,1,146,5,191,5,5,191,5,250,129,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5, + 5,191,5,252,19,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,1,146,5,191,5,5,191,5,5,40,5,5,251, + 5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,254,0,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251, + 5,5,251,5,5,254,0,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,254,0,5,5,251,5,5,251,5,5, + 251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,254,0,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5, + 254,0,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,254,0,5,5,251,5,5,251,5,5,251,5,5,251,5, + 5,251,5,5,251,5,5,251,5,5,254,0,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,251,5,5,0,0,7,255,236, + 254,0,6,59,6,40,0,25,0,29,0,33,0,37,0,41,0,45,0,49,0,0,3,17,51,17,35,17,51,17,35,17,51,17,33,17,51,17,33,17, + 35,17,35,17,33,17,35,25,1,51,17,35,1,51,17,35,1,51,17,35,1,51,17,35,1,51,17,35,1,51,17,35,20,201,201,201,201,201,2,94, + 202,2,94,202,202,253,162,202,202,202,3,40,202,202,254,108,202,202,254,108,202,202,3,40,202,202,254,108,202,202,254,0,1,109,1,5,1,214,1,5, + 1,214,1,5,254,251,1,5,247,216,1,5,254,251,1,5,254,251,5,182,1,5,254,251,1,5,253,141,1,5,253,142,1,5,254,251,1,5,253,141, + 1,5,0,0,255,255,255,236,5,35,6,59,6,40,16,7,14,83,0,0,7,35,0,0,255,255,5,113,254,0,6,58,6,40,16,7,14,97,5,133, + 0,0,0,0,0,1,255,236,254,0,3,20,2,20,0,3,0,0,3,17,33,17,20,3,40,254,0,4,20,251,236,0,0,1,3,19,254,0,6,59, + 2,20,0,3,0,0,1,17,33,17,3,19,3,40,254,0,4,20,251,236,0,1,255,236,2,20,3,20,6,40,0,3,0,0,3,17,33,17,20,3, + 40,2,20,4,20,251,236,0,0,1,255,236,254,0,6,59,6,40,0,5,0,0,1,33,17,33,17,33,6,59,249,177,3,40,3,39,254,0,8,40, + 251,236,0,0,0,1,255,236,254,0,6,59,6,40,0,7,0,0,3,17,33,17,33,17,33,17,20,3,40,3,39,252,216,2,20,4,20,251,236,251, + 236,4,20,0,0,1,255,236,254,0,6,59,6,40,0,5,0,0,1,17,33,17,33,17,6,59,252,217,252,216,6,40,251,236,251,236,8,40,0,0, + 0,1,255,236,254,0,6,59,6,40,0,5,0,0,3,33,17,33,17,33,20,6,79,252,216,252,217,6,40,247,216,4,20,0,0,0,0,1,3,19, + 2,20,6,59,6,40,0,3,0,0,1,17,33,17,3,19,3,40,2,20,4,20,251,236,0,1,255,236,254,0,6,59,6,40,0,7,0,0,3,33, + 17,33,17,33,17,33,20,3,39,3,40,252,217,252,216,2,20,4,20,251,236,251,236,0,0,1,255,236,254,0,6,59,6,40,0,5,0,0,3,17, + 33,17,33,17,20,3,39,3,40,254,0,4,20,4,20,247,216,0,0,0,0,1,0,186,255,4,6,213,5,36,0,3,0,0,23,17,33,17,186,6, + 27,252,6,32,249,224,0,0,0,2,0,186,255,4,6,213,5,36,0,3,0,7,0,0,5,33,17,33,3,17,33,17,1,44,5,55,250,201,114,6, + 27,138,5,60,250,82,6,32,249,224,0,0,0,2,0,186,255,4,6,213,5,36,0,11,0,23,0,0,37,20,51,33,50,53,17,52,35,33,34,21, + 3,17,16,41,1,32,25,1,16,41,1,32,1,44,228,3,111,228,228,252,145,228,114,1,86,3,111,1,86,254,170,252,145,254,170,90,228,228,3,116, + 228,228,252,140,3,116,1,86,254,170,252,140,254,170,0,0,255,255,0,186,255,4,6,213,5,36,16,39,14,124,1,17,0,0,16,6,14,115,0,0, + 0,6,0,186,255,4,6,213,5,36,0,3,0,7,0,11,0,15,0,19,0,23,0,0,23,17,33,17,37,33,53,33,53,33,53,33,53,33,53,33, + 53,33,53,33,53,33,53,33,186,6,27,250,87,5,55,250,201,5,55,250,201,5,55,250,201,5,55,250,201,5,55,250,201,252,6,32,249,224,114,176, + 114,178,114,176,114,178,114,176,0,6,0,186,255,4,6,213,5,36,0,3,0,7,0,11,0,15,0,19,0,23,0,0,23,17,33,17,37,51,17,35, + 1,51,17,35,1,51,17,35,1,51,17,35,1,51,17,35,186,6,27,254,225,176,176,254,220,178,178,254,222,176,176,254,220,178,178,254,222,176,176,252, + 6,32,249,224,116,5,56,250,200,5,56,250,200,5,56,250,200,5,56,250,200,5,56,0,0,26,0,186,255,4,6,213,5,36,0,3,0,7,0,11, + 0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,59,0,63,0,67,0,71,0,75,0,79,0,83,0,87,0,91, + 0,95,0,99,0,103,0,0,5,51,53,35,5,51,53,35,5,51,53,35,1,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35, + 1,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,1,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,1,51,53,35,17,51,53,35, + 17,51,53,35,17,51,53,35,1,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,17,51,53,35,1,17,33,17,2,76,178,178,1,36,176,176, + 1,34,178,178,252,154,174,174,174,174,174,174,174,174,174,174,1,32,178,178,178,178,178,178,178,178,1,36,176,176,176,176,176,176,176,176,1,34,178,178, + 178,178,178,178,178,178,1,36,173,173,173,173,173,173,173,173,173,173,251,4,6,27,136,174,174,174,174,174,3,220,174,254,46,178,254,44,176,254,44,178, + 254,46,174,3,220,174,254,46,178,254,44,176,254,44,178,2,184,174,254,46,178,254,44,176,254,44,178,2,184,174,254,46,178,254,44,176,254,44,178,2, + 184,174,254,46,178,254,44,176,254,44,178,254,46,174,254,222,6,32,249,224,0,8,0,186,255,4,6,213,5,36,0,3,0,6,0,10,0,14,0,20, + 0,24,0,28,0,31,0,0,23,17,33,17,1,21,51,3,21,1,51,1,21,1,55,1,21,1,55,53,1,51,1,53,1,51,1,53,1,51,23,53, + 186,6,27,250,87,226,226,1,132,251,253,129,3,33,251,251,228,4,190,121,251,66,162,4,28,252,223,162,2,127,254,124,162,226,252,6,32,249,224,1, + 84,226,2,127,252,254,125,4,28,252,252,223,1,5,60,127,251,66,1,127,4,189,251,228,252,3,32,253,129,252,1,131,226,226,0,0,0,8,0,186, + 255,4,6,213,5,36,0,3,0,6,0,10,0,14,0,20,0,24,0,28,0,31,0,0,23,17,33,17,37,51,53,5,51,1,53,1,23,1,53,1, + 23,1,53,35,1,53,1,35,1,53,1,35,1,53,55,35,186,6,27,254,172,226,253,129,251,1,132,251,228,251,3,33,250,201,121,4,190,121,251,66, + 4,28,251,252,223,2,127,251,254,124,226,226,252,6,32,249,224,114,226,226,1,131,252,253,129,1,3,33,252,251,228,1,4,190,127,251,67,161,4,28, + 252,224,161,2,127,254,125,161,226,0,0,0,0,26,0,186,255,4,6,213,5,36,0,4,0,9,0,14,0,18,0,23,0,28,0,32,0,36,0,40, + 0,45,0,49,0,53,0,57,0,61,0,65,0,70,0,75,0,79,0,83,0,87,0,92,0,97,0,101,0,106,0,111,0,115,0,0,1,23,55,39, + 35,17,23,55,39,7,1,23,55,39,35,1,23,55,39,3,23,55,39,7,1,23,55,39,35,1,23,55,39,1,23,55,39,1,23,55,39,1,23,55, + 53,35,1,23,55,39,1,23,55,39,1,23,55,39,1,23,55,39,1,23,55,39,1,51,55,39,7,1,23,55,53,39,1,23,55,39,1,23,55,39, + 1,23,55,39,1,23,51,55,39,1,23,55,53,39,1,23,55,39,1,23,51,55,39,5,23,51,53,39,1,17,33,17,1,44,50,124,53,121,50,126, + 126,50,1,79,126,126,53,146,254,254,126,124,126,254,50,126,126,50,2,236,126,126,53,146,254,253,126,125,125,254,181,125,125,126,254,181,126,126,126,3, + 137,125,49,121,254,253,124,126,124,254,179,124,126,124,254,181,125,124,124,254,181,124,126,124,254,179,125,125,124,255,0,122,52,124,50,4,136,126,49,50, + 254,180,126,126,126,254,181,126,124,126,254,182,126,126,126,254,179,53,147,52,126,2,187,125,50,50,254,181,126,125,126,254,181,52,147,53,126,1,31,52, + 122,50,250,137,6,27,4,51,49,124,52,253,228,50,126,126,49,1,79,126,126,52,254,255,126,124,126,252,204,49,126,125,49,2,236,126,126,52,254,253, + 125,125,126,254,181,126,125,125,254,182,126,126,126,1,236,124,49,127,254,253,124,126,124,254,180,125,126,124,254,182,124,124,124,254,181,124,126,124,254,180, + 124,125,125,254,129,52,124,49,2,237,126,50,153,49,254,180,126,126,126,254,181,126,124,126,254,181,126,126,126,254,180,52,52,126,1,30,126,49,153,49, + 254,181,125,124,126,254,181,52,52,126,126,52,127,49,254,222,6,32,249,224,0,1,0,186,0,22,4,178,4,18,0,3,0,0,55,17,33,17,186,3, + 248,22,3,252,252,4,0,0,0,2,0,186,0,22,4,178,4,18,0,3,0,7,0,0,37,33,17,33,3,17,33,17,1,44,3,20,252,236,114,3, + 248,136,3,24,252,118,3,252,252,4,0,0,0,1,0,186,0,154,6,213,3,142,0,3,0,0,37,33,17,33,6,213,249,229,6,27,154,2,244,0, + 0,2,0,186,0,154,6,213,3,142,0,3,0,7,0,0,1,17,33,17,5,33,17,33,6,99,250,201,5,169,249,229,6,27,1,12,2,16,253,240, + 114,2,244,0,0,1,0,186,255,6,3,173,5,34,0,3,0,0,23,17,33,17,186,2,243,250,6,28,249,228,0,0,0,2,0,186,255,6,3,173, + 5,34,0,3,0,7,0,0,5,33,17,33,3,17,33,17,1,44,2,15,253,241,114,2,243,136,5,56,250,86,6,28,249,228,0,0,0,1,0,6, + 0,154,6,33,3,142,0,3,0,0,37,33,1,33,4,152,251,110,1,138,4,145,154,2,244,0,0,0,0,2,0,6,0,154,6,33,3,142,0,3, + 0,7,0,0,9,1,33,1,5,33,1,33,4,98,1,16,252,83,254,239,3,228,251,110,1,138,4,145,1,12,2,16,253,240,114,2,244,0,0,0, + 0,1,0,6,255,4,6,33,5,36,0,2,0,0,23,9,1,6,3,13,3,14,252,6,32,249,224,0,0,2,0,6,255,4,6,33,5,36,0,2, + 0,5,0,0,23,33,9,3,177,4,197,253,157,252,243,3,13,3,14,138,4,202,250,196,6,32,249,224,0,1,0,6,0,22,3,254,4,18,0,2, + 0,0,55,9,1,6,1,252,1,252,22,3,252,252,4,0,0,2,0,6,0,22,3,254,4,18,0,2,0,5,0,0,55,33,9,3,177,2,162,254, + 175,254,4,1,252,1,252,136,2,166,252,232,3,252,252,4,0,1,0,6,255,4,6,33,5,36,0,2,0,0,23,17,1,6,6,27,252,6,32,252, + 240,0,0,0,0,2,0,6,255,4,6,33,5,36,0,2,0,5,0,0,23,9,1,3,17,1,120,4,197,251,59,114,6,27,82,2,102,2,102,250, + 138,6,32,252,240,0,0,0,0,1,0,6,0,22,3,254,4,18,0,2,0,0,55,17,1,6,3,248,22,3,252,254,2,0,0,0,0,2,0,6, + 0,22,3,254,4,18,0,2,0,5,0,0,55,9,1,3,17,1,120,2,162,253,94,114,3,248,193,1,83,1,83,252,175,3,252,254,2,0,0,0, + 0,1,0,6,0,22,6,33,4,18,0,2,0,0,55,17,1,6,6,27,22,3,252,254,2,0,0,0,0,2,0,6,0,22,6,33,4,18,0,2, + 0,5,0,0,55,9,1,3,17,1,120,4,140,251,116,114,6,27,193,1,83,1,83,252,175,3,252,254,2,0,0,0,0,1,0,6,255,4,6,33, + 5,36,0,2,0,0,19,33,1,6,6,27,252,242,5,36,249,224,0,0,0,2,0,6,255,4,6,33,5,36,0,2,0,5,0,0,19,9,1,37, + 33,1,177,2,98,2,99,250,144,6,27,252,242,4,178,251,54,4,202,114,249,224,0,0,0,1,0,6,0,22,3,254,4,18,0,2,0,0,19,33, + 1,6,3,248,254,4,4,18,252,4,0,0,0,2,0,6,0,22,3,254,4,18,0,2,0,5,0,0,19,9,1,37,33,1,177,1,81,1,81,252, + 179,3,248,254,4,3,160,253,90,2,166,114,252,4,0,0,0,1,0,6,255,4,6,33,5,36,0,2,0,0,19,1,17,6,6,27,2,20,3,16, + 249,224,0,0,0,2,0,6,255,4,6,33,5,36,0,2,0,5,0,0,19,1,17,9,1,17,234,4,197,250,87,6,27,2,20,253,154,4,204,253, + 154,3,16,249,224,0,0,0,0,1,0,6,0,22,3,254,4,18,0,2,0,0,19,1,17,6,3,248,2,20,1,254,252,4,0,0,0,2,0,6, + 0,22,3,254,4,18,0,2,0,5,0,0,19,1,17,9,1,17,234,2,162,252,122,3,248,2,20,254,173,2,166,254,173,1,254,252,4,0,0,0, + 0,1,0,6,0,22,6,33,4,18,0,2,0,0,19,1,17,6,6,27,2,20,1,254,252,4,0,0,0,2,0,6,0,22,6,33,4,18,0,2, + 0,5,0,0,9,1,17,9,1,17,1,35,4,140,250,87,6,27,2,20,254,173,2,166,254,173,1,254,252,4,0,0,0,1,0,6,255,4,6,33, + 5,36,0,3,0,0,19,9,2,6,3,13,3,14,252,242,2,20,3,16,252,240,252,240,0,2,0,6,255,4,6,33,5,36,0,3,0,7,0,0, + 19,9,6,158,2,117,2,118,253,138,252,243,3,13,3,14,252,242,2,20,253,136,2,120,2,120,253,136,3,16,252,240,252,240,0,0,0,3,0,6, + 255,4,6,33,5,36,0,3,0,7,0,11,0,0,9,11,1,62,1,213,1,213,254,43,253,139,2,117,2,118,253,138,252,243,3,13,3,14,252,242, + 2,20,1,215,254,41,254,41,1,215,253,136,2,120,2,120,253,136,3,16,252,240,252,240,0,3,0,112,254,255,6,139,5,41,0,13,0,27,0,41, + 0,0,36,16,55,54,51,50,23,22,16,7,6,35,34,39,0,16,5,22,51,50,55,36,16,37,38,35,34,7,0,16,37,54,51,50,23,4,16,5, + 6,35,34,39,1,130,254,126,127,128,126,254,254,126,128,127,126,254,101,1,77,165,166,167,165,1,77,254,179,165,167,166,165,254,62,1,135,195,195,196, + 195,1,135,254,121,195,196,195,195,239,2,74,146,74,74,146,253,182,146,74,74,3,54,253,2,192,96,96,192,2,254,192,96,96,251,255,3,132,226,113, + 113,226,252,124,226,113,113,0,0,2,0,6,254,35,3,238,6,117,0,3,0,7,0,34,64,17,2,6,0,8,4,6,8,6,4,3,2,1,0,6, + 5,7,8,16,212,204,23,57,49,0,16,212,204,17,57,18,57,48,9,7,1,250,254,127,1,129,1,129,254,127,1,244,254,12,254,12,5,129,252,207, + 252,199,3,57,4,37,251,219,251,211,4,45,0,2,0,112,254,255,6,139,5,41,0,13,0,27,0,0,18,16,5,22,51,50,55,36,16,37,38,35, + 34,7,0,16,37,54,51,50,23,4,16,5,6,35,34,39,229,1,77,165,166,167,165,1,77,254,179,165,167,166,165,254,62,1,135,195,195,196,195,1, + 135,254,121,195,196,195,195,3,147,253,2,192,96,96,192,2,254,192,96,96,251,255,3,132,226,113,113,226,252,124,226,113,113,0,0,0,0,8,0,114, + 255,1,6,137,5,39,0,9,0,19,0,29,0,39,0,47,0,55,0,63,0,71,0,0,37,22,23,22,23,7,38,39,38,39,5,54,55,54,55,23, + 6,7,6,7,19,38,39,38,39,55,22,23,22,23,37,6,7,6,7,39,54,55,54,55,19,22,50,55,23,6,34,39,1,54,52,39,55,22,20,7, + 1,38,34,7,39,54,50,23,1,6,20,23,7,38,52,55,1,92,43,59,46,56,49,70,57,75,53,3,218,56,46,52,50,100,59,69,57,71,156,44, + 58,46,56,48,71,57,74,54,252,38,56,46,59,43,100,49,79,57,70,237,76,154,76,38,95,192,96,3,74,16,16,110,20,20,253,161,76,154,76,39, + 96,192,95,252,184,16,16,110,20,20,143,60,49,38,32,106,40,48,61,74,117,32,38,44,65,61,78,58,48,40,4,39,60,49,38,32,106,40,48,61, + 74,117,32,38,49,60,62,69,66,48,40,250,212,22,22,110,27,27,2,95,73,160,73,39,91,202,91,3,74,22,22,110,27,27,253,161,73,160,73,39, + 91,202,91,0,0,6,0,112,254,255,6,139,5,41,0,13,0,23,0,27,0,37,0,47,0,51,0,0,54,16,37,54,51,50,23,4,16,5,6,35, + 34,39,19,17,22,23,22,23,17,6,7,6,7,6,16,23,1,17,22,51,50,55,17,38,35,34,23,17,54,55,54,55,17,38,39,38,23,17,54,16, + 112,1,135,195,195,196,195,1,135,254,121,195,196,195,195,11,23,25,65,65,65,65,25,137,171,171,1,150,44,43,45,44,44,45,43,246,65,64,26,23, + 23,26,64,227,170,82,3,132,226,113,113,226,252,124,226,113,113,4,197,251,190,15,15,37,23,4,246,23,37,15,109,177,253,220,177,4,91,250,208,7, + 7,5,48,7,36,251,10,23,37,15,16,4,64,16,15,37,162,252,124,177,2,34,0,0,0,4,0,112,254,255,6,139,5,41,0,13,0,27,0,41, + 0,55,0,0,0,16,23,22,51,50,55,54,16,39,38,35,34,7,2,16,55,54,51,50,23,22,16,7,6,35,34,39,0,16,5,22,51,50,55,36, + 16,37,38,35,34,7,0,16,37,54,51,50,23,4,16,5,6,35,34,39,2,153,114,57,57,58,57,114,114,57,58,57,57,237,176,88,87,88,88,176, + 176,88,88,87,88,254,23,1,77,165,166,167,165,1,77,254,179,165,167,166,165,254,62,1,135,195,195,196,195,1,135,254,121,195,196,195,195,2,152,254, + 248,66,33,33,66,1,8,66,33,33,254,111,1,150,101,51,51,101,254,106,101,51,51,2,175,253,2,192,96,96,192,2,254,192,96,96,251,255,3,132, + 226,113,113,226,252,124,226,113,113,0,0,0,0,1,0,112,255,4,6,139,5,32,0,23,0,19,64,7,6,18,24,25,12,0,24,16,220,212,204,49, + 0,16,212,196,48,19,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,112,105,104,182,181,210,209,181,182,104,105, + 105,104,182,181,209,210,181,182,104,105,2,18,209,182,181,105,105,105,105,181,182,209,209,182,181,105,105,105,105,181,182,0,0,2,0,112,255,4,6,139, + 5,32,0,13,0,21,0,0,18,16,18,36,51,50,4,18,16,2,4,35,34,36,5,50,55,36,16,37,38,35,112,209,1,107,210,209,1,107,209,209, + 254,149,209,210,254,149,2,60,167,165,1,77,254,179,165,167,1,65,1,162,1,107,210,210,254,149,254,94,254,149,210,210,97,96,192,2,254,192,96,0, + 0,2,0,112,255,4,6,139,5,32,0,13,0,21,0,0,18,16,18,36,51,50,4,18,16,2,4,35,34,36,1,34,7,4,16,5,22,51,112,209, + 1,107,210,209,1,107,209,209,254,149,209,210,254,149,2,60,166,165,254,179,1,77,165,166,1,65,1,162,1,107,210,210,254,149,254,94,254,149,210,210, + 4,221,96,192,253,2,192,96,0,2,0,112,255,4,6,139,5,32,0,13,0,22,0,0,18,16,18,36,51,50,4,18,16,2,4,35,34,36,1,16, + 37,38,35,34,7,4,17,112,209,1,107,210,209,1,107,209,209,254,149,209,210,254,149,4,213,254,179,165,167,166,165,254,179,1,65,1,162,1,107,210, + 210,254,149,254,94,254,149,210,210,2,62,1,127,192,96,96,192,254,129,0,0,2,0,112,255,4,6,139,5,32,0,13,0,22,0,0,18,16,18,36, + 51,50,4,18,16,2,4,35,34,36,3,16,5,22,51,50,55,36,17,112,209,1,107,210,209,1,107,209,209,254,149,209,210,254,149,92,1,77,165,166, + 167,165,1,77,1,65,1,162,1,107,210,210,254,149,254,94,254,149,210,210,2,62,254,129,192,96,96,192,1,127,0,0,0,2,0,112,255,4,6,139, + 5,32,0,11,0,24,0,0,18,16,18,36,32,4,18,16,2,4,32,36,1,34,7,4,16,5,22,51,50,55,36,17,33,112,209,1,107,1,163,1, + 107,209,209,254,149,254,93,254,149,2,60,166,165,254,179,1,77,165,166,167,165,1,77,253,103,1,65,1,162,1,107,210,210,254,149,254,94,254,149,210, + 210,4,221,96,192,253,2,192,96,96,192,1,127,0,0,0,0,2,0,112,255,4,6,139,5,32,0,11,0,17,0,0,18,16,18,36,32,4,18,16, + 2,4,32,36,1,34,7,4,17,33,112,209,1,107,1,163,1,107,209,209,254,149,254,93,254,149,2,60,166,165,254,179,2,152,1,65,1,162,1,107, + 210,210,254,149,254,94,254,149,210,210,4,221,96,192,254,129,0,1,0,112,254,255,3,125,5,41,0,7,0,0,54,16,37,54,51,17,34,39,112,1, + 135,195,195,195,195,82,3,132,226,113,249,214,113,0,0,0,0,1,0,186,254,255,3,199,5,41,0,7,0,0,0,16,5,6,35,17,50,23,3,199, + 254,121,195,195,195,195,3,214,252,124,226,113,6,42,113,0,0,2,0,186,255,236,5,154,6,40,0,10,0,14,0,0,1,20,22,50,54,53,52,38, + 35,34,6,1,17,33,17,2,1,172,250,172,171,124,126,173,254,185,4,224,2,250,125,172,172,125,124,171,171,252,118,6,60,249,196,0,0,3,0,186, + 254,0,7,9,6,40,0,13,0,27,0,31,0,0,36,16,37,54,51,50,23,4,16,5,6,35,34,39,0,16,5,22,51,50,55,36,16,37,38,35, + 34,7,1,17,33,17,1,73,1,77,165,166,167,165,1,77,254,179,165,167,166,165,254,62,1,135,195,195,196,195,1,135,254,121,195,196,195,195,254,95, + 6,79,149,2,254,192,96,96,192,253,2,192,96,96,4,1,252,124,226,113,113,226,3,132,226,113,113,249,72,8,40,247,216,0,0,0,0,2,0,186, + 2,20,7,9,6,40,0,12,0,21,0,0,19,17,33,17,35,16,37,38,35,34,7,4,17,41,1,16,37,54,51,50,23,4,186,6,79,26,254,121, + 195,196,195,195,254,121,5,166,250,207,1,77,166,165,166,166,1,77,2,20,4,20,251,236,1,194,226,113,113,226,254,62,1,126,193,96,96,193,0,0, + 0,2,0,186,254,0,7,9,2,20,0,12,0,21,0,0,19,17,51,16,5,22,51,50,55,36,17,51,17,1,33,16,5,6,35,34,39,36,186,26, + 1,135,195,195,196,195,1,135,26,250,64,5,49,254,179,166,166,165,166,254,179,254,0,4,20,254,62,226,113,113,226,1,194,251,236,4,20,254,130,193, + 96,96,193,0,0,1,0,6,2,20,3,19,5,41,0,9,0,0,19,16,37,54,51,21,34,7,4,17,6,1,135,195,195,166,165,254,179,2,20,1, + 194,226,113,118,96,192,254,129,0,1,0,6,2,20,3,19,5,41,0,9,0,0,19,50,23,4,17,35,16,37,38,35,6,195,195,1,135,117,254,179, + 165,166,5,41,113,226,254,62,1,127,192,96,0,1,0,6,254,255,3,19,2,20,0,9,0,0,19,53,50,55,36,17,51,16,5,6,6,166,165,1, + 77,117,254,121,195,254,255,118,96,192,1,127,254,62,226,113,0,1,0,6,254,255,3,19,2,20,0,9,0,0,1,34,39,36,17,51,16,5,22,51, + 3,19,195,195,254,121,117,1,77,165,166,254,255,113,226,1,194,254,129,192,96,0,0,0,0,1,0,112,2,20,6,139,5,41,0,17,0,0,19,16, + 37,54,51,50,23,4,17,35,16,37,38,35,34,7,4,17,112,1,135,195,195,196,195,1,135,117,254,179,165,167,166,165,254,179,2,20,1,194,226,113, + 113,226,254,62,1,127,192,96,96,192,254,129,0,1,0,112,254,255,6,139,2,20,0,18,0,0,19,48,51,16,5,22,51,50,55,36,17,51,16,5, + 6,35,34,39,36,112,117,1,77,165,166,167,165,1,77,117,254,121,195,196,195,195,254,121,2,20,254,129,192,96,96,192,1,127,254,62,226,113,113,226, + 0,1,0,6,255,4,6,33,5,36,0,2,0,0,23,1,17,6,6,27,252,6,32,249,224,0,0,0,0,1,0,6,255,4,6,33,5,36,0,2, + 0,0,23,17,1,6,6,27,252,6,32,249,224,0,0,0,0,1,0,6,255,4,6,33,5,36,0,2,0,0,23,17,33,6,6,27,252,6,32,0, + 0,1,0,6,255,4,6,33,5,36,0,2,0,0,19,33,17,6,6,27,5,36,249,224,0,2,1,51,1,209,3,133,4,33,0,10,0,21,0,0, + 1,20,22,50,54,53,52,38,35,34,6,7,52,54,51,50,22,21,20,6,34,38,1,110,138,200,138,137,99,101,139,59,173,126,124,171,172,250,172,2, + 250,100,138,138,100,99,137,137,99,124,171,171,124,125,172,172,0,2,0,186,255,4,6,213,5,36,0,3,0,7,0,0,23,17,33,17,37,33,17,33, + 186,6,27,252,242,2,156,253,100,252,6,32,249,224,114,5,60,0,0,0,0,2,0,186,255,4,6,213,5,36,0,3,0,7,0,0,23,17,33,17, + 37,33,17,33,186,6,27,250,87,2,155,253,101,252,6,32,249,224,114,5,60,0,0,0,0,2,0,186,255,4,6,213,5,36,0,3,0,6,0,0, + 23,17,33,17,37,33,17,186,6,27,250,87,5,55,252,6,32,249,224,114,5,60,0,0,0,2,0,186,255,4,6,213,5,36,0,3,0,6,0,0, + 23,17,33,17,37,1,33,186,6,27,250,87,5,55,250,201,252,6,32,249,224,114,5,60,0,3,0,186,255,4,6,213,5,36,0,3,0,7,0,11, + 0,0,23,17,33,17,37,33,17,33,1,33,17,33,186,6,27,253,43,2,99,253,157,253,44,2,98,253,158,252,6,32,249,224,114,5,60,250,196,5, + 60,0,0,0,0,3,0,6,255,4,6,33,5,36,0,7,0,10,0,13,0,0,0,52,54,50,22,20,6,34,1,33,9,3,2,127,87,124,86,86, + 125,253,220,4,197,253,157,252,243,3,13,3,14,1,44,124,86,86,124,86,254,160,4,202,250,196,6,32,249,224,0,0,0,2,0,6,255,4,6,33, + 5,36,0,2,0,5,0,0,5,33,9,3,3,19,2,99,253,157,252,243,3,13,3,14,138,4,202,250,196,6,32,249,224,0,0,0,0,2,0,6, + 255,4,6,33,5,36,0,2,0,5,0,0,23,33,17,9,2,177,2,98,252,243,3,13,3,14,138,4,202,250,196,6,32,249,224,0,0,2,0,112, + 254,0,8,132,6,40,0,11,0,23,0,0,18,16,1,22,32,55,0,16,1,38,32,7,0,16,1,36,32,5,0,16,1,4,32,37,241,1,197,226, + 1,196,226,1,197,254,59,226,254,60,226,253,186,2,5,1,3,2,4,1,3,2,5,253,251,254,253,253,252,254,253,4,30,251,236,254,251,131,131,1, + 5,4,20,1,5,131,131,250,157,4,168,1,42,150,150,254,214,251,88,254,214,150,150,0,0,3,0,186,255,4,6,213,5,36,0,5,0,9,0,13, + 0,0,5,33,17,33,17,33,3,17,33,17,1,33,17,33,1,44,5,55,253,157,253,44,114,6,27,250,87,2,98,253,158,138,5,60,253,41,253,41, + 6,32,249,224,3,73,2,101,0,3,0,186,255,4,6,213,5,36,0,5,0,9,0,13,0,0,1,33,17,33,17,33,3,17,33,17,37,33,17,33, + 1,44,2,212,2,99,250,201,114,6,27,250,87,2,98,253,158,2,77,253,41,5,60,250,82,6,32,249,224,114,2,101,0,3,0,186,255,4,6,213, + 5,36,0,5,0,9,0,13,0,0,5,33,17,33,17,33,3,17,33,17,37,33,17,33,1,44,2,98,2,213,250,201,114,6,27,253,43,2,99,253, + 157,138,2,215,2,101,250,82,6,32,249,224,114,2,101,0,0,3,0,186,255,4,6,213,5,36,0,5,0,9,0,13,0,0,5,33,17,33,17,33, + 3,17,33,17,1,33,17,33,1,44,5,55,253,43,253,158,114,6,27,253,43,2,99,253,157,138,2,101,2,215,250,82,6,32,249,224,3,73,2,101, + 0,3,0,112,255,4,6,139,5,32,0,13,0,19,0,32,0,0,18,16,18,36,51,50,4,18,16,2,4,35,34,36,1,6,7,4,3,33,5,18, + 5,22,51,50,55,36,16,37,38,39,17,112,209,1,107,210,209,1,107,209,209,254,149,209,210,254,149,2,3,137,137,254,204,23,2,93,253,163,23,1, + 52,166,165,166,166,1,77,254,179,137,138,1,65,1,162,1,107,210,210,254,149,254,94,254,149,210,210,4,218,14,79,178,254,172,114,254,172,178,96,96, + 193,2,252,193,79,14,253,43,0,3,0,112,255,4,6,139,5,32,0,13,0,26,0,32,0,0,18,16,18,36,51,50,4,18,16,2,4,35,34,36, + 5,54,55,36,16,37,38,35,34,7,4,3,33,5,18,5,22,23,17,112,209,1,107,210,209,1,107,209,209,254,149,209,210,254,149,2,117,138,137,1, + 77,254,179,166,166,165,166,254,204,23,2,207,253,49,23,1,52,137,137,1,65,1,162,1,107,210,210,254,149,254,94,254,149,210,210,94,14,79,193,2, + 252,193,96,96,178,254,172,114,254,172,178,79,14,2,99,0,0,3,0,112,255,4,6,139,5,32,0,13,0,26,0,32,0,0,18,16,18,36,51,50, + 4,18,16,2,4,35,34,36,2,16,5,22,23,17,33,2,37,38,35,34,7,1,54,55,36,19,33,112,209,1,107,210,209,1,107,209,209,254,149,209, + 210,254,149,92,1,77,137,137,2,208,23,254,204,166,166,165,166,1,132,138,137,1,52,23,253,162,1,65,1,162,1,107,210,210,254,149,254,94,254,149, + 210,210,3,188,253,4,193,79,14,2,213,1,84,178,96,96,251,37,14,79,178,1,84,0,0,3,0,112,255,4,6,139,5,32,0,13,0,26,0,32, + 0,0,18,16,18,36,51,50,4,18,16,2,4,35,34,36,2,16,5,22,51,50,55,36,19,33,17,6,7,1,2,37,38,39,17,112,209,1,107,210, + 209,1,107,209,209,254,149,209,210,254,149,92,1,77,166,165,166,166,1,52,23,253,48,137,137,3,226,23,254,204,137,138,1,65,1,162,1,107,210,210, + 254,149,254,94,254,149,210,210,3,188,253,4,193,96,96,178,1,84,2,213,14,79,253,250,1,84,178,79,14,253,157,0,0,2,0,6,255,4,6,33, + 5,36,0,2,0,5,0,0,55,1,33,3,17,33,120,4,140,251,116,114,6,27,32,4,146,250,82,6,32,0,0,0,0,2,0,6,255,4,6,33, + 5,36,0,2,0,5,0,0,9,1,17,37,33,17,1,35,4,140,250,87,6,27,4,178,251,110,4,146,114,249,224,0,0,2,0,6,255,4,6,33, + 5,36,0,2,0,5,0,0,23,33,1,3,17,1,120,4,140,251,116,114,6,27,138,4,146,250,252,6,32,249,224,0,0,2,0,186,255,121,5,234, + 4,175,0,3,0,7,0,0,5,33,17,33,3,17,33,17,1,44,4,76,251,180,114,5,48,21,4,82,251,60,5,54,250,202,0,0,0,1,0,186, + 255,121,5,234,4,175,0,3,0,0,23,17,33,17,186,5,48,135,5,54,250,202,0,0,0,2,0,186,255,221,5,34,4,75,0,3,0,7,0,0, + 37,33,17,33,3,17,33,17,1,44,3,132,252,124,114,4,104,79,3,138,252,4,4,110,251,146,0,0,0,1,0,186,255,221,5,34,4,75,0,3, + 0,0,23,17,33,17,186,4,104,35,4,110,251,146,0,0,0,2,0,6,255,4,6,33,5,36,0,2,0,5,0,0,5,33,17,9,1,17,1,35, + 4,140,250,87,6,27,138,4,146,250,252,6,32,249,224,0,0,9,0,171,0,0,6,128,5,213,0,7,0,12,0,19,0,34,0,42,0,50,0,58, + 0,65,0,73,0,0,1,51,23,17,7,35,39,17,5,23,21,7,39,37,23,7,35,38,39,53,5,50,31,1,20,7,6,35,34,39,38,53,52,55, + 54,1,33,23,21,7,33,39,53,37,33,23,21,7,33,39,53,3,51,22,23,21,7,39,53,37,51,23,21,7,39,53,37,51,23,17,7,35,39,17, + 3,115,77,6,6,77,6,2,55,58,248,61,252,253,252,61,3,200,45,2,48,208,89,13,190,71,46,175,98,35,183,67,253,75,1,83,6,6,254,173, + 6,4,117,1,89,7,7,254,167,6,71,3,134,114,61,248,253,181,3,59,246,62,2,27,77,6,6,77,6,5,213,6,254,162,6,6,1,94,155,63, + 3,254,63,238,254,64,199,55,4,181,225,96,189,100,23,167,63,92,181,103,27,254,237,6,79,6,6,79,6,6,79,6,6,79,254,232,130,121,3,62, + 253,4,42,60,3,254,63,4,118,6,254,162,6,6,1,94,0,1,0,104,255,251,7,151,2,225,0,34,0,0,1,51,50,31,1,54,51,22,21,20, + 7,22,29,1,6,35,33,53,50,55,54,59,1,39,52,63,1,23,39,52,63,1,50,23,54,4,245,22,217,117,21,39,54,135,34,103,18,80,249,51, + 57,134,46,52,33,12,160,39,42,5,204,67,48,46,120,2,225,232,86,35,27,109,49,52,23,72,26,101,9,174,39,49,108,49,4,4,12,147,90,8, + 43,100,0,0,0,1,0,100,0,0,6,200,5,213,0,63,0,0,1,51,23,21,51,32,1,22,29,1,35,38,39,38,43,1,34,7,21,20,7,39, + 38,35,17,20,15,1,34,47,1,53,55,51,23,21,22,59,1,50,63,1,17,34,7,6,35,39,53,55,35,38,39,35,34,15,1,35,53,54,55,54, + 33,53,3,139,58,6,2,1,184,1,24,43,2,22,19,35,57,44,150,112,8,33,151,136,106,30,91,37,2,6,43,5,11,62,10,55,20,6,211,86, + 17,14,7,7,4,67,197,67,99,34,20,3,58,192,239,1,56,5,213,6,125,254,26,86,13,8,15,46,24,101,51,15,2,66,61,253,83,101,24,2, + 96,28,26,6,6,12,101,57,42,2,164,61,57,6,12,51,64,27,61,18,2,144,218,223,125,0,0,0,0,26,0,170,255,255,6,130,7,107,0,13, + 0,21,0,29,0,37,0,67,0,96,0,140,0,183,0,227,1,14,1,58,1,100,1,144,1,187,1,230,2,15,2,59,2,101,2,109,2,117,2,125, + 2,169,2,211,2,253,3,39,3,83,0,0,1,22,51,50,55,51,6,7,38,39,51,22,51,50,55,38,39,54,55,22,23,6,5,38,39,54,55,22, + 23,6,3,38,39,54,55,22,23,6,39,6,21,20,22,51,50,54,53,52,39,38,39,50,51,50,55,54,53,52,38,35,34,6,21,20,23,22,51,6, + 19,54,55,50,31,1,22,20,7,6,7,22,23,22,21,20,4,32,36,53,52,55,54,55,38,39,38,52,55,1,23,39,38,51,50,15,1,55,54,51, + 50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,1,23,39,38,50,15,1, + 55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,5,23,39,38, + 51,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50, + 19,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,53,55,7,6,35,34,53,52,63,1,39,38,53, + 52,51,50,1,23,39,38,51,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,20,35,34,53,55,7,6,35,34,53,52,63, + 1,39,38,53,52,51,50,1,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,20,34,53,55,7,6,35,34,53, + 52,63,1,39,38,53,52,51,50,5,23,39,52,51,50,21,7,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,53,55,7, + 6,35,34,53,52,63,1,39,38,53,52,51,50,3,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34, + 53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,5,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23, + 22,35,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,31,1,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,20,35,34,47, + 1,23,20,35,34,53,55,7,6,35,34,52,63,1,39,38,53,52,51,50,55,23,39,52,51,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20, + 35,34,47,1,23,22,35,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,55,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23, + 22,21,20,35,34,47,1,23,22,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,19,38,39,54,55,22,23,6,5,38,39,54,55,22, + 23,6,23,38,39,54,55,22,23,6,1,23,39,38,51,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,22,35,34,53,55, + 7,6,35,34,53,52,63,1,39,38,53,52,51,50,1,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23,20,34, + 53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,5,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47,1,23, + 22,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,1,23,39,38,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20,35,34,47, + 1,23,22,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,1,23,39,38,51,50,15,1,55,54,51,50,21,20,15,1,23,22,21,20, + 35,34,47,1,23,22,35,34,53,55,7,6,35,34,53,52,63,1,39,38,53,52,51,50,3,252,8,8,66,25,25,5,128,126,9,24,37,60,7,122, + 42,1,3,43,39,3,3,254,235,41,3,3,43,40,3,3,64,38,2,3,39,36,2,2,202,124,247,175,174,248,124,101,139,2,3,60,45,65,125,93, + 92,138,66,45,55,144,21,26,147,132,49,2,83,76,20,24,111,87,142,254,228,254,106,254,227,143,92,118,21,19,76,76,253,169,41,6,1,15,17,2, + 6,40,4,4,16,8,48,47,9,16,4,4,40,6,1,16,14,5,40,3,5,14,9,46,49,7,15,5,1,40,37,6,2,30,2,6,37,4,4,14, + 7,44,42,7,12,5,3,35,4,1,14,13,5,36,3,4,13,8,41,42,8,14,4,3,102,36,5,2,14,16,2,6,37,3,5,13,7,43,41,8, + 12,6,2,36,5,1,15,12,4,35,4,3,14,8,42,43,8,15,3,102,37,6,2,30,2,6,37,4,4,14,7,44,42,7,12,6,2,36,5,1, + 14,13,5,36,3,4,13,8,41,42,8,14,4,251,203,19,2,1,7,8,1,3,20,1,2,8,3,24,23,4,8,2,1,19,2,7,6,2,19,2, + 3,6,4,23,24,3,8,1,3,23,21,3,1,18,1,4,22,2,2,9,4,26,24,5,8,2,2,22,4,16,3,21,2,2,8,4,25,26,4,9, + 2,252,187,19,4,7,8,4,19,3,2,8,5,22,22,4,7,2,3,19,3,1,8,7,4,19,3,2,7,4,22,22,5,8,2,92,20,4,1,16, + 1,3,19,3,2,7,4,23,22,5,7,2,3,19,3,1,8,7,3,19,2,2,8,5,22,22,5,8,2,1,28,19,2,1,16,1,3,19,1,3, + 8,4,23,22,5,8,3,1,19,3,1,8,7,2,19,2,1,8,5,22,23,4,8,1,111,19,2,2,16,1,3,20,1,2,8,4,23,23,4,8, + 2,1,19,2,7,6,2,19,2,3,6,4,22,23,3,6,3,247,21,3,7,9,1,3,22,1,4,8,5,26,25,6,8,4,2,20,2,1,9,7, + 3,21,3,2,8,5,24,25,4,8,2,91,22,3,1,18,1,4,22,2,2,8,3,26,24,5,8,2,2,22,3,1,16,2,21,1,3,8,5,25, + 26,4,9,2,174,37,2,2,41,35,3,3,254,183,38,2,3,39,37,1,1,252,38,2,2,41,35,3,3,1,96,35,5,1,14,15,1,6,36,3, + 5,13,7,42,41,8,13,5,3,36,4,2,14,13,5,35,4,4,14,8,43,44,7,14,4,252,85,21,3,1,18,1,4,21,3,2,9,5,25,24, + 5,8,2,3,21,4,16,3,21,2,2,8,4,25,26,4,9,2,254,81,23,4,1,18,1,3,21,2,2,8,3,26,25,4,8,2,2,21,2,1, + 16,4,23,1,2,9,6,24,26,4,9,2,4,48,23,4,1,18,1,3,21,2,2,8,3,26,25,4,8,2,2,21,2,1,16,3,22,1,3,8, + 6,24,25,5,9,2,252,69,37,5,2,14,16,3,5,37,3,5,13,7,43,41,8,12,6,2,36,4,2,15,12,4,36,3,3,14,8,42,43,8, + 15,3,3,137,1,38,69,5,7,67,38,86,2,42,44,3,3,41,45,4,2,41,45,3,3,42,44,254,18,2,37,38,2,2,37,38,158,102,147,145, + 208,208,145,147,102,85,32,51,72,104,102,101,101,102,104,72,50,30,1,217,112,24,117,19,94,232,81,24,16,28,70,115,165,163,230,230,163,165,115,75, + 26,15,22,81,232,71,253,104,33,57,15,15,57,33,4,17,11,3,21,22,3,12,15,2,33,55,16,16,55,33,2,15,12,3,22,21,3,11,17,1, + 209,31,52,13,13,52,31,3,16,7,5,20,19,3,9,14,2,30,50,15,15,50,30,2,14,9,3,19,20,5,7,16,75,31,52,14,14,52,31,3, + 16,7,3,21,19,4,9,14,2,30,50,14,14,50,30,2,14,9,4,19,21,3,7,16,1,27,30,50,14,14,50,30,2,14,9,4,19,20,3,9, + 15,3,29,49,14,14,49,29,3,15,9,3,20,19,4,9,14,2,154,16,28,6,6,28,16,1,7,6,2,9,11,2,4,8,2,14,25,7,7,25, + 14,2,8,4,2,11,9,2,6,7,254,227,17,29,10,10,29,17,3,10,5,1,13,10,3,6,7,1,17,30,7,7,30,17,1,7,6,3,10,13, + 1,5,10,168,16,28,7,7,28,16,2,7,6,2,9,11,2,5,8,2,15,26,8,8,26,15,2,8,5,2,11,9,2,6,7,1,24,16,28,6, + 6,28,16,2,8,4,3,10,10,2,5,7,1,15,25,8,8,25,15,1,7,5,2,10,10,3,4,8,24,15,27,7,7,27,15,2,8,5,1,10, + 11,1,6,7,1,16,27,8,8,27,16,1,7,6,1,11,10,1,6,7,161,15,27,7,7,27,15,1,7,4,1,12,10,1,12,1,15,27,7,7, + 27,15,1,12,1,10,12,1,4,7,55,18,31,7,7,31,18,1,8,5,2,12,12,2,5,8,1,18,29,10,10,29,18,1,8,5,2,12,12,2, + 5,8,217,18,31,7,7,31,18,1,8,5,2,11,12,2,5,10,3,16,28,9,9,28,16,3,10,5,2,12,11,2,6,7,250,224,2,37,38,2, + 2,37,38,226,2,37,39,2,3,37,38,2,2,37,39,2,3,37,38,1,129,29,50,14,14,50,29,3,15,9,3,19,20,3,10,14,4,27,47,15, + 15,47,27,4,14,10,3,20,19,3,9,15,2,103,18,30,8,8,30,18,1,10,4,2,11,12,2,6,8,2,17,29,9,9,29,17,2,8,6,2, + 12,11,2,4,10,251,18,31,7,7,31,18,1,8,5,3,11,12,2,5,9,1,18,28,10,10,28,18,1,9,5,2,12,11,3,5,8,1,130,17, + 30,8,8,30,17,2,8,7,1,11,12,2,5,9,1,17,28,9,9,28,17,1,9,5,2,12,11,1,7,8,253,127,31,52,14,14,52,31,3,16, + 7,4,20,19,3,10,14,3,29,50,14,14,50,29,3,14,10,3,19,20,4,7,16,0,0,15,0,131,0,0,6,169,7,11,0,23,0,45,0,62, + 0,79,0,96,0,113,0,130,0,147,0,164,0,181,0,198,0,215,0,232,0,249,1,10,0,0,1,22,21,20,7,6,15,1,6,43,1,38,39,38, + 53,52,63,2,54,51,50,51,22,5,6,21,20,23,22,31,1,22,51,50,63,1,54,53,52,47,1,38,35,34,7,19,50,23,22,29,1,20,7,6, + 35,34,47,1,53,52,55,54,19,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,19,50,23,22,29,1,20,7,6,35,34,47,1,53,52, + 55,54,19,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,19,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,3,50,23,22, + 29,1,20,7,6,35,34,47,1,53,52,55,54,1,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,55,50,23,22,29,1,20,7,6,35, + 34,47,1,53,52,55,54,19,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,1,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55, + 54,37,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,37,50,23,22,29,1,20,7,6,35,34,47,1,53,52,55,54,37,50,23,22,29, + 1,20,7,6,35,34,47,1,53,52,55,54,2,68,46,26,20,50,21,96,123,22,52,38,47,60,41,12,101,136,4,3,62,254,250,79,9,5,14,14, + 30,44,52,72,51,82,4,32,32,48,55,75,247,29,15,7,26,11,13,36,13,1,26,13,168,29,15,7,26,11,13,36,13,1,26,13,138,28,15,7, + 26,10,14,35,14,1,26,13,155,28,15,7,26,10,14,35,14,1,26,13,3,28,15,7,26,10,14,35,14,1,26,13,189,29,15,7,26,11,13,36, + 13,1,26,13,1,138,28,15,7,26,10,14,35,14,1,26,13,194,29,15,7,26,11,13,36,13,1,26,13,194,29,15,7,26,11,13,36,13,1,26, + 13,253,85,29,15,7,26,11,13,36,13,1,26,13,1,18,28,15,7,26,10,14,35,14,1,26,13,1,34,29,15,7,26,11,13,36,13,1,26,13, + 1,3,28,15,7,26,10,14,35,14,1,26,13,2,32,55,81,61,75,71,60,26,115,7,45,56,80,90,121,57,14,122,12,128,95,101,34,34,22,16, + 18,35,47,50,100,116,26,27,48,38,50,1,106,31,12,15,6,31,18,7,44,14,3,31,20,8,1,58,30,12,15,7,30,19,8,46,12,5,30,20, + 8,1,52,31,12,14,7,30,20,7,46,12,5,30,20,8,1,61,31,12,15,6,31,18,7,44,13,4,31,20,8,253,2,31,12,15,6,31,18,7, + 44,14,3,32,19,8,254,252,31,12,14,6,32,18,7,45,13,4,31,19,8,2,7,30,12,15,7,30,19,7,45,12,5,30,21,7,250,30,12,15, + 7,30,19,7,45,12,5,30,21,7,1,4,32,12,14,6,31,18,8,45,13,4,31,19,9,251,12,30,12,15,7,30,19,8,46,12,5,30,20,8, + 211,30,12,14,7,30,20,7,46,12,5,30,20,7,231,31,12,14,6,32,18,7,44,14,3,32,19,8,202,31,12,14,6,32,18,7,45,13,3,32, + 19,8,0,0,0,1,0,133,255,247,6,167,5,201,0,9,0,0,19,33,27,1,33,1,19,9,1,19,133,2,87,186,187,2,86,254,28,186,254,25, + 254,26,185,3,144,2,57,253,199,254,159,253,200,1,96,254,160,2,56,0,0,2,0,133,255,247,6,167,5,201,0,9,0,19,0,0,19,33,27,1, + 33,1,19,9,1,19,55,3,9,1,3,1,33,11,1,33,133,2,87,186,187,2,86,254,28,186,254,25,254,26,185,68,140,1,117,1,128,152,1,143, + 254,26,145,142,254,24,3,144,2,57,253,199,254,159,253,200,1,96,254,160,2,56,21,254,78,1,12,254,230,1,194,1,24,1,183,254,73,0,0,0, + 0,1,0,170,0,4,3,235,5,213,0,17,0,0,1,22,23,20,7,9,1,55,19,37,55,1,38,53,52,55,1,54,3,176,57,2,9,253,125,1, + 238,86,38,254,55,224,253,221,19,65,2,147,11,5,213,2,54,36,12,253,133,253,244,230,254,56,39,94,2,52,23,23,27,63,2,134,10,0,0,0, + 0,1,0,170,0,0,6,129,5,217,0,25,0,0,19,33,50,21,20,7,9,1,55,19,37,55,1,38,53,52,55,1,33,17,6,7,38,39,17,54, + 237,5,73,64,27,253,193,1,231,89,37,254,49,231,253,239,15,52,1,229,251,168,1,72,70,1,1,5,217,83,34,27,253,197,254,27,213,254,61,34, + 108,2,22,16,45,28,50,1,223,250,252,68,1,1,67,5,91,57,0,0,0,3,0,170,0,0,6,130,5,216,0,13,0,25,0,38,0,0,1,16, + 0,33,32,0,17,52,18,36,51,50,4,18,5,16,0,32,0,17,52,2,36,32,4,2,5,20,6,35,34,38,53,52,62,1,50,30,1,6,130,254, + 74,254,201,254,203,254,74,201,1,104,186,189,1,104,200,250,113,1,138,2,48,1,138,180,254,188,254,172,254,188,180,3,94,109,78,77,110,50,90,94, + 90,50,2,236,254,201,254,75,1,181,1,55,194,1,105,193,193,254,153,196,254,232,254,119,1,137,1,24,177,1,66,174,174,254,190,177,78,109,109,78, + 49,90,48,48,90,0,0,0,0,3,0,125,0,0,6,159,5,209,0,10,0,22,0,67,0,0,0,34,6,21,20,22,51,50,54,53,52,37,34,6, + 21,20,22,51,50,54,53,52,38,37,22,23,22,21,20,6,35,34,38,53,52,55,54,55,54,53,52,36,32,4,21,20,23,22,23,22,16,6,35,34, + 38,16,55,54,55,38,53,52,0,33,32,0,21,20,5,177,148,103,103,74,73,104,251,156,73,104,104,73,74,103,103,4,23,25,22,91,182,130,129,182, + 90,81,111,121,254,177,254,32,254,177,121,125,87,90,182,130,128,183,91,18,19,122,1,192,1,65,1,68,1,192,1,233,103,74,73,103,103,73,74,103, + 103,74,73,104,104,73,74,103,85,17,22,92,130,129,183,183,129,130,92,81,9,115,153,180,253,253,180,153,114,4,87,92,254,252,183,183,1,4,92,17, + 15,142,182,248,1,94,254,162,248,177,0,0,0,3,0,125,0,0,6,159,5,201,0,10,0,22,0,65,0,0,1,52,38,35,34,6,21,20,22,50, + 54,37,52,38,35,34,6,21,20,22,51,50,54,1,20,0,33,32,0,53,52,55,38,39,38,16,54,51,50,22,16,7,6,7,6,21,20,4,32,36, + 53,52,39,38,39,38,16,54,51,50,22,16,7,6,7,22,6,24,104,73,74,103,103,148,103,252,77,103,74,73,104,104,73,74,103,4,35,254,64,254, + 188,254,191,254,64,122,19,18,91,183,128,130,182,90,87,125,121,1,79,1,224,1,79,121,111,81,90,182,129,130,182,91,22,25,115,4,145,73,104,104, + 73,74,103,103,74,74,103,103,74,73,103,103,254,12,247,254,163,1,93,247,180,141,15,18,91,1,2,182,182,254,254,91,88,3,114,151,180,251,251,180, + 152,113,9,81,92,1,2,182,182,254,254,92,22,17,139,0,0,2,0,125,255,253,4,226,5,198,0,11,0,27,0,0,1,34,6,21,20,22,51,50, + 54,53,52,38,55,22,23,22,16,0,35,34,0,16,0,51,50,23,1,23,2,134,143,201,201,143,142,201,199,190,19,18,152,254,206,217,215,254,206,1, + 47,218,96,84,1,14,154,3,95,200,144,142,201,201,142,144,200,59,16,19,153,254,80,254,207,1,49,1,176,1,50,29,1,211,89,0,0,3,0,125, + 0,1,7,158,5,201,0,8,0,17,0,49,0,0,1,34,6,20,22,50,54,52,38,0,34,6,20,22,51,50,54,52,1,22,21,20,0,35,34,0, + 53,52,0,51,50,23,22,23,55,38,53,52,0,51,50,0,21,20,0,35,34,39,38,39,2,51,120,169,169,240,169,168,3,179,242,168,168,121,120,169, + 252,190,38,254,255,183,181,254,255,0,255,183,185,128,2,2,220,28,0,255,183,184,1,0,254,255,183,181,129,11,11,2,218,169,240,169,169,240,169,2, + 90,169,240,169,169,240,253,228,84,100,181,254,255,1,1,181,183,1,1,128,3,2,137,73,85,183,1,1,254,255,183,181,254,255,129,11,12,0,0,0, + 0,14,0,140,0,0,9,107,5,213,0,35,0,53,0,65,0,77,0,89,0,101,0,114,0,128,0,141,0,154,0,167,0,181,0,197,0,217,0,0, + 1,51,4,5,4,21,6,35,34,39,37,38,53,52,55,54,53,52,39,33,6,21,20,23,22,21,20,7,5,6,35,34,39,52,37,36,1,53,51,21, + 20,23,22,25,1,33,17,16,55,54,61,1,51,21,3,20,22,51,50,54,53,52,38,35,34,6,5,20,6,35,34,38,53,52,54,51,50,22,39,20, + 6,35,34,38,53,52,54,51,50,22,17,20,6,35,34,38,53,52,54,51,50,22,2,22,6,7,6,38,39,38,54,55,54,51,50,1,22,6,7,6, + 35,34,38,39,38,54,55,54,22,1,30,1,14,1,39,46,1,53,52,55,62,1,4,30,1,21,20,7,14,1,39,46,1,55,54,36,54,22,23,22, + 6,7,6,38,39,38,53,52,37,54,22,23,22,21,20,6,7,6,38,39,38,54,1,62,1,23,30,1,7,14,1,35,34,39,46,1,53,52,1,62, + 1,51,50,23,30,1,21,20,7,14,1,35,34,39,46,1,53,52,4,247,9,2,91,1,1,1,15,36,103,6,7,254,105,60,12,68,34,251,156,34, + 68,12,61,254,105,7,6,102,37,1,16,1,0,3,76,144,241,231,249,87,232,240,145,171,236,165,168,234,233,169,167,234,2,114,131,94,93,131,131,93, + 94,131,159,32,24,23,33,33,23,24,32,32,24,23,33,33,23,24,32,209,26,6,19,19,46,14,14,8,19,15,17,5,1,155,15,7,20,15,17,5, + 27,15,13,7,19,19,46,254,12,24,20,14,42,22,22,18,3,8,41,2,88,44,17,3,8,41,22,22,21,7,8,253,175,44,42,7,7,20,22,24, + 41,8,3,2,127,22,41,8,3,17,22,22,43,6,7,21,254,21,14,46,19,19,8,15,13,28,5,17,15,19,5,1,125,15,27,5,17,15,20,4, + 12,13,27,5,18,15,19,4,5,213,17,155,164,170,153,1,140,18,43,19,25,71,32,23,3,3,23,32,71,24,20,43,18,140,1,153,170,164,153,254, + 118,75,152,75,57,95,254,226,254,22,1,234,1,30,95,57,75,152,75,253,221,167,234,234,167,166,236,236,165,93,132,132,93,95,131,131,222,22,34,34, + 22,24,34,34,253,115,24,33,33,24,23,34,34,2,87,38,46,13,15,7,19,20,45,15,10,253,236,19,46,15,10,4,20,19,45,14,13,6,1,97, + 8,41,44,21,6,7,34,13,9,9,22,21,195,14,34,13,8,9,22,21,8,7,41,23,22,6,14,20,22,24,41,8,6,21,22,9,8,13,236,7, + 21,22,9,8,13,33,8,7,21,22,22,41,254,148,18,7,13,14,47,17,20,4,10,15,28,5,17,2,12,19,4,10,15,27,4,18,16,19,4,12, + 13,28,5,17,0,16,0,145,0,0,9,112,5,213,0,17,0,29,0,37,0,45,0,53,0,65,0,77,0,89,0,100,0,112,0,124,0,136,0,148, + 0,166,0,202,0,240,0,0,1,53,35,21,6,7,6,21,17,33,17,52,39,38,39,53,35,21,5,50,22,21,20,6,35,34,38,53,52,54,4,34, + 6,20,22,50,54,52,2,34,6,20,22,50,54,52,2,34,6,20,22,50,54,52,1,14,1,23,30,1,55,62,1,39,46,1,1,14,1,23,30,1, + 55,62,1,39,46,1,1,6,22,23,22,54,55,54,38,39,38,6,5,6,22,23,22,62,1,38,39,38,6,5,30,1,55,62,1,39,46,1,7,14, + 1,37,30,1,55,62,1,39,46,1,7,14,1,1,22,54,55,54,38,39,38,6,7,6,22,1,22,54,55,54,38,39,38,6,7,6,22,19,53,51, + 21,20,23,22,25,1,33,17,16,55,54,61,1,51,21,37,6,21,20,23,22,21,20,7,5,35,34,39,54,55,54,37,22,50,55,4,23,22,23,6, + 43,1,37,38,53,52,55,54,53,52,39,55,22,21,20,7,6,21,20,23,5,22,51,50,55,38,39,36,37,39,21,35,4,5,6,7,22,51,50,55, + 37,54,53,52,39,38,53,52,55,3,236,49,15,203,195,5,157,196,202,8,56,254,250,166,229,230,165,163,231,230,1,0,184,129,129,184,129,188,46,32, + 32,46,32,32,46,32,32,46,32,254,242,18,8,13,15,45,19,18,6,13,13,45,1,89,19,7,13,14,45,19,19,7,14,13,45,253,252,7,22,21, + 22,41,7,7,20,23,22,41,2,71,7,20,22,21,41,14,20,22,21,41,253,171,7,41,23,22,20,7,7,41,22,21,22,2,85,6,42,21,22,20, + 7,7,41,21,22,20,254,62,19,45,13,15,8,18,19,45,15,13,8,1,126,19,45,13,14,7,19,19,45,14,13,7,86,134,225,216,249,201,216,225, + 134,254,169,26,75,28,59,254,138,10,121,65,13,248,248,2,67,24,48,24,2,66,248,248,13,65,120,10,254,137,59,28,75,25,25,39,54,31,31,1, + 70,15,15,74,62,10,236,254,199,254,36,48,54,254,35,254,199,235,10,62,74,15,15,1,70,31,31,54,38,3,194,64,142,64,49,65,241,254,101,1, + 155,241,65,49,64,142,64,72,231,163,164,230,230,164,163,231,173,129,184,128,128,184,1,20,32,46,32,32,46,253,181,32,46,32,32,46,2,69,13,45, + 19,18,8,13,15,45,19,17,7,253,255,14,45,19,19,7,15,13,44,19,19,7,1,49,22,41,7,7,20,23,22,41,7,7,22,213,21,41,7,7, + 21,44,40,8,7,20,57,23,20,7,7,41,21,22,22,7,8,40,169,21,22,7,7,41,22,21,22,7,7,41,254,117,15,7,19,19,45,13,14,7, + 19,19,44,1,230,13,8,18,19,45,13,15,8,18,19,45,1,32,71,156,55,55,87,254,245,254,54,1,202,1,11,87,55,55,156,71,229,6,18,32, + 68,38,26,38,11,165,203,199,101,139,17,1,1,17,139,101,199,203,165,11,38,26,38,68,32,18,6,28,18,34,40,61,22,21,20,19,136,6,151,157, + 112,129,25,1,1,25,129,112,157,151,6,136,19,20,21,22,61,40,34,18,0,2,0,184,0,0,6,117,5,213,0,7,0,11,0,0,19,33,23,17, + 7,33,39,17,23,17,33,17,190,5,176,7,7,250,80,6,110,4,224,5,213,7,250,56,6,6,5,200,104,251,8,4,248,0,0,0,0,3,0,183, + 0,0,6,118,5,213,0,7,0,11,0,34,0,0,19,33,23,17,7,33,39,17,23,17,33,17,7,21,6,7,0,3,6,35,6,35,2,43,1,53, + 55,50,23,51,54,55,54,55,54,189,5,179,6,6,250,77,6,111,4,224,135,76,41,254,185,62,6,16,117,13,101,205,23,162,151,73,6,51,63,98, + 155,97,5,213,6,250,56,7,7,5,200,104,251,8,4,248,158,6,65,58,254,70,254,189,59,47,1,2,7,73,131,166,116,179,187,120,0,3,0,183, + 0,0,6,118,5,213,0,7,0,11,0,26,0,0,19,33,23,17,7,33,39,17,23,17,33,17,5,9,1,23,9,1,21,7,1,35,1,35,39,9, + 1,189,5,179,6,6,250,77,6,111,4,224,251,247,1,155,1,151,95,254,104,1,152,91,254,101,4,254,105,4,91,1,151,254,105,5,213,6,250,56, + 7,7,5,200,104,251,8,4,248,134,254,105,1,151,91,254,101,254,102,3,91,1,151,254,108,91,1,154,1,155,0,0,0,1,0,154,0,160,3,167, + 5,64,0,20,0,0,19,51,1,54,1,50,55,51,23,9,1,21,7,1,35,1,35,39,1,0,53,241,5,1,41,11,1,26,4,6,4,85,254,210, + 1,46,87,254,212,2,254,210,3,87,1,49,254,207,5,64,254,11,8,1,222,15,85,254,4,254,7,3,83,1,247,254,11,86,1,249,1,245,7,0, + 0,8,0,100,0,0,6,245,7,118,0,8,0,17,0,26,0,35,0,44,0,53,0,62,0,126,0,0,1,51,6,43,1,38,61,1,52,1,51,6, + 43,1,38,61,1,52,37,51,6,43,1,38,61,1,52,23,51,6,43,1,38,61,1,52,1,51,6,43,1,38,61,1,52,5,51,6,43,1,38,61, + 1,52,23,51,6,43,1,38,61,1,52,37,51,23,21,51,32,1,22,29,1,35,38,39,38,43,1,34,7,21,20,7,39,38,35,17,20,15,1,34, + 47,1,53,55,51,23,21,22,59,1,50,63,1,17,34,7,6,35,39,53,55,35,38,39,35,34,15,1,35,53,54,55,54,33,53,1,214,3,30,92, + 6,58,2,86,2,29,92,7,57,2,30,3,30,92,6,58,247,4,30,92,6,58,2,30,3,29,93,6,58,1,38,2,28,93,7,57,91,3,30,92, + 6,58,253,171,58,6,2,1,184,1,24,43,2,22,19,35,57,44,150,112,8,33,151,136,106,30,91,37,2,6,43,5,11,62,10,55,20,6,211,86, + 17,14,7,7,4,67,197,67,99,34,20,3,58,192,239,1,56,6,1,207,10,35,2,56,1,100,207,8,35,3,55,227,207,8,36,3,54,185,207,8, + 36,2,56,1,59,206,7,36,3,55,105,207,7,36,3,55,235,207,9,35,2,57,154,5,112,254,80,76,12,7,13,41,22,90,46,13,2,59,54,253, + 159,90,21,2,86,24,23,6,6,10,90,51,37,2,89,54,51,5,11,46,56,25,55,16,2,128,194,198,112,0,0,0,0,9,0,152,0,0,6,147, + 5,217,0,11,0,17,0,28,0,51,0,68,0,77,0,121,0,127,0,143,0,0,1,20,21,20,23,33,54,55,52,35,33,6,19,22,23,33,54,63, + 1,6,7,54,55,54,53,52,53,38,35,39,6,7,51,50,21,20,7,6,7,6,7,51,50,55,54,55,54,55,54,53,52,35,1,51,20,6,7,20, + 22,23,35,38,39,38,39,52,53,52,54,1,22,51,50,55,54,55,33,22,5,54,55,50,23,21,20,5,7,23,20,7,33,38,61,1,55,53,36,47, + 1,53,54,51,22,23,38,17,52,51,33,22,21,51,50,21,20,7,6,7,6,43,1,39,1,22,23,33,54,55,1,6,7,6,7,35,62,1,53,52, + 38,53,51,30,1,21,1,35,15,4,129,11,3,30,251,160,28,63,5,16,3,244,13,9,73,9,58,87,48,29,1,32,57,2,1,54,59,69,44,81, + 32,50,7,58,38,19,108,54,29,24,120,253,48,9,98,1,136,4,8,19,109,33,10,111,254,219,184,189,174,177,34,92,252,62,37,3,69,254,102,18, + 6,254,153,126,2,16,253,241,17,4,254,101,50,3,4,18,85,214,201,54,4,103,33,54,143,86,35,112,53,67,7,17,252,43,6,10,4,67,11,4, + 254,152,6,19,63,11,6,3,80,57,5,10,64,2,180,6,7,55,72,52,88,22,4,254,205,26,18,22,22,199,109,134,1,77,55,82,6,5,17,86, + 28,32,47,130,77,40,1,61,72,58,13,31,44,113,76,85,68,3,41,56,136,87,113,107,177,146,101,45,80,5,6,101,120,250,243,13,11,16,151,78, + 87,24,10,10,10,16,61,36,10,15,8,7,16,6,2,2,85,18,13,4,11,9,20,254,1,47,48,2,24,99,155,153,41,22,72,4,1,63,26,18, + 19,25,1,245,50,28,64,91,110,68,70,56,84,36,46,74,63,0,0,0,0,2,0,172,0,1,6,129,5,217,0,7,0,12,0,0,9,1,19,7, + 33,39,19,9,1,3,33,3,1,3,158,2,143,84,3,250,52,6,88,2,151,253,205,75,4,243,71,253,207,5,217,254,119,251,180,3,6,4,76,1, + 134,254,53,252,95,3,161,1,75,0,0,0,0,1,0,172,0,0,6,129,5,208,0,9,0,0,9,1,19,23,7,33,39,19,0,55,3,155,2,140, + 87,3,3,250,52,6,90,2,126,20,5,208,254,119,251,191,3,3,6,4,68,1,128,6,0,1,0,159,0,0,6,141,5,212,0,83,0,0,1,3, + 38,53,52,55,54,51,50,22,50,54,51,50,23,22,21,20,7,3,37,54,51,50,23,22,23,22,21,20,7,14,1,21,20,22,21,20,7,6,7,6, + 35,34,39,38,39,3,22,21,16,7,35,54,17,52,39,3,6,7,6,35,34,39,38,39,38,53,52,54,53,52,38,39,38,53,52,55,54,55,54,51, + 50,23,3,120,216,74,88,37,38,88,65,44,66,58,92,56,13,91,199,1,69,77,72,57,53,35,35,70,7,18,108,37,12,11,33,57,64,33,35,106, + 76,207,9,112,95,146,7,206,77,105,35,34,63,56,34,12,11,37,108,18,7,70,35,35,53,56,72,78,3,8,1,52,104,111,107,64,22,82,82,114, + 42,37,127,116,254,235,101,28,17,12,27,66,66,21,21,57,39,29,17,55,42,31,36,37,27,41,12,34,102,1,22,88,83,254,221,231,242,1,53,69, + 73,254,234,102,34,12,41,27,37,35,30,44,55,17,29,39,57,21,20,67,66,27,12,17,28,0,0,0,0,2,0,171,1,30,6,129,4,152,0,62, + 0,69,0,0,1,22,23,20,7,6,7,4,19,51,23,7,35,6,7,34,39,52,51,22,51,50,51,50,55,36,39,35,34,7,22,21,6,5,36,3, + 52,55,22,23,21,7,20,23,50,55,18,37,22,29,1,20,7,54,55,50,53,54,55,54,53,52,38,3,6,21,20,23,53,38,5,167,111,20,74,176, + 20,1,0,55,27,19,46,3,17,152,98,25,20,16,57,2,1,77,13,254,250,7,3,131,68,134,9,254,178,253,153,44,66,51,8,13,113,89,13,53, + 1,42,196,42,93,100,61,72,78,57,37,135,1,229,32,4,152,5,115,87,25,36,44,27,254,240,74,13,174,9,93,84,45,77,77,241,109,64,101,246, + 16,3,1,100,58,9,3,44,23,39,90,12,77,1,222,20,6,160,8,39,99,77,20,38,84,41,36,36,13,60,254,165,8,9,132,73,3,181,0,0, + 0,1,0,172,0,231,6,129,4,141,0,50,0,0,37,33,34,38,53,52,54,55,54,55,51,55,35,38,39,38,53,52,62,1,59,1,55,33,34,38, + 53,52,54,55,54,55,33,55,33,34,38,53,52,62,1,51,33,54,55,54,51,33,50,22,21,6,54,253,80,43,61,28,25,18,19,54,4,136,47,25, + 31,29,50,26,180,1,254,255,68,62,29,25,20,22,1,82,2,253,3,43,62,29,50,26,3,44,8,16,31,43,1,118,42,62,231,62,43,27,50,13, + 10,3,12,2,26,30,44,27,50,28,10,61,44,26,50,14,11,2,10,61,44,27,51,26,22,17,31,62,44,0,0,0,0,1,0,172,0,231,6,129, + 4,141,0,50,0,0,19,52,54,51,33,50,23,22,23,33,50,30,1,21,20,6,35,33,23,33,22,23,30,1,21,20,6,35,33,23,51,50,30,1, + 21,20,7,6,7,35,23,51,22,23,30,1,21,20,6,35,33,172,62,42,1,118,43,30,17,8,3,44,26,49,30,62,43,253,3,2,1,82,22,20, + 25,28,61,68,254,255,1,179,27,50,28,30,25,48,135,4,54,19,18,24,29,61,43,253,80,4,35,44,62,31,17,22,26,51,27,44,61,10,2,11, + 14,50,26,44,61,10,28,50,27,44,30,26,2,12,3,10,13,50,27,43,62,0,0,0,0,2,0,178,0,212,6,123,4,141,0,34,0,68,0,0, + 37,19,52,38,35,33,34,7,33,48,35,34,20,51,33,7,33,34,21,20,51,33,7,35,34,21,20,59,1,7,35,34,21,20,51,7,38,39,54,55, + 51,55,35,38,39,54,55,51,55,33,34,39,54,55,33,55,33,38,39,54,51,33,54,55,33,50,22,21,3,6,8,73,48,33,254,159,54,23,252,217, + 4,79,83,2,255,13,254,158,83,83,1,58,9,221,83,83,174,19,62,83,83,28,93,1,1,93,74,4,171,93,1,1,93,228,2,254,198,93,1,1, + 93,1,104,4,253,4,92,1,1,92,3,44,32,66,1,118,42,62,75,241,3,21,37,51,57,146,76,75,73,79,75,72,76,75,73,29,1,104,103,1, + 14,1,104,103,1,19,104,103,1,15,1,104,103,69,2,63,45,252,179,0,0,2,0,147,0,0,4,76,5,202,0,33,0,68,0,0,55,5,50,54, + 53,17,52,39,17,54,35,34,21,17,39,17,52,35,34,21,17,39,53,52,35,34,29,1,39,53,52,35,34,21,39,54,55,22,23,21,23,53,54,55, + 22,23,21,23,17,52,55,22,23,17,23,17,54,55,22,21,17,22,23,17,20,6,35,37,19,177,3,21,36,52,58,2,74,73,76,76,72,79,75,72, + 76,75,73,29,1,104,103,1,14,1,104,103,1,18,105,103,1,15,1,104,103,68,2,62,45,252,178,1,115,74,49,32,1,98,54,22,3,39,83,83, + 253,2,13,1,99,82,82,254,196,9,223,83,83,174,18,63,83,83,28,92,1,1,92,75,4,172,92,1,1,92,228,3,1,59,92,1,1,92,254,150, + 4,2,253,93,1,1,93,252,212,33,65,254,138,42,62,75,2,155,0,0,0,2,0,177,0,211,6,123,4,141,0,33,0,67,0,0,37,50,53,52, + 43,1,39,51,50,53,52,43,1,39,33,50,53,52,35,33,39,33,50,52,43,1,33,38,35,33,34,6,21,19,7,3,52,54,51,33,22,23,33,50, + 23,6,7,33,23,33,22,23,6,35,33,23,51,22,23,6,7,35,23,51,22,23,6,7,3,193,83,83,63,18,174,83,83,223,9,1,60,82,82,254, + 157,13,2,254,83,79,4,252,217,22,54,254,158,32,49,74,40,75,62,42,1,118,65,33,3,44,93,1,1,93,253,3,4,1,106,92,1,1,92,254, + 197,3,228,92,1,1,92,172,4,75,92,1,1,92,241,73,75,76,72,75,79,73,75,76,146,57,51,37,252,235,30,3,78,45,63,2,69,103,104,1, + 15,1,103,104,19,1,103,104,1,14,1,103,105,1,0,0,0,2,0,147,255,249,4,76,5,194,0,33,0,67,0,0,19,20,51,50,61,1,55,21, + 20,51,50,61,1,55,17,20,51,50,53,17,55,17,20,51,50,39,17,54,53,17,52,38,35,5,39,37,50,22,21,17,6,7,17,20,7,38,39,17, + 7,17,6,7,38,53,17,7,21,6,7,38,39,53,7,21,6,7,38,39,177,73,75,76,72,75,79,72,76,76,73,74,2,58,52,36,252,235,30,3, + 78,45,62,2,68,103,104,1,15,1,103,105,18,1,103,104,1,14,1,103,104,1,2,179,83,83,61,20,174,83,83,221,9,254,198,83,83,1,98,13, + 253,1,83,83,3,39,23,54,1,97,33,48,74,41,75,62,42,254,138,66,32,252,212,92,1,1,92,2,252,4,254,152,93,1,1,93,1,58,2,228, + 93,1,1,93,171,4,74,93,1,1,93,0,0,29,0,125,0,0,6,175,5,216,0,79,0,128,0,139,0,149,0,164,0,179,0,186,0,193,0,214, + 0,220,0,227,0,231,0,235,0,239,0,243,0,247,0,251,0,255,1,3,1,7,1,11,1,26,1,38,1,42,1,46,1,50,1,54,1,58,1,62, + 0,0,1,32,23,22,29,1,20,7,23,21,20,7,51,54,53,54,59,1,50,21,22,29,1,6,35,39,6,7,21,23,55,22,21,20,7,20,43,1, + 34,47,1,6,35,34,39,6,21,6,43,1,34,53,38,53,52,55,23,55,53,37,7,34,39,53,52,55,54,59,1,50,31,1,53,39,55,38,53,54, + 37,54,1,20,23,51,53,38,53,54,59,1,23,7,23,21,7,21,20,23,22,29,1,23,51,55,52,55,54,53,39,55,53,39,55,22,29,1,7,23, + 54,61,1,52,39,38,43,1,32,7,6,5,22,21,20,7,6,43,1,34,39,52,33,22,23,6,35,34,39,52,53,52,19,51,36,51,23,54,53,38, + 53,38,35,6,7,6,21,37,6,35,6,21,23,55,22,23,53,52,39,38,53,38,5,23,21,7,38,53,52,55,22,21,20,7,39,53,1,22,51,54, + 55,38,53,52,55,6,7,6,43,1,38,39,38,39,22,21,20,55,22,23,51,53,38,5,21,50,63,1,34,7,5,21,23,53,37,21,55,53,5,21, + 23,53,51,21,55,39,7,21,55,39,7,21,51,53,51,21,51,53,7,21,23,53,23,21,51,53,7,21,51,53,5,39,7,21,22,21,22,51,50,55, + 54,55,38,53,6,37,7,22,21,20,23,50,63,1,38,35,7,37,7,23,53,7,21,23,53,39,21,23,53,23,21,55,53,55,21,55,53,55,21,55, + 53,3,167,1,49,146,58,101,6,25,6,160,44,36,8,63,70,26,63,89,248,62,234,70,95,76,65,6,51,69,190,76,172,175,72,209,51,44,14,56, + 76,89,76,228,254,208,108,69,7,70,4,39,33,48,60,133,25,12,107,35,1,7,103,254,154,70,7,31,11,13,13,19,13,32,19,153,69,101,89,127, + 196,33,26,33,13,31,25,31,6,71,224,128,112,38,254,173,105,20,1,113,46,2,56,90,6,78,36,1,207,203,6,37,96,66,67,235,6,1,24,24, + 102,32,70,7,20,28,52,249,252,34,17,14,52,46,95,63,241,101,203,25,2,101,14,51,38,123,69,40,49,254,245,45,214,217,43,1,28,36,28,75, + 116,56,191,12,7,45,22,16,20,25,6,9,1,135,15,3,25,13,24,254,150,18,1,36,26,254,214,25,204,27,2,71,23,3,115,32,20,25,165,25, + 115,25,77,32,253,249,114,7,69,6,14,19,70,155,34,19,186,3,15,18,227,50,21,12,62,6,31,95,253,163,3,29,25,25,112,25,204,27,15,25, + 20,26,5,216,193,108,84,69,114,102,94,6,53,46,62,61,57,124,53,34,24,45,7,108,41,18,100,13,18,44,38,62,118,118,93,99,99,99,25,87, + 112,67,45,43,13,13,100,18,149,7,56,13,27,66,112,112,62,6,87,93,111,216,230,97,29,254,120,118,117,80,112,56,50,19,44,142,68,168,12,94, + 30,56,44,24,13,26,94,66,36,75,187,156,18,43,20,11,34,49,174,24,82,91,43,210,101,42,241,59,208,13,50,11,13,155,155,87,10,81,151,155, + 3,2,80,254,18,130,5,8,10,73,38,63,9,103,112,19,235,111,37,25,11,5,18,119,13,94,25,83,65,36,13,7,159,50,12,57,105,45,53,110, + 48,8,50,162,254,134,199,14,191,10,12,65,105,38,174,73,22,89,94,80,93,68,19,155,37,136,92,63,63,92,79,87,67,13,44,5,44,5,49,10, + 47,15,50,5,49,49,8,47,6,61,2,59,6,55,55,55,55,61,51,5,50,14,49,56,7,49,49,123,5,5,19,57,48,56,104,78,29,37,30,98, + 92,68,104,44,15,41,104,63,18,5,204,49,6,55,73,50,6,49,33,49,7,50,24,50,6,50,4,50,5,51,10,50,7,49,0,0,0,1,0,172, + 0,0,6,129,5,216,0,38,0,0,1,50,23,22,21,20,7,1,7,20,23,37,50,23,21,20,35,5,34,39,38,61,1,52,55,0,55,54,53,52, + 39,35,5,34,39,53,52,55,51,4,66,143,113,52,124,253,108,11,97,3,110,78,9,105,252,161,161,108,27,139,2,109,20,11,98,11,252,181,57,11, + 98,14,5,216,141,77,79,138,98,253,160,62,89,26,209,97,3,89,198,174,53,56,24,138,108,2,55,27,27,22,80,32,204,80,30,64,12,0,0,0, + 0,6,0,170,0,0,6,130,5,216,0,17,0,36,0,48,0,60,0,70,0,88,0,0,1,32,1,22,21,16,5,6,43,1,32,1,38,61,1,16, + 1,54,5,38,35,32,3,6,21,16,5,22,51,32,19,54,61,1,2,37,38,1,35,34,39,19,22,59,1,50,55,19,6,1,6,29,1,33,53,16, + 37,54,55,19,6,37,22,23,33,38,39,38,39,19,22,1,50,23,22,21,20,7,6,43,1,34,39,38,61,1,52,55,54,3,137,1,127,1,8,114, + 254,195,194,212,32,254,132,254,250,99,1,82,185,2,30,166,167,254,212,235,126,1,23,178,223,1,85,234,89,1,254,173,5,254,212,28,168,141,209,48, + 56,8,50,46,212,141,254,224,95,254,87,1,31,18,19,210,7,2,134,95,3,254,86,1,31,34,43,210,125,254,73,82,56,25,68,41,46,7,80,57, + 20,72,39,5,216,254,141,175,214,254,176,253,147,1,131,174,178,28,1,83,1,2,132,172,93,254,217,177,194,254,196,226,138,1,90,150,166,15,1,89, + 224,4,251,72,89,1,111,31,29,254,146,88,3,40,73,95,5,16,1,32,219,13,12,254,146,4,143,145,176,59,46,50,25,1,108,79,254,207,80,37, + 46,71,54,31,82,37,38,5,73,56,28,0,0,6,0,100,0,0,6,200,5,216,0,15,0,29,0,41,0,78,0,108,0,141,0,0,1,62,1,53, + 52,39,54,55,22,21,20,6,7,38,53,52,3,38,35,34,6,7,38,39,54,51,50,22,23,6,1,20,22,23,6,7,46,1,53,52,55,22,1,6, + 35,34,39,38,39,7,6,7,6,35,34,39,22,51,50,54,55,54,53,52,39,55,22,51,50,55,23,6,21,20,23,30,1,51,50,1,22,23,22,21, + 20,7,51,22,23,22,17,21,46,1,35,6,7,39,54,53,52,39,53,54,55,54,53,52,38,1,38,53,52,55,54,59,1,39,38,39,18,37,14,1, + 21,20,23,22,31,1,6,21,20,23,7,38,43,1,34,35,34,6,4,56,68,72,1,36,36,2,121,85,10,14,63,76,7,91,62,33,21,87,116,7, + 133,74,25,254,40,91,70,3,16,104,111,2,42,3,193,109,166,46,50,164,92,1,61,119,92,96,124,128,85,80,55,184,58,47,27,69,34,32,31,29, + 64,26,55,63,160,69,80,254,166,162,93,16,69,4,105,120,195,13,210,112,183,130,70,1,64,182,84,53,24,251,134,4,121,109,180,18,2,44,2,17, + 1,20,177,34,38,101,191,1,66,2,64,113,166,14,3,4,128,178,1,145,40,139,65,12,12,14,5,19,18,95,195,37,24,25,14,2,13,35,4,43, + 22,28,66,5,55,33,254,234,78,143,32,38,34,46,203,79,16,15,6,253,178,83,6,36,170,2,88,69,47,75,40,65,97,93,100,76,80,42,24,23, + 39,70,67,97,89,114,61,5,160,67,217,52,52,109,111,10,67,130,254,255,10,157,182,10,147,40,7,7,70,25,75,31,156,87,89,26,142,252,70,24, + 25,149,161,118,2,98,137,1,14,112,104,180,39,85,68,152,39,82,29,60,9,10,36,136,147,0,0,0,0,23,0,100,255,252,4,246,5,209,0,7, + 0,29,0,35,0,43,0,63,0,86,0,109,0,131,0,162,0,173,0,178,0,183,0,188,0,193,0,201,0,208,0,213,0,218,0,223,0,229,0,237, + 0,244,1,35,0,0,1,6,21,20,51,50,55,38,23,34,7,6,35,34,39,55,39,54,51,50,23,22,23,6,7,38,39,36,53,52,1,6,7,35, + 38,55,3,22,51,50,53,52,39,38,19,21,6,35,34,39,53,38,53,54,55,22,23,6,21,20,4,7,35,38,39,21,39,53,36,39,54,55,22,23, + 6,21,20,4,21,20,7,39,54,53,52,39,54,3,21,39,53,36,39,54,55,22,23,6,21,20,23,6,4,23,6,7,39,54,53,52,7,36,39,54, + 55,22,23,6,21,20,4,23,6,7,38,39,54,53,52,39,21,39,19,21,39,53,36,53,54,55,51,50,23,7,23,6,35,34,39,38,35,34,21,20, + 4,23,6,7,38,39,36,39,54,1,20,30,1,51,38,52,55,34,14,1,5,22,23,55,38,39,22,23,55,38,39,22,23,55,38,39,22,7,55,38, + 39,20,21,20,7,23,53,52,39,6,7,23,54,53,52,5,23,54,55,6,7,23,54,55,6,7,23,54,55,6,31,1,53,52,55,6,23,55,38,53, + 52,53,6,21,63,1,38,39,6,21,20,23,21,39,53,38,35,34,7,32,39,54,37,22,23,22,51,53,38,39,46,1,53,52,62,1,50,30,1,21, + 20,6,7,6,7,51,20,35,21,54,55,4,23,6,33,38,35,34,3,87,4,11,12,25,10,79,7,8,66,55,25,22,91,108,35,62,11,13,204,13, + 2,141,70,157,1,18,254,136,95,31,15,1,86,104,27,13,10,5,34,239,11,26,34,3,174,4,64,46,44,61,1,54,2,15,26,116,74,254,232,4, + 2,128,52,86,174,1,182,112,49,69,2,1,81,74,254,147,3,5,113,77,105,206,1,10,2,118,2,5,150,104,163,253,254,243,5,1,112,72,73,163, + 2,21,3,4,174,33,58,175,189,74,74,74,254,129,13,205,8,61,52,109,92,23,24,56,66,8,7,42,2,210,6,7,174,63,111,1,7,2,12,254, + 118,18,33,18,15,15,17,34,18,1,186,116,44,27,96,151,115,38,42,95,126,80,17,49,62,129,53,1,61,39,103,22,61,62,50,52,60,43,253,19, + 27,45,115,91,44,42,38,115,100,20,49,17,80,84,16,62,51,74,64,61,22,39,104,60,52,50,1,229,74,45,72,35,42,254,245,89,84,1,95,23, + 89,2,1,3,2,20,23,23,41,42,41,23,22,20,3,3,1,1,88,24,1,94,84,89,254,245,42,36,68,4,32,8,4,9,10,20,63,2,24,5, + 23,25,62,2,4,125,62,32,17,9,20,42,48,252,116,34,60,72,35,3,166,11,8,5,9,9,252,45,56,26,56,41,30,54,49,24,13,6,21,21, + 41,54,102,56,173,90,13,92,43,72,68,32,19,9,26,39,42,62,74,46,14,11,17,29,5,5,23,1,153,140,13,137,38,98,53,22,20,7,15,29, + 2,2,52,67,85,69,32,27,39,26,39,164,33,96,57,30,12,7,33,44,40,77,84,69,21,15,11,30,42,33,29,133,12,2,4,127,8,125,21,113, + 126,4,61,24,23,5,24,2,47,43,41,102,91,20,16,15,28,52,31,2,102,18,32,17,33,66,34,17,32,60,64,48,38,57,21,99,63,34,86,43, + 128,71,19,111,77,147,75,8,126,97,17,15,132,63,11,12,125,98,137,57,25,101,92,13,80,38,48,64,17,107,34,63,99,42,137,19,71,128,69,137, + 8,6,74,142,88,141,11,63,132,15,17,101,125,4,25,57,137,13,13,92,171,206,6,194,52,12,165,92,6,54,30,1,24,1,2,10,39,22,21,39, + 22,22,39,21,22,39,10,2,1,1,22,30,54,6,92,165,13,0,0,0,0,2,0,170,0,0,5,78,5,217,0,8,0,40,0,0,1,38,39,6, + 7,22,23,54,53,3,38,39,54,55,22,23,21,20,7,51,50,55,17,38,43,2,17,20,23,33,54,53,17,43,1,34,7,17,22,51,3,121,2,121, + 121,2,8,115,123,197,119,12,3,202,202,3,131,163,181,174,169,179,6,164,99,254,166,99,168,6,179,169,174,181,4,222,177,2,2,177,142,113,88,159, + 254,241,101,184,243,2,2,243,14,183,88,99,254,247,54,254,12,181,174,174,181,1,244,54,1,9,99,0,0,3,0,170,255,253,4,136,5,217,0,3, + 0,32,0,44,0,0,1,21,51,53,39,53,51,21,51,21,35,21,51,5,21,33,17,23,21,39,3,35,3,39,53,23,17,33,53,33,53,35,53,19, + 51,17,33,53,33,53,35,21,33,21,33,2,45,202,183,171,125,125,9,1,148,254,99,143,136,1,177,1,134,134,254,107,1,150,118,164,71,1,12,254, + 244,71,254,245,1,11,5,64,60,60,51,102,102,162,88,1,175,253,232,139,156,133,254,238,1,188,134,155,130,1,113,176,88,162,252,207,1,187,71,99, + 99,71,0,0,0,2,0,170,0,0,5,155,7,74,0,7,0,32,0,0,1,17,51,50,54,16,38,35,1,17,33,50,22,21,20,6,43,1,17,55, + 51,9,1,35,3,17,35,17,3,35,9,1,51,3,40,209,116,127,127,116,254,138,1,118,206,212,212,206,209,218,220,254,103,1,174,219,239,166,254,219, + 1,183,254,110,220,6,167,253,216,144,1,8,144,252,4,4,159,223,216,217,222,254,205,237,254,66,254,40,1,6,254,250,1,23,254,233,1,225,1,181, + 0,1,0,170,0,0,3,178,5,215,0,31,0,0,1,51,23,21,51,23,21,7,35,21,33,23,21,7,33,17,7,35,39,17,33,39,53,55,33,53, + 35,39,53,55,51,53,1,215,171,6,165,5,5,165,1,36,6,6,254,220,6,171,6,254,222,5,5,1,34,163,5,5,163,5,215,5,155,6,148,6, + 113,6,152,5,252,130,5,5,3,126,5,152,6,113,6,148,6,155,0,0,0,1,0,170,255,253,6,130,5,213,0,43,0,0,1,33,23,21,7,35, + 17,33,53,55,51,23,17,7,35,39,53,33,17,51,23,21,7,33,39,53,55,51,17,33,21,7,35,39,17,55,51,23,21,33,17,35,39,53,2,187, + 1,182,6,6,160,2,59,6,106,6,6,106,6,253,197,160,6,6,254,74,6,6,170,253,196,6,115,6,6,115,6,2,60,170,6,5,213,6,119,6, + 253,209,161,6,6,254,73,6,6,158,253,200,6,106,6,6,106,6,2,56,158,6,6,1,183,6,6,161,2,47,6,119,0,2,0,178,0,0,6,123, + 5,216,0,27,0,44,0,0,1,51,50,23,35,39,32,3,6,21,16,5,22,51,37,21,6,7,6,43,1,32,3,38,53,16,37,54,1,51,50,23, + 51,21,7,22,21,39,7,35,53,55,39,53,51,3,156,21,221,210,6,239,254,169,209,94,1,86,136,156,1,1,160,138,81,54,28,254,145,238,132,1, + 134,172,2,127,3,6,62,209,168,65,177,169,3,66,172,213,5,216,146,54,254,202,158,185,254,146,214,71,50,6,107,26,11,1,62,192,233,1,170,238, + 89,254,51,201,3,126,187,17,124,124,3,201,126,3,0,0,0,4,0,170,0,0,6,131,5,217,0,22,0,79,0,98,0,115,0,0,1,22,51,50, + 55,22,51,50,55,53,51,23,21,20,15,1,34,39,6,35,34,39,52,23,51,22,23,50,21,3,51,36,17,52,39,53,22,17,21,16,7,6,7,21, + 22,59,1,21,6,43,1,34,7,39,35,34,39,53,51,50,55,53,39,38,39,38,53,16,63,1,21,6,21,16,5,53,3,53,55,50,37,21,6,7, + 6,21,20,23,21,35,38,39,38,53,16,37,54,51,52,37,22,23,22,29,1,20,7,6,7,52,55,54,61,1,16,37,2,234,27,64,46,33,37,44, + 66,21,5,2,69,30,44,35,33,45,81,16,178,2,50,34,8,10,2,1,36,110,222,224,76,47,80,165,26,117,72,129,22,69,68,144,56,136,60,121, + 86,88,125,36,99,199,33,117,1,38,18,3,35,255,0,95,65,134,146,2,158,93,38,1,12,121,35,2,123,132,130,176,166,89,31,54,92,254,214,5, + 217,75,48,48,68,7,40,5,59,27,4,44,44,101,34,135,64,11,5,252,32,228,1,112,194,207,3,215,254,235,36,254,241,221,66,22,5,40,5,33, + 99,99,28,5,42,3,64,114,74,177,177,1,1,230,31,5,192,226,254,167,245,2,3,38,22,169,42,6,69,99,204,239,233,214,2,74,233,107,103,1, + 12,205,70,4,2,30,112,183,216,47,212,182,81,6,7,82,175,191,2,1,109,244,0,0,0,3,0,170,0,0,5,5,5,217,0,91,0,102,0,110, + 0,0,1,50,23,15,1,22,23,22,21,20,7,23,35,21,50,55,54,53,52,39,55,51,22,17,16,3,38,35,34,21,20,23,22,21,20,21,6,35, + 6,35,34,39,38,39,21,20,21,20,23,20,35,34,53,54,61,1,6,21,6,43,1,34,39,52,54,53,52,35,34,7,2,17,52,55,51,23,6,21, + 20,23,22,23,53,35,53,38,53,52,55,47,1,54,3,20,23,51,54,53,52,39,6,7,6,37,6,21,20,23,54,53,52,2,216,66,82,19,15,127, + 51,56,205,1,120,121,142,135,125,21,5,234,149,120,79,56,120,30,13,42,12,9,44,6,59,94,80,104,111,80,154,7,57,6,41,14,150,46,82,116, + 154,228,5,21,125,214,63,121,119,204,238,24,16,87,206,135,4,70,29,89,51,40,1,112,34,65,144,5,217,75,15,124,46,80,81,85,199,98,75,120, + 129,157,198,176,114,19,165,254,254,254,224,254,201,174,45,28,147,38,42,2,3,59,2,34,238,49,150,3,4,70,113,59,60,116,77,146,93,191,35,59, + 64,164,34,43,173,1,33,1,77,233,166,19,121,174,251,163,47,18,120,75,92,204,190,103,124,18,72,253,255,146,74,105,139,83,126,25,74,63,162,115, + 99,137,102,61,168,152,0,0,0,1,0,171,0,0,6,129,5,215,0,50,0,0,1,50,23,22,21,20,7,23,7,35,39,6,35,34,39,21,1,35, + 38,39,54,1,54,51,22,51,50,55,39,7,35,38,39,19,4,21,7,22,23,53,54,61,1,52,39,38,43,1,34,7,54,3,232,237,209,150,125,194, + 140,3,185,165,217,170,143,254,252,3,204,4,26,1,89,24,7,113,158,191,151,217,108,6,187,9,233,1,27,126,230,29,66,251,137,119,37,98,120,170, + 5,215,189,155,215,201,138,148,131,170,110,88,3,254,49,141,7,25,1,152,29,85,104,198,115,116,12,1,2,14,5,159,175,14,2,90,124,36,254,101, + 69,55,143,0,0,5,0,170,0,0,6,130,5,216,0,11,0,18,0,22,0,26,0,33,0,0,19,16,0,33,32,0,17,16,0,33,32,0,19,20, + 23,1,3,6,0,19,22,23,27,1,54,55,9,1,54,53,52,0,39,17,170,1,182,1,54,1,55,1,181,254,75,254,201,254,202,254,74,152,121,1, + 170,2,196,254,163,173,176,192,2,95,205,170,254,137,1,187,113,254,161,211,2,234,1,55,1,183,254,73,254,201,254,202,254,76,1,180,1,54,229,120, + 1,245,1,194,4,254,163,253,98,177,6,2,104,253,150,8,164,1,182,254,151,112,245,249,1,93,4,254,66,0,0,0,0,4,0,170,0,0,6,130, + 5,216,0,18,0,30,0,40,0,52,0,0,1,21,30,1,51,50,54,53,16,0,33,32,0,3,62,1,51,50,22,5,20,6,35,34,38,53,52,54, + 51,50,22,5,52,38,34,6,21,20,22,50,54,37,16,0,33,32,0,17,16,0,33,32,0,3,150,10,197,144,146,201,254,98,254,228,254,222,254,123, + 20,24,177,149,143,198,1,202,61,38,42,60,60,42,40,59,253,69,59,82,58,58,82,59,3,229,254,75,254,201,254,202,254,74,1,182,1,54,1,55, + 1,181,2,248,26,142,193,207,154,1,22,1,152,254,123,254,201,172,178,192,158,41,58,58,41,42,60,60,42,42,60,60,42,41,58,60,39,254,202,254, + 76,1,180,1,54,1,55,1,183,254,73,0,255,255,0,170,0,0,6,130,5,213,18,38,15,92,0,0,16,39,15,92,0,0,2,134,16,7,15,92, + 0,0,5,13,255,255,0,170,0,0,6,131,5,212,18,38,15,92,0,0,16,39,15,92,0,1,2,133,16,7,15,93,0,0,5,12,255,255,0,170, + 0,0,6,130,5,213,18,38,15,92,0,0,16,39,15,93,0,0,2,133,16,7,15,92,0,0,5,13,255,255,0,170,0,0,6,130,5,213,18,38, + 15,92,0,0,16,39,15,93,0,0,2,133,16,7,15,93,0,0,5,13,255,255,0,170,0,0,6,130,5,213,18,38,15,93,0,0,16,39,15,92, + 0,0,2,133,16,7,15,92,0,0,5,13,255,255,0,170,0,0,6,130,5,213,18,38,15,93,0,0,16,39,15,92,0,0,2,133,16,7,15,93, + 0,0,5,13,255,255,0,170,0,0,6,130,5,213,18,38,15,93,0,0,16,39,15,93,0,0,2,133,16,7,15,92,0,0,5,13,255,255,0,170, + 0,0,6,130,5,213,18,38,15,93,0,0,16,39,15,93,0,0,2,133,16,7,15,93,0,0,5,13,0,10,0,135,255,234,6,165,5,225,0,12, + 0,64,0,70,0,76,0,82,0,88,0,94,0,100,0,106,0,112,0,0,0,20,23,22,51,50,54,52,39,38,35,34,7,5,38,52,55,51,54,55, + 39,54,55,23,54,55,53,54,50,23,21,22,23,55,22,23,7,22,23,51,22,20,7,35,6,7,23,6,7,39,6,7,21,6,35,39,53,38,39,7, + 38,39,55,38,39,1,54,55,3,6,7,5,22,23,55,38,39,1,54,55,39,6,7,37,22,23,37,38,39,1,38,39,5,22,23,37,6,7,23,54, + 55,5,6,7,19,54,55,37,38,39,7,22,23,2,244,48,47,67,66,94,48,47,65,67,47,253,127,28,28,112,27,107,84,15,99,82,124,194,39,78, + 40,182,137,79,102,17,85,105,28,112,28,28,112,20,113,85,17,102,79,138,182,39,39,78,181,138,81,97,17,81,104,27,1,251,33,36,12,142,98,1, + 128,41,29,183,100,140,254,175,8,22,203,76,23,2,247,24,6,1,18,19,81,253,107,20,10,254,240,22,75,2,180,8,22,204,82,17,254,116,33,37, + 12,141,99,254,127,29,39,184,100,141,3,38,132,47,47,94,132,48,48,48,195,39,78,39,183,124,80,95,16,80,102,30,112,28,28,112,22,111,81,15, + 96,81,121,185,39,78,39,176,131,80,92,11,81,103,29,112,28,28,112,23,109,81,11,92,80,121,186,1,44,19,10,1,13,22,77,170,10,19,198,78, + 21,254,62,38,26,171,96,130,55,30,34,10,127,98,254,75,30,42,17,140,86,244,38,34,172,103,123,137,18,11,254,240,30,77,165,9,20,194,77,30, + 0,5,0,170,255,106,7,173,6,110,0,10,0,21,0,33,0,45,0,61,0,0,1,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20, + 6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,54,55,54,32,23,22,23,7,38,39,38, + 32,7,6,7,2,130,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253, + 242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,236,36,51,182,2,4,182,50,37,115,29,39,142,254,108,142,40,28,3,253,59,81, + 81,118,82,83,58,59,81,81,59,58,83,83,217,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1, + 192,254,64,253,37,56,51,181,181,51,56,72,44,39,142,141,40,43,0,0,0,5,0,170,255,106,7,173,6,110,0,10,0,21,0,33,0,45,0,61, + 0,0,1,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33, + 32,0,17,16,0,33,32,0,19,55,22,23,22,32,55,54,55,23,6,7,6,32,39,38,2,130,81,59,58,82,82,58,59,81,2,66,82,116,83,83, + 58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,236,115, + 28,40,142,1,148,142,39,29,115,37,50,182,253,252,182,51,3,253,59,81,81,118,82,83,58,59,81,81,59,58,83,83,217,1,117,2,15,253,241,254, + 139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,253,170,71,43,39,142,142,39,44,72,56,51,181,181,51,0,0, + 0,4,0,170,255,106,7,173,6,110,0,10,0,21,0,33,0,49,0,0,1,20,22,51,50,54,52,38,35,34,6,5,20,22,51,50,54,53,52,38, + 34,6,1,16,0,33,32,0,17,16,0,33,32,0,37,22,23,22,32,55,54,55,39,6,7,6,32,39,38,39,2,130,81,59,58,82,82,58,59,81, + 2,66,81,59,58,83,83,116,82,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,1,115,36,51,182,2,4,182,50,37,115,29,39, + 142,254,108,142,40,28,3,253,58,83,82,118,81,81,59,58,83,83,58,59,81,81,254,178,1,117,2,15,253,241,254,139,254,140,253,244,2,12,91,56, + 51,181,181,51,56,72,44,39,142,142,39,43,0,10,0,170,0,0,6,130,5,216,0,7,0,12,0,19,0,34,0,42,0,50,0,58,0,65,0,73, + 0,88,0,0,1,51,23,17,7,35,39,17,5,23,21,7,39,37,23,7,35,38,39,53,5,50,31,1,20,7,6,35,34,39,38,53,52,55,54,1, + 33,23,21,7,33,39,53,37,33,23,21,7,33,39,53,3,51,22,23,21,7,39,53,37,51,23,21,7,39,53,37,51,23,17,7,35,39,17,3,6, + 21,20,23,22,51,50,55,54,53,39,38,35,34,3,115,78,6,6,78,6,2,57,57,248,61,252,251,253,62,3,200,45,2,49,215,92,13,196,72,48, + 181,101,37,189,70,253,75,1,83,6,6,254,173,6,4,119,1,90,7,7,254,166,6,71,3,134,114,61,248,253,180,3,59,247,61,2,27,78,6,6, + 78,6,36,130,25,69,124,32,49,134,9,63,146,39,5,216,6,254,161,6,6,1,95,156,62,3,255,63,238,254,64,199,55,4,181,226,96,189,100,24, + 168,64,92,180,104,27,254,237,6,80,6,6,80,6,6,80,6,6,80,254,231,130,121,3,63,253,4,43,60,3,254,62,4,119,6,254,161,6,6,1, + 95,2,86,71,123,63,44,114,17,67,130,65,154,0,0,0,0,2,2,221,0,0,6,131,5,215,0,23,0,43,0,0,1,32,1,22,21,16,1,6, + 43,1,34,39,53,36,55,54,17,16,37,38,39,53,52,55,23,21,4,17,16,5,7,21,51,50,55,54,55,54,61,1,16,1,38,35,3,126,1,139, + 1,16,106,254,116,179,176,49,47,81,1,21,125,155,254,178,136,93,149,40,1,201,254,175,43,6,86,158,233,82,29,254,165,163,158,5,215,254,135,173, + 198,254,120,254,255,98,15,6,79,177,202,1,12,1,144,224,80,16,3,11,14,62,3,197,254,20,254,110,232,24,4,83,152,244,93,93,9,1,61,1, + 5,102,0,0,0,2,0,170,0,0,4,80,5,216,0,23,0,43,0,0,33,32,1,38,53,16,1,54,59,1,50,23,21,4,7,6,17,16,5,22, + 23,21,20,7,39,53,36,17,16,37,55,53,35,34,7,6,7,6,29,1,16,1,22,51,3,175,254,117,254,239,105,1,140,179,177,49,46,80,254,236, + 126,154,1,78,136,93,149,40,254,55,1,80,44,6,86,159,232,83,28,1,90,164,158,1,121,173,198,1,136,1,1,99,15,7,79,177,203,254,245,254, + 112,225,79,16,4,10,14,62,3,197,1,237,1,145,232,24,3,83,150,245,92,94,9,254,194,254,252,102,0,2,0,175,255,48,4,58,5,219,0,49, + 0,62,0,0,1,22,23,22,21,20,7,6,7,21,55,21,7,23,35,39,35,53,51,39,38,39,38,53,52,55,54,55,38,39,38,61,1,51,21,20, + 23,22,23,51,54,55,54,61,1,51,21,20,7,6,5,35,6,7,6,16,22,51,50,54,16,39,38,3,105,40,36,133,132,108,143,216,220,1,129,1, + 202,202,2,147,109,133,133,36,40,40,36,133,142,91,85,117,38,116,85,91,142,133,36,254,247,38,117,85,91,183,130,127,183,91,85,4,86,26,36,131, + 189,188,124,100,14,209,2,100,1,202,203,98,209,13,101,124,188,189,131,36,26,25,37,131,188,8,10,130,90,83,7,7,83,90,130,10,8,188,131,37, + 95,6,84,89,254,252,170,170,1,4,89,84,0,2,0,175,254,255,5,45,5,218,0,11,0,35,0,0,1,34,6,21,20,22,51,50,54,53,52,38, + 1,38,53,52,0,51,50,0,16,7,6,7,17,33,21,33,17,35,17,33,53,33,17,38,2,238,164,231,231,164,161,234,234,253,201,169,1,80,239,236, + 1,83,169,136,180,1,16,254,240,180,254,240,1,16,181,5,39,228,164,163,216,216,163,164,228,252,237,157,238,239,1,76,254,180,254,34,156,126,18,254, + 248,124,254,255,1,1,124,1,9,17,0,0,0,2,0,175,255,227,5,45,6,190,0,11,0,35,0,0,37,50,54,53,52,38,35,34,6,21,20,22, + 1,22,21,20,0,35,34,0,16,55,54,55,17,33,53,33,17,51,17,33,21,33,17,22,2,238,164,231,231,164,161,234,234,2,55,169,254,176,239,236, + 254,173,169,136,180,254,241,1,15,180,1,16,254,240,181,150,228,164,163,216,216,163,164,228,3,19,157,238,239,254,180,1,76,1,222,156,126,18,1,8, + 124,1,1,254,255,124,254,247,17,0,0,0,0,2,0,162,255,227,6,165,5,195,0,9,0,30,0,0,1,34,6,16,22,51,50,54,16,38,19,6, + 35,34,0,16,0,23,22,23,1,33,55,33,17,7,17,1,22,21,20,2,225,164,231,231,164,161,234,234,251,168,244,235,254,172,1,89,230,228,112,1, + 105,254,141,140,1,238,143,254,154,112,3,150,228,254,184,216,216,1,72,228,252,241,164,1,61,1,220,1,85,9,8,103,1,92,142,254,20,143,1,117, + 254,164,146,193,232,0,0,0,0,1,1,83,0,0,5,215,5,216,0,27,0,0,1,53,50,54,52,38,35,34,6,29,1,35,52,0,51,50,0,21, + 20,7,51,17,51,17,35,17,33,53,3,13,122,170,169,123,121,171,150,1,2,184,187,1,2,109,227,151,151,252,19,2,19,1,171,242,171,171,121,2, + 185,1,4,254,252,185,168,123,3,197,250,40,1,124,151,0,0,1,1,192,0,0,5,106,5,216,0,31,0,0,1,35,53,51,53,51,21,51,21,35, + 17,54,51,50,18,21,20,6,29,1,35,52,54,53,52,38,35,34,6,21,17,35,2,42,106,106,152,178,178,111,152,178,239,140,151,141,155,111,110,154, + 152,4,141,151,180,180,151,254,125,109,254,254,187,90,229,121,2,132,238,72,123,169,170,122,254,70,0,0,0,2,0,248,0,0,6,50,5,216,0,10, + 0,49,0,0,0,34,6,21,20,22,51,50,54,53,52,39,22,23,22,20,6,35,34,38,52,55,54,55,17,33,17,33,53,51,17,35,53,33,17,33, + 17,51,17,33,17,33,21,35,17,51,21,33,17,33,3,205,112,79,79,56,55,79,58,61,48,76,152,109,107,153,76,47,62,254,224,254,206,155,155,1, + 50,1,32,151,1,32,1,49,153,153,254,207,254,224,1,140,79,55,57,78,78,57,55,194,18,48,76,216,153,153,216,76,49,17,1,140,254,75,151,2, + 211,152,254,74,1,182,254,74,1,182,152,253,45,151,1,181,0,1,1,4,0,0,6,39,5,216,0,60,0,0,37,21,35,53,35,53,51,53,38,39, + 38,39,53,7,39,55,51,23,21,39,21,51,21,35,22,23,22,23,17,7,39,55,51,23,21,39,17,54,55,54,61,1,51,53,7,39,55,51,23,21, + 39,21,51,21,6,7,6,7,21,51,21,3,226,151,176,176,165,122,150,1,144,1,145,152,144,144,2,2,1,104,78,103,145,1,146,151,145,145,101,77, + 106,1,144,1,145,152,144,144,1,1,150,122,165,175,187,187,187,151,139,22,122,150,215,84,142,140,153,153,140,142,84,2,151,104,79,20,2,202,141,139, + 154,154,139,141,253,55,20,78,106,150,1,89,142,140,153,153,140,142,89,4,211,150,121,23,139,151,0,0,0,2,1,236,0,0,5,63,5,216,0,18, + 0,29,0,0,1,33,32,23,22,21,16,7,6,35,33,17,33,23,21,7,33,39,17,23,17,33,50,55,54,55,52,39,38,35,1,244,1,153,1,46, + 100,32,251,59,54,254,170,2,122,8,8,252,253,8,145,1,70,130,72,16,8,162,37,81,5,216,208,77,95,254,246,92,17,253,173,8,130,8,8,5, + 199,131,254,36,130,26,80,164,60,16,0,0,0,1,0,93,0,0,6,206,5,218,0,36,0,0,33,16,0,35,34,6,21,20,23,35,38,53,52,54, + 51,32,19,22,23,54,55,18,33,50,22,21,20,7,35,54,53,52,38,35,34,0,17,3,86,254,226,169,129,34,84,134,93,163,146,1,116,131,8,5, + 4,8,132,1,115,147,162,93,134,85,34,130,168,254,226,2,88,3,5,197,34,128,128,132,161,132,187,252,251,49,40,40,49,3,5,187,132,161,132,128, + 129,34,196,252,251,253,168,0,0,2,0,183,0,0,6,117,5,216,0,8,0,46,0,0,1,34,6,16,22,32,54,16,38,39,54,55,62,2,51,21, + 34,2,7,6,7,22,23,22,21,20,0,35,34,0,53,52,55,54,55,38,39,38,2,35,53,50,30,1,23,22,3,149,147,206,206,1,38,207,205,149, + 131,76,86,97,161,185,123,167,131,21,23,46,43,146,254,217,211,208,254,216,148,41,48,24,21,129,171,122,185,186,72,85,77,3,92,207,254,218,206,206, + 1,38,207,150,5,61,66,180,174,108,254,200,108,19,15,30,41,149,210,209,254,217,1,39,209,210,149,42,30,14,19,108,1,56,108,174,180,66,61,0, + 0,2,0,192,0,0,6,106,5,218,0,19,0,27,0,0,1,38,39,53,4,32,37,21,6,7,17,22,23,21,36,32,5,53,54,63,1,54,51,23, + 17,6,35,39,2,18,168,170,1,91,2,248,1,87,176,166,166,176,254,169,253,8,254,165,170,168,152,116,117,233,116,117,233,4,252,22,52,148,90,90, + 151,47,24,251,226,23,47,152,91,91,148,53,21,12,13,13,4,7,13,13,0,4,0,231,0,64,6,69,5,111,0,8,0,29,0,38,0,60,0,0, + 0,34,6,20,22,51,50,54,52,1,44,1,39,53,22,4,51,50,39,38,53,52,54,51,50,22,16,7,14,1,1,50,54,52,38,34,6,20,22,1, + 12,1,23,21,38,36,35,34,23,22,21,20,6,35,34,38,53,52,55,62,1,5,66,190,132,132,95,94,133,254,94,254,200,254,148,153,253,1,108,59, + 130,8,131,205,147,149,206,104,73,246,253,171,94,133,133,188,134,133,1,29,1,57,1,108,153,253,254,150,58,133,8,131,205,147,149,206,104,73,245,2, + 184,132,190,133,133,190,254,12,2,40,43,124,84,22,26,108,167,147,207,207,254,218,103,77,76,2,182,132,190,132,132,190,132,2,120,2,41,43,123,84, + 21,26,108,166,148,207,207,148,146,103,77,77,0,2,1,30,0,0,6,13,5,216,0,19,0,77,0,0,1,62,1,53,52,39,46,1,35,34,7,14, + 1,21,20,23,30,1,51,50,19,52,54,51,50,22,21,20,0,21,22,23,50,55,23,6,35,34,38,53,52,0,53,52,38,35,34,6,21,20,22,23, + 30,1,21,20,7,6,7,6,35,34,38,39,38,53,52,55,54,55,54,51,50,23,50,53,52,38,2,148,75,50,14,29,113,39,36,35,75,49,14,30, + 111,39,35,48,223,180,172,218,254,222,4,134,71,100,65,127,111,99,144,1,31,164,132,127,150,46,25,37,9,32,51,116,56,56,60,173,47,22,27,51, + 117,55,55,76,74,8,77,1,140,29,113,39,35,35,75,50,14,30,111,39,35,36,76,49,2,240,161,201,221,176,187,254,10,180,124,3,88,72,119,121, + 111,199,1,225,194,134,165,155,129,60,145,62,98,128,17,87,68,115,45,22,75,120,54,56,60,60,114,46,21,41,13,26,184,0,0,0,0,2,0,109, + 254,143,6,190,5,216,0,58,0,68,0,0,1,50,22,21,62,1,51,50,22,29,1,62,1,51,50,22,17,16,1,22,23,35,38,39,6,7,53,54, + 55,39,17,52,53,16,39,14,1,7,17,35,17,16,38,43,2,34,6,7,17,35,17,52,39,51,22,23,62,1,1,17,36,19,52,38,43,1,34,6, + 2,168,63,119,40,198,75,62,82,48,131,68,60,100,254,131,1,146,168,46,74,167,175,191,124,9,46,58,133,63,151,31,35,1,1,41,179,19,149,152, + 142,118,36,23,183,2,196,1,2,24,45,28,4,30,143,5,216,198,128,119,207,167,219,202,125,119,232,254,239,254,104,254,191,94,193,41,161,101,7,116, + 28,87,217,3,87,18,17,1,25,1,1,217,200,252,97,3,154,1,65,106,226,215,252,116,4,65,190,191,79,176,93,188,252,146,253,208,250,1,82,193, + 139,206,0,0,0,2,0,171,0,107,6,129,5,57,0,3,0,35,0,0,19,33,21,33,1,33,53,33,38,53,52,0,51,50,0,21,20,7,33,21, + 33,53,35,54,55,54,53,52,38,34,6,21,20,23,22,23,171,5,214,250,42,2,45,253,211,1,98,67,1,1,185,186,1,3,68,1,132,253,175,1, + 18,17,86,170,244,170,85,16,19,1,3,152,1,143,152,104,131,185,1,3,254,253,185,131,104,152,152,13,17,85,121,122,170,170,122,121,85,17,13,0, + 0,1,0,69,255,60,6,232,5,216,0,56,0,0,1,20,22,23,51,53,51,23,7,39,53,35,34,39,38,39,3,52,53,16,39,14,1,7,17,35, + 17,16,38,43,2,34,6,7,17,35,17,52,39,51,22,23,62,1,51,50,22,21,62,1,51,50,22,29,1,19,5,0,103,89,89,4,203,203,4,89, + 203,68,44,8,21,46,58,133,63,151,31,35,1,1,41,179,19,149,152,142,118,36,23,183,69,63,119,40,198,75,62,82,1,1,15,111,125,1,118,173, + 175,4,118,120,74,118,3,22,18,17,1,25,1,1,217,200,252,97,3,154,1,65,106,226,215,252,116,4,65,190,191,79,176,93,188,198,128,119,207,167, + 219,202,253,132,0,1,0,169,255,255,6,130,5,216,0,20,0,0,1,17,9,1,7,9,1,47,2,9,1,63,2,9,1,33,53,33,17,5,234,253, + 63,1,61,108,254,195,254,88,1,106,1,1,168,254,195,1,106,1,1,61,2,193,254,4,3,0,2,216,1,252,253,63,254,195,108,1,61,254,88,1, + 106,1,1,168,1,61,1,106,1,254,195,2,193,152,253,0,0,2,0,192,0,0,6,106,5,216,0,41,0,49,0,0,1,50,18,55,54,51,50,22, + 21,20,6,35,34,39,14,1,7,35,53,55,54,19,38,2,35,34,2,21,20,21,7,52,2,39,53,50,22,19,54,55,62,1,1,22,51,50,55,38, + 39,34,3,83,107,81,25,109,195,121,153,143,142,155,122,44,126,138,168,154,122,105,50,64,58,36,154,158,141,132,147,161,40,46,45,41,122,1,87,93, + 130,161,9,7,159,152,5,216,252,158,4,221,190,103,145,171,133,160,215,4,118,1,4,1,120,16,3,21,254,45,195,15,14,2,253,1,240,6,97,222, + 254,237,201,88,91,150,252,38,145,197,157,19,0,2,0,176,1,57,6,123,4,162,0,39,0,81,0,0,19,0,51,50,23,22,50,54,51,50,23,22, + 50,55,54,51,50,19,7,38,35,34,7,6,34,39,38,35,34,7,6,35,34,39,38,35,34,4,35,39,17,0,51,50,23,22,51,50,55,54,50,23, + 22,51,50,55,54,51,50,19,7,38,35,34,7,6,35,34,39,38,35,34,7,6,35,34,39,38,34,4,35,39,176,1,69,115,45,13,24,112,172,56, + 54,24,26,114,86,43,41,124,109,94,63,95,51,60,86,112,25,28,59,55,83,87,55,56,25,24,54,55,254,254,5,53,1,68,116,44,14,24,56,55, + 86,87,110,23,27,56,57,86,43,41,125,109,94,63,95,51,60,87,55,56,26,27,59,55,84,86,56,55,25,24,110,254,255,5,53,1,157,1,15,40, + 71,142,71,71,71,36,254,196,51,185,53,76,75,78,67,71,72,70,213,98,1,217,1,13,39,70,70,72,72,70,70,35,254,197,50,185,54,77,76,78, + 68,71,72,72,213,97,0,0,0,1,1,65,0,0,5,234,5,216,0,28,0,0,1,7,2,1,7,0,19,33,53,33,2,1,23,0,19,51,18,1, + 55,0,3,33,7,33,18,1,39,0,3,4,14,241,32,254,234,165,1,51,27,254,216,1,40,28,254,205,166,1,22,32,242,31,1,23,165,254,205,27, + 1,39,1,254,216,29,1,51,166,254,233,31,2,153,3,254,174,254,191,3,1,95,1,55,172,1,54,1,96,3,254,192,254,173,1,83,1,64,3,254, + 160,254,202,172,254,201,254,161,3,1,65,1,82,0,0,0,0,5,0,201,0,0,6,99,5,216,0,15,0,32,0,36,0,84,0,100,0,0,1,54, + 55,38,39,38,34,14,1,21,20,22,23,22,23,33,51,33,54,55,62,1,53,52,46,1,35,34,7,6,7,22,23,1,17,33,17,1,17,38,39,46, + 1,53,52,62,1,51,50,23,53,52,54,55,54,55,53,35,53,51,53,51,21,51,21,35,21,22,23,30,1,29,1,54,51,50,30,1,21,20,6,7, + 6,7,17,1,20,30,1,51,50,62,1,53,52,46,1,35,34,14,1,3,80,1,2,35,51,74,156,147,84,82,74,22,23,1,87,141,1,86,24,22, + 74,81,83,147,79,77,74,52,34,2,1,254,63,2,245,252,185,42,38,69,108,110,198,104,80,76,36,32,13,16,108,108,105,108,108,16,13,31,37,76, + 79,104,198,110,108,68,39,41,253,214,25,45,23,24,45,24,24,45,24,23,45,25,3,199,3,3,43,28,41,81,149,80,81,146,40,14,8,8,14,40, + 146,81,80,149,81,41,28,43,3,3,253,184,254,209,1,47,254,129,1,127,13,22,54,196,107,108,197,106,31,2,36,63,18,7,4,54,70,87,87,70, + 54,4,7,18,63,36,2,31,106,197,108,107,196,54,22,13,254,129,4,125,25,43,25,25,43,25,24,45,23,23,45,0,0,8,0,226,0,0,6,74, + 5,216,0,72,0,78,0,82,0,104,0,124,0,144,0,165,0,187,0,0,1,38,39,52,62,1,51,50,30,1,21,6,7,19,3,34,39,52,62,1, + 51,50,30,1,21,6,7,27,1,38,39,52,62,1,51,50,30,1,21,6,7,27,1,38,53,52,62,1,51,50,30,1,21,6,7,3,1,38,53,52, + 62,1,51,50,30,1,21,6,35,3,17,33,17,1,53,7,33,39,29,2,33,53,1,23,3,54,55,62,1,53,52,46,1,35,34,14,1,21,20,30, + 1,51,50,55,1,23,3,54,55,62,1,52,46,1,35,34,14,1,20,30,1,51,50,55,1,55,19,22,51,50,62,1,52,46,1,35,34,14,1,20, + 22,23,22,23,1,51,3,50,55,62,1,53,52,46,1,35,34,14,1,21,20,22,23,22,23,1,55,19,22,51,50,62,1,53,52,46,1,35,34,14, + 1,21,20,22,23,22,23,1,77,95,12,29,54,29,28,54,28,4,57,239,52,83,18,29,53,31,28,53,29,2,46,189,43,67,2,30,53,27,29,53, + 30,3,67,38,185,46,29,54,27,30,54,29,11,86,92,1,1,43,29,53,28,30,53,29,13,99,160,252,163,3,36,181,254,149,183,2,215,252,255,77, + 231,7,7,18,20,20,35,20,18,35,21,20,36,18,7,9,1,54,136,187,6,5,17,19,19,36,18,19,35,20,19,36,19,7,8,1,173,115,96,5, + 5,19,37,19,21,35,19,18,36,20,20,18,8,7,254,154,100,48,19,16,17,21,22,34,19,18,37,19,19,19,14,15,1,41,104,166,11,11,19,35, + 20,21,34,19,20,35,19,19,18,4,3,3,251,2,95,28,51,28,28,51,28,64,22,254,6,2,190,93,28,50,28,28,50,28,45,34,253,20,3,52, + 30,48,28,52,26,26,52,28,54,24,252,202,2,228,47,42,27,51,28,28,51,27,85,16,253,74,2,3,34,43,28,51,27,27,51,28,94,254,49,253, + 209,2,47,254,223,225,75,61,211,48,164,164,1,84,42,2,14,3,4,10,35,19,20,35,20,20,35,20,19,35,20,1,253,248,32,2,249,2,3,10, + 35,38,36,19,19,36,38,35,20,1,253,19,27,2,209,1,20,35,38,36,19,19,36,38,35,10,5,2,253,10,3,66,10,10,35,20,19,35,20,20, + 35,19,20,35,10,8,2,252,218,42,1,234,3,21,34,20,19,36,19,19,36,19,20,34,11,2,2,0,0,5,1,85,255,254,5,214,5,214,0,29, + 0,33,0,39,0,45,0,50,0,0,1,33,21,51,53,33,21,35,21,7,17,23,21,51,21,33,53,51,53,55,51,17,35,39,53,35,53,33,21,51, + 1,53,33,21,1,55,53,33,21,23,17,7,21,33,53,39,53,17,55,33,17,3,8,1,21,171,1,14,115,92,92,115,251,127,115,93,1,1,93,115, + 1,9,170,2,151,251,238,3,74,82,252,218,82,73,3,20,74,1,253,126,5,214,155,155,162,144,150,253,183,149,143,163,163,143,152,2,69,151,144,162, + 155,250,251,55,55,3,234,131,95,95,131,253,118,116,128,128,116,52,2,33,2,253,221,0,0,4,1,182,0,0,5,118,5,216,0,55,0,67,0,81, + 0,94,0,0,1,38,53,52,55,54,55,38,39,38,39,53,54,55,54,55,54,55,38,39,38,53,52,62,1,51,50,30,1,21,20,7,6,7,22,23, + 22,23,22,23,21,6,7,6,7,22,23,22,21,20,7,6,7,1,33,9,1,53,51,53,35,53,35,21,35,21,51,21,19,54,53,52,46,1,34,14, + 1,21,20,23,3,33,0,20,30,1,50,62,1,52,46,1,35,34,6,2,203,31,32,8,11,60,36,41,1,1,41,43,78,28,30,26,17,22,45,78, + 42,41,78,45,21,16,26,28,29,77,44,42,1,1,42,37,58,11,8,31,32,2,2,1,26,252,64,1,15,1,12,172,172,118,172,172,162,60,45,77, + 84,77,45,63,222,2,138,254,75,29,53,58,54,29,30,54,28,29,52,1,148,53,57,60,53,17,14,38,63,72,80,4,80,73,75,42,14,10,18,29, + 39,41,43,75,42,42,75,43,41,39,29,19,9,14,42,75,73,80,4,80,72,62,38,15,17,53,60,58,54,3,4,254,117,1,148,1,78,124,108,124, + 124,108,124,254,178,45,73,43,78,41,41,78,43,64,54,254,172,5,25,58,53,28,28,53,58,53,27,27,0,4,1,81,0,0,5,219,5,216,0,41, + 0,53,0,62,0,111,0,0,1,54,53,52,38,53,52,55,22,21,20,7,0,19,33,38,53,52,0,61,1,6,7,6,7,39,7,38,39,54,53,52, + 39,54,55,46,1,53,52,55,22,23,3,54,59,1,6,21,20,43,1,34,39,53,3,23,20,7,35,34,61,1,54,19,38,39,6,21,20,22,21,20, + 7,6,7,22,21,20,7,22,23,55,7,54,55,54,55,22,21,20,0,21,20,23,37,2,1,50,53,35,54,53,52,38,39,6,21,20,22,21,20,7, + 3,30,4,22,70,122,8,1,234,45,252,54,13,1,138,90,56,46,158,9,44,139,31,78,2,48,72,21,7,33,104,54,162,37,96,6,43,69,21,8, + 4,6,7,72,10,28,41,216,35,77,25,29,11,59,44,4,74,25,103,97,35,135,29,105,82,11,254,130,12,3,107,39,254,18,1,4,31,13,77,31, + 18,8,4,232,8,11,21,43,14,49,94,104,103,26,27,254,189,252,111,56,58,160,1,40,64,6,115,3,142,18,22,30,46,80,249,192,30,28,109,122, + 32,19,5,27,110,27,120,254,235,63,46,35,49,30,15,254,112,35,52,15,30,23,49,2,167,96,38,62,37,27,33,18,16,15,97,99,44,44,197,192, + 76,24,72,74,10,144,4,173,30,30,120,254,236,125,54,52,1,3,55,1,124,1,10,43,12,79,74,74,41,19,33,19,17,15,0,0,0,4,1,48, + 255,255,5,251,5,215,0,13,0,29,0,80,0,91,0,0,0,20,30,1,51,50,62,1,52,46,1,35,34,6,19,20,30,1,51,50,62,1,53,52, + 46,1,35,34,14,1,1,21,33,53,7,38,53,52,18,55,54,55,38,39,38,53,52,54,55,54,55,38,39,38,52,62,1,51,50,30,1,20,7,6, + 7,22,23,30,1,21,20,7,6,7,22,23,22,18,21,20,7,39,38,39,46,1,35,34,6,7,6,7,2,191,58,101,55,57,101,56,57,102,55,54, + 101,96,16,28,15,16,28,16,16,29,15,14,29,16,2,91,251,217,83,11,165,146,38,40,30,21,42,85,77,27,29,26,15,23,44,78,41,40,78,45, + 21,17,25,27,30,75,86,41,22,30,38,38,147,166,12,92,4,64,69,245,128,129,245,67,65,4,3,193,112,100,56,56,100,112,103,54,54,1,14,16, + 27,15,15,27,16,15,28,16,16,28,250,187,1,1,1,57,58,160,1,37,78,21,15,29,38,75,82,83,151,42,14,10,19,29,39,84,77,42,42,77, + 84,39,29,20,9,14,42,151,83,82,75,38,29,16,20,78,254,219,160,58,57,132,125,113,121,131,131,121,113,125,0,0,0,8,0,201,0,0,6,99, + 5,216,0,15,0,32,0,36,0,84,0,100,0,104,0,121,0,138,0,0,1,54,55,38,39,38,34,14,1,21,20,22,23,22,23,33,51,33,54,55, + 62,1,53,52,46,1,35,34,7,6,7,22,23,1,17,33,17,1,17,38,39,46,1,53,52,62,1,51,50,23,53,52,54,55,54,55,53,35,53,51, + 53,51,21,51,21,35,21,22,23,30,1,29,1,54,51,50,30,1,21,20,6,7,6,7,17,1,20,30,1,51,50,62,1,53,52,46,1,35,34,14, + 1,1,21,33,53,55,33,38,39,46,1,53,52,62,1,51,50,23,22,23,6,21,51,52,39,54,55,54,51,50,30,1,21,20,6,7,6,7,33,3, + 80,1,2,35,51,74,156,147,84,82,74,22,23,1,87,141,1,86,24,22,74,81,83,147,79,77,74,52,34,2,1,254,63,2,245,252,185,42,38,69, + 108,110,198,104,80,76,36,32,13,16,108,108,105,108,108,16,13,31,37,76,79,104,198,110,108,68,39,41,253,214,25,45,23,24,45,24,24,45,24,23, + 45,25,1,164,253,115,206,254,232,18,17,61,66,68,119,64,62,61,41,29,2,241,2,29,41,61,61,65,119,68,66,61,18,18,254,233,3,199,3,3, + 43,28,41,81,149,80,81,146,40,14,8,8,14,40,146,81,80,149,81,41,28,43,3,3,253,184,254,209,1,47,254,129,1,127,13,22,54,196,107,108, + 197,106,31,2,36,63,18,7,4,54,70,87,87,70,54,4,7,18,63,36,2,31,106,197,108,107,196,54,22,13,254,129,4,125,25,43,25,25,43,25, + 24,45,23,23,45,252,182,200,200,206,7,12,33,121,67,66,123,67,33,23,36,3,2,2,3,36,23,33,67,123,66,67,121,33,12,7,0,3,0,226, + 0,0,6,74,5,216,0,72,0,76,0,80,0,0,1,38,39,52,62,1,51,50,30,1,21,6,7,19,3,34,39,52,62,1,51,50,30,1,21,6, + 7,27,1,38,39,52,62,1,51,50,30,1,21,6,7,27,1,38,53,52,62,1,51,50,30,1,21,6,7,3,1,38,53,52,62,1,51,50,30,1, + 21,6,35,3,17,33,17,5,53,33,21,1,53,33,21,1,77,95,12,29,54,29,28,54,28,4,57,239,52,83,18,29,53,31,28,53,29,2,46,189, + 43,67,2,30,53,27,29,53,30,3,67,38,185,46,29,54,27,30,54,29,11,86,92,1,1,43,29,53,28,30,53,29,13,99,160,252,163,3,36,253, + 41,2,215,253,41,3,251,2,95,28,51,28,28,51,28,64,22,254,6,2,190,93,28,50,28,28,50,28,45,34,253,20,3,52,30,48,28,52,26,26, + 52,28,54,24,252,202,2,228,47,42,27,51,28,28,51,27,85,16,253,74,2,3,34,43,28,51,27,27,51,28,94,254,49,253,209,2,47,203,78,78, + 254,214,79,79,0,4,1,85,255,254,5,214,5,214,0,3,0,7,0,37,0,41,0,0,1,53,33,21,1,53,33,21,19,33,21,51,53,33,21,35, + 21,7,17,23,21,51,21,33,53,51,53,55,51,17,35,39,53,35,53,33,21,51,1,53,33,21,4,214,253,128,2,202,252,236,252,1,21,171,1,14, + 115,92,92,115,251,127,115,93,1,1,93,115,1,9,170,2,151,251,238,4,132,94,94,252,47,111,111,5,35,155,155,162,144,150,253,183,149,143,163,163, + 143,152,2,69,151,144,162,155,250,251,55,55,0,2,1,182,0,0,5,118,5,216,0,52,0,64,0,0,1,52,55,54,55,38,39,38,39,53,54,55, + 54,55,54,55,38,39,38,53,52,62,1,51,50,30,1,21,20,7,6,7,22,23,22,23,22,23,21,6,7,6,7,22,23,22,21,20,7,1,33,1, + 38,1,53,51,53,35,53,35,21,35,21,51,21,2,172,32,8,11,60,36,41,1,1,41,43,78,28,30,26,17,22,45,78,42,41,78,45,21,16,26, + 28,29,77,44,42,1,1,42,37,58,11,8,31,32,1,22,252,64,1,15,25,1,37,172,172,118,172,172,2,2,60,53,17,14,38,63,72,80,4,80, + 73,75,42,14,10,18,29,39,41,43,75,42,42,75,43,41,39,29,19,9,14,42,75,73,80,4,80,72,62,38,15,17,53,60,58,54,254,110,1,148, + 53,1,25,124,108,124,124,108,124,0,0,0,0,4,1,76,0,0,5,224,5,216,0,51,0,63,0,72,0,78,0,0,1,54,53,52,38,53,52,55, + 30,1,21,20,7,51,20,35,0,19,33,38,53,52,0,53,52,39,6,43,1,6,35,34,35,55,7,38,39,54,53,52,39,54,55,54,53,52,38,53, + 52,55,22,23,7,21,22,59,1,50,53,52,55,35,34,7,3,21,20,59,1,54,53,39,34,1,23,0,19,51,2,3,22,37,30,58,85,15,34,4, + 2,2,24,45,252,54,13,1,149,1,66,117,10,90,103,4,3,48,107,114,27,88,2,48,99,3,45,20,104,56,170,4,8,21,69,43,6,96,37,115, + 28,10,72,7,62,1,201,52,1,119,6,77,45,4,230,23,39,25,57,22,46,30,81,89,13,47,12,1,254,172,252,111,56,58,160,1,27,113,8,7, + 167,146,104,80,28,83,229,190,27,26,109,104,10,9,28,26,35,37,66,27,122,255,16,30,49,34,48,64,254,41,24,29,15,53,34,2,64,89,254,243, + 253,4,3,82,0,1,1,48,255,255,5,251,5,215,0,46,0,0,5,38,53,52,18,55,54,55,38,39,38,53,52,54,55,54,55,38,39,38,52,62, + 1,51,50,30,1,20,7,6,7,22,23,30,1,21,20,7,6,7,22,23,22,18,21,20,7,1,59,11,165,146,38,40,30,21,42,85,77,27,29,26, + 15,23,44,78,41,40,78,45,21,17,25,27,30,75,86,41,22,30,38,38,147,166,12,1,57,58,160,1,37,78,21,15,29,38,75,82,83,151,42,14, + 10,19,29,39,84,77,42,42,77,84,39,29,20,9,14,42,151,83,82,75,38,29,16,20,78,254,219,160,58,57,0,0,0,1,1,67,0,0,5,232, + 5,212,0,35,0,0,1,22,19,18,23,22,29,1,20,7,6,35,34,39,35,21,16,23,35,53,54,17,39,35,7,6,35,34,47,1,53,52,55,0, + 63,1,3,152,94,216,237,6,39,162,53,64,154,95,42,83,215,85,3,38,47,85,127,187,76,9,187,1,59,89,3,5,212,167,254,236,254,234,57,85, + 80,40,167,96,22,221,12,254,229,150,6,151,1,29,3,88,133,209,73,46,183,203,1,130,165,3,0,0,0,2,0,185,0,1,6,115,5,209,0,24, + 0,50,0,0,1,50,19,22,21,50,55,18,51,50,23,22,29,1,16,7,0,7,35,1,38,53,52,55,54,3,21,20,23,1,51,1,54,61,1,52, + 39,38,35,32,3,6,21,35,52,39,38,35,34,7,6,2,42,218,116,28,6,13,112,235,209,122,38,221,254,61,60,6,253,160,120,199,81,229,208,1, + 219,3,2,62,104,189,71,58,254,248,86,10,6,72,101,189,174,107,37,5,209,254,237,80,24,70,1,53,211,78,80,13,254,254,231,253,217,66,2,237, + 178,182,210,124,45,254,143,16,219,228,253,188,2,187,161,151,38,172,112,28,254,65,38,26,78,209,224,177,70,0,0,0,0,2,1,88,0,0,5,210, + 5,212,0,8,0,13,0,0,9,1,21,0,7,38,1,38,53,9,4,3,150,2,60,253,227,31,15,254,23,70,2,58,254,3,2,1,2,1,254,94, + 5,212,253,26,7,253,59,34,11,2,128,86,13,2,150,253,103,253,100,2,156,2,30,0,0,1,0,228,0,0,6,71,5,212,0,55,0,0,1,50, + 23,22,23,20,15,1,51,54,59,1,50,23,22,21,20,7,6,7,34,3,35,21,16,23,21,35,39,54,17,53,35,2,35,34,39,38,53,52,55,54, + 59,1,50,23,51,53,38,39,38,61,1,52,55,54,3,151,214,101,13,3,120,60,3,74,84,19,238,96,23,209,40,71,242,101,3,82,208,6,85,3, + 100,245,191,102,25,246,66,51,9,86,78,3,84,29,60,215,71,5,212,227,52,56,117,160,60,28,202,66,60,205,104,12,6,1,18,9,254,169,109,6, + 6,128,1,77,3,254,235,201,68,58,233,83,12,28,3,71,69,110,81,14,201,104,19,0,0,3,1,66,0,1,5,234,5,213,0,34,0,60,0,66, + 0,0,1,22,1,22,29,1,20,7,6,43,1,34,39,35,21,16,23,35,53,54,17,35,7,6,43,1,34,39,38,53,55,53,52,55,0,55,6,1, + 6,21,22,23,22,59,1,50,55,51,50,23,22,59,1,50,55,54,61,1,52,39,2,3,51,38,39,34,7,3,151,126,1,127,86,181,34,48,22,145, + 98,42,83,215,86,42,56,85,105,22,160,81,25,3,206,1,34,95,124,254,174,81,10,148,22,41,16,119,96,183,7,31,83,103,19,137,65,10,203,230, + 142,63,13,15,6,16,5,213,225,254,54,139,134,3,209,78,16,218,13,254,232,155,6,151,1,35,101,117,174,66,63,13,3,200,212,1,103,73,199,254, + 111,130,133,187,53,9,218,70,148,167,40,30,31,176,207,1,31,251,112,23,90,82,0,0,0,1,0,182,0,0,6,119,5,212,0,23,0,0,1,50, + 23,22,23,51,54,55,54,51,50,23,22,21,20,7,1,35,1,38,53,52,55,54,2,40,203,116,42,2,3,35,92,108,135,209,126,32,208,253,239,6, + 253,206,168,199,84,5,212,235,93,49,162,107,108,224,83,73,250,227,253,133,2,177,205,218,211,124,45,0,0,1,1,88,0,0,5,210,5,212,0,8, + 0,0,9,1,22,21,1,38,1,52,55,3,150,1,247,69,253,196,12,253,206,111,5,212,253,115,85,13,253,27,8,2,221,14,138,0,0,3,0,228, + 0,0,6,72,5,220,0,50,0,96,0,103,0,0,1,50,23,22,21,20,15,1,54,59,1,50,23,22,21,20,7,6,7,34,3,35,21,16,23,21, + 35,39,54,17,53,35,2,35,34,39,38,53,52,55,54,59,1,50,23,38,39,53,52,55,54,3,20,31,1,21,38,43,1,34,15,1,20,23,22,51, + 50,19,54,55,51,22,23,22,51,50,55,54,61,1,52,47,1,35,34,7,53,54,55,54,53,52,39,38,35,34,7,1,20,7,51,53,38,53,3,155, + 203,104,25,114,22,31,61,41,248,92,16,210,34,73,241,102,3,82,209,6,85,3,100,246,192,103,25,247,67,51,38,61,31,99,28,216,71,240,169,12, + 107,118,9,243,61,7,136,61,78,210,114,16,22,7,37,83,90,158,168,85,12,253,54,6,118,107,129,32,26,187,54,41,184,83,1,7,28,60,28,5, + 220,206,70,57,132,166,23,6,215,56,58,211,100,12,7,1,20,9,254,167,109,6,6,128,1,79,4,254,232,203,69,58,235,82,12,6,112,177,38,203, + 105,19,254,179,155,204,12,3,9,212,67,148,93,38,1,39,27,65,120,134,133,190,46,43,6,222,48,3,9,3,137,110,77,44,182,87,16,200,251,206, + 28,96,3,99,22,0,0,0,0,4,0,216,255,254,6,84,5,212,0,16,0,33,0,49,0,77,0,0,1,51,20,6,7,20,22,23,35,38,39,38, + 39,48,53,52,54,37,51,20,6,7,20,22,19,35,38,39,38,39,52,53,52,54,5,51,20,6,7,20,22,23,35,38,39,38,39,53,52,54,19,30, + 1,21,20,6,4,32,36,38,53,52,54,55,51,6,7,6,20,22,4,32,36,54,52,39,38,39,2,118,13,145,2,204,7,13,29,163,48,15,165,1, + 65,13,146,2,205,6,13,29,162,49,15,166,1,89,13,146,2,205,6,13,28,163,49,15,166,44,168,190,185,254,177,254,148,254,177,185,189,168,3,131, + 75,86,167,1,46,1,74,1,47,166,86,76,131,5,57,63,155,99,130,121,201,166,116,51,90,14,114,136,237,96,237,151,197,187,254,206,251,178,78,139, + 8,9,177,209,91,79,196,125,161,154,253,208,145,66,114,14,145,173,254,30,49,177,97,96,176,98,98,176,96,97,177,49,41,69,77,168,152,85,85,152, + 168,77,69,41,0,1,0,172,255,246,2,183,5,213,0,17,0,0,1,51,23,17,20,15,1,35,34,47,1,52,63,1,50,23,51,17,2,104,72,7, + 196,48,35,212,28,4,211,33,99,90,4,5,213,8,250,253,163,45,4,133,31,130,24,5,64,4,212,0,0,1,0,172,255,246,4,111,5,213,0,29, + 0,0,1,51,23,21,22,23,22,21,20,7,35,39,54,53,52,39,38,39,17,20,7,35,34,53,52,55,51,50,23,17,2,88,87,8,27,173,240,122, + 4,30,61,228,92,25,224,57,242,212,23,96,89,5,213,7,39,54,63,70,138,146,96,32,49,84,70,71,42,26,251,214,153,45,168,131,23,64,4,214, + 0,1,1,120,255,47,5,179,5,213,0,30,0,0,1,5,23,17,20,7,35,34,61,1,52,63,1,50,23,17,37,17,20,15,1,35,34,61,1,52, + 63,1,50,23,17,2,253,2,179,3,192,54,213,177,39,86,81,253,220,150,67,26,216,170,43,89,80,5,213,202,4,250,237,155,42,164,4,126,22,3, + 58,4,11,169,251,219,137,56,8,155,7,122,34,4,67,4,211,0,0,0,0,2,0,188,255,246,6,111,5,213,0,24,0,28,0,0,1,23,17,20, + 5,34,39,52,55,50,23,51,17,33,17,6,7,35,32,53,52,55,50,23,17,23,21,33,53,6,107,4,254,251,233,18,233,109,79,3,252,165,8,242, + 4,254,254,236,100,88,88,3,91,5,213,4,251,18,213,21,164,138,14,59,2,149,253,90,207,36,177,125,16,64,4,225,207,156,156,0,0,2,0,181, + 255,250,3,34,5,217,0,12,0,21,0,0,19,51,23,17,51,54,51,22,19,2,5,39,17,19,17,36,17,54,53,52,39,34,187,45,5,3,170,145, + 227,20,29,253,179,3,56,1,162,1,149,119,5,217,6,252,63,237,3,254,255,254,87,88,3,5,214,251,212,254,157,99,1,49,13,12,148,8,0,0, + 0,2,0,172,0,0,2,48,5,217,0,13,0,19,0,0,19,51,23,17,37,23,17,7,35,39,17,5,35,17,19,17,51,37,17,35,177,41,6,1, + 78,2,4,40,5,254,175,2,52,2,1,29,2,5,217,5,254,47,161,2,251,99,5,5,1,229,160,4,138,253,153,254,125,144,1,127,0,2,0,173, + 0,0,3,52,5,217,0,40,0,44,0,0,1,51,23,17,55,23,21,6,7,17,55,21,6,7,17,7,35,39,17,5,17,7,35,39,17,7,53,52, + 55,17,35,7,53,55,17,55,51,23,17,37,17,1,17,37,17,2,135,46,5,119,3,3,119,122,1,121,5,46,5,254,224,5,42,5,129,129,2,127, + 129,5,42,5,1,32,254,224,1,32,5,217,5,254,208,60,2,141,7,60,254,139,55,135,4,67,254,215,4,4,1,17,140,254,166,4,4,1,65,60, + 142,6,60,1,123,56,139,65,1,31,4,4,254,250,134,1,77,253,150,254,135,139,1,116,0,1,0,172,0,0,5,80,5,217,0,72,0,0,1,35, + 48,35,34,7,35,34,39,53,54,53,52,39,53,54,55,51,22,59,1,53,52,39,53,54,55,51,22,50,55,51,22,23,21,6,29,1,51,50,55,51, + 22,23,21,6,21,20,23,21,6,43,1,38,43,2,17,20,23,21,6,7,35,38,34,7,35,38,39,53,54,53,2,182,168,4,179,80,56,24,11,99, + 99,2,32,57,83,181,167,131,3,29,58,45,140,45,58,29,3,131,163,181,83,56,33,2,99,99,11,25,55,80,179,4,164,131,3,29,58,45,140,45, + 58,29,3,131,3,17,90,35,59,49,55,70,45,58,29,3,131,175,181,83,56,33,2,99,99,2,33,56,83,181,175,131,3,29,58,45,70,55,49,59, + 35,90,254,82,181,83,57,32,2,99,99,2,32,57,83,181,0,6,0,132,0,0,5,156,5,217,0,6,0,13,0,20,0,27,0,59,0,71,0,0, + 1,6,7,22,23,55,53,5,21,23,54,55,38,39,1,38,39,6,7,23,51,3,35,7,22,23,54,55,3,51,55,22,23,6,7,39,35,17,23,6, + 7,38,39,55,17,35,7,38,39,54,55,23,51,53,39,54,55,22,23,15,1,21,35,21,51,17,51,17,51,53,35,53,1,59,22,48,47,23,95,2, + 237,94,23,47,47,23,254,134,44,47,44,45,68,45,1,45,67,45,44,46,45,7,228,208,10,122,122,10,208,228,126,106,105,104,104,126,228,208,11,122, + 122,11,208,228,126,104,105,104,106,126,110,116,116,54,116,116,3,180,45,46,44,45,67,46,1,46,67,46,44,46,45,1,110,23,47,47,23,95,252,82, + 95,23,47,47,23,2,247,126,105,106,104,104,126,254,78,208,11,121,121,11,208,1,178,126,104,105,105,105,126,214,209,11,122,122,11,209,115,159,46,254, + 128,1,128,46,159,0,0,0,0,12,0,172,0,0,6,129,5,172,0,20,0,35,0,46,0,54,0,67,0,77,0,104,0,119,0,140,0,151,0,166, + 0,175,0,0,1,33,50,31,1,55,51,50,21,3,33,39,53,54,55,53,2,39,38,61,1,7,51,50,23,22,21,2,7,35,36,39,53,18,55,54, + 5,21,19,7,21,51,55,7,38,47,1,1,23,19,38,43,1,34,7,1,22,19,23,21,20,7,6,43,1,38,3,53,23,19,51,50,63,1,52,47, + 1,6,37,51,50,23,22,21,7,35,39,2,15,1,23,7,35,38,3,38,61,1,52,63,1,35,39,53,55,23,21,23,51,21,20,7,21,22,23,19, + 51,23,53,39,1,51,23,21,33,50,55,51,23,21,6,3,6,43,1,21,7,35,2,61,1,39,23,17,7,33,34,47,1,53,52,55,5,7,23,51, + 53,52,59,1,50,63,1,33,38,61,1,5,6,7,21,20,31,1,33,17,3,40,1,139,58,29,77,98,8,5,173,254,164,5,18,82,187,16,46,113, + 23,112,55,30,176,16,3,254,211,4,158,17,44,1,18,202,22,202,95,28,113,16,20,253,30,240,160,62,77,28,84,44,3,155,18,149,5,80,23,36, + 146,12,180,54,156,133,54,36,2,48,95,228,253,19,20,9,117,51,5,5,100,180,15,3,5,7,3,22,173,20,85,20,2,100,5,128,18,3,116,1, + 156,200,2,28,95,2,125,5,5,1,115,42,36,2,5,6,196,25,34,195,5,8,172,82,8,5,254,214,116,48,6,88,2,88,95,95,5,8,231,22, + 47,105,254,107,8,253,184,61,6,90,30,1,14,5,172,71,134,56,7,254,212,5,5,17,42,5,1,70,20,22,4,5,13,128,49,10,254,198,17,172, + 8,2,1,26,8,46,23,2,254,157,15,3,173,13,197,13,5,254,209,138,1,23,144,102,254,245,17,254,239,41,20,77,67,18,11,1,61,5,15,254, + 234,103,26,57,69,162,129,107,215,79,13,5,57,254,203,33,21,40,5,27,1,45,26,31,7,28,131,41,59,5,5,38,5,13,2,8,198,10,26,254, + 1,93,8,3,172,254,212,5,116,33,5,2,21,254,177,29,121,5,1,34,13,3,179,7,254,165,5,134,38,13,50,124,12,172,170,8,28,98,179,1, + 20,8,29,97,36,10,85,43,6,1,21,0,0,4,0,156,0,32,6,143,5,217,0,10,0,35,0,56,0,77,0,0,1,51,17,7,53,55,51,17, + 51,21,33,5,38,53,52,63,1,39,55,19,39,7,6,21,20,23,22,51,50,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54, + 53,52,39,3,55,19,22,21,20,1,22,31,1,55,3,39,55,39,38,35,34,7,6,7,3,39,19,54,55,54,2,213,171,186,202,127,171,254,27,253, + 243,44,38,84,62,235,24,61,99,7,23,35,93,15,16,1,150,254,28,75,57,46,5,139,85,175,167,210,210,198,58,25,7,49,202,136,243,37,252,230, + 169,96,84,63,25,234,60,99,34,52,7,7,63,53,204,136,241,39,56,47,1,234,1,154,26,97,30,254,1,92,184,77,79,72,75,146,36,107,254,255, + 36,172,20,19,35,32,44,1,159,33,27,97,147,10,73,151,149,70,11,55,17,19,52,72,1,96,79,254,93,66,65,54,4,158,1,146,145,36,254,255, + 107,35,172,40,1,9,107,254,161,78,1,164,65,33,27,0,0,4,0,156,0,32,6,143,5,217,0,28,0,53,0,74,0,95,0,0,1,33,21,33, + 53,62,1,55,62,1,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,7,14,1,1,38,53,52,63,1,39,55,19,39,7,6,21,20,23, + 22,51,50,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,53,52,39,3,55,19,22,21,20,1,22,31,1,55,3,39,55,39, + 38,35,34,7,6,7,3,39,19,54,55,54,3,93,1,84,253,241,64,205,25,49,36,74,60,47,103,89,76,112,48,127,154,38,48,14,139,253,10,44, + 38,84,62,235,24,61,99,7,23,35,93,15,16,1,150,254,28,75,57,46,5,139,85,175,167,210,210,198,58,25,7,49,202,136,243,37,252,230,169,96, + 84,63,25,234,60,99,34,52,7,7,63,53,204,136,241,39,56,47,1,210,93,85,49,158,21,41,56,26,40,51,24,38,110,25,20,99,81,38,68,45, + 13,109,254,186,77,79,72,75,146,36,107,254,255,36,172,20,19,35,32,44,1,159,33,27,97,147,10,73,151,149,70,11,55,17,19,52,72,1,96,79, + 254,93,66,65,54,4,158,1,146,145,36,254,255,107,35,172,40,1,9,107,254,161,78,1,164,65,33,27,0,4,0,156,0,32,6,143,5,217,0,40, + 0,65,0,86,0,107,0,0,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7, + 53,62,1,51,50,22,21,20,6,1,38,53,52,63,1,39,55,19,39,7,6,21,20,23,22,51,50,55,33,21,33,34,39,38,37,6,7,35,21,39, + 55,21,51,54,55,54,53,52,39,3,55,19,22,21,20,1,22,31,1,55,3,39,55,39,38,35,34,7,6,7,3,39,19,54,55,54,4,90,11,95, + 173,157,51,108,70,72,101,53,94,92,86,79,111,115,72,71,74,73,41,96,86,75,109,49,129,154,83,252,106,44,38,84,62,235,24,61,99,7,23,35, + 93,15,16,1,150,254,28,75,57,46,5,139,85,175,167,210,210,198,58,25,7,49,202,136,243,37,252,230,169,96,84,63,25,234,60,99,34,52,7,7, + 63,53,204,136,241,39,56,47,2,190,2,83,60,92,101,14,18,108,30,18,50,51,45,50,91,39,38,39,41,14,20,98,15,13,89,75,52,74,254,24, + 77,79,72,75,146,36,107,254,255,36,172,20,19,35,32,44,1,159,33,27,97,147,10,73,151,149,70,11,55,17,19,52,72,1,96,79,254,93,66,65, + 54,4,158,1,146,145,36,254,255,107,35,172,40,1,9,107,254,161,78,1,164,65,33,27,0,5,0,156,0,32,6,143,5,217,0,2,0,13,0,38, + 0,59,0,80,0,0,1,3,51,3,51,17,51,21,35,21,35,53,33,53,1,38,53,52,63,1,39,55,19,39,7,6,21,20,23,22,51,50,55,33, + 21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,53,52,39,3,55,19,22,21,20,1,22,31,1,55,3,39,55,39,38,35,34,7,6, + 7,3,39,19,54,55,54,3,182,230,230,20,177,121,121,157,254,130,254,144,44,38,84,62,235,24,61,99,7,23,35,93,15,16,1,150,254,28,75,57, + 46,5,139,85,175,167,210,210,198,58,25,7,49,202,136,243,37,252,230,169,96,84,63,25,234,60,99,34,52,7,7,63,53,204,136,241,39,56,47,3, + 82,254,255,1,138,254,118,95,142,142,96,254,132,77,79,72,75,146,36,107,254,255,36,172,20,19,35,32,44,1,159,33,27,97,147,10,73,151,149,70, + 11,55,17,19,52,72,1,96,79,254,93,66,65,54,4,158,1,146,145,36,254,255,107,35,172,40,1,9,107,254,161,78,1,164,65,33,27,0,0,0, + 0,4,0,156,0,32,6,143,5,217,0,29,0,54,0,75,0,96,0,0,1,33,21,33,21,6,54,51,50,22,21,20,6,35,34,38,39,53,30,1, + 51,50,54,53,52,38,35,34,6,7,1,38,53,52,63,1,39,55,19,39,7,6,21,20,23,22,51,50,55,33,21,33,34,39,38,37,6,7,35,21, + 39,55,21,51,54,55,54,53,52,39,3,55,19,22,21,20,1,22,31,1,55,3,39,55,39,38,35,34,7,6,7,3,39,19,54,55,54,2,187,1, + 195,254,197,2,49,24,139,162,167,150,50,104,70,76,93,53,82,93,93,82,39,80,70,254,13,44,38,84,62,235,24,61,99,7,23,35,93,15,16,1, + 150,254,28,75,57,46,5,139,85,175,167,210,210,198,58,25,7,49,202,136,243,37,252,230,169,96,84,63,25,234,60,99,34,52,7,7,63,53,204,136, + 241,39,56,47,3,208,95,112,1,7,116,99,100,114,14,15,114,31,18,64,56,57,64,13,25,254,83,77,79,72,75,146,36,107,254,255,36,172,20,19, + 35,32,44,1,159,33,27,97,147,10,73,151,149,70,11,55,17,19,52,72,1,96,79,254,93,66,65,54,4,158,1,146,145,36,254,255,107,35,172,40, + 1,9,107,254,161,78,1,164,65,33,27,0,0,5,0,156,0,32,6,143,5,217,0,9,0,34,0,59,0,80,0,101,0,0,1,34,6,20,22,51, + 50,54,52,38,19,21,46,1,35,34,6,7,6,54,51,50,22,21,20,6,35,34,38,53,52,54,51,50,22,1,38,53,52,63,1,39,55,19,39,7, + 6,21,20,23,22,51,50,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,53,52,39,3,55,19,22,21,20,1,22,31,1,55, + 3,39,55,39,38,35,34,7,6,7,3,39,19,54,55,54,3,134,55,68,68,55,58,66,66,153,61,70,34,87,92,3,7,93,56,117,135,141,117,133, + 140,169,146,38,77,252,165,44,38,84,62,235,24,61,99,7,23,35,93,15,16,1,150,254,28,75,57,46,5,139,85,175,167,210,210,198,58,25,7,49, + 202,136,243,37,252,230,169,96,84,63,25,234,60,99,34,52,7,7,63,53,204,136,241,39,56,47,2,188,65,118,64,64,118,65,1,14,102,22,14,96, + 53,7,40,115,97,95,116,165,150,143,174,12,252,253,77,79,72,75,146,36,107,254,255,36,172,20,19,35,32,44,1,159,33,27,97,147,10,73,151,149, + 70,11,55,17,19,52,72,1,96,79,254,93,66,65,54,4,158,1,146,145,36,254,255,107,35,172,40,1,9,107,254,161,78,1,164,65,33,27,0,0, + 0,4,0,156,0,32,6,143,5,217,0,6,0,31,0,52,0,73,0,0,1,33,21,1,35,19,33,1,38,53,52,63,1,39,55,19,39,7,6,21, + 20,23,22,51,50,55,33,21,33,34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,53,52,39,3,55,19,22,21,20,1,22,31,1,55,3,39, + 55,39,38,35,34,7,6,7,3,39,19,54,55,54,2,162,2,2,254,240,147,254,254,163,254,38,44,38,84,62,235,24,61,99,7,23,35,93,15,16, + 1,150,254,28,75,57,46,5,139,85,175,167,210,210,198,58,25,7,49,202,136,243,37,252,230,169,96,84,63,25,234,60,99,34,52,7,7,63,53,204, + 136,241,39,56,47,3,186,50,253,185,2,26,253,123,77,79,72,75,146,36,107,254,255,36,172,20,19,35,32,44,1,159,33,27,97,147,10,73,151,149, + 70,11,55,17,19,52,72,1,96,79,254,93,66,65,54,4,158,1,146,145,36,254,255,107,35,172,40,1,9,107,254,161,78,1,164,65,33,27,0,0, + 0,3,0,156,0,32,6,143,5,217,0,24,0,45,0,66,0,0,55,38,53,52,63,1,39,55,19,39,7,6,21,20,23,22,51,50,55,33,21,33, + 34,39,38,37,6,7,35,21,39,55,21,51,54,55,54,53,52,39,3,55,19,22,21,20,1,22,31,1,55,3,39,55,39,38,35,34,7,6,7,3, + 39,19,54,55,54,200,44,38,84,62,235,24,61,99,7,23,35,93,15,16,1,150,254,28,75,57,46,5,139,85,175,167,210,210,198,58,25,7,49,202, + 136,243,37,252,230,169,96,84,63,25,234,60,99,34,52,7,7,63,53,204,136,241,39,56,47,214,77,79,72,75,146,36,107,254,255,36,172,20,19,35, + 32,44,1,159,33,27,97,147,10,73,151,149,70,11,55,17,19,52,72,1,96,79,254,93,66,65,54,4,158,1,146,145,36,254,255,107,35,172,40,1, + 9,107,254,161,78,1,164,65,33,27,0,0,0,6,0,172,0,0,6,127,5,161,0,16,0,26,0,39,0,57,0,72,0,82,0,0,1,33,50,31, + 1,55,51,21,2,7,33,53,54,55,3,38,35,7,50,31,1,3,36,39,18,55,54,1,18,21,23,20,7,6,43,1,38,3,54,55,5,18,23,39, + 2,15,1,23,35,3,39,54,55,54,53,39,53,51,1,51,21,33,50,55,51,20,3,6,43,1,21,35,3,39,23,17,7,33,34,47,1,52,55,3, + 42,1,134,58,33,74,99,6,157,16,254,169,97,5,198,35,13,102,105,42,49,193,254,245,27,149,22,49,3,90,166,2,97,15,40,125,14,175,24,201, + 252,121,171,2,112,192,4,3,5,5,201,8,4,80,26,100,228,2,216,2,1,138,33,30,3,201,24,31,204,5,168,94,5,5,254,222,116,47,5,84, + 5,161,84,125,55,2,254,237,21,5,53,9,1,98,26,5,92,86,254,182,154,19,1,4,28,47,254,86,254,234,23,39,102,58,8,15,1,58,23,112, + 27,254,224,13,63,254,182,16,41,29,1,92,32,31,128,41,11,57,3,254,165,115,26,9,254,164,23,115,1,37,176,6,254,169,5,128,48,48,130,0, + 0,7,0,170,0,0,6,131,5,217,0,19,0,37,0,50,0,60,0,74,0,92,0,101,0,0,1,51,32,19,22,29,1,16,5,6,43,1,32,3, + 38,61,1,16,37,54,23,21,50,31,1,21,6,7,21,33,54,55,35,7,38,39,38,35,1,22,51,54,19,38,35,38,35,34,7,6,7,5,21,19, + 51,50,55,52,47,1,34,5,23,6,7,20,31,1,51,52,63,1,51,23,39,1,7,22,23,51,53,55,51,50,63,1,53,35,6,35,33,39,53,5, + 6,29,1,20,31,1,51,17,3,137,27,1,139,243,97,254,111,163,183,3,254,80,232,83,1,60,190,137,38,51,121,27,58,1,24,10,132,3,83,79, + 18,21,26,253,136,242,9,4,149,66,23,29,50,95,53,78,13,2,129,153,118,98,26,101,41,14,251,205,80,75,11,139,29,3,27,142,9,76,139,1, + 249,135,6,129,3,6,172,36,61,106,3,22,34,254,196,6,253,234,65,106,26,252,5,217,254,146,174,207,6,254,79,235,76,1,134,168,163,53,1,95, + 241,131,147,3,107,206,3,22,31,3,8,240,44,137,22,12,254,223,139,15,1,1,126,18,121,125,31,222,3,254,244,138,47,157,77,60,52,123,49,22, + 232,59,67,25,248,44,241,254,229,251,3,236,91,6,128,177,3,16,6,95,101,105,39,12,91,41,4,1,36,0,0,0,0,8,0,170,0,0,6,131, + 5,217,0,15,0,32,0,47,0,58,0,66,0,82,0,96,0,106,0,0,1,32,19,22,21,16,5,6,35,32,3,38,53,16,37,54,1,16,5,22, + 59,1,32,19,54,53,16,37,38,35,32,3,6,1,33,50,31,1,55,21,6,7,33,53,55,38,47,1,35,50,31,1,3,35,38,39,54,55,54,1, + 22,29,1,6,43,1,3,37,33,23,7,35,39,35,2,7,21,38,3,39,52,55,39,1,51,21,33,50,55,21,3,7,35,7,21,35,39,37,33,23, + 17,7,35,34,47,1,54,3,152,1,151,237,103,254,132,164,209,254,94,231,95,1,136,170,253,249,1,98,157,170,48,1,104,229,92,254,150,160,184,254, + 123,223,92,2,91,1,58,53,24,58,81,109,27,254,240,77,146,26,27,77,91,30,45,154,3,227,18,119,28,44,2,163,137,21,108,100,156,252,216,1, + 20,145,3,3,78,3,166,6,12,156,2,86,78,2,253,6,1,71,20,24,173,23,169,6,6,135,254,138,1,43,6,6,245,81,39,6,1,5,217,254, + 151,178,212,254,88,233,89,1,116,162,219,1,169,235,84,253,18,254,112,216,88,1,89,165,197,1,140,224,83,254,166,159,1,109,69,98,44,3,204,35, + 3,52,254,39,12,70,86,254,254,127,16,213,26,32,254,167,226,33,23,130,1,9,89,244,3,49,254,234,21,26,11,1,18,17,28,141,49,254,236,95, + 20,6,254,220,9,6,85,238,140,5,254,235,5,103,44,49,0,5,0,170,0,0,6,131,5,217,0,7,0,23,0,31,0,65,0,82,0,0,1,22, + 23,50,55,38,39,6,1,32,19,22,21,16,5,6,35,32,3,38,53,16,37,54,1,6,7,22,51,54,55,38,1,21,35,6,43,1,46,1,53,52, + 55,52,53,52,54,55,50,23,54,51,30,1,21,20,21,22,21,20,6,7,35,34,39,35,37,16,5,22,59,1,32,19,54,53,16,37,38,35,32,3, + 6,1,194,2,183,144,97,87,162,175,1,212,1,151,237,103,254,132,164,209,254,94,231,95,1,136,170,1,225,162,87,97,144,183,2,2,254,43,3,118, + 178,14,140,122,1,155,135,157,127,128,158,135,155,1,122,140,14,178,119,2,253,60,1,98,157,170,48,1,104,229,92,254,150,160,184,254,123,223,92,2, + 244,205,2,203,194,4,3,2,38,254,151,178,212,254,88,233,89,1,116,162,219,1,169,235,84,253,221,4,194,203,2,205,191,254,243,28,189,15,185,80, + 7,8,4,5,116,153,1,170,170,1,153,116,5,4,8,7,80,185,15,189,97,254,112,216,88,1,89,165,197,1,140,224,83,254,166,159,0,2,1,49, + 0,2,5,250,5,217,0,24,0,46,0,0,1,50,21,6,7,23,33,50,23,7,33,23,33,22,19,55,23,6,5,38,3,33,34,3,52,1,6,35, + 34,46,1,53,52,55,54,55,23,6,7,20,30,1,50,54,55,23,6,2,154,153,1,128,24,1,19,12,16,4,254,237,12,1,189,12,141,134,48,5, + 254,238,16,149,254,35,12,85,1,248,113,123,124,226,125,64,33,47,40,25,2,83,152,166,151,42,69,46,5,217,142,163,2,230,146,4,101,6,254,114, + 40,141,8,89,24,1,173,3,36,133,250,104,63,125,225,125,124,114,60,46,217,60,67,83,152,83,83,76,169,50,0,0,0,3,0,150,0,0,6,96, + 5,205,0,22,0,26,0,30,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,37,33,17, + 33,2,239,19,20,31,27,43,42,28,30,21,19,19,20,31,28,84,28,30,21,19,253,167,5,202,250,219,4,128,251,128,2,233,42,28,30,21,19,19, + 20,31,27,43,42,28,30,21,19,19,20,31,27,253,66,5,205,250,51,165,4,131,0,0,0,4,0,150,0,0,6,96,5,205,0,22,0,45,0,49, + 0,53,0,0,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21, + 20,7,6,7,6,34,39,38,39,38,1,17,33,17,37,33,17,33,1,185,19,20,31,28,84,28,30,21,19,19,20,31,27,43,42,28,30,21,19,2, + 108,19,20,31,27,43,42,28,30,21,19,19,20,31,28,84,28,30,21,19,252,113,5,202,250,219,4,128,251,128,1,174,42,28,30,21,19,19,20,31, + 27,43,42,28,30,21,19,19,20,31,27,2,156,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,252,12,5,205,250,51,165,4, + 131,0,0,0,0,5,0,150,0,0,6,96,5,205,0,22,0,45,0,68,0,72,0,76,0,0,1,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,51,50, + 23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,37,33,17,33,1,185,19,20,31,28,84,28,30,21,19,19,20,31,27,43,42, + 28,30,21,19,1,54,19,20,31,27,43,42,28,30,21,19,19,20,31,28,84,28,30,21,19,1,54,19,20,31,27,43,42,28,30,21,19,19,20,31, + 28,84,28,30,21,19,252,113,5,202,250,219,4,128,251,128,1,174,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,1,102,42, + 28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,1,97,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,252, + 12,5,205,250,51,165,4,131,0,6,0,150,0,0,6,96,5,205,0,22,0,45,0,68,0,91,0,95,0,99,0,0,1,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,52, + 55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34, + 39,38,39,38,1,17,33,17,37,33,17,33,1,185,19,20,31,28,84,28,30,21,19,19,20,31,27,43,42,28,30,21,19,2,108,19,20,31,27,43, + 42,28,30,21,19,19,20,31,28,84,28,30,21,19,253,148,19,20,31,28,84,28,30,21,19,19,20,31,27,43,42,28,30,21,19,2,108,19,20,31, + 27,43,42,28,30,21,19,19,20,31,28,84,28,30,21,19,252,113,5,202,250,219,4,128,251,128,4,31,42,28,30,21,19,19,20,31,27,43,42,28, + 30,21,19,19,20,31,27,253,186,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42, + 28,30,21,19,19,20,31,27,2,156,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,252,12,5,205,250,51,165,4,131,0,0, + 0,7,0,150,0,0,6,96,5,205,0,22,0,45,0,68,0,91,0,114,0,118,0,122,0,0,1,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,52, + 55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,37,33,17,33,1,185,19,20,31,28,84,28,30,21,19, + 19,20,31,27,43,42,28,30,21,19,2,108,19,20,31,27,43,42,28,30,21,19,19,20,31,28,84,28,30,21,19,253,148,19,20,31,28,84,28,30, + 21,19,19,20,31,27,43,42,28,30,21,19,2,108,19,20,31,27,43,42,28,30,21,19,19,20,31,28,84,28,30,21,19,254,202,19,20,31,27,43, + 42,28,30,21,19,19,20,31,28,84,28,30,21,19,253,167,5,202,250,219,4,128,251,128,4,31,42,28,30,21,19,19,20,31,27,43,42,28,30,21, + 19,19,20,31,27,253,186,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30, + 21,19,19,20,31,27,2,156,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,254,245,42,28,30,21,19,19,20,31,27,43,42, + 28,30,21,19,19,20,31,27,253,66,5,205,250,51,165,4,131,0,0,0,0,8,0,150,0,0,6,96,5,205,0,23,0,47,0,70,0,93,0,116, + 0,139,0,143,0,147,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,37,52,55,54,55,54,51,50, + 23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,17,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1, + 52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35, + 34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,37,33,17,33,4,36,19,20, + 31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,253,149,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19, + 19,20,31,28,84,28,30,21,19,19,20,31,27,43,42,28,30,21,19,2,108,19,20,31,27,43,42,28,30,21,19,19,20,31,28,84,28,30,21,19, + 253,148,19,20,31,28,84,28,30,21,19,19,20,31,27,43,42,28,30,21,19,2,108,19,20,31,27,43,42,28,30,21,19,19,20,31,28,84,28,30, + 21,19,252,113,5,202,250,219,4,128,251,128,2,233,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19, + 20,31,27,43,42,28,30,21,19,19,20,31,27,1,147,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,253,86,42,28,30,21, + 19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,3,0,42,28,30, + 21,19,19,20,31,27,43,42,28,30,21,19,19,20,31,27,251,218,5,205,250,51,165,4,131,0,0,0,0,3,0,170,0,1,6,130,5,217,0,12, + 0,27,0,41,0,0,1,50,4,18,16,2,4,32,36,2,16,18,36,1,20,18,4,32,36,18,53,52,2,36,35,34,4,2,4,52,62,1,51,50, + 30,1,20,14,1,35,34,38,3,150,188,1,101,203,197,254,155,254,124,254,155,197,201,1,101,254,40,174,1,60,1,88,1,60,174,179,254,196,167,168, + 254,195,177,3,147,34,60,33,32,60,34,35,60,31,33,59,5,217,193,254,152,254,122,254,157,198,198,1,99,1,134,1,104,193,253,20,173,254,197,174, + 174,1,59,173,172,1,63,171,171,254,193,205,66,60,33,33,60,66,61,32,32,0,0,0,0,4,0,170,0,1,6,130,5,217,0,12,0,27,0,41, + 0,54,0,0,1,50,4,18,16,2,4,32,36,2,16,18,36,1,20,18,4,32,36,18,53,52,2,36,35,34,4,2,4,52,62,1,51,50,30,1, + 20,14,1,35,34,38,36,50,30,1,20,14,1,35,34,46,1,52,54,3,150,188,1,101,203,197,254,155,254,124,254,155,197,201,1,101,254,40,174,1, + 60,1,88,1,60,174,179,254,196,167,168,254,195,177,3,147,34,60,33,32,60,34,35,60,31,33,59,253,62,64,60,35,34,60,33,32,60,34,35,5, + 217,193,254,152,254,122,254,157,198,198,1,99,1,134,1,104,193,253,20,173,254,197,174,174,1,59,173,172,1,63,171,171,254,193,205,66,60,33,33,60, + 66,61,32,32,220,32,61,66,60,33,33,60,66,61,0,0,0,2,0,170,0,1,6,130,5,217,0,12,0,26,0,0,1,50,4,18,16,2,4,32, + 36,2,16,18,36,1,50,62,1,52,46,1,35,34,14,1,20,30,1,3,150,188,1,101,203,197,254,155,254,124,254,155,197,201,1,101,2,58,31,60, + 35,34,60,32,33,60,34,35,59,5,217,193,254,152,254,122,254,157,198,198,1,99,1,134,1,104,193,252,150,32,61,66,60,33,33,60,66,61,32,0, + 0,3,0,170,0,1,6,130,5,217,0,12,0,26,0,39,0,0,1,50,4,18,16,2,4,32,36,2,16,18,36,1,50,62,1,52,46,1,35,34, + 14,1,20,30,1,36,20,30,1,51,50,62,1,52,46,1,34,6,3,150,188,1,101,203,197,254,155,254,124,254,155,197,201,1,101,2,58,31,60,35, + 34,60,32,33,60,34,35,59,252,165,34,60,32,33,60,34,35,60,64,59,5,217,193,254,152,254,122,254,157,198,198,1,99,1,134,1,104,193,252,150, + 32,61,66,60,33,33,60,66,61,32,159,66,60,33,33,60,66,61,32,32,0,1,0,170,0,0,6,130,0,200,0,3,0,0,55,33,21,33,170,5, + 216,250,40,200,200,0,0,0,0,2,0,170,0,0,6,130,0,200,0,3,0,7,0,0,55,33,21,33,37,33,21,33,170,2,96,253,160,3,120,2, + 96,253,160,200,200,200,200,0,255,255,0,170,0,0,6,130,3,77,18,38,15,92,0,0,16,7,15,92,0,0,2,133,255,255,0,170,0,0,6,130, + 3,77,18,38,15,92,0,0,16,7,15,93,0,0,2,133,255,255,0,170,0,0,6,130,3,78,18,38,15,93,0,0,16,7,15,92,0,0,2,134, + 255,255,0,170,0,0,6,130,3,78,18,38,15,93,0,0,16,7,15,93,0,0,2,134,0,2,1,88,0,6,5,210,5,217,0,17,0,42,0,0, + 1,54,51,50,4,51,50,55,17,6,35,34,39,38,35,34,7,47,1,35,39,33,21,35,21,54,51,50,23,22,51,50,55,17,6,35,34,36,35,34, + 7,17,35,2,7,52,60,128,1,78,187,70,72,52,53,167,177,139,191,50,54,20,99,75,1,1,14,76,53,51,194,171,169,161,78,75,106,102,171,254, + 195,128,80,70,96,2,159,17,163,12,2,98,10,95,126,9,2,93,53,53,26,8,120,92,21,253,13,28,154,30,253,198,0,1,1,88,0,6,5,210, + 5,217,0,24,0,0,1,35,39,33,21,35,21,54,51,50,23,22,51,50,55,17,6,35,34,36,35,34,7,17,35,1,164,75,1,1,14,76,53,51, + 194,171,169,161,78,75,106,102,171,254,195,128,80,70,96,5,164,53,53,26,8,120,92,21,253,13,28,154,30,253,198,0,0,1,0,106,0,1,6,193, + 5,218,0,31,0,0,9,1,7,39,55,39,55,23,55,23,7,9,1,39,55,23,55,23,7,22,19,9,1,23,1,7,1,39,7,1,39,1,3,54, + 254,179,185,198,186,46,138,43,185,197,184,1,77,1,77,184,198,184,44,136,44,69,35,254,211,254,179,178,1,63,185,254,242,179,178,254,242,184,1,61, + 2,126,1,81,187,199,187,44,138,44,186,200,186,254,176,1,79,187,200,187,45,138,44,113,254,116,1,53,254,175,179,254,240,185,1,64,180,180,254,192, + 185,1,16,0,0,2,0,198,255,236,6,101,5,219,0,15,0,82,0,0,1,20,30,1,51,50,62,1,53,52,46,1,35,34,14,1,19,21,35,6, + 35,34,39,53,35,21,35,34,36,39,38,39,7,3,5,7,48,23,22,23,22,23,17,33,53,33,53,38,39,46,1,52,62,1,51,50,30,1,20,6, + 7,6,7,21,33,21,33,17,54,55,54,55,54,55,39,37,3,39,6,7,6,7,6,3,16,39,72,38,40,71,40,41,71,39,37,72,40,227,8,37, + 39,3,3,7,7,169,254,203,86,16,13,87,29,1,51,87,6,73,132,109,117,254,137,1,119,26,25,62,68,69,125,65,66,124,71,69,61,27,26,1, + 109,254,147,100,94,132,74,2,3,87,1,52,30,87,12,17,86,155,115,4,214,39,72,39,39,72,39,40,72,39,39,72,250,242,1,3,1,2,2,96, + 88,17,16,65,1,75,124,64,6,88,49,40,7,2,212,129,51,8,14,34,124,136,125,68,68,125,136,124,34,14,9,50,129,253,47,10,34,49,88,3, + 3,64,124,254,181,65,16,17,88,49,35,0,0,1,1,13,0,0,6,31,5,214,0,47,0,0,9,1,54,55,51,6,7,23,22,23,14,1,7,38, + 47,1,6,7,39,54,55,11,1,22,23,7,38,39,7,6,7,34,38,39,54,63,1,38,39,51,22,23,9,1,39,9,1,7,3,226,1,22,75,27, + 91,25,93,156,62,2,6,60,43,71,4,157,103,91,39,102,66,244,242,66,101,38,92,104,156,1,63,40,75,4,1,63,156,93,26,92,27,75,1,22, + 253,227,32,2,136,2,138,33,2,189,254,208,59,60,117,73,182,3,64,42,34,1,4,79,168,56,8,66,17,49,1,34,254,222,49,17,66,8,56,168, + 72,11,29,36,76,3,182,73,117,60,59,1,48,2,132,149,253,58,2,198,149,0,0,0,0,5,0,125,255,236,3,213,5,219,0,7,0,26,0,46, + 0,79,0,96,0,0,1,22,51,50,53,52,39,38,19,21,6,35,34,39,53,38,53,52,55,23,6,21,20,4,7,35,38,3,36,53,52,37,21,6, + 21,20,4,23,6,5,39,54,53,52,39,17,39,19,17,39,17,36,39,54,55,50,51,50,23,7,23,6,35,34,39,38,35,34,21,20,4,23,6,5, + 53,36,39,54,53,52,37,39,3,46,1,53,52,62,1,51,50,30,1,21,20,6,7,1,84,28,13,11,5,36,249,12,27,35,3,181,164,1,65,1, + 67,2,15,28,197,254,226,1,14,171,2,44,3,4,254,237,1,182,197,77,77,77,254,118,4,13,213,4,3,65,53,112,95,24,26,57,68,8,7,45, + 2,239,6,7,254,150,1,18,2,1,254,227,77,5,21,24,24,42,22,23,42,24,23,21,4,164,12,9,6,10,11,251,148,66,29,64,48,34,64,82, + 26,47,24,24,47,62,119,65,1,183,38,111,99,47,68,38,51,46,89,97,81,47,53,34,49,39,34,254,180,19,3,1,254,129,16,1,117,19,138,144, + 5,69,30,25,6,27,2,54,50,47,117,138,16,61,32,61,1,2,33,109,7,1,45,11,46,24,25,46,24,24,46,25,24,46,11,0,0,3,0,121, + 255,236,6,178,5,219,0,4,0,9,0,55,0,0,37,9,1,22,32,37,9,1,22,32,1,51,50,29,1,20,43,1,1,6,7,14,1,35,34,46, + 1,61,1,1,33,1,21,20,14,1,34,38,39,38,39,1,35,38,61,1,52,59,1,55,23,51,27,1,51,55,6,95,254,236,254,236,139,1,20,253, + 37,254,237,254,236,138,1,20,3,9,214,56,41,194,1,20,2,48,47,173,95,94,171,94,1,16,253,77,1,18,94,172,188,173,49,47,1,1,19,204, + 32,57,215,53,51,252,129,129,252,52,237,3,60,252,196,38,38,3,60,252,196,38,3,209,42,25,40,252,199,68,62,63,71,71,122,66,8,3,54,252, + 202,6,67,123,71,71,63,62,68,3,57,17,28,15,47,155,155,1,67,254,189,155,0,0,0,2,0,125,0,0,6,174,5,219,0,26,0,38,0,0, + 1,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,38,39,46,1,35,34,7,6,3,39,18,1,19,35,3,33,17,35,3,33,3,35,19,2, + 210,184,158,54,50,201,75,35,17,43,126,75,70,48,157,82,33,57,39,47,78,163,199,120,229,4,237,95,127,84,254,226,138,1,254,227,86,127,95,5, + 135,84,9,39,166,78,81,57,59,141,58,35,56,179,72,76,34,67,254,223,68,1,153,253,124,253,166,1,215,254,41,1,215,254,41,2,90,0,0,0, + 0,2,1,41,0,0,6,1,5,219,0,13,0,53,0,0,0,20,30,1,51,50,62,1,52,46,1,35,34,6,19,21,59,1,50,54,55,20,4,7, + 6,7,35,38,61,1,38,36,3,30,1,51,50,55,51,53,38,39,46,1,52,62,1,50,30,1,20,6,7,6,2,230,50,91,48,50,91,50,52,90, + 49,47,91,187,6,3,150,225,173,254,41,39,53,2,42,43,5,254,15,88,199,235,129,13,14,6,65,60,78,87,88,157,166,158,90,88,78,57,4,196, + 100,89,50,50,89,100,91,48,48,254,45,156,191,38,231,154,151,136,245,168,154,20,132,143,1,49,2,233,1,155,7,35,43,156,172,158,85,85,158,172, + 156,43,32,0,0,3,0,194,255,221,6,106,5,208,0,63,0,71,0,79,0,0,0,50,31,1,22,23,55,22,23,7,22,23,55,22,23,7,22,20, + 7,23,6,7,39,6,7,23,6,7,39,6,15,1,6,34,47,1,38,39,7,38,39,55,38,39,7,38,39,55,38,52,55,39,54,55,23,54,55,39, + 54,55,23,54,63,1,0,32,0,16,0,32,0,16,4,20,6,34,38,52,54,50,3,106,88,43,26,67,64,126,76,64,84,47,33,165,37,16,148,4, + 4,148,16,37,165,33,47,84,64,76,126,64,67,26,43,88,43,26,67,64,126,76,64,84,47,33,165,37,16,148,4,4,148,16,37,165,33,47,84,64, + 76,126,64,67,26,1,13,254,148,254,254,1,2,1,108,1,2,254,227,91,128,91,91,128,5,208,5,187,13,30,132,45,64,156,50,60,31,84,92,69, + 35,68,35,70,91,84,31,60,51,155,64,46,132,29,14,186,6,6,186,14,29,132,46,64,155,50,61,31,84,91,70,35,68,35,69,92,84,31,60,51, + 155,64,45,131,29,13,187,254,196,254,253,254,149,254,254,1,2,1,107,117,128,91,91,128,91,0,0,0,0,15,1,6,255,237,6,37,5,221,0,9, + 0,14,0,19,0,24,0,29,0,37,0,44,0,49,0,54,0,59,0,64,0,72,0,79,0,91,0,159,0,0,0,20,30,1,51,38,52,55,34,6, + 5,22,23,55,38,39,22,23,55,38,39,22,23,55,38,39,22,7,55,38,39,20,21,20,7,23,53,52,39,6,7,23,54,53,52,5,23,54,55,6, + 7,23,54,55,6,7,23,54,55,6,31,1,38,55,6,23,55,38,53,52,55,6,21,63,1,38,39,6,21,20,5,34,6,21,20,22,51,50,54,53, + 52,38,39,53,38,39,46,1,52,62,1,51,50,30,1,20,6,7,6,7,51,20,35,21,22,23,22,23,54,55,4,23,6,35,38,34,7,22,21,20, + 7,6,7,3,21,6,35,34,47,1,3,38,39,38,53,52,55,38,35,34,7,34,39,54,37,22,23,54,55,54,3,86,17,31,18,14,14,17,32,1, + 243,110,42,26,91,145,110,37,39,90,120,76,16,48,60,123,50,1,59,38,98,21,59,60,47,50,58,40,252,115,26,42,110,87,41,39,36,111,96,20, + 48,16,76,80,15,59,1,50,70,60,59,22,1,38,99,58,50,47,1,1,28,55,76,76,55,53,77,76,90,3,2,19,21,21,39,21,20,38,22,21, + 19,2,3,1,1,52,41,3,3,80,22,1,78,80,85,254,40,68,28,4,52,40,52,1,11,23,25,8,1,2,51,40,52,3,31,41,34,40,254,85, + 80,1,78,21,82,7,9,40,5,160,34,31,18,32,66,34,17,118,62,48,38,56,20,97,62,33,85,42,126,69,19,109,76,145,75,8,125,96,17,16, + 129,63,10,12,123,97,136,55,26,99,91,13,79,38,48,62,16,106,33,62,97,41,134,19,69,126,67,136,8,75,145,87,139,10,61,123,20,21,100,123, + 3,26,55,136,14,13,91,43,77,53,55,76,76,55,53,77,45,90,1,2,10,39,42,39,21,21,39,42,39,10,2,1,1,89,9,40,3,4,128,53, + 6,91,163,12,12,20,21,74,53,40,9,252,214,92,22,28,100,3,28,9,40,53,74,18,17,17,12,163,91,6,52,140,10,9,39,0,0,15,1,5, + 0,0,6,39,5,211,0,15,0,31,0,47,0,55,0,79,0,95,0,159,0,171,0,179,0,187,0,203,0,211,0,219,0,227,0,239,0,0,1,50, + 30,1,21,20,14,1,35,34,46,1,53,52,62,1,7,38,39,6,7,6,21,20,23,22,51,50,51,54,55,38,37,6,7,22,23,50,51,50,55,54, + 53,52,39,38,39,6,39,22,21,20,7,54,55,38,39,38,39,38,39,6,7,6,7,6,21,20,23,22,23,22,23,54,55,54,55,54,53,52,19,22, + 23,22,23,54,55,54,53,52,39,38,35,34,7,6,5,55,62,1,51,50,22,23,21,54,51,50,51,22,23,22,21,20,7,6,7,23,22,23,22,21, + 20,7,14,1,35,34,39,35,6,7,6,35,34,39,38,39,6,35,34,38,39,38,53,52,55,54,55,38,39,38,53,52,55,54,55,50,51,50,5,38, + 39,38,35,34,7,6,7,22,23,54,23,6,7,22,23,22,23,38,37,6,7,54,55,54,55,38,39,38,39,38,35,34,7,6,21,20,23,22,23,54, + 55,54,7,6,7,22,23,38,53,52,23,22,23,54,55,38,39,38,23,22,23,54,55,6,7,6,7,6,7,22,23,22,51,50,55,54,55,38,3,150, + 19,36,20,20,36,19,20,36,20,20,36,225,79,71,127,51,37,8,23,86,8,9,99,152,14,1,226,6,14,153,99,9,8,86,23,8,37,52,127,71, + 76,2,2,57,52,52,109,47,49,50,50,49,48,50,47,2,2,46,51,48,51,49,49,50,46,3,25,15,6,79,70,125,54,38,8,23,86,9,11,101, + 253,180,1,34,119,63,62,118,34,164,112,3,4,116,32,12,35,56,136,1,138,55,33,12,31,118,6,110,164,1,34,58,59,64,65,60,58,34,162,110, + 6,120,31,11,33,54,138,136,54,35,11,32,115,4,3,112,2,37,27,46,47,49,51,47,46,27,85,86,84,92,60,62,34,36,33,33,5,254,149,9, + 5,33,34,35,34,62,107,149,99,11,9,86,22,9,38,54,124,70,79,6,9,57,51,51,57,1,57,5,9,60,62,35,34,35,214,62,60,9,5,32, + 34,36,90,84,85,26,46,47,52,51,46,46,26,86,3,53,19,36,21,20,35,20,20,35,20,21,36,19,217,53,57,103,84,59,38,18,14,39,4,57, + 90,94,94,90,57,4,39,14,18,39,58,84,103,57,167,39,40,39,39,38,40,41,73,30,28,28,26,26,28,28,30,56,58,57,56,30,28,29,26,26, + 29,28,30,56,57,58,1,12,90,95,53,57,101,85,59,39,19,14,40,1,5,9,2,179,192,192,179,2,58,2,56,20,27,46,62,101,117,1,118,99, + 62,45,27,20,55,3,58,176,98,99,99,98,176,59,4,55,20,26,45,63,99,119,117,100,63,47,26,20,56,2,75,162,87,90,90,87,162,32,42,42, + 16,25,29,18,20,21,20,68,64,64,68,20,21,20,18,29,43,56,5,1,40,15,19,39,58,84,101,57,53,94,157,38,41,40,38,39,39,40,214,68, + 65,25,29,18,20,20,58,29,25,65,68,21,20,20,46,42,33,158,89,91,91,89,158,33,0,7,1,5,0,0,6,38,5,214,0,11,0,20,0,33, + 0,45,0,120,0,134,0,148,0,0,1,20,23,54,55,38,39,54,55,38,39,6,5,52,38,21,6,21,22,23,54,37,6,21,20,23,54,55,46,1, + 39,6,21,20,37,52,39,6,7,22,23,6,7,22,23,54,1,38,35,34,7,6,7,38,39,54,55,22,23,54,55,38,53,52,63,1,21,22,21,20, + 7,30,1,23,54,55,22,23,6,7,38,39,38,35,34,7,22,23,22,20,7,6,7,22,23,6,35,38,39,6,7,6,7,35,38,39,53,38,39,6, + 7,34,39,54,55,38,39,38,52,55,54,6,20,30,1,51,50,62,1,52,46,1,35,34,6,37,50,30,1,20,14,1,35,34,46,1,52,62,1,3, + 206,39,55,44,51,9,3,51,37,47,48,254,220,41,44,8,55,21,1,223,1,17,61,3,3,42,1,35,254,215,48,42,43,51,3,14,46,50,50,39, + 254,247,56,32,14,9,32,89,102,2,2,183,169,84,44,49,39,165,1,164,39,41,46,5,85,168,184,1,2,102,89,32,6,14,29,62,26,20,57,56, + 24,32,34,50,1,13,66,50,59,70,95,25,32,32,88,66,63,50,67,13,1,51,34,32,23,56,57,20,52,105,188,104,103,188,105,107,190,99,101,189, + 1,34,83,159,91,88,159,86,87,159,88,90,159,2,132,163,167,15,35,101,141,170,106,28,15,112,205,77,99,1,78,84,118,74,75,114,27,25,90,49, + 86,108,76,87,2,77,73,9,17,169,112,13,30,106,170,133,107,37,15,167,1,110,65,13,86,2,2,123,119,2,6,119,25,17,91,49,135,244,1,1, + 244,135,49,91,13,26,3,119,6,2,119,123,2,2,86,13,64,30,35,102,220,100,45,35,74,77,12,55,66,47,21,34,137,137,34,1,20,48,67,55, + 12,78,75,34,44,100,220,102,35,136,206,189,104,104,189,206,191,103,103,81,85,160,174,157,88,88,157,174,160,85,0,0,0,4,0,100,0,0,6,200, + 5,212,0,7,0,13,0,21,0,37,0,0,1,51,1,21,33,39,35,0,23,1,21,33,53,0,7,50,21,2,35,34,3,54,19,50,30,1,21,20, + 14,1,35,34,46,1,53,52,62,1,3,159,7,3,34,249,173,8,9,3,27,23,253,104,5,57,253,124,20,77,52,25,23,54,25,51,19,37,21,20, + 38,19,20,36,21,21,36,5,212,250,53,9,9,5,170,155,251,79,17,9,4,157,194,68,253,155,2,110,59,253,13,20,36,21,20,36,20,20,36,20, + 21,36,20,0,0,1,0,170,0,4,4,244,5,216,0,19,0,0,1,51,23,21,1,20,51,4,21,23,1,39,53,0,53,52,35,36,47,1,4,209, + 14,21,253,142,91,1,131,7,252,81,14,2,135,119,254,147,16,7,5,216,21,7,253,226,71,83,14,71,253,85,21,7,2,87,13,71,74,17,71,0, + 0,5,0,175,254,255,7,90,5,218,0,30,0,42,0,49,0,61,0,67,0,0,1,38,16,0,51,50,23,54,51,50,0,16,7,6,7,17,33,21, + 33,17,35,17,33,17,35,17,33,53,33,17,38,1,34,6,16,22,51,50,55,38,16,55,38,19,6,7,17,33,17,38,55,22,51,50,54,16,38,35, + 34,7,22,16,5,54,16,39,6,16,1,88,169,1,80,239,153,125,125,155,236,1,82,168,136,180,1,16,254,240,180,254,134,180,254,240,1,16,181,1, + 15,164,231,231,164,63,57,138,139,57,215,88,101,1,122,102,72,57,63,160,234,234,160,65,58,140,254,215,117,117,116,2,20,157,1,221,1,76,70,70, + 254,180,254,34,156,126,18,254,248,124,254,255,1,1,254,255,1,1,124,1,9,17,3,145,228,254,185,216,17,149,1,174,157,18,252,148,45,10,254,248, + 1,9,10,165,16,216,1,71,228,18,157,254,80,56,108,1,71,114,114,254,185,0,0,0,0,5,0,162,254,91,8,48,5,195,0,11,0,36,0,44, + 0,56,0,62,0,0,1,38,32,6,16,23,22,23,54,0,55,38,1,20,0,32,39,38,39,38,39,38,16,0,4,23,1,33,55,33,17,33,17,7, + 17,1,22,3,1,22,23,22,23,1,33,3,6,0,7,22,23,22,32,54,16,39,38,1,50,54,53,34,6,3,247,117,254,187,231,116,46,55,16,1, + 55,204,28,2,133,254,181,254,33,170,117,36,134,108,170,1,89,1,203,111,1,105,254,141,140,1,238,1,139,143,254,154,112,149,254,154,64,27,113,68, + 1,105,254,237,247,14,254,208,222,29,52,116,1,69,234,117,46,253,141,161,234,164,227,3,36,114,228,254,184,108,44,26,206,1,51,7,54,253,144,232, + 254,189,159,108,146,37,101,158,1,220,1,85,17,103,1,92,142,254,120,254,20,143,1,117,254,164,146,3,118,254,164,83,99,27,63,1,92,254,55,204, + 254,215,11,61,49,108,216,1,72,114,45,254,201,216,164,224,0,4,0,175,254,131,8,223,6,217,0,5,0,45,0,57,0,69,0,0,0,2,23,54, + 16,39,1,20,0,35,34,39,6,7,17,33,21,33,17,35,17,33,53,33,17,38,39,38,16,0,51,50,23,54,23,22,23,1,33,55,33,17,7,17, + 1,22,37,34,6,16,22,51,50,55,38,16,55,38,1,22,51,50,54,16,38,35,34,7,22,16,3,146,1,115,117,117,3,87,254,179,243,154,126,87, + 100,1,16,254,240,180,254,240,1,16,181,135,169,1,80,239,151,124,128,154,229,111,1,106,254,140,140,1,238,142,254,154,112,251,147,164,231,231,164,63, + 57,137,139,58,1,118,56,63,162,234,234,162,65,58,141,3,200,254,184,108,108,1,71,114,254,235,231,254,188,69,44,10,254,248,124,254,255,1,1,124, + 1,9,17,126,157,1,221,1,76,68,74,6,8,103,1,92,142,254,20,143,1,117,254,164,146,198,228,254,185,216,17,149,1,172,159,18,253,13,16,216, + 1,72,228,18,157,254,79,0,0,2,0,175,254,255,6,178,7,85,0,7,0,40,0,0,0,38,32,6,16,22,32,54,5,38,16,0,51,50,23,1, + 33,55,33,17,7,17,1,22,21,20,7,6,7,17,33,21,33,17,35,17,33,53,33,17,38,4,121,234,254,187,231,231,1,69,234,252,223,169,1,80, + 239,192,149,1,104,254,141,140,1,238,143,254,154,112,169,136,180,1,16,254,240,180,254,240,1,16,181,4,67,228,228,254,185,216,216,232,157,1,221,1, + 76,110,1,91,142,254,20,143,1,117,254,164,146,194,239,156,126,18,254,248,124,254,255,1,1,124,1,9,17,0,0,0,0,2,1,13,255,227,5,208, + 6,244,0,43,0,68,0,0,1,7,22,23,22,23,22,20,7,14,1,7,6,35,34,39,38,39,38,39,38,52,55,62,1,55,54,51,50,23,55,39, + 55,23,19,7,39,37,19,7,39,3,23,7,1,22,50,55,62,1,55,54,52,39,38,39,46,1,34,7,14,1,7,6,20,23,22,23,22,4,40,70, + 51,34,68,34,38,37,35,125,98,86,96,90,90,94,59,68,34,38,38,36,131,91,88,93,58,51,71,254,57,254,134,225,58,1,206,192,139,93,134,254, + 58,253,70,61,126,61,60,90,26,25,25,23,47,42,126,122,63,60,89,27,25,24,24,46,40,4,0,170,33,36,72,83,92,180,91,86,131,42,37,37, + 39,62,72,83,93,179,94,88,130,38,37,12,171,105,138,105,1,68,94,139,191,254,50,57,225,254,189,105,139,252,252,26,25,25,92,61,60,128,60,57, + 50,45,49,25,25,88,63,58,132,60,57,49,42,0,0,0,0,2,0,207,254,163,5,238,7,18,0,61,0,88,0,0,1,54,50,23,19,7,39,37, + 19,7,39,3,22,23,30,1,21,20,6,7,6,7,6,7,21,33,21,33,21,35,53,33,53,33,53,38,39,38,39,46,1,53,52,54,55,54,55,39, + 7,39,55,39,7,39,19,5,7,39,23,55,23,7,23,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39, + 38,2,238,52,112,54,179,226,57,1,206,192,140,93,179,46,40,69,71,71,69,64,90,45,60,1,19,254,237,150,254,237,1,19,56,49,86,68,69,71, + 70,70,39,49,31,254,57,254,84,93,140,192,1,206,57,226,84,254,58,254,138,71,53,62,43,46,49,49,46,47,58,57,138,53,62,43,46,49,49,46, + 47,58,57,4,135,12,12,1,158,92,138,191,254,50,58,226,254,97,29,40,69,171,98,95,171,69,64,40,20,10,184,150,240,240,150,184,9,21,37,67, + 69,171,95,98,169,71,40,30,72,105,138,106,203,226,58,1,206,191,138,92,203,105,138,106,211,24,28,43,46,119,66,65,119,46,47,24,24,24,28,43, + 46,119,65,66,119,46,47,24,24,0,0,0,0,2,1,128,255,227,5,52,6,244,0,43,0,70,0,0,1,17,33,21,33,21,22,23,22,23,30,1, + 21,20,6,7,6,7,6,35,34,39,38,39,46,1,53,52,54,55,54,55,54,55,53,33,53,33,17,7,39,9,1,7,3,50,55,54,55,62,1,53, + 52,38,39,38,39,38,34,7,6,7,14,1,21,20,22,23,22,23,22,3,165,1,19,254,237,60,45,90,64,69,71,71,69,68,86,82,98,102,78,90, + 64,69,71,71,69,68,86,49,56,254,237,1,19,172,107,1,98,1,98,106,248,67,57,58,47,46,49,49,46,43,62,53,138,57,58,47,46,49,49,46, + 43,62,53,5,213,254,231,150,145,10,20,40,64,69,171,95,98,171,69,67,37,35,35,40,64,69,171,98,95,171,69,67,37,21,9,145,150,1,25,173, + 107,1,97,254,159,106,251,80,24,24,47,46,119,66,65,119,46,43,28,24,24,24,47,46,119,65,66,119,46,43,28,24,0,2,0,9,1,16,6,161, + 4,196,0,43,0,70,0,0,1,35,17,35,17,35,6,7,6,7,14,1,35,34,38,39,38,39,38,53,52,55,54,55,62,1,51,50,22,23,22,23, + 22,23,51,17,51,17,51,39,55,9,1,39,37,20,23,22,23,30,1,51,50,54,55,54,55,54,52,39,38,39,46,1,35,34,6,7,6,7,6,5, + 130,220,150,85,10,20,40,64,69,171,95,98,171,69,67,37,35,35,40,64,69,171,98,95,171,69,67,37,21,9,85,150,220,173,107,1,97,254,159,106, + 251,201,24,24,47,46,119,66,65,119,46,43,28,24,24,24,47,46,119,65,66,119,46,43,28,24,2,159,254,237,1,19,60,45,90,64,69,71,71,69, + 68,86,82,98,102,78,90,64,69,71,71,69,68,86,49,56,1,19,254,237,172,107,254,158,254,158,106,248,67,57,58,47,46,49,49,46,43,62,53,138, + 57,58,47,46,49,49,46,43,62,53,0,0,0,2,1,127,1,16,5,53,4,197,0,11,0,23,0,31,64,15,21,18,3,15,18,9,24,25,18,18, + 6,12,18,0,24,16,220,236,212,236,196,49,0,16,212,236,212,236,48,1,52,0,51,50,0,21,20,0,35,34,0,55,20,22,51,50,54,53,52,38, + 35,34,6,1,127,1,23,196,196,1,23,254,233,196,196,254,233,153,189,133,133,189,189,133,133,189,2,235,196,1,22,254,234,196,197,254,234,1,22,194, + 133,189,189,133,134,189,189,0,0,1,1,127,1,16,5,53,4,197,0,11,0,19,64,7,3,9,12,13,6,0,12,16,220,212,204,49,0,16,212,196, + 48,1,52,0,51,50,0,21,20,0,35,34,0,1,127,1,23,196,196,1,23,254,233,196,196,254,233,2,235,196,1,22,254,234,196,197,254,234,1,22, + 0,2,1,250,1,141,4,186,4,75,0,11,0,23,0,43,64,15,21,107,3,15,107,9,24,25,18,107,6,12,107,0,24,16,220,236,212,75,176,16, + 84,88,185,0,6,255,192,56,89,236,196,49,0,16,212,236,212,236,48,1,52,54,51,50,22,21,20,6,35,34,38,55,20,22,51,50,54,53,52,38, + 35,34,6,1,250,207,145,145,207,207,145,145,207,152,117,83,83,117,117,83,83,117,2,236,146,205,205,146,145,206,206,144,83,117,117,83,83,118,118,0, + 0,4,1,100,1,141,5,80,4,75,0,19,0,33,0,41,0,55,0,101,75,176,11,82,88,64,31,3,7,13,17,29,42,25,46,8,27,44,15,38, + 34,5,4,40,36,10,107,51,44,107,40,36,107,27,20,107,0,56,16,212,236,212,236,212,236,212,236,17,18,23,57,17,18,23,57,49,0,64,21,38, + 34,23,31,5,3,31,15,23,17,31,54,107,7,3,48,23,107,13,17,56,16,212,60,236,50,212,60,236,50,17,18,57,17,18,57,17,18,57,57,48, + 89,1,52,54,51,50,23,54,51,50,22,21,20,6,35,34,39,6,35,34,38,55,20,22,51,50,51,38,53,52,55,38,35,34,6,37,6,21,20,23, + 54,53,52,55,22,21,20,7,50,51,50,54,53,52,38,35,34,1,100,207,145,82,68,68,82,145,207,207,145,82,68,68,82,145,207,152,117,83,6,5, + 63,62,5,5,83,117,1,94,50,50,50,90,62,63,5,6,83,117,117,83,5,2,236,146,205,32,32,205,146,145,206,33,33,206,144,83,117,88,113,112, + 87,1,118,50,56,77,76,56,56,76,77,123,87,112,113,88,117,83,83,118,0,5,0,84,1,90,6,96,4,122,0,3,0,29,0,56,0,82,0,109, + 0,0,1,51,17,35,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,47,1,50,23,22,23,30,1,21, + 20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,54,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53, + 52,38,39,38,47,1,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,54,3,15,150,150,2,29,82,35, + 41,24,29,30,31,28,29,36,35,82,35,36,29,29,30,32,27,29,36,76,75,58,67,46,50,53,53,50,49,64,61,147,58,67,46,50,53,53,50,49, + 64,61,253,31,82,35,41,24,29,30,31,28,29,36,35,82,35,36,29,29,30,32,27,29,36,76,75,58,67,46,50,53,53,50,49,64,61,147,58,67, + 46,50,53,53,50,49,64,61,4,122,252,224,2,90,15,18,26,31,70,41,40,74,27,28,16,15,15,16,28,30,71,40,41,75,26,28,16,165,26,30, + 46,50,127,73,70,127,50,49,27,26,26,30,46,50,127,70,73,127,50,49,27,26,150,15,18,26,31,70,41,40,74,27,28,16,15,15,16,28,30,71, + 40,41,75,26,28,16,165,26,30,46,50,127,73,70,127,50,49,27,26,26,30,46,50,127,70,73,127,50,49,27,26,0,0,3,0,10,1,141,6,170, + 4,74,0,55,0,81,0,107,0,0,1,62,1,55,54,55,54,51,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,39,33,14, + 1,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,54,51,50,23,22,23,30,1,23,36,34,7,6,7,14,1,21,20,22,23,22,23,22, + 50,55,54,55,62,1,53,52,38,39,38,39,36,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,39,3,247, + 7,35,54,49,64,61,72,75,58,67,46,50,53,53,50,49,64,61,147,58,67,46,53,37,6,254,197,6,39,50,49,64,61,147,58,67,46,50,53,53, + 50,49,64,61,72,75,58,67,46,54,35,7,2,185,82,35,36,29,29,30,30,29,29,36,35,82,35,36,29,29,30,30,29,29,36,251,247,82,35,41, + 24,29,30,31,28,29,36,35,82,35,36,29,29,30,32,27,29,36,3,53,31,91,53,49,27,26,26,30,46,50,127,73,70,127,50,49,27,26,26,30, + 46,52,96,24,29,93,50,49,27,26,26,30,46,50,127,70,73,127,50,49,27,26,26,30,46,53,91,31,127,15,16,28,31,70,41,40,71,30,28,16, + 15,15,16,28,30,71,40,41,70,31,28,16,15,15,18,26,31,70,41,40,74,27,28,16,15,15,16,28,30,71,40,41,75,26,28,16,0,2,0,210, + 1,230,6,14,4,82,0,5,0,11,0,0,1,53,37,7,21,23,1,37,5,17,5,37,5,120,252,204,220,220,254,142,1,114,3,202,252,54,254,142, + 2,215,138,101,77,186,77,1,94,130,120,254,132,120,130,0,0,2,1,177,0,86,5,3,5,150,0,21,0,41,0,0,1,55,54,53,52,39,38,39, + 53,55,53,35,21,23,21,6,7,6,21,20,31,2,33,3,38,53,52,55,54,55,39,53,33,21,7,22,23,22,21,20,7,3,115,95,118,82,36,78, + 58,200,58,78,36,82,118,95,163,254,236,164,123,97,84,44,88,2,64,88,44,84,97,123,1,17,180,223,52,98,92,41,49,162,37,61,61,37,162,49, + 41,92,98,52,223,180,187,1,58,234,96,190,92,75,25,68,250,250,68,25,75,92,190,96,234,0,0,0,0,2,0,175,254,255,5,45,5,218,0,7, + 0,21,0,0,0,38,32,6,16,22,32,54,5,38,16,0,32,0,16,7,6,7,17,35,17,38,4,121,234,254,187,231,231,1,69,234,252,223,169,1, + 80,1,219,1,83,169,136,180,180,181,4,67,228,228,254,185,216,216,232,157,1,221,1,76,254,180,254,34,156,126,18,253,123,2,134,17,0,1,1,89, + 254,255,5,44,5,218,0,26,0,0,33,17,35,17,33,53,33,17,22,51,50,54,16,38,32,7,39,54,32,0,16,7,6,7,17,33,21,3,73,181, + 254,240,1,16,40,52,161,232,232,254,187,126,117,168,1,219,1,80,167,137,179,1,15,254,255,1,1,124,1,178,7,216,1,71,228,106,116,166,254,180, + 254,32,154,126,18,254,248,124,0,2,0,176,254,255,5,44,5,218,0,19,0,23,0,0,19,9,2,17,50,51,21,34,35,17,34,35,17,34,35,53, + 50,51,17,55,9,2,176,2,62,2,62,254,33,135,136,136,135,91,90,136,136,136,136,86,1,76,254,180,254,180,3,159,2,59,253,197,253,233,254,244, + 124,254,255,1,1,124,1,12,168,1,111,1,74,254,182,0,0,1,0,176,254,255,5,44,5,218,0,31,0,0,1,55,23,17,51,17,55,23,1,33, + 21,33,1,7,39,17,33,21,33,17,35,17,33,53,33,17,7,39,1,33,53,33,1,29,123,253,179,252,123,254,228,1,137,254,126,1,21,122,253,1, + 16,254,240,180,254,240,1,16,253,122,1,21,254,126,1,137,4,249,122,253,1,100,254,157,252,122,254,228,124,254,235,123,253,253,174,124,254,255,1,1, + 124,2,82,253,123,1,21,124,0,3,0,120,255,15,6,84,5,37,0,9,0,13,0,23,0,0,1,21,33,9,1,33,53,33,9,1,3,17,35,17, + 1,33,23,55,33,21,35,9,1,35,6,84,254,211,254,63,254,63,254,211,1,162,1,76,1,76,241,172,254,119,1,4,214,214,1,4,142,254,180,254, + 180,142,1,74,124,254,65,1,191,124,254,182,1,74,3,219,253,166,2,90,253,116,213,213,124,254,182,1,74,0,0,0,0,2,1,142,255,44,4,194, + 5,175,0,7,0,28,0,0,36,20,22,50,54,52,38,34,2,38,16,55,54,55,17,51,17,37,23,13,1,7,37,17,22,23,22,16,6,2,38,117, + 166,117,117,166,62,207,104,72,93,172,1,37,86,254,153,1,103,86,254,219,89,70,104,207,221,166,117,117,166,118,253,217,206,1,35,103,71,22,3,206, + 254,206,173,148,209,210,148,174,254,210,22,69,103,254,221,206,0,1,1,68,254,255,4,88,5,218,0,30,0,0,33,17,35,17,33,53,33,17,38,39, + 38,53,16,37,54,55,54,23,6,7,6,21,16,23,22,23,6,39,21,33,21,3,72,180,254,240,1,16,156,102,78,1,41,93,174,72,59,203,98,116, + 250,87,85,74,110,1,16,254,255,1,1,124,1,51,76,152,117,161,1,46,185,58,16,7,23,59,133,157,196,254,205,162,56,15,37,19,255,124,0,0, + 0,3,0,86,0,8,6,94,4,109,0,15,0,29,0,51,0,0,19,21,20,23,22,32,55,54,61,1,6,7,6,32,39,38,0,32,7,6,21,20, + 23,22,32,55,54,53,52,39,55,30,1,21,17,20,6,7,6,33,32,39,46,1,53,17,52,54,55,54,33,32,186,171,206,2,78,206,171,46,56,240, + 253,108,237,63,3,157,253,178,206,171,171,206,2,78,206,171,171,44,115,112,112,112,230,254,194,254,199,232,115,112,112,112,230,1,62,1,57,2,29,147, + 96,86,104,104,86,96,146,34,28,120,120,32,2,11,104,86,99,96,86,104,104,86,96,99,86,89,57,136,81,254,162,78,136,57,115,115,57,136,78,1, + 94,81,136,57,115,0,0,0,0,4,0,86,0,8,6,94,5,203,0,13,0,29,0,45,0,69,0,0,0,32,7,6,21,20,23,22,32,55,54,53, + 52,39,1,21,20,23,22,32,55,54,61,1,6,7,6,32,39,38,3,21,20,23,22,32,55,54,61,1,6,7,6,32,39,38,1,30,1,21,25,1, + 20,6,7,6,33,32,39,46,1,53,25,1,52,54,55,54,33,32,4,129,253,178,206,171,171,206,2,78,206,171,171,251,107,171,206,2,78,206,171,46, + 56,240,253,108,237,63,42,171,206,2,78,206,171,46,56,240,253,108,237,63,4,151,115,112,112,112,230,254,194,254,199,232,115,112,112,112,230,1,62,1, + 57,5,103,104,86,99,96,86,104,104,86,96,99,86,254,124,147,96,86,104,104,86,96,146,34,28,120,120,32,254,193,147,96,86,104,104,86,96,146,34, + 28,120,120,32,3,90,57,136,81,254,162,254,162,78,136,57,115,115,57,136,78,1,94,1,94,81,136,57,115,0,0,0,0,5,0,86,0,8,6,94, + 4,109,0,11,0,33,0,49,0,63,0,85,0,0,1,6,7,6,33,32,39,38,39,22,33,32,0,32,23,22,23,22,21,6,7,6,7,6,32,39, + 38,39,38,55,54,55,54,55,3,21,20,23,22,32,55,54,61,1,6,7,6,32,39,38,0,32,7,6,21,20,23,22,32,55,54,53,52,39,55,30, + 1,21,17,20,6,7,6,33,32,39,46,1,53,17,52,54,55,54,33,32,5,120,31,56,184,254,241,254,239,182,59,30,236,1,52,1,49,253,192,2, + 32,182,58,31,28,2,26,31,58,184,253,224,182,59,30,29,1,1,27,32,57,217,171,206,2,78,206,171,46,56,240,253,108,237,63,3,157,253,178,206, + 171,171,206,2,78,206,171,171,44,115,112,112,112,230,254,194,254,199,232,115,112,112,112,230,1,62,1,57,1,100,27,28,93,93,30,26,99,2,163,93, + 29,28,25,14,14,22,28,29,93,93,30,27,24,12,15,24,28,29,254,213,147,96,86,104,104,86,96,146,34,28,120,120,32,2,11,104,86,99,96,86, + 104,104,86,96,99,86,89,57,136,81,254,162,78,136,57,115,115,57,136,78,1,94,81,136,57,115,0,0,0,7,0,86,0,8,6,94,5,203,0,21, + 0,33,0,45,0,59,0,75,0,91,0,115,0,0,0,32,23,22,23,22,21,6,7,6,7,6,32,39,38,39,38,55,54,55,54,55,1,6,7,6, + 33,32,39,38,39,22,33,32,23,6,7,6,33,32,39,38,39,22,33,32,2,32,7,6,21,20,23,22,32,55,54,53,52,39,1,21,20,23,22,32, + 55,54,61,1,6,7,6,32,39,38,3,21,20,23,22,32,55,54,61,1,6,7,6,32,39,38,1,30,1,21,25,1,20,6,7,6,33,32,39,46, + 1,53,25,1,52,54,55,54,33,32,2,75,2,32,182,58,31,28,2,26,31,58,184,253,224,182,59,30,29,1,1,27,32,57,3,229,31,56,184,254, + 241,254,239,182,59,30,236,1,52,1,49,237,31,56,184,254,241,254,239,182,59,30,236,1,52,1,49,10,253,178,206,171,171,206,2,78,206,171,171,251, + 107,171,206,2,78,206,171,46,56,240,253,108,237,63,42,171,206,2,78,206,171,46,56,240,253,108,237,63,4,151,115,112,112,112,230,254,194,254,199,232, + 115,112,112,112,230,1,62,1,57,5,3,93,29,28,25,14,14,22,28,29,93,93,30,27,24,12,15,24,28,29,254,28,27,28,93,93,30,26,99,252, + 27,28,93,93,30,26,99,4,101,104,86,99,96,86,104,104,86,96,99,86,254,124,147,96,86,104,104,86,96,146,34,28,120,120,32,254,193,147,96,86, + 104,104,86,96,146,34,28,120,120,32,3,90,57,136,81,254,162,254,162,78,136,57,115,115,57,136,78,1,94,1,94,81,136,57,115,0,0,3,0,175, + 255,227,5,45,6,190,0,11,0,32,0,44,0,0,1,34,38,53,52,54,51,50,22,21,20,6,19,22,23,22,21,20,0,35,34,0,16,55,54,55, + 3,1,39,9,1,21,1,3,50,54,53,52,38,35,34,6,21,20,22,2,238,64,97,94,67,70,91,94,23,181,135,169,254,176,239,236,254,173,169,136, + 180,1,254,249,1,1,99,1,99,254,247,90,164,231,231,164,161,234,234,1,125,91,68,62,88,85,65,66,93,2,187,17,126,157,238,239,254,180,1,76, + 1,222,156,126,18,1,103,254,250,199,1,93,254,163,199,1,5,250,247,228,164,163,216,216,163,164,228,0,0,3,0,22,1,133,6,108,5,20,0,80, + 0,106,0,133,0,0,1,39,35,34,39,38,7,6,20,7,14,1,7,6,35,34,39,38,39,38,39,38,52,55,62,1,55,54,51,50,31,1,22,51, + 50,55,62,1,55,54,38,39,38,39,38,47,1,38,39,38,39,38,52,55,62,1,55,54,50,22,23,22,23,22,20,7,14,1,7,6,23,22,31,1, + 33,50,23,22,23,33,23,37,22,51,50,55,62,1,55,54,52,39,38,39,46,1,35,34,7,14,1,7,6,20,23,30,1,1,38,35,34,7,14,1, + 7,6,20,23,22,23,30,1,51,50,55,62,1,55,54,52,39,38,39,38,3,205,214,115,174,28,42,3,2,9,13,48,36,28,43,36,36,36,26,21, + 23,18,12,13,49,35,29,42,35,9,90,97,90,37,14,22,37,3,3,7,13,12,22,78,84,49,50,25,28,15,19,12,13,52,32,35,72,72,26,31, + 13,18,12,9,30,3,5,34,41,109,82,1,139,232,79,101,17,253,98,213,252,13,21,20,24,16,21,29,5,5,12,10,15,17,44,17,20,20,21,26, + 7,6,13,10,30,1,48,18,23,28,12,21,30,4,5,12,10,15,15,43,20,23,17,21,28,5,6,13,10,15,11,1,133,205,6,8,13,8,41,23, + 32,46,13,11,15,14,25,21,36,29,74,30,32,46,13,11,3,37,39,3,5,28,7,8,46,19,19,19,68,34,20,20,24,27,30,38,66,29,32,49, + 10,11,30,24,30,28,36,67,30,23,29,7,13,22,26,109,82,32,41,75,207,121,9,5,7,24,16,17,31,23,18,13,16,16,6,6,23,17,17,32, + 22,18,28,2,181,9,5,7,25,15,17,33,21,18,14,13,18,5,7,25,14,18,32,22,18,14,9,0,0,3,0,86,1,33,6,69,4,181,0,21, + 0,100,0,122,0,0,18,50,54,55,62,1,53,52,38,39,46,1,34,6,7,14,1,21,20,22,23,22,1,5,6,35,34,39,37,7,14,1,21,20, + 22,21,20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,54,59,1,50,55,62,2,52,46,1,39,38,43,1,34,39,38,39,46,1, + 53,52,54,55,54,55,54,50,23,22,23,30,1,21,20,6,21,20,22,31,1,37,54,51,50,23,36,34,6,7,14,1,21,20,22,23,30,1,50,54, + 55,62,1,53,52,38,39,38,253,46,38,16,17,16,16,17,16,38,46,38,16,17,16,16,17,16,3,1,2,109,44,109,81,219,254,145,106,150,80,17, + 28,28,22,40,33,78,33,34,28,26,30,28,28,22,40,33,9,97,86,102,27,38,24,24,38,27,98,90,53,53,33,40,22,28,28,30,26,28,34,33, + 78,33,40,22,28,28,17,80,150,106,1,111,219,81,109,44,250,230,46,38,16,17,16,16,17,16,38,46,38,16,17,16,16,17,16,1,113,14,13,14, + 31,19,18,31,14,13,14,14,13,14,31,18,19,31,14,13,1,108,252,63,87,146,44,62,14,14,8,38,25,35,60,26,21,16,13,13,14,23,21,65, + 35,34,60,26,21,16,13,34,9,26,40,16,40,26,9,34,13,16,21,26,60,34,35,65,21,23,14,13,13,16,21,26,60,35,25,38,8,14,14,62, + 44,146,87,63,126,14,13,14,31,19,18,31,14,13,14,14,13,14,31,18,19,31,14,13,0,3,0,22,0,192,6,108,4,79,0,79,0,106,0,133, + 0,0,1,51,7,33,6,7,6,35,33,7,6,7,6,21,20,22,23,22,20,7,6,7,14,1,34,39,46,1,39,38,52,55,54,55,54,63,1,54, + 55,54,55,62,1,39,46,1,39,38,35,34,15,1,6,35,34,39,46,1,39,38,52,55,62,1,55,54,51,50,23,30,1,23,22,20,23,22,55,54, + 59,1,37,6,7,6,7,6,20,23,30,1,23,22,51,50,54,55,54,55,54,52,39,46,1,39,38,35,34,1,54,55,54,55,54,52,39,46,1,39, + 38,35,34,6,7,6,7,6,20,23,30,1,23,22,51,50,3,205,214,213,2,158,17,101,79,232,254,117,82,100,50,29,33,9,12,18,13,31,26,72, + 72,35,32,55,10,12,19,12,31,25,9,90,84,78,22,12,13,7,3,3,29,30,8,43,90,97,50,49,35,43,28,36,48,13,12,18,18,52,36,36, + 36,43,28,36,48,13,9,2,6,39,25,177,115,253,185,21,15,9,16,13,6,7,23,24,17,23,21,42,15,15,10,13,6,7,22,26,17,23,20,1, + 6,21,15,9,16,13,6,7,28,19,18,22,21,42,15,15,10,12,5,7,30,18,20,20,14,4,79,207,75,41,32,82,100,35,20,15,6,30,23,33, + 62,38,28,30,24,30,11,10,51,30,34,57,42,27,30,24,4,36,34,68,19,19,19,46,8,7,22,11,3,39,20,20,11,14,45,32,32,68,33,32, + 50,14,15,11,13,46,32,23,44,5,14,9,6,84,8,14,8,24,19,37,15,17,21,8,6,18,14,13,18,22,35,14,18,21,8,5,253,58,9,13, + 8,24,19,38,15,16,25,5,5,18,13,14,18,19,40,12,17,25,5,5,0,9,0,73,0,244,6,152,4,232,0,90,0,120,0,150,0,180,0,210, + 0,254,1,45,1,52,1,72,0,0,1,54,55,38,39,38,39,38,43,1,34,39,38,39,38,39,38,52,55,54,55,54,55,54,51,50,23,22,23,22, + 23,22,21,20,7,22,31,1,37,54,51,50,23,22,21,20,7,13,1,22,21,20,7,6,35,34,39,37,7,6,7,22,21,20,7,6,7,6,7,6, + 35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,59,1,50,55,54,0,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,34,7,6, + 7,6,7,6,21,20,23,22,23,22,23,18,50,55,54,55,54,55,54,53,52,39,38,39,38,39,38,34,7,6,7,6,7,6,21,20,23,22,23,22, + 23,18,34,39,38,39,38,39,38,53,52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,6,7,6,7,2,34,39,38,39,38,39,38,53, + 52,55,54,55,54,55,54,50,23,22,23,22,23,22,21,20,7,6,7,6,7,5,39,38,39,38,39,38,53,52,55,54,53,52,39,38,39,38,39,38, + 34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,59,1,50,23,22,23,22,23,55,54,3,45,1,38,35,34,7,5,6,7,6,7,6,7,6, + 43,1,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52,39,38,53,52,55,54,37,5,22,51,50,55,37,38, + 20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,50,23,22,23,2,73,11,7,7,11,9,25,81,92,67,45,45,37,40,34,19,18,18,16,40, + 27,47,42,48,46,44,43,34,40,13,18,6,47,142,88,1,93,226,92,136,57,8,30,254,2,1,254,30,8,60,133,92,226,254,163,88,142,47,6,18, + 19,34,36,41,48,42,51,39,41,34,42,13,18,18,16,37,28,49,42,48,67,82,91,23,254,235,28,11,12,9,10,3,3,3,3,10,9,12,11,28, + 11,12,9,10,3,3,3,3,10,9,12,11,28,11,12,9,10,3,3,3,3,10,9,12,11,28,11,12,9,10,3,3,3,3,10,9,12,50,50,21, + 21,17,19,9,9,9,9,19,17,21,21,50,21,21,17,19,9,9,9,9,19,17,21,21,50,21,21,17,19,9,9,9,9,19,17,21,21,50,21,21, + 17,19,9,9,9,9,19,17,21,1,134,37,149,39,22,11,16,11,6,13,13,27,20,38,31,74,31,32,27,24,15,13,13,13,27,20,38,31,37,67, + 92,100,30,18,23,7,35,28,189,1,237,2,95,42,93,79,217,254,145,148,18,17,23,20,28,104,88,67,37,31,38,20,27,13,13,13,15,24,27,32, + 31,74,31,38,20,27,13,13,6,11,16,12,1,147,1,31,217,79,93,42,253,221,217,5,6,9,9,22,9,9,6,5,5,6,9,9,22,9,9,6, + 2,217,8,13,14,7,6,10,32,16,13,34,28,41,38,96,38,34,39,26,18,16,16,16,31,36,34,47,39,29,18,9,60,37,139,90,83,13,17,31, + 12,207,207,12,37,13,11,83,90,139,37,60,9,24,23,47,39,42,29,32,14,16,16,17,28,34,37,53,34,45,40,36,35,27,19,16,32,9,254,210, + 4,5,8,7,7,4,8,7,5,6,8,7,5,4,4,5,8,7,7,4,7,8,5,6,8,7,5,2,59,4,5,8,7,7,4,7,8,5,6,8, + 7,5,4,4,5,8,7,7,4,8,7,5,6,8,7,5,253,130,7,8,14,16,17,18,22,21,18,17,16,14,8,7,7,8,14,16,17,18,21,22, + 18,17,16,14,8,2,56,7,8,14,16,17,18,21,22,18,17,16,14,8,7,7,8,14,16,17,18,22,21,18,17,16,14,8,92,15,61,7,4,6, + 8,14,10,24,14,23,33,28,27,25,19,16,12,12,14,22,19,32,28,33,32,28,27,25,19,16,12,34,10,14,17,8,24,17,254,242,194,247,47,86, + 146,67,30,30,15,14,10,34,12,16,19,25,27,28,32,33,28,32,19,22,14,12,12,16,19,25,27,28,33,23,13,25,10,20,2,2,91,117,86,47, + 225,43,22,9,9,6,5,5,6,9,9,22,9,9,6,5,5,6,9,0,0,3,0,86,255,227,6,94,5,240,0,97,0,117,0,135,0,0,1,14, + 1,21,20,22,23,22,23,22,32,55,54,55,62,1,53,52,38,39,38,39,38,35,34,7,6,7,14,1,21,20,22,23,21,38,2,53,52,18,55,54, + 55,54,51,50,23,22,23,22,18,21,20,2,7,6,7,6,32,39,46,2,53,52,54,55,38,53,52,55,18,51,50,23,22,21,20,7,6,35,34,7, + 6,7,6,21,20,23,22,21,20,7,6,7,6,35,34,23,54,55,54,55,54,55,22,23,22,7,6,7,6,7,6,35,34,39,38,1,22,23,22,21, + 20,7,6,7,6,35,34,39,54,55,54,53,52,2,19,3,12,21,19,20,24,111,1,27,122,119,98,100,97,95,102,95,122,120,138,134,124,119,98,100, + 97,77,44,107,114,110,117,108,141,140,156,154,142,134,115,112,115,110,117,110,139,141,254,199,138,42,68,36,32,28,4,108,181,169,81,6,16,36,34,9, + 54,42,31,68,63,16,18,22,34,53,39,18,16,75,24,40,50,25,23,3,45,6,18,2,10,19,27,35,32,19,3,3,27,1,158,62,22,16,21,13, + 30,10,28,10,58,17,29,30,1,55,6,30,27,28,50,18,19,11,51,51,49,99,100,237,136,141,232,105,96,52,51,51,49,99,100,237,141,135,188,62, + 152,109,1,16,156,157,1,16,119,110,60,59,59,56,114,111,254,236,161,152,254,240,119,112,58,59,59,18,66,86,48,47,77,31,16,15,205,239,1,144, + 8,20,56,58,68,64,42,31,124,115,97,32,22,27,30,9,45,70,40,28,55,12,34,42,61,56,25,38,8,21,15,48,33,50,29,28,1,6,4,32, + 22,17,12,49,45,53,36,38,12,10,18,54,58,66,52,0,0,6,0,86,255,227,6,94,5,240,0,13,0,26,0,40,0,66,0,92,0,119,0,0, + 1,46,1,39,37,6,21,20,22,23,22,23,22,23,19,38,39,38,34,7,6,7,19,54,51,50,23,19,5,14,1,7,37,54,55,54,55,62,1,53, + 52,36,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,19,34,7,6,7,14,1,21,20,22,23,30,1, + 32,55,54,55,62,1,53,52,38,39,38,39,38,39,50,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,54, + 1,169,63,39,5,1,42,8,38,36,32,49,20,8,243,36,45,43,104,43,45,36,70,51,55,56,50,136,1,42,2,42,63,254,146,14,14,49,32,36, + 38,254,231,62,26,27,22,22,22,22,22,22,27,26,62,26,27,22,22,22,22,22,22,27,57,134,124,119,98,100,97,98,99,96,242,1,17,122,119,98, + 100,97,95,102,95,122,120,138,154,142,134,115,112,115,110,117,110,139,141,254,203,142,134,115,112,115,110,117,108,141,140,1,119,73,95,15,253,30,34,50, + 91,36,32,22,9,1,1,163,34,20,19,19,20,34,1,131,9,9,254,11,253,7,103,73,131,4,6,22,32,36,91,50,33,118,11,12,21,23,53,31, + 30,53,23,21,12,11,11,12,21,23,53,30,31,53,23,21,12,2,21,51,49,99,100,237,141,133,241,99,97,102,51,49,99,100,237,136,141,232,105,96, + 52,51,100,59,56,114,111,254,236,161,152,254,240,119,112,58,59,59,56,114,111,1,20,156,157,1,16,119,110,60,59,0,0,1,0,120,0,44,6,65, + 5,170,0,45,0,0,19,53,55,39,51,23,54,37,2,3,51,23,51,21,35,23,51,21,35,23,33,50,23,22,20,7,6,35,33,7,51,21,35,7, + 51,21,35,7,35,18,19,36,39,7,35,55,148,36,64,100,146,146,1,30,53,171,123,115,148,86,100,154,93,152,1,8,70,48,32,32,48,70,254,248, + 152,93,154,100,86,148,115,123,171,53,254,226,146,146,100,64,2,215,40,5,218,201,13,10,1,20,1,106,150,80,130,80,198,26,17,44,17,26,198,80, + 130,80,150,1,96,1,30,11,12,201,218,0,0,5,0,132,0,220,6,48,4,249,0,13,0,20,0,34,0,41,0,45,0,0,9,1,33,1,54,55, + 54,55,54,50,23,22,23,22,23,1,17,1,22,21,20,5,1,33,1,6,7,6,7,6,34,39,38,39,38,39,1,17,1,38,53,52,1,17,33,17, + 3,246,1,184,251,88,1,184,7,8,29,36,35,82,35,43,22,8,47,1,174,254,82,3,254,159,254,70,4,168,254,70,6,7,29,36,35,82,35,36, + 29,7,49,254,83,1,173,3,253,242,5,172,3,104,1,44,254,212,9,8,28,16,15,15,19,25,9,170,254,222,2,141,254,221,17,18,19,107,254,211, + 1,45,8,7,28,16,15,15,16,28,7,170,1,34,253,115,1,33,19,19,18,253,223,4,29,251,227,0,0,4,1,179,0,0,4,124,5,239,0,80, + 0,208,0,227,0,243,0,0,1,52,55,54,63,1,54,55,54,51,23,38,39,38,39,38,53,52,55,54,51,50,23,22,23,22,31,1,22,23,54,55, + 54,55,54,55,54,53,52,39,38,53,52,55,54,51,50,23,22,23,22,21,20,7,3,20,21,20,31,1,22,21,20,7,23,22,7,6,29,1,33,53, + 52,39,38,39,38,53,52,39,38,1,38,35,34,15,1,6,15,1,6,15,1,39,38,47,1,38,39,38,39,38,35,34,7,6,21,20,23,22,31,2, + 22,23,22,21,20,7,6,35,34,39,38,39,38,47,1,38,39,38,35,34,7,6,7,22,23,22,23,22,23,22,23,20,7,6,7,21,20,23,22,23, + 22,23,22,21,20,7,38,39,38,39,38,63,1,54,39,38,39,6,35,34,39,38,39,38,35,34,23,22,23,22,31,1,22,21,7,33,39,52,55,54, + 61,1,39,54,53,52,39,38,53,52,53,19,52,53,52,39,1,7,22,23,22,23,22,23,22,51,50,55,54,53,52,39,38,39,38,7,6,7,22,23, + 22,51,50,55,54,53,52,39,38,47,1,1,179,37,23,17,52,14,45,2,2,4,26,41,30,20,34,23,27,36,16,18,48,17,74,75,38,15,14,18, + 7,5,10,5,12,5,1,1,31,27,41,55,29,13,1,10,1,9,2,2,4,1,3,1,22,3,253,223,5,9,37,48,27,18,2,135,3,39,35,4, + 5,1,10,35,5,22,54,25,9,43,17,45,76,26,20,17,14,17,8,7,29,13,19,95,136,95,94,4,20,5,4,22,18,6,3,47,115,52,7,42, + 30,19,12,7,5,3,8,49,40,13,8,46,50,1,21,15,1,54,23,24,54,9,3,28,124,47,6,7,14,2,7,2,7,7,15,28,40,14,15,24, + 17,49,9,4,2,10,7,4,10,92,1,1,1,171,1,12,13,2,3,9,5,12,2,253,254,17,35,58,55,17,4,1,17,10,11,4,2,12,5,6, + 108,128,15,3,83,38,15,11,16,8,4,12,8,11,120,2,235,55,49,7,31,93,24,23,1,1,47,126,91,35,60,36,28,27,32,5,12,26,111,187, + 95,37,21,16,64,44,31,16,134,58,6,11,10,6,6,36,34,30,59,26,18,118,82,21,18,254,212,7,9,24,29,22,36,88,36,43,124,25,137,19, + 141,137,182,18,33,53,68,88,38,80,89,59,2,182,57,68,111,30,54,194,29,6,15,11,13,98,39,110,149,50,15,12,11,6,11,31,56,26,51,254, + 101,70,93,12,8,19,4,1,20,6,7,52,84,38,3,31,22,10,7,12,22,38,32,18,12,47,53,48,36,63,45,32,2,49,64,27,17,38,17,6, + 5,16,9,51,108,15,10,23,23,75,15,11,10,5,25,3,5,13,67,4,34,80,49,22,214,9,11,159,183,58,48,51,60,8,68,58,53,88,73,46, + 41,6,7,1,68,4,7,19,38,254,91,20,43,45,49,58,13,12,17,16,9,9,21,23,9,5,113,18,20,47,65,56,9,18,10,10,18,17,11,6, + 103,0,0,0,0,8,0,43,0,169,6,106,5,108,0,6,0,57,0,76,0,112,0,123,0,127,0,137,0,141,0,0,19,22,55,54,53,52,39,1, + 34,39,38,35,34,7,6,43,1,34,39,7,5,19,38,53,52,63,1,54,55,54,55,54,55,54,51,50,23,55,54,51,50,23,22,21,7,23,22,51, + 50,55,51,22,21,20,7,35,53,6,37,54,55,54,55,1,39,38,35,34,7,6,15,1,22,21,20,7,54,1,34,47,1,7,20,7,54,55,22,21, + 20,7,6,35,34,7,22,21,20,7,50,55,54,51,50,23,22,51,50,55,54,53,52,39,6,55,22,21,20,7,21,51,54,53,52,39,5,54,55,15, + 1,6,21,20,23,22,23,54,53,52,5,7,55,38,216,27,20,15,16,3,112,47,108,48,29,38,150,74,33,99,83,37,89,254,248,129,6,14,69,28, + 25,93,123,64,67,34,36,52,62,153,45,59,37,30,13,190,204,44,40,54,6,225,89,62,248,109,252,188,33,30,8,5,1,78,36,17,31,88,236,54, + 34,20,47,44,40,3,171,52,25,242,115,83,63,88,15,36,85,129,62,24,34,20,115,74,63,75,40,96,46,47,52,137,43,50,25,75,50,46,158,48, + 62,252,176,83,13,162,90,112,48,31,43,23,254,160,49,94,7,1,240,3,39,31,31,32,16,254,199,14,5,16,8,59,99,115,1,12,18,32,26,47, + 232,94,34,124,89,47,26,13,52,171,50,56,25,29,219,135,29,30,131,180,207,149,108,37,233,37,111,29,15,1,116,30,14,233,53,111,65,61,39,89, + 36,9,1,97,16,157,133,163,84,2,42,13,22,18,16,39,1,39,71,43,45,13,11,12,6,37,95,107,106,126,7,29,114,141,125,106,76,96,208,134, + 124,239,92,103,195,75,26,64,47,30,20,3,46,56,53,150,99,40,36,0,0,7,0,182,0,154,5,203,5,175,0,19,0,25,0,32,0,40,0,50, + 0,76,0,83,0,0,1,62,1,53,52,47,1,6,35,20,7,6,35,20,7,23,22,51,50,54,1,63,1,15,2,19,37,1,19,37,1,19,5,1, + 51,50,53,52,39,1,0,54,53,52,39,1,7,1,22,51,1,62,1,55,54,51,50,22,21,20,7,14,1,7,14,1,7,6,35,34,38,53,52,55, + 62,1,23,7,1,22,51,50,39,5,37,8,12,2,59,23,30,54,54,73,22,237,8,7,10,26,252,128,153,13,146,153,13,131,1,9,2,125,184,253, + 103,253,132,17,1,189,2,13,2,63,2,253,194,1,164,54,6,253,251,113,2,5,17,15,253,110,13,31,16,13,10,14,17,5,6,19,14,14,29,17, + 14,9,14,16,4,5,20,45,127,2,62,11,10,57,1,1,64,8,28,10,5,8,238,23,72,54,55,28,24,59,2,11,2,249,152,146,13,152,146,1, + 122,18,253,131,253,104,184,2,124,1,9,20,253,243,56,10,12,2,62,252,182,54,33,15,17,2,6,113,253,250,6,2,234,13,21,5,4,17,13,10, + 14,16,31,13,14,20,5,4,14,16,11,13,16,30,244,14,253,194,2,66,0,7,0,53,1,150,6,142,4,62,0,17,0,23,0,30,0,37,0,43, + 0,63,0,70,0,0,0,52,38,39,38,47,1,20,7,22,20,7,22,21,55,54,55,54,5,53,39,7,21,23,3,55,33,9,1,33,39,1,33,54, + 53,52,39,33,0,52,39,33,21,33,36,52,54,55,62,1,50,22,23,30,1,20,6,7,14,1,34,38,39,38,23,7,33,54,53,52,39,5,163,7, + 7,5,10,210,21,51,51,21,210,10,5,7,251,166,94,94,94,175,175,3,82,2,88,253,168,252,174,175,1,73,2,180,25,35,253,6,3,74,50,253, + 86,2,170,252,108,7,8,7,18,20,18,7,8,7,7,8,7,18,20,18,7,8,197,80,2,250,35,25,2,222,24,21,9,7,6,126,33,20,56,144, + 56,20,33,126,6,7,9,75,216,112,112,216,112,1,104,200,254,172,254,172,200,1,44,25,23,27,25,254,196,112,24,160,60,40,35,15,14,16,16,14, + 15,35,40,35,15,14,16,16,14,15,105,100,25,27,23,25,0,7,0,182,0,154,5,203,5,175,0,19,0,25,0,32,0,40,0,50,0,76,0,83, + 0,0,1,46,1,35,34,15,1,22,21,50,23,22,21,50,23,55,54,53,52,38,1,39,31,2,39,7,39,3,1,37,3,1,39,23,1,54,53,52, + 43,1,46,1,35,34,7,1,23,1,54,53,1,46,1,39,38,53,52,54,51,50,23,30,1,23,30,1,23,22,21,20,6,35,34,39,46,1,19,1, + 54,35,34,7,1,5,37,9,26,10,7,8,237,22,73,54,54,30,23,59,2,12,252,111,146,13,153,146,13,168,198,17,2,124,2,153,184,253,131,18, + 14,2,62,2,63,2,37,54,33,15,17,253,251,113,2,5,6,253,23,14,20,5,4,16,14,9,14,17,29,14,14,19,6,5,17,14,10,13,16,31, + 18,2,12,1,57,10,11,253,194,5,9,9,11,2,59,24,28,55,54,72,23,238,8,5,10,28,253,24,13,146,152,13,146,213,198,1,9,2,124,184, + 253,104,253,131,236,127,2,62,12,10,56,136,54,6,253,250,113,2,6,17,15,253,109,14,30,16,13,11,16,14,4,5,20,14,13,31,16,14,10,13, + 17,4,5,21,1,15,2,12,66,2,253,194,0,2,0,88,1,123,6,14,4,91,0,37,0,71,0,0,18,16,39,50,51,32,37,1,21,37,46,1, + 39,38,34,7,6,7,14,1,20,22,23,22,23,22,50,55,62,1,55,37,21,1,36,33,34,35,18,20,7,50,51,50,5,37,5,6,7,6,34,39, + 38,39,46,1,52,54,55,54,55,54,50,23,22,23,5,37,4,35,34,35,138,50,8,7,1,37,2,23,2,107,253,191,5,14,18,13,30,13,14,11, + 10,12,14,8,11,14,13,30,13,18,14,5,2,65,253,149,253,233,254,219,7,8,153,23,4,5,177,2,15,1,183,254,156,22,27,26,62,26,27,22, + 22,22,22,22,22,27,26,62,26,27,22,1,100,254,73,253,241,177,5,4,2,73,1,68,96,110,254,237,83,28,8,16,8,6,6,6,10,9,29,32, + 31,7,10,6,6,6,8,16,8,28,83,254,237,110,1,71,138,89,110,185,24,21,12,11,11,12,21,23,53,62,53,23,21,12,11,11,12,21,24,185, + 110,0,0,0,0,1,0,138,1,173,6,14,4,41,0,40,0,0,1,37,21,1,36,35,34,35,54,52,39,50,51,50,37,1,21,37,38,39,38,39, + 38,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,54,3,232,2,38,253,149,253,236,248,7,6,50,50,6,7,248,2,20,2,107,253, + 218,7,15,14,18,17,42,17,18,14,15,15,15,15,14,18,17,42,17,18,14,15,2,197,28,33,254,237,110,96,224,96,110,254,237,33,29,17,15,14, + 8,8,8,8,14,15,35,21,20,35,15,14,8,8,8,8,14,15,0,0,0,1,1,51,0,198,5,87,5,10,0,28,0,0,1,50,23,22,51,50, + 55,0,19,54,51,50,22,21,20,7,0,1,6,35,34,39,38,39,38,53,52,55,54,1,197,39,20,40,17,13,14,1,25,239,62,135,32,22,33,254, + 126,254,182,23,71,72,13,34,46,52,70,43,2,142,64,120,20,1,194,1,22,72,12,9,14,41,254,48,253,252,36,6,15,138,153,39,42,39,24,0, + 0,1,0,237,0,178,5,197,5,12,0,30,0,0,1,50,23,22,51,50,55,0,55,54,51,50,23,22,21,20,7,0,7,6,35,34,39,38,39,38, + 53,52,55,54,51,1,197,39,20,40,17,13,14,1,25,239,101,96,127,26,11,23,253,125,123,42,152,50,55,23,57,72,70,96,48,3,26,64,120,20, + 1,157,175,74,8,3,22,18,27,253,30,222,76,26,12,141,178,134,49,32,44,0,0,0,0,1,1,3,0,148,5,177,5,65,0,11,0,0,9,1, + 7,9,1,39,9,1,55,9,1,23,3,231,1,201,142,254,56,254,55,142,1,201,254,55,142,1,201,1,201,142,2,234,254,55,141,1,201,254,55,141, + 1,201,1,201,141,254,56,1,201,141,0,0,0,1,0,175,0,63,6,5,5,150,0,11,0,0,9,11,4,145,1,116,254,201,254,140,254,140,254,201, + 1,116,254,140,1,55,1,116,1,116,1,55,2,234,254,140,254,201,1,116,254,140,1,55,1,116,1,116,1,55,254,140,1,117,254,201,0,1,0,241, + 255,238,5,156,5,220,0,66,0,0,1,50,23,22,23,54,51,50,23,22,21,20,7,6,3,22,23,22,21,20,15,1,22,21,20,7,6,35,34,39, + 38,39,6,3,6,35,34,39,38,53,52,55,54,55,18,19,2,39,38,53,52,55,54,51,50,23,54,55,54,51,50,23,22,23,54,55,54,4,248,10, + 16,17,18,29,17,15,26,16,22,208,196,81,143,12,30,32,4,22,26,12,26,20,120,128,172,222,32,76,36,4,51,11,5,27,204,228,122,40,9,18, + 19,16,15,23,9,13,18,28,32,10,54,88,142,204,24,5,220,16,16,26,51,27,17,21,27,23,226,254,241,198,239,20,12,23,25,22,12,20,30,16, + 18,26,154,208,224,254,138,54,42,28,61,80,31,14,42,1,62,1,10,1,34,157,35,10,14,26,26,29,17,12,16,30,168,152,184,204,24,0,0,0, + 0,1,0,252,0,0,6,8,5,234,0,82,0,0,1,50,23,22,23,54,23,22,23,22,21,20,7,6,3,22,23,22,21,20,7,6,7,6,7,6, + 35,34,39,6,7,6,35,34,39,38,39,2,7,6,43,1,34,39,38,39,6,35,34,39,38,53,52,55,38,39,38,53,52,55,54,55,38,3,38,53, + 52,55,54,51,50,23,54,55,54,51,50,23,22,23,18,55,54,5,84,29,27,20,8,26,10,32,14,14,16,241,235,148,148,17,30,20,37,2,14,24, + 32,36,30,8,14,36,27,23,26,89,121,230,88,17,21,2,18,17,15,2,20,18,25,29,36,30,9,9,18,24,130,196,122,99,22,23,16,22,26,48, + 1,11,23,17,43,13,106,150,231,249,12,5,234,30,22,58,1,5,12,14,13,21,40,16,219,254,199,204,162,18,24,49,26,17,2,17,35,58,24,18, + 11,27,28,95,191,254,251,135,26,36,31,13,12,30,35,17,27,45,3,13,24,24,21,31,176,212,189,1,11,61,28,26,49,32,39,14,25,50,26,196, + 186,1,8,218,12,0,0,0,0,3,0,112,0,0,6,68,5,213,0,11,0,23,0,35,0,0,1,17,33,17,33,17,33,17,33,17,33,17,37,33, + 17,33,17,33,17,33,17,33,17,33,3,33,21,33,17,35,17,33,53,33,17,51,4,54,254,72,254,86,1,170,1,184,1,170,254,166,1,190,254,66, + 253,168,254,66,1,190,2,88,200,1,190,254,66,200,254,66,1,190,200,3,198,1,171,254,85,254,72,254,86,1,170,1,184,80,253,168,254,66,1,190, + 2,88,1,191,253,121,200,254,66,1,190,200,1,191,0,0,0,1,0,112,0,0,6,68,5,213,0,11,0,0,1,33,17,33,17,33,17,33,17,33, + 17,33,4,34,2,34,253,222,254,112,253,222,2,34,1,144,3,178,254,112,253,222,2,34,1,144,2,35,0,2,0,112,0,0,6,68,5,213,0,3, + 0,15,0,0,1,51,53,35,55,33,21,33,17,35,17,33,53,33,17,51,2,227,238,238,239,2,114,253,142,240,253,142,2,114,240,2,115,238,1,240, + 253,142,2,114,240,2,115,0,0,2,0,112,0,0,6,68,5,213,0,3,0,15,0,0,1,33,17,33,37,33,17,33,17,33,17,33,17,33,17,33, + 2,147,1,142,254,114,1,143,2,34,253,222,254,112,253,222,2,34,1,144,2,35,1,142,1,254,112,253,222,2,34,1,144,2,35,0,0,1,1,82, + 0,0,5,98,5,213,0,11,0,0,1,33,21,33,17,35,17,33,53,33,17,51,3,210,1,144,254,112,240,254,112,1,144,240,4,69,240,252,171,3, + 85,240,1,144,0,2,1,12,0,0,5,108,5,213,0,15,0,27,0,0,1,51,23,17,33,17,33,39,17,35,39,17,33,17,33,23,7,17,35,17, + 33,21,33,17,51,17,33,53,4,64,150,150,254,212,254,142,150,150,150,1,44,1,114,150,200,220,254,212,1,44,220,1,44,4,169,150,254,142,253,95, + 150,2,11,150,1,114,1,44,150,250,1,44,254,212,220,253,95,2,161,220,0,3,1,62,0,0,5,118,5,213,0,11,0,23,0,35,0,0,1,17, + 33,17,33,17,33,17,33,17,33,17,39,33,17,33,17,33,17,33,17,33,17,33,3,33,21,33,17,35,17,33,53,33,17,51,4,14,254,152,254,232, + 1,24,1,104,1,24,200,1,24,254,232,253,248,254,232,1,24,2,8,160,1,24,254,232,200,254,232,1,24,200,4,109,1,24,254,232,254,132,253,95, + 2,161,1,124,80,253,228,253,95,2,161,2,28,1,24,254,72,220,253,95,2,161,220,1,24,0,0,0,0,1,0,112,0,0,6,68,5,213,0,75, + 0,0,1,35,34,6,7,6,7,6,21,7,17,23,22,23,22,23,30,1,59,1,53,52,38,39,38,39,38,35,39,33,7,6,7,6,7,14,1,29, + 1,51,50,54,55,54,55,54,53,55,17,39,38,39,38,39,46,1,43,1,21,20,22,23,22,23,22,51,23,33,55,54,55,54,55,62,1,53,3,15, + 123,100,179,73,66,44,36,50,25,25,36,42,68,69,179,104,123,76,71,67,95,82,27,81,4,124,54,54,82,95,67,73,74,123,104,179,69,68,42,36, + 50,25,25,36,44,66,70,182,100,123,76,71,67,95,82,27,81,251,132,54,54,82,95,67,73,74,2,160,75,73,66,96,79,27,84,4,124,56,55,79, + 92,70,71,75,122,100,182,71,66,43,37,50,25,25,37,43,66,73,180,100,122,75,71,70,92,79,27,84,251,132,56,55,79,96,66,72,76,123,100,182, + 71,66,43,37,50,25,25,37,43,66,73,180,100,0,0,0,0,8,0,187,255,229,5,249,5,243,0,11,0,17,0,20,0,23,0,26,0,29,0,32, + 0,35,0,0,1,19,33,3,19,33,11,1,33,19,3,33,23,3,19,33,19,11,1,7,51,31,1,55,3,7,51,5,35,23,1,39,7,19,55,35, + 3,90,224,1,191,224,224,254,65,224,224,254,65,224,224,1,191,58,166,166,1,76,166,166,166,108,216,173,109,108,108,109,217,254,122,216,108,254,231,109, + 108,108,109,217,5,243,254,124,254,125,254,125,254,124,1,132,1,131,1,131,100,254,225,254,224,1,32,1,31,1,31,187,100,187,187,254,125,188,99,188, + 1,31,188,188,1,132,187,0,0,1,0,84,255,227,6,96,5,240,0,67,0,0,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29,1, + 51,50,55,54,51,50,23,22,20,7,6,35,34,39,38,43,1,21,20,23,22,21,20,7,6,34,39,38,53,52,55,54,61,1,35,34,7,6,35,34, + 39,38,52,55,54,51,50,23,22,51,3,40,76,44,54,56,120,56,54,44,76,32,186,122,70,118,100,48,48,48,48,100,118,70,122,186,32,76,44,54, + 56,120,56,54,44,76,32,186,122,70,118,100,48,48,48,48,100,118,70,122,186,3,28,32,186,122,70,118,100,48,48,48,48,100,118,70,122,186,32,76, + 44,54,56,120,56,54,44,76,32,187,121,70,118,100,48,49,49,48,100,118,70,121,187,32,76,44,54,56,120,56,54,44,76,0,0,0,0,1,0,86, + 255,231,6,94,5,240,0,131,0,0,1,38,39,35,6,7,6,7,14,1,35,34,38,39,38,39,38,52,55,54,55,62,1,51,50,22,23,22,23,22, + 23,51,54,55,54,55,53,38,39,38,39,46,1,53,52,54,55,54,55,54,50,23,22,23,30,1,21,20,6,7,6,7,6,7,21,22,23,22,23,51, + 54,55,54,55,62,1,51,50,22,23,22,23,22,20,7,6,7,14,1,35,34,38,39,38,39,38,39,35,6,7,6,7,21,22,23,22,23,30,1,21, + 20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,54,55,53,38,3,2,16,10,212,2,10,20,29,32,82,46,45,82,32,31,18,17, + 17,18,31,32,82,45,46,82,32,34,15,9,3,212,10,16,17,21,16,20,42,30,33,34,34,33,32,40,40,92,40,40,32,33,34,34,33,35,37,23, + 13,21,17,16,10,212,3,9,15,34,32,82,46,45,82,32,31,18,17,17,18,31,32,82,45,46,82,32,29,20,10,2,212,10,16,17,21,13,23,37, + 35,33,34,34,33,32,40,40,92,40,40,32,33,34,34,33,30,42,20,16,21,2,147,17,21,16,20,42,30,33,34,34,33,32,40,40,92,40,40,32, + 33,34,34,33,35,37,23,13,21,17,16,10,213,2,10,20,29,32,82,46,45,82,32,31,18,17,17,18,31,32,82,45,46,82,32,34,15,9,3,213, + 10,16,17,21,13,23,37,35,33,34,34,33,32,40,40,92,40,40,32,33,34,34,33,30,42,20,16,21,17,16,10,212,3,9,15,34,32,82,46,45, + 82,32,31,18,17,17,18,31,32,82,45,46,82,32,29,20,10,2,212,10,0,1,0,83,255,227,6,97,5,240,0,131,0,0,1,52,38,39,38,39, + 38,39,46,1,53,52,54,55,54,55,54,50,23,22,23,30,1,21,20,6,7,6,7,6,7,14,1,21,50,54,55,54,55,54,55,62,1,51,50,22, + 23,22,23,22,20,7,6,7,14,1,35,34,38,39,38,39,38,39,46,1,35,20,22,23,22,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38, + 39,46,1,53,52,54,55,54,55,54,55,62,1,53,34,6,7,6,7,6,7,14,1,35,34,38,39,38,39,38,52,55,54,55,62,1,51,50,22,23, + 22,23,22,23,30,1,3,40,44,36,14,16,24,10,40,40,42,38,32,58,46,114,48,54,36,38,42,42,38,10,26,8,20,41,39,68,101,33,13,12, + 18,10,39,100,56,58,98,38,36,24,21,21,24,36,38,98,58,56,100,39,10,18,12,13,41,97,64,47,33,13,16,25,10,39,41,42,38,36,54,47, + 114,47,54,36,38,42,41,39,10,25,16,13,39,41,63,99,39,14,12,18,10,38,100,56,58,98,38,33,27,22,22,24,36,38,98,58,61,95,38,10, + 18,6,20,40,98,3,28,67,99,34,14,12,18,10,38,100,56,58,98,38,32,28,22,22,24,36,38,98,58,61,95,38,10,18,6,20,40,97,63,47, + 33,13,16,25,10,39,41,42,38,36,54,47,114,47,54,36,38,42,41,39,10,25,16,13,39,41,68,101,33,13,12,18,10,39,100,56,58,98,38,36, + 24,21,21,24,36,38,98,58,56,100,39,10,18,12,13,41,97,64,41,39,14,16,24,10,40,40,42,38,32,58,46,114,48,54,36,38,42,42,38,10, + 26,8,20,40,40,0,0,0,0,1,0,84,255,229,6,96,5,242,1,48,0,0,1,50,23,22,23,22,23,22,21,20,7,6,7,54,55,54,51,50, + 23,22,23,22,23,22,21,20,7,14,1,7,6,35,34,39,38,39,38,39,17,33,38,39,38,39,38,53,52,54,55,54,55,54,51,50,23,22,23,22, + 23,22,21,20,7,6,7,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,22,23,22,21,20,6,7,6,7, + 6,35,34,39,38,39,38,39,38,53,52,55,54,55,54,55,33,17,54,55,54,55,54,51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35, + 34,39,38,39,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,6,7,6,35,34,39,38,39,38,39,38,53,52, + 55,54,55,54,55,54,51,50,22,23,22,23,17,33,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,39,38,39,38,53,52,55,54,55, + 6,7,6,35,34,39,38,39,38,39,38,52,55,54,55,54,55,54,51,50,23,22,23,38,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,22, + 23,22,21,20,7,6,7,6,7,33,17,6,7,6,7,6,35,34,39,46,1,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,38,39,38,53, + 52,55,54,55,54,55,54,3,90,30,23,27,18,20,11,10,10,11,20,11,20,25,28,30,24,26,19,20,11,10,10,11,40,25,25,29,30,23,25,20, + 14,10,1,38,17,14,19,11,11,22,19,20,26,25,28,29,25,26,20,19,11,11,11,8,9,20,25,25,28,32,23,25,20,19,12,10,10,12,19,22, + 23,26,29,28,25,25,20,9,8,11,22,19,17,29,25,29,24,29,26,20,19,11,11,11,11,19,14,17,254,219,9,14,17,29,23,30,29,24,26,19, + 20,11,10,10,11,20,18,27,23,30,25,28,20,11,19,11,11,11,11,20,18,27,23,60,23,27,18,20,11,11,11,11,19,11,20,24,29,30,23,27, + 18,20,11,10,10,11,20,19,26,24,29,27,52,20,14,9,254,219,17,13,22,9,10,10,11,20,22,23,26,27,30,25,25,20,19,12,10,10,8,10, + 22,23,26,28,29,25,26,20,18,12,10,10,12,18,17,29,25,29,28,26,25,20,10,8,10,10,12,19,19,26,25,30,27,26,25,20,20,11,10,10, + 12,19,13,17,1,37,10,14,20,25,23,30,29,24,26,40,10,11,11,10,20,19,27,23,30,29,24,20,11,20,11,10,10,11,20,19,26,23,5,242, + 11,12,18,20,26,25,29,28,25,26,20,10,8,10,10,12,18,20,26,25,29,31,23,25,40,11,10,10,12,19,13,17,254,219,10,14,20,25,23,30, + 29,50,20,20,11,10,10,11,20,19,26,24,30,28,25,20,11,20,11,10,10,11,20,18,27,24,29,30,24,27,18,22,9,10,10,11,20,11,20,25, + 28,26,54,19,17,13,11,11,10,20,20,26,24,29,30,23,25,20,14,10,254,218,18,13,16,14,11,11,11,19,20,26,25,28,29,25,26,20,18,12, + 11,11,8,9,19,26,25,28,29,26,25,20,19,12,10,10,12,19,20,25,26,29,28,25,26,19,9,8,11,11,12,18,20,26,25,29,28,25,26,20, + 19,11,11,22,19,13,18,1,37,9,14,23,22,24,30,28,25,26,19,22,9,10,10,11,20,18,27,23,30,29,25,19,12,22,9,10,10,11,20,18, + 27,23,60,23,27,19,17,13,11,11,10,20,11,20,24,29,30,23,27,18,20,11,11,11,11,20,19,26,24,29,30,23,26,19,14,10,1,37,17,13, + 19,12,10,10,11,40,25,26,28,25,29,26,20,18,12,10,10,8,10,20,26,25,28,29,25,26,20,18,12,11,0,0,0,1,0,87,255,227,6,95, + 5,245,0,27,0,0,19,50,55,54,55,54,18,53,20,18,23,22,23,22,51,34,7,6,7,6,2,21,52,2,39,38,39,38,87,155,141,134,115,112, + 115,110,117,108,141,140,156,156,140,141,108,117,110,115,112,115,134,141,2,236,59,56,114,111,1,20,161,157,254,240,119,110,60,59,59,60,110,119,254,240, + 157,161,1,20,111,114,56,59,0,2,0,87,255,227,6,95,5,245,0,27,0,55,0,0,1,50,23,22,23,30,1,21,52,54,55,54,55,54,51,34, + 39,38,39,46,1,53,20,6,7,6,7,6,33,50,55,54,55,54,18,53,20,18,23,22,23,22,51,34,7,6,7,6,2,21,52,2,39,38,39,38, + 1,101,101,92,87,74,73,75,71,77,70,91,91,102,102,91,91,70,77,71,75,73,74,87,92,254,141,155,141,134,115,112,115,110,117,108,141,140,156,156, + 140,141,108,117,110,115,112,115,134,141,2,236,38,37,74,72,179,105,102,177,77,72,39,38,38,39,72,77,177,102,105,179,72,74,37,38,59,56,114,111, + 1,20,161,157,254,240,119,110,60,59,59,60,110,119,254,240,157,161,1,20,111,114,56,59,0,2,0,47,255,236,6,133,5,243,0,9,0,19,0,0, + 19,37,9,1,5,1,19,37,5,19,1,3,33,1,3,9,1,3,1,33,47,2,13,1,30,1,30,2,13,254,166,37,254,10,254,10,37,1,209,191, + 253,149,1,244,191,1,245,1,245,191,1,244,253,149,3,165,131,1,203,254,53,131,254,97,253,230,202,202,2,26,3,236,253,179,254,148,253,180,1,108, + 254,148,2,76,1,108,0,0,0,2,0,86,255,227,6,94,5,240,0,9,0,36,0,0,1,3,33,1,3,9,1,3,1,33,3,50,23,22,23,22, + 18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,54,3,90,172,253,211,1,194,172,1,195,1,195,172,1,194,253,211,172,154, + 142,134,115,112,115,110,117,110,139,141,254,203,142,134,115,112,115,110,117,108,141,140,5,234,253,238,254,184,253,239,1,72,254,184,2,17,1,72,2,24, + 59,56,114,111,254,236,161,152,254,240,119,112,58,59,59,56,114,111,1,20,156,157,1,16,119,110,60,59,0,2,0,48,255,237,6,132,5,242,0,29, + 0,39,0,0,0,34,7,6,7,6,7,6,21,20,23,22,23,22,23,22,50,55,54,55,54,55,54,53,52,39,38,39,38,39,3,19,33,1,19,9, + 1,19,1,33,3,157,134,57,57,48,48,23,24,24,23,48,48,57,57,134,57,57,48,48,23,24,24,23,48,48,57,124,191,2,107,254,12,191,254,11, + 254,11,191,254,12,2,107,3,228,24,26,45,50,56,59,66,65,59,56,50,45,26,24,24,26,45,50,56,59,65,66,59,56,50,45,26,2,38,253,179, + 254,148,253,180,1,107,254,149,2,76,1,108,0,3,0,47,255,236,6,133,5,243,0,9,0,39,0,49,0,0,19,37,9,1,5,1,19,37,5,19, + 0,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,34,39,38,39,38,39,38,53,52,55,54,55,54,55,19,3,33,1,3,9,1,3,1,33, + 47,2,13,1,30,1,30,2,13,254,166,37,254,10,254,10,37,1,142,134,57,57,48,48,23,24,24,23,48,48,57,57,134,57,57,48,48,23,24,24, + 23,48,48,57,124,191,253,149,1,244,191,1,245,1,245,191,1,244,253,149,3,165,131,1,203,254,53,131,254,97,253,230,202,202,2,26,1,222,24,26, + 45,50,56,59,66,65,59,56,50,45,26,24,24,26,45,50,56,59,65,66,59,56,50,45,26,2,38,253,179,254,148,253,180,1,107,254,149,2,76,1, + 108,0,0,0,0,3,0,48,255,237,6,132,5,242,0,9,0,19,0,29,0,0,1,19,33,7,19,39,7,19,39,33,19,3,33,1,3,9,1,3, + 1,33,3,19,33,1,19,9,1,19,1,33,3,90,96,1,53,250,95,250,250,95,250,1,53,96,143,254,47,1,120,144,1,120,1,120,144,1,120,254, + 47,143,191,2,107,254,12,191,254,11,254,11,191,254,12,2,107,4,73,254,217,182,254,218,182,182,1,38,182,1,251,254,71,254,239,254,71,1,17,254, + 239,1,185,1,17,2,142,253,179,254,148,253,180,1,108,254,148,2,76,1,108,0,0,0,0,3,0,48,255,237,6,132,5,242,0,9,0,19,0,29, + 0,0,1,23,51,7,23,39,7,55,39,51,27,1,33,1,19,9,1,19,1,33,55,3,33,5,3,37,5,3,37,33,3,90,38,124,100,38,100,100, + 38,100,124,38,191,2,107,254,12,191,254,11,254,11,191,254,12,2,107,191,115,254,138,1,47,117,1,47,1,47,117,1,47,254,138,3,73,118,73,118, + 73,73,118,73,3,31,253,179,254,148,253,180,1,108,254,148,2,76,1,108,251,254,157,219,254,157,219,219,1,99,219,0,0,6,0,48,255,237,6,132, + 5,242,0,2,0,5,0,8,0,11,0,14,0,24,0,0,37,1,53,37,1,55,1,3,39,37,33,7,11,1,23,17,19,33,1,19,9,1,19,1, + 33,1,225,1,120,253,160,1,120,232,1,122,144,232,2,96,254,47,143,1,143,143,191,2,107,254,12,191,254,11,254,11,191,254,12,2,107,153,1,17, + 243,199,254,239,75,253,251,1,185,75,199,198,2,128,254,71,198,3,83,253,179,254,148,253,180,1,108,254,148,2,76,1,108,0,0,0,0,2,0,50, + 0,24,6,134,5,183,0,13,0,23,0,0,9,1,19,39,37,1,39,19,1,33,19,23,19,33,1,3,33,5,3,1,5,3,1,33,6,134,254,62, + 172,162,254,178,254,106,162,172,254,62,2,45,172,162,155,1,156,253,39,134,254,79,1,94,134,1,95,1,95,134,1,94,254,79,3,113,254,184,253,239, + 52,243,254,217,52,2,17,1,72,2,18,52,254,34,1,104,254,100,255,254,100,0,255,255,1,156,0,255,0,1,0,132,0,0,6,48,5,213,0,17, + 0,0,1,17,33,17,37,19,13,1,3,37,17,33,17,5,3,45,1,19,2,186,1,64,1,150,160,254,106,1,150,160,254,106,254,192,254,106,160,1, + 149,254,107,160,4,0,1,213,254,42,235,254,235,234,235,254,235,235,254,42,1,214,235,1,21,235,234,1,21,0,0,0,0,2,0,152,0,0,6,28, + 5,213,0,5,0,23,0,0,1,7,23,51,55,39,5,1,55,1,17,51,17,1,23,9,1,7,1,17,35,17,1,39,2,227,120,120,238,120,120,254, + 153,254,46,120,1,210,240,1,210,120,254,46,1,210,120,254,46,240,254,46,120,3,185,206,208,208,206,206,1,13,208,254,242,2,27,253,229,1,14,208, + 254,243,254,242,208,1,13,253,230,2,26,254,243,208,0,0,0,1,0,112,0,0,6,68,5,213,0,23,0,0,9,1,7,1,17,35,17,1,39,1, + 33,53,33,1,55,1,17,51,17,1,23,1,33,21,3,212,1,185,71,254,70,100,254,70,71,1,186,253,143,2,114,254,69,71,1,186,100,1,186,71, + 254,69,2,114,2,184,254,70,71,1,187,253,142,2,113,254,70,71,1,186,100,1,187,71,254,70,2,113,253,143,1,186,71,254,69,100,0,1,0,64, + 255,227,6,76,5,240,0,15,0,0,1,19,9,1,13,1,9,1,11,1,9,1,45,1,9,1,3,70,79,1,212,254,157,2,70,253,186,1,99,254, + 44,79,79,254,44,1,99,253,186,2,70,254,157,1,212,5,240,253,185,1,100,254,44,80,79,254,44,1,100,253,185,2,71,254,156,1,212,79,80,1, + 212,254,156,0,0,9,0,84,255,227,6,96,5,240,0,2,0,5,0,8,0,11,0,14,0,17,0,20,0,23,0,39,0,0,1,5,3,5,37,5, + 1,3,37,3,19,3,1,37,19,37,5,37,1,19,5,19,3,19,17,19,37,3,13,1,19,37,11,1,5,19,45,1,3,5,4,245,254,221,119,2, + 68,254,219,254,225,1,154,123,254,225,1,119,119,254,101,1,35,119,253,188,1,37,1,31,254,102,123,1,31,1,119,119,159,1,132,164,1,135,254,121, + 164,254,124,159,159,254,124,164,254,121,1,135,164,1,132,4,133,123,254,224,1,120,120,254,101,1,35,119,253,188,1,37,1,31,254,102,123,1,31,1, + 119,119,1,156,254,221,120,2,69,254,219,254,224,3,6,254,121,164,254,124,160,159,254,124,164,254,121,1,135,164,1,132,159,160,1,132,164,0,0,0, + 0,1,0,187,255,227,5,249,5,240,0,11,0,0,1,19,37,9,1,37,11,1,5,9,1,5,3,90,112,2,47,254,65,1,191,253,209,112,112,253, + 209,1,191,254,65,2,47,5,240,253,188,193,254,125,254,125,193,253,187,2,69,193,1,131,1,131,193,0,0,1,0,84,255,227,6,96,5,240,0,15, + 0,0,1,19,9,1,13,1,9,1,11,1,9,1,45,1,9,1,3,90,113,1,178,254,239,1,244,254,12,1,17,254,78,113,113,254,78,1,17,254, + 12,1,244,254,239,1,178,5,240,254,11,1,18,254,78,114,113,254,78,1,18,254,11,1,245,254,238,1,178,113,114,1,178,254,238,0,0,1,0,84, + 255,227,6,96,5,240,0,15,0,0,1,19,37,3,13,1,19,37,11,1,5,19,45,1,3,5,3,90,170,1,121,137,1,108,254,148,137,254,135,170, + 170,254,135,137,254,148,1,108,137,1,121,5,240,254,148,137,254,135,171,170,254,135,137,254,148,1,108,137,1,121,170,171,1,121,137,0,0,1,0,84, + 255,227,6,96,5,240,0,23,0,0,1,19,37,3,37,3,13,1,19,37,19,37,11,1,5,19,5,19,45,1,3,5,3,5,3,90,116,1,15,71, + 1,99,239,1,86,254,170,239,254,157,71,254,241,116,116,254,241,71,254,157,239,254,170,1,86,239,1,99,71,1,15,5,240,254,169,239,254,157,71,254, + 241,115,116,254,241,71,254,157,239,254,169,1,87,239,1,99,71,1,15,116,115,1,15,71,1,99,239,0,0,1,0,112,0,0,6,68,5,213,0,47, + 0,0,1,17,51,17,19,23,3,1,23,1,37,23,5,33,21,33,5,7,37,1,7,1,19,7,3,17,35,17,3,39,19,1,39,1,5,39,37,33, + 53,33,37,55,5,1,55,1,3,55,3,30,120,170,111,170,1,58,85,254,197,1,156,46,254,99,1,190,254,70,1,153,46,254,100,1,59,85,254,199, + 169,111,170,120,170,111,170,254,198,85,1,58,254,101,46,1,154,254,69,1,190,254,99,46,1,153,254,200,85,1,57,169,111,4,23,1,190,254,69,1, + 153,46,254,102,1,58,85,254,197,171,111,171,120,170,111,172,254,196,85,1,57,254,103,46,1,152,254,70,1,188,254,102,46,1,155,254,197,85,1,58, + 170,111,170,120,171,111,169,1,57,85,254,199,1,153,46,0,0,1,0,167,255,227,6,13,5,240,0,155,0,0,1,53,52,39,38,53,52,55,54,50, + 23,22,21,20,7,6,29,1,23,22,23,55,54,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,43,1,34,35,34,15,1,22,21,20,7, + 23,22,51,50,59,1,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,47,1,6,15,1,21,20,23,22,21,20,7,6,34,39,38,53, + 52,55,54,61,1,38,39,38,39,7,6,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,59,1,50,51,50,63,1,38,53,52,55,39,38, + 35,34,43,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,54,55,54,3,39,75,44,54,56,120,56,54,44,76,16,31,24, + 10,113,65,39,67,60,52,22,21,71,30,20,5,14,87,62,76,12,11,10,131,100,12,4,5,12,102,130,11,10,12,76,62,87,14,5,20,30,71,21, + 22,52,60,67,39,67,110,14,27,25,16,76,44,54,56,120,56,54,44,77,9,8,29,23,14,110,67,39,67,60,52,22,21,71,30,20,5,14,87,62, + 76,12,11,10,132,100,12,5,4,12,100,131,10,11,12,76,62,87,14,5,20,30,71,21,22,52,60,67,39,69,108,11,26,29,8,3,148,12,128,119, + 70,78,100,48,49,49,48,100,78,70,121,126,12,6,14,23,6,68,122,73,39,35,7,24,52,35,44,22,24,71,50,36,58,7,19,20,21,20,7,59, + 36,50,71,24,22,44,35,52,24,7,35,39,73,126,63,8,25,9,6,15,127,121,70,78,100,48,49,49,48,100,78,70,121,127,15,3,3,13,21,8, + 63,126,73,39,35,7,24,52,35,44,22,24,71,50,36,58,7,20,22,20,19,7,58,36,50,71,24,22,44,35,52,24,7,35,39,73,130,59,6,25, + 11,3,0,0,0,2,0,167,255,227,6,13,5,240,0,25,0,181,0,0,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1, + 53,52,38,39,38,47,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29,1,23,22,23,55,54,55,54,55,54,51,50,23,22,23,22,21, + 20,7,6,7,6,43,1,34,35,34,15,1,22,21,20,7,23,22,51,50,59,1,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,47, + 1,6,15,1,21,20,23,22,21,20,7,6,34,39,38,53,52,55,54,61,1,38,39,38,39,7,6,7,6,7,6,35,34,39,38,39,38,53,52,55, + 54,55,54,59,1,50,51,50,63,1,38,53,52,55,39,38,35,34,43,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,54, + 55,54,3,111,42,17,18,14,15,15,15,15,14,18,17,42,17,18,14,15,15,15,15,14,18,89,75,44,54,56,120,56,54,44,76,16,31,24,10,113, + 65,39,67,60,52,22,21,71,30,20,5,14,87,62,76,12,11,10,131,100,12,4,5,12,102,130,11,10,12,76,62,87,14,5,20,30,71,21,22,52, + 60,67,39,67,110,14,27,25,16,76,44,54,56,120,56,54,44,77,9,8,29,23,14,110,67,39,67,60,52,22,21,71,30,20,5,14,87,62,76,12, + 11,10,132,100,12,5,4,12,100,131,10,11,12,76,62,87,14,5,20,30,71,21,22,52,60,67,39,69,108,11,26,29,8,3,80,8,8,14,15,35, + 21,20,35,15,14,8,8,8,8,14,15,35,20,21,35,15,14,8,76,12,128,119,70,78,100,48,49,49,48,100,78,70,121,126,12,6,14,23,6,68, + 122,73,39,35,7,24,52,35,44,22,24,71,50,36,58,7,19,20,21,20,7,59,36,50,71,24,22,44,35,52,24,7,35,39,73,126,63,8,25,9, + 6,15,127,121,70,78,100,48,49,49,48,100,78,70,121,127,15,3,3,13,21,8,63,126,73,39,35,7,24,52,35,44,22,24,71,50,36,58,7,20, + 22,20,19,7,58,36,50,71,24,22,44,35,52,24,7,35,39,73,130,59,6,25,11,3,0,1,0,161,255,227,6,18,5,240,0,104,0,0,1,23, + 50,63,1,39,38,35,7,34,38,39,38,52,55,54,55,54,50,22,23,22,31,1,53,52,39,38,52,55,54,50,23,22,20,7,6,29,1,55,54,55, + 62,1,50,23,22,21,20,7,14,1,35,39,34,15,1,23,22,51,55,50,22,23,22,20,7,6,7,6,34,39,38,39,38,47,1,21,20,23,22,20, + 7,6,34,39,38,52,55,54,61,1,7,6,7,14,1,34,39,38,53,52,55,62,1,1,181,159,81,33,47,47,31,86,150,90,162,18,11,25,42,110, + 20,78,153,43,71,56,48,106,64,54,82,168,82,54,64,106,48,47,80,49,147,78,20,177,11,18,162,84,158,80,35,48,48,31,86,150,90,162,18,11, + 25,44,108,21,79,64,87,43,71,56,48,106,64,54,82,172,78,54,64,106,48,51,76,47,149,78,20,178,12,19,161,2,196,10,20,28,27,18,7,93, + 72,44,96,44,72,32,6,89,99,162,33,28,55,55,153,92,202,52,79,79,52,208,86,143,65,55,28,28,167,103,85,6,51,154,39,44,72,94,10,20, + 27,28,18,7,93,72,44,96,44,76,28,6,38,51,99,162,33,28,55,55,153,92,202,52,79,79,55,205,86,143,65,55,28,30,165,102,86,6,52,154, + 38,44,72,94,0,4,0,161,255,227,6,18,5,240,0,14,0,153,0,177,0,201,0,0,1,54,55,54,53,52,39,38,34,7,6,21,20,23,22,19, + 23,22,51,50,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,47,1,21,20,23,22,21,20,7,6,35,34,39,38,53,52, + 55,54,61,1,7,6,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,51,50,63,1,39,38,35,34,7,6,35,34,39,38, + 39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,53,52,39,38,53,52,55,54,50,23,22,21,20,7,6,29,1,55,54,55,54,55,54,51, + 50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,35,34,7,5,6,35,34,39,38,35,34,7,6,7,6,21,20,23,22,23,22,51,50,55,54, + 55,54,37,22,23,22,23,22,51,50,55,54,55,54,53,52,39,38,39,38,35,34,7,6,35,34,3,90,28,56,37,30,49,84,49,30,37,56,168,18, + 53,101,32,37,18,16,90,70,92,18,11,25,43,109,20,22,56,66,83,47,63,74,18,86,64,54,82,84,88,78,54,64,86,18,71,66,49,81,66,56, + 22,20,110,42,25,11,18,92,70,90,16,18,37,32,101,53,18,18,51,101,33,38,18,16,90,70,90,20,12,26,42,110,20,22,56,66,83,47,63,74, + 18,86,64,54,82,168,82,54,64,86,18,71,66,49,81,66,56,22,20,109,43,25,11,18,92,70,90,16,18,38,33,101,51,254,152,68,65,30,29,9, + 10,53,60,59,7,5,13,21,62,10,12,31,43,70,25,36,1,220,72,36,25,70,43,31,12,10,62,21,13,5,7,59,60,53,10,9,29,30,65,3, + 211,99,74,50,81,68,26,43,43,26,68,81,50,74,254,180,11,32,3,1,40,53,72,44,39,57,44,74,30,6,38,48,102,137,41,10,20,84,124,92, + 96,106,52,79,79,55,103,96,92,124,84,20,10,39,139,103,47,38,6,32,72,44,57,39,44,73,52,40,1,3,32,11,11,31,3,1,40,51,74,44, + 38,57,45,72,32,6,38,48,102,137,41,10,20,84,124,92,96,106,52,79,79,52,106,96,92,124,84,20,10,39,139,103,47,38,6,30,74,44,57,39, + 44,72,53,40,1,3,31,128,18,4,1,34,34,39,24,21,33,23,36,21,4,25,40,58,85,74,74,85,58,40,25,4,21,36,23,33,21,24,39,34, + 34,1,4,0,0,2,0,110,0,0,6,70,5,173,0,25,0,119,0,0,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1, + 53,52,38,39,38,39,55,54,55,54,51,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,22,23,30,1,21,20,6,7,6,7,6,34,39,38, + 39,46,1,39,14,1,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,6,34,39,38,39,46,1,53,52,54,55,54,55,54,51,50,23,22, + 23,46,1,53,52,54,55,54,55,54,51,50,23,22,23,30,1,21,20,6,3,162,144,61,62,51,52,51,51,52,51,62,61,144,61,62,51,52,51,51, + 52,51,62,120,62,37,56,53,54,55,48,45,41,44,40,45,37,56,47,91,27,48,33,45,40,44,41,45,48,50,121,47,56,37,48,29,5,5,37,41, + 45,48,50,121,47,56,37,45,40,46,39,38,36,23,87,47,58,35,45,40,44,41,45,48,50,59,62,47,59,41,8,27,44,41,45,48,50,59,62,47, + 56,37,45,40,27,4,11,26,28,48,54,123,73,70,123,54,48,28,26,26,28,48,54,123,70,73,123,54,48,28,19,53,16,23,23,20,43,39,103,62, + 58,99,46,38,25,21,5,23,34,46,99,59,61,103,39,43,20,21,21,25,38,49,78,37,38,87,39,43,20,21,21,25,38,46,99,58,62,107,35,34, + 21,4,21,27,36,46,99,58,62,103,39,43,20,21,21,25,44,14,66,58,62,103,39,43,20,21,21,25,38,46,99,59,61,63,0,0,0,6,0,110, + 0,0,6,70,5,173,0,92,0,118,0,141,0,166,0,189,0,214,0,0,37,14,1,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,6, + 34,39,38,39,46,1,53,52,54,55,54,55,54,51,50,23,22,23,46,1,53,52,54,55,54,55,54,50,23,22,23,30,1,21,20,6,7,54,55,54, + 51,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,2,50,23,22,23,55,54, + 53,52,38,39,38,39,38,34,7,6,7,14,1,21,20,31,1,54,55,19,38,39,38,39,38,39,7,14,1,21,20,22,23,22,23,22,50,55,54,55, + 54,55,3,38,53,52,54,55,39,38,39,38,35,34,7,6,7,14,1,21,20,22,23,22,23,22,51,1,23,22,23,22,23,22,50,55,54,55,62,1, + 53,52,38,47,1,6,7,6,7,6,19,55,54,55,54,55,62,1,53,52,38,39,38,39,38,35,34,7,6,15,1,30,1,21,20,3,90,5,29,48, + 37,56,47,121,50,48,45,41,44,40,45,33,48,27,91,47,56,37,45,40,44,41,48,45,60,49,58,51,37,62,7,27,40,45,37,56,47,124,47,56, + 37,45,40,27,7,62,37,56,53,54,55,48,45,41,44,40,45,37,56,47,91,27,48,33,45,40,44,41,45,48,50,121,47,56,37,48,29,77,144,61, + 8,7,14,13,25,27,25,32,30,72,30,32,25,27,25,3,24,7,8,67,35,32,66,47,30,27,103,24,28,25,27,25,32,30,72,30,32,25,24,4, + 214,3,47,42,120,8,7,35,31,36,30,32,25,24,28,25,27,25,32,21,4,2,56,35,35,24,25,32,30,72,30,32,25,27,25,28,24,103,27,30, + 47,66,32,245,80,80,21,32,25,27,25,28,24,25,32,30,36,31,35,7,8,120,42,47,248,37,78,49,38,25,21,21,20,43,39,103,61,59,99,46, + 34,23,5,21,25,38,46,99,58,62,103,39,46,17,23,23,16,53,13,63,61,59,99,46,38,25,21,21,25,38,46,99,59,61,63,13,53,16,23,23, + 20,43,39,103,62,58,99,46,38,25,21,5,23,34,46,99,59,61,103,39,43,20,21,21,25,38,49,78,3,56,26,3,4,71,71,20,36,62,27,24, + 14,13,13,14,24,27,62,36,20,12,130,4,3,253,99,6,14,30,46,30,44,98,23,66,36,35,62,27,24,14,13,13,14,24,24,9,1,186,22,23, + 73,114,48,67,4,3,13,13,14,24,24,62,39,35,62,27,24,14,9,254,194,76,77,24,24,14,13,13,14,24,27,62,35,36,66,23,98,44,30,46, + 30,14,1,36,10,10,9,14,24,27,62,35,39,62,24,24,14,13,13,3,4,67,48,114,73,23,0,0,0,10,0,84,255,227,6,96,5,240,0,41, + 0,84,0,189,0,230,1,17,1,58,1,101,1,127,1,169,1,211,0,0,1,38,39,7,6,35,34,38,39,38,39,38,52,55,54,55,62,1,51,50, + 31,1,54,55,39,38,35,34,6,7,6,7,6,20,23,22,23,30,1,51,50,55,37,6,7,23,22,51,50,54,55,54,55,54,52,39,38,39,46,1, + 35,34,15,1,22,23,55,54,51,50,22,23,22,23,22,21,20,7,6,7,14,1,35,34,35,1,46,1,52,55,54,55,54,55,54,51,50,22,23,52, + 54,55,54,55,54,50,23,22,23,30,1,21,62,1,51,50,23,22,23,22,23,22,21,20,6,7,50,22,23,22,23,22,21,20,7,6,7,14,1,35, + 30,1,21,20,7,14,1,7,6,35,34,38,39,20,6,7,6,7,6,34,39,38,39,46,1,53,14,1,35,34,39,46,1,39,38,52,54,55,34,38, + 39,38,39,38,52,55,54,55,62,1,1,38,39,7,6,7,14,1,7,38,39,46,1,39,38,39,62,1,55,54,63,1,38,39,7,6,7,14,1,21, + 22,23,30,2,51,50,54,55,54,55,1,22,23,55,54,55,62,1,53,38,39,38,39,46,1,35,34,6,7,6,15,1,22,23,55,54,55,62,1,55, + 22,23,22,23,22,23,22,23,14,1,7,6,7,3,6,7,23,22,23,30,1,23,6,7,14,1,7,6,7,46,1,39,38,47,1,6,7,23,22,23, + 30,1,51,50,62,1,55,54,55,52,38,39,38,39,1,54,55,39,38,39,46,1,35,34,6,7,6,7,6,7,20,22,23,22,31,1,54,55,39,38, + 39,46,1,39,54,55,54,55,54,55,54,55,30,1,23,22,23,4,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38, + 39,38,39,19,6,7,23,22,21,20,6,7,6,7,6,34,39,38,39,46,1,53,52,63,1,38,39,7,6,21,20,22,23,22,23,22,50,55,54,55, + 62,1,53,52,39,3,22,23,55,54,53,52,38,39,38,39,38,34,7,6,7,14,1,21,20,31,1,54,55,39,38,53,52,54,55,54,55,54,50,23, + 22,23,30,1,21,20,7,2,58,6,2,228,17,9,10,26,10,8,6,4,4,6,8,10,24,12,9,17,228,2,6,206,36,20,28,52,22,20,12,10, + 10,12,20,22,52,28,20,36,3,26,2,6,119,119,18,30,52,22,20,12,10,10,12,20,22,52,30,18,9,229,6,2,120,121,7,16,22,10,8,6, + 4,4,6,8,12,24,12,7,5,251,202,37,34,17,16,32,33,40,41,45,43,85,36,34,33,32,40,40,92,40,40,32,33,34,38,83,43,45,41,40, + 33,28,20,17,32,39,55,77,34,35,15,16,16,18,32,28,86,50,37,32,17,16,65,40,41,45,46,82,36,34,33,32,40,40,92,40,40,32,33,34, + 40,79,45,44,42,40,65,16,17,34,35,50,80,34,35,15,16,16,18,32,34,77,1,193,20,16,142,11,6,7,25,14,13,11,12,19,5,4,1,1, + 9,9,6,14,180,14,11,184,33,14,21,21,1,10,10,42,52,29,32,50,21,14,19,1,235,15,10,107,107,13,22,21,1,10,10,21,21,52,29,32, + 50,22,13,5,117,20,17,75,75,5,10,23,14,13,11,12,10,9,5,4,1,1,11,8,5,3,166,11,14,180,14,6,7,11,1,1,4,5,19,12, + 11,13,14,23,9,6,11,142,17,19,105,19,14,21,50,32,29,52,42,10,10,1,21,21,14,33,253,137,18,19,61,61,13,22,50,32,29,52,21,21, + 10,10,1,21,22,13,9,205,11,14,96,95,5,10,9,1,1,4,5,9,10,12,11,13,17,22,8,5,3,1,119,82,35,36,29,29,30,30,29,29, + 36,35,82,35,36,29,29,30,30,29,29,36,3,22,21,27,2,10,9,10,11,12,26,12,11,10,9,10,2,27,22,21,56,10,21,22,21,26,25,60, + 25,26,21,22,21,10,99,23,21,32,33,21,22,21,26,25,60,25,26,21,22,21,3,62,22,22,14,15,10,9,10,11,12,26,12,11,10,11,8,1, + 2,154,22,22,28,2,10,10,10,10,12,26,12,12,10,8,10,2,26,22,20,56,10,20,22,22,26,24,60,26,26,20,22,22,10,100,24,20,33,33, + 22,22,20,26,26,60,24,26,22,22,20,2,62,23,21,14,14,10,8,10,12,12,12,14,12,10,10,12,8,1,34,37,85,86,42,41,32,33,16,16, + 33,36,51,82,32,31,18,17,17,18,31,32,82,51,38,31,16,16,33,28,45,40,45,37,90,38,32,34,35,37,40,46,50,36,40,32,30,38,38,83, + 43,44,41,41,65,16,16,33,36,51,82,32,31,18,17,17,18,31,32,82,51,39,30,16,16,65,41,41,88,84,36,34,34,35,37,40,96,36,40,32, + 34,32,254,28,11,13,180,13,6,8,10,1,1,4,5,18,12,12,13,13,24,9,6,10,142,17,19,105,19,14,20,51,31,29,27,25,43,20,21,20, + 14,33,2,120,18,19,61,61,13,21,51,31,29,27,25,22,21,20,21,21,13,9,205,12,14,95,96,5,11,8,1,1,4,5,9,9,12,12,13,16, + 22,9,5,2,254,29,19,17,142,10,6,8,25,13,13,12,12,18,5,4,1,1,9,9,6,13,180,14,10,185,33,14,20,21,20,43,25,27,29,31, + 51,20,14,19,1,235,15,11,107,107,13,21,21,20,21,22,25,27,29,31,51,21,13,5,117,19,18,75,74,5,11,23,13,13,12,12,9,9,5,4, + 1,1,10,9,5,3,223,15,16,28,31,70,41,40,71,30,28,16,15,15,16,28,30,71,40,41,70,31,28,16,254,36,6,2,228,17,8,11,25,10, + 9,5,5,5,5,9,10,23,13,8,17,228,2,6,205,37,19,29,51,22,20,12,11,11,12,20,22,51,29,19,37,3,26,2,6,119,119,18,30,51, + 22,20,12,11,11,12,20,22,51,30,18,9,229,6,2,120,121,7,15,22,10,9,5,5,5,5,9,12,23,12,7,5,0,4,0,86,255,227,6,94, + 5,240,0,25,0,51,0,78,0,94,0,0,0,34,7,6,7,14,1,21,20,22,23,22,23,22,50,55,54,55,62,1,53,52,38,39,38,47,1,50, + 23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,52,54,55,54,55,54,19,50,23,22,23,22,18,21,20,2,7,6,7,6,32,39, + 38,39,38,2,53,52,18,55,54,55,54,23,3,37,19,13,1,3,37,27,1,5,3,45,1,19,5,3,151,122,51,53,43,43,43,43,43,43,53,51, + 122,51,53,43,43,43,43,43,43,53,112,87,68,77,54,57,63,61,59,57,74,72,170,68,77,54,57,63,61,59,57,74,72,83,154,142,134,115,112,115, + 110,117,110,139,141,254,203,142,134,115,112,115,110,117,108,141,140,156,157,254,127,163,254,125,1,131,163,1,129,157,157,1,129,163,1,131,254,125,163,254, + 127,4,19,22,24,40,46,104,60,59,104,46,40,24,22,22,24,40,46,104,59,60,104,46,40,24,134,31,34,54,56,150,84,78,150,59,57,31,31,31, + 34,54,56,150,162,150,59,57,31,31,1,109,59,56,114,111,254,236,161,152,254,240,119,112,58,59,59,56,114,111,1,20,156,157,1,16,119,110,60,59, + 8,254,125,163,254,127,158,157,254,127,163,254,125,1,131,163,1,129,157,158,1,129,163,0,0,7,0,161,255,227,6,18,5,240,0,8,0,147,0,156, + 0,167,0,178,0,193,0,208,0,0,1,17,34,7,6,21,20,23,22,19,23,22,51,50,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34, + 39,38,39,38,47,1,21,20,23,22,21,20,7,6,35,34,39,38,53,52,55,54,61,1,7,6,7,6,7,6,35,34,39,38,39,38,53,52,55,54, + 55,54,51,50,23,22,51,50,63,1,39,38,35,34,7,6,35,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,31,1,53,52,39,38, + 53,52,55,54,50,23,22,21,20,7,6,29,1,55,54,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,35,34,15,1,17, + 50,55,54,53,52,39,38,19,37,38,39,38,35,34,7,6,7,6,1,5,22,23,22,51,50,55,54,55,54,19,37,6,21,20,23,22,23,22,51,50, + 55,54,51,50,13,1,54,53,52,39,38,39,38,35,34,7,6,35,34,3,90,42,49,30,37,56,168,18,53,101,32,37,18,16,90,70,92,18,11,25, + 43,109,20,22,56,66,83,47,63,74,18,86,64,54,82,84,88,78,54,64,86,18,71,66,49,81,66,56,22,20,110,42,25,11,18,92,70,90,16,18, + 37,32,101,53,18,18,51,101,33,38,18,16,90,70,90,20,12,26,42,110,20,22,56,66,83,47,63,74,18,86,64,54,82,168,82,54,64,86,18,71, + 66,49,81,66,56,22,20,109,43,25,11,18,92,70,90,16,18,38,33,101,51,158,42,49,30,37,56,174,1,126,21,62,10,12,31,43,70,25,36,254, + 36,254,130,21,62,10,12,31,43,70,25,36,72,254,130,13,5,7,59,60,53,10,9,29,30,65,1,216,1,126,13,5,7,59,60,53,10,9,29,30, + 65,3,211,1,185,43,26,68,81,50,74,254,180,11,32,3,1,40,53,72,44,39,57,44,74,30,6,38,48,102,137,41,10,20,84,124,92,96,106,52, + 79,79,55,103,96,92,124,84,20,10,39,139,103,47,38,6,32,72,44,57,39,44,73,52,40,1,3,32,11,11,31,3,1,40,51,74,44,38,57,45, + 72,32,6,38,48,102,137,41,10,20,84,124,92,96,106,52,79,79,52,106,96,92,124,84,20,10,39,139,103,47,38,6,30,74,44,57,39,44,72,53, + 40,1,3,31,245,254,71,43,26,68,81,50,74,1,193,221,36,21,4,25,40,58,85,254,205,221,36,21,4,25,40,58,85,1,51,221,23,33,21,24, + 39,34,34,1,4,251,221,23,33,21,24,39,34,34,1,4,0,1,0,182,0,0,5,254,5,213,0,65,0,0,1,39,7,39,55,39,55,23,53,51, + 21,23,17,39,55,23,53,51,21,55,23,7,17,55,53,51,21,55,23,7,23,7,39,7,23,55,23,7,23,7,39,21,35,53,39,17,23,7,39,21, + 35,53,7,39,55,17,7,21,35,53,7,39,55,39,55,23,2,226,240,194,60,134,196,60,196,120,240,194,60,134,120,134,60,194,240,120,196,60,196,134, + 60,194,240,240,194,60,134,196,60,196,120,240,194,60,134,120,134,60,194,240,120,196,60,196,134,60,194,2,235,138,112,104,77,114,104,114,155,224,139,1, + 22,111,104,77,227,227,77,104,111,254,235,138,224,155,114,104,114,77,104,112,138,139,112,104,77,114,104,114,155,224,139,254,234,111,104,77,227,227,77,104, + 111,1,22,139,224,155,114,104,114,77,104,112,0,7,0,156,0,0,6,24,5,213,0,29,0,33,0,37,0,41,0,45,0,49,0,53,0,0,1,51, + 17,37,17,37,23,13,3,7,37,17,37,17,35,17,5,17,5,39,45,3,55,5,17,5,7,21,23,53,37,7,21,55,5,7,23,55,37,7,23,55, + 5,7,21,63,1,21,23,53,3,30,120,1,35,1,9,60,254,246,1,36,254,221,1,9,60,254,247,254,221,120,254,221,254,247,60,1,9,254,221,1, + 36,254,246,60,1,9,1,35,171,171,1,35,171,171,253,247,172,171,171,1,154,170,171,171,253,246,171,171,120,171,5,213,254,204,169,254,176,154,104,154, + 168,168,153,104,154,254,175,169,254,205,1,51,169,1,81,154,104,153,168,168,154,104,154,1,80,169,39,197,99,197,99,99,197,99,104,99,98,98,99,99, + 98,98,103,99,198,99,198,198,99,198,0,0,0,1,0,130,0,4,6,48,5,213,0,65,0,0,1,51,21,55,23,7,17,37,17,51,21,55,23,7, + 23,7,39,13,1,55,23,7,23,7,39,21,35,17,37,17,23,7,39,21,35,53,7,39,55,17,5,17,35,53,7,39,55,39,55,23,45,1,7,39, + 55,39,55,23,53,51,17,5,17,39,55,23,3,30,120,140,100,240,1,12,200,88,60,91,140,100,240,254,246,1,11,240,100,140,89,60,92,200,254,249, + 240,100,140,120,140,100,240,254,247,200,91,60,88,140,100,240,1,11,254,247,240,100,140,92,60,89,200,1,13,240,100,140,5,213,104,81,173,139,254,206, + 155,1,21,162,52,104,53,81,173,138,153,155,139,173,81,52,104,53,161,1,21,152,254,208,139,173,81,104,101,81,173,139,1,53,153,254,235,161,53,104, + 51,81,174,139,154,153,139,173,81,53,104,51,161,254,235,155,1,54,139,173,81,0,0,0,0,1,0,161,255,229,6,19,5,240,0,135,0,0,1,22, + 21,20,7,6,7,6,35,34,39,38,39,7,23,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,53,52,55,39,17,22, + 23,30,1,20,14,1,34,46,1,52,54,55,54,55,17,7,22,21,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,55, + 39,6,7,6,35,34,46,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,23,17,38,39,46,1,52,54,55,54,51,50,30,1,20,6,7,6, + 7,17,55,38,53,52,55,54,55,54,51,50,23,22,5,248,27,27,27,46,47,53,54,46,19,17,241,241,17,19,46,54,53,47,46,27,27,27,28,45, + 47,53,51,49,47,27,26,4,241,21,19,46,54,54,92,108,92,54,54,46,19,21,241,4,26,27,47,47,53,54,46,46,27,27,27,27,46,47,106,47, + 19,17,241,241,16,20,49,51,54,92,54,27,27,46,47,53,51,49,47,27,26,4,241,21,19,46,54,54,46,47,53,54,92,54,54,46,19,21,241,4, + 26,26,48,46,54,53,47,51,4,109,54,46,53,47,46,27,27,27,11,15,139,140,15,11,27,27,27,46,47,53,52,47,47,27,27,27,26,47,46,54, + 22,21,140,254,233,7,11,27,92,108,92,54,54,92,108,92,27,11,7,1,23,140,21,22,54,46,47,26,27,27,26,47,46,54,53,47,46,27,27,27, + 11,15,140,139,15,11,27,54,92,108,46,47,26,27,27,26,47,46,54,22,21,140,1,23,7,11,27,92,108,92,27,27,54,92,108,92,27,11,7,254, + 233,140,21,22,54,46,45,28,27,27,30,0,0,9,0,97,255,229,6,83,5,215,0,7,0,11,0,15,0,19,0,23,0,46,0,69,0,92,0,115, + 0,0,0,20,6,34,38,52,54,50,9,1,55,9,2,55,9,2,39,9,2,39,1,19,38,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22, + 21,20,7,6,7,6,3,22,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,3,6,7,6,7,6,35,34,39,38,39, + 38,52,55,54,55,54,51,50,23,22,23,22,5,54,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,3,240,88,124,88, + 88,124,1,167,254,125,85,1,131,253,13,254,127,85,1,129,2,158,254,125,85,1,131,253,183,254,127,85,1,129,185,57,15,23,4,1,2,3,15,23, + 114,23,15,3,2,1,4,23,15,57,57,15,23,4,1,2,3,15,23,114,23,15,3,2,1,4,23,15,159,60,24,37,68,29,82,69,30,65,32,49, + 49,32,65,30,69,82,29,68,37,24,1,236,60,24,37,68,29,82,69,30,65,32,49,49,32,65,30,69,82,29,68,37,24,3,44,124,88,88,124,88, + 253,46,1,132,85,254,124,2,74,1,129,85,254,126,1,45,254,124,85,1,132,253,13,254,126,85,1,129,1,46,60,24,37,68,29,82,69,30,65,32, + 49,49,32,65,30,69,82,29,68,37,24,254,20,60,24,37,68,29,82,69,30,65,32,49,49,32,65,30,69,82,29,68,37,24,1,20,57,15,23,4, + 1,2,3,15,23,114,23,15,3,2,1,4,23,15,57,57,15,23,4,1,2,3,15,23,114,23,15,3,2,1,4,23,15,0,0,0,0,9,0,97, + 255,229,6,83,5,215,0,7,0,11,0,15,0,19,0,23,0,43,0,63,0,83,0,103,0,0,0,20,6,34,38,52,54,50,9,1,23,9,2,23, + 9,2,7,9,2,7,1,2,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,50,23,22,23,18,20,7,6,7,6,34,39,38,39,38,52,55, + 54,55,54,50,23,22,23,0,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,36,50,23,22,23,22,20,7,6,7,6,34,39, + 38,39,38,52,55,54,55,4,59,132,186,132,132,186,253,105,1,41,85,254,215,2,161,1,41,85,254,215,253,10,1,41,85,254,215,3,75,1,41,85, + 254,215,8,19,21,39,46,110,46,39,21,19,19,21,39,46,110,46,39,21,19,19,21,39,46,110,46,39,21,19,19,21,39,46,110,46,39,21,253,25, + 112,49,55,35,40,40,35,55,49,112,49,55,35,40,40,35,55,4,77,112,49,55,35,40,40,35,55,49,112,49,55,35,40,40,35,55,3,75,186,132, + 132,186,132,253,56,1,41,85,254,215,3,76,1,41,85,254,215,1,126,254,215,85,1,41,253,94,254,215,85,1,41,3,73,112,49,55,35,40,40,35, + 55,49,112,49,55,35,40,40,35,55,251,179,112,49,55,35,40,40,35,55,49,112,49,55,35,40,40,35,55,2,89,19,21,39,46,110,46,39,21,19, + 19,21,39,46,110,46,39,21,19,19,21,39,46,110,46,39,21,19,19,21,39,46,110,46,39,21,0,0,0,9,0,84,255,229,6,96,5,242,0,12, + 0,24,0,37,0,50,0,63,0,75,0,87,0,95,0,107,0,0,1,20,7,6,43,1,37,53,37,51,50,23,22,5,52,54,59,1,5,21,5,35, + 34,39,38,1,22,21,20,15,1,1,39,1,55,54,51,50,1,38,53,52,63,1,1,23,1,7,6,35,34,3,54,51,50,31,1,1,7,1,39,38, + 53,52,1,6,34,47,1,1,55,1,23,22,21,20,0,50,23,22,29,1,3,35,3,53,52,55,18,20,6,34,38,52,54,50,2,34,39,38,61,1, + 19,51,19,21,20,7,6,96,28,28,40,10,254,96,1,160,10,38,30,28,249,244,56,40,10,1,160,254,96,10,38,30,28,5,42,29,27,7,254,183, + 71,1,2,7,28,41,42,251,213,29,27,7,1,73,71,254,254,7,28,41,40,31,29,42,40,29,7,1,2,71,254,183,7,27,4,101,30,82,28,7, + 254,254,71,1,73,7,27,253,150,82,30,29,50,100,50,29,221,88,124,88,88,124,21,82,30,29,50,100,50,29,2,236,42,30,28,50,100,50,30,30, + 40,40,60,50,100,50,28,30,2,77,29,42,39,29,7,254,254,70,1,73,7,28,251,155,29,42,39,29,7,1,2,70,254,183,7,28,4,101,30,28, + 7,254,183,70,1,2,7,27,41,42,251,214,30,28,7,1,73,70,254,254,7,27,41,42,5,13,29,28,40,10,254,97,1,159,10,39,29,253,85,124, + 88,88,124,88,252,99,29,28,40,10,1,159,254,97,10,39,29,0,0,0,0,1,0,84,255,229,6,96,5,242,0,108,0,0,1,50,23,22,21,20, + 7,3,1,54,55,54,51,50,23,22,21,20,7,6,7,1,37,54,51,50,23,22,20,7,6,35,34,39,37,1,22,23,22,21,20,7,6,35,34,39, + 38,39,1,19,22,21,20,7,6,34,39,38,53,52,55,19,1,6,7,6,35,34,39,38,53,52,55,54,55,1,5,6,35,34,39,38,52,55,54,51, + 50,23,5,1,38,39,38,53,52,55,54,51,22,23,22,23,1,3,38,53,52,55,54,3,90,43,47,35,5,78,1,28,21,2,52,50,66,31,30,52, + 10,25,254,123,1,223,25,12,76,34,46,46,36,74,7,37,254,40,1,138,28,2,52,30,31,66,43,59,10,18,254,233,78,5,35,47,86,47,35,5, + 78,254,233,18,10,52,50,66,31,30,52,2,28,1,138,254,40,37,7,74,36,46,46,34,76,12,25,1,223,254,123,25,10,52,30,31,66,36,66,2, + 21,1,28,78,5,35,46,5,242,47,35,74,7,31,254,34,1,137,29,1,53,31,30,67,55,47,9,18,254,233,78,4,34,46,88,46,36,6,77,254, + 229,22,1,53,49,67,30,31,53,9,25,1,133,254,34,31,7,74,35,47,47,35,74,14,30,1,216,254,123,25,9,53,31,30,67,76,26,1,22,1, + 27,77,6,36,46,88,46,34,4,78,1,23,18,9,53,49,67,30,31,20,33,1,29,254,119,1,216,30,14,74,35,47,0,2,0,102,255,236,6,198, + 5,232,0,13,0,35,0,231,186,0,0,0,19,0,3,43,186,0,31,0,6,0,3,43,184,0,31,16,65,27,0,22,0,0,0,38,0,0,0,54, + 0,0,0,70,0,0,0,86,0,0,0,102,0,0,0,118,0,0,0,134,0,0,0,150,0,0,0,166,0,0,0,182,0,0,0,198,0,0,0,214, + 0,0,0,13,93,65,5,0,229,0,0,0,245,0,0,0,2,93,65,5,0,234,0,6,0,250,0,6,0,2,93,65,27,0,25,0,6,0,41,0, + 6,0,57,0,6,0,73,0,6,0,89,0,6,0,105,0,6,0,121,0,6,0,137,0,6,0,153,0,6,0,169,0,6,0,185,0,6,0,201,0, + 6,0,217,0,6,0,13,93,184,0,37,220,0,186,0,3,0,16,0,3,43,184,0,3,16,186,0,23,0,10,0,3,43,184,0,23,16,184,0,16, + 16,184,0,14,208,184,0,14,47,184,0,23,16,184,0,25,208,184,0,25,47,184,0,23,16,184,0,27,208,184,0,16,16,184,0,34,208,48,49,19, + 16,0,33,32,0,17,52,2,36,35,34,4,2,1,6,35,32,0,17,52,18,36,51,50,23,54,51,50,4,18,21,16,0,33,34,185,1,143,1,28, + 1,28,1,143,182,254,184,173,173,254,184,182,2,220,25,25,254,196,254,63,206,1,113,190,25,25,25,25,193,1,113,205,254,63,254,194,25,2,234,254, + 228,254,112,1,144,1,28,179,1,71,177,177,254,185,252,81,2,1,191,1,63,198,1,114,198,2,2,198,254,144,200,254,193,254,65,0,0,2,0,122, + 255,156,6,178,5,212,0,3,0,11,0,55,186,0,3,0,5,0,3,43,184,0,3,16,186,0,10,0,0,0,3,43,184,0,10,16,184,0,13,220, + 0,186,0,0,0,10,0,3,43,184,0,0,16,186,0,7,0,1,0,3,43,184,0,7,16,48,49,37,17,33,17,23,35,17,33,21,51,17,33,5, + 251,250,210,17,100,5,212,100,250,44,83,5,46,250,210,83,5,212,100,250,44,0,0,0,0,2,0,122,0,0,6,178,6,56,0,3,0,11,0,55, + 186,0,3,0,6,0,3,43,184,0,3,16,186,0,11,0,0,0,3,43,184,0,11,16,184,0,13,220,0,186,0,0,0,5,0,3,43,184,0,0, + 16,186,0,10,0,1,0,3,43,184,0,10,16,48,49,37,17,33,17,37,21,33,17,51,53,33,17,5,251,250,210,5,129,250,44,100,5,212,83,5, + 46,250,210,17,100,5,212,100,250,44,0,0,0,2,0,122,255,156,6,178,5,212,0,3,0,9,0,55,186,0,3,0,4,0,3,43,184,0,3,16, + 186,0,8,0,0,0,3,43,184,0,8,16,184,0,11,220,0,186,0,0,0,8,0,3,43,184,0,0,16,186,0,6,0,1,0,3,43,184,0,6, + 16,48,49,37,17,33,17,7,17,33,23,17,33,5,251,250,210,83,5,212,100,250,74,83,5,46,250,210,83,5,212,130,250,74,0,0,0,2,0,122, + 0,0,6,178,6,56,0,3,0,9,0,55,186,0,3,0,5,0,3,43,184,0,3,16,186,0,9,0,0,0,3,43,184,0,9,16,184,0,11,220, + 0,186,0,0,0,4,0,3,43,184,0,0,16,186,0,8,0,1,0,3,43,184,0,8,16,48,49,37,17,33,17,5,33,17,55,33,17,5,251,250, + 210,5,129,250,44,130,5,182,83,5,46,250,210,83,5,212,100,250,74,0,0,4,0,170,255,251,6,130,5,211,0,3,0,7,0,11,0,15,0,11, + 0,184,0,9,47,184,0,15,47,48,49,19,9,14,170,1,83,1,83,254,173,1,223,1,84,1,82,254,174,253,21,1,83,1,83,254,173,254,173,1, + 83,1,83,254,173,2,233,1,83,254,173,254,173,1,83,1,82,254,174,254,171,2,234,1,85,254,171,254,174,254,34,1,83,254,173,254,173,0,0,0, + 0,1,3,5,254,20,3,175,6,20,0,3,0,0,1,17,35,17,3,175,170,6,20,248,0,8,0,0,0,1,2,176,254,20,4,4,6,20,0,3, + 0,0,1,17,33,17,4,4,254,172,6,20,248,0,8,0,0,1,2,6,254,20,4,174,6,20,0,3,0,0,1,17,33,17,4,174,253,88,6,20, + 248,0,8,0,0,1,0,174,3,40,2,28,5,213,0,6,0,27,186,0,0,0,1,0,3,43,0,184,0,3,47,186,0,6,0,0,0,3,43,184, + 0,6,16,48,49,1,33,17,19,51,3,51,2,28,254,146,164,129,82,155,3,40,1,110,1,63,254,193,0,1,0,120,3,40,1,230,5,213,0,6, + 0,39,186,0,1,0,0,0,3,43,184,0,1,16,0,184,0,3,47,186,0,1,0,2,0,3,43,184,0,1,16,184,0,2,16,184,0,5,208,48, + 49,19,33,17,3,35,19,35,120,1,110,164,129,82,155,5,213,254,146,254,193,1,63,0,255,255,0,174,3,40,3,214,5,213,16,38,15,221,0,0, + 16,7,15,221,1,186,0,0,255,255,0,120,3,40,3,160,5,213,16,38,15,222,0,0,16,7,15,222,1,186,0,0,0,2,1,62,255,66,6,45, + 6,207,0,68,0,72,0,0,1,50,23,22,23,30,1,21,20,6,7,6,7,6,35,34,7,6,7,14,1,20,22,23,22,23,22,50,55,54,55,62, + 1,53,17,33,34,38,53,52,36,51,33,53,55,21,33,7,35,17,20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,54,1,17,35, + 17,2,221,31,26,27,22,21,23,23,21,22,27,26,26,28,19,19,16,17,16,19,16,20,16,24,95,62,73,45,55,52,254,205,222,253,1,4,215,1, + 51,141,1,84,140,200,80,62,67,80,78,177,68,71,45,50,46,49,47,38,68,57,1,168,190,1,208,11,12,21,20,56,31,30,56,20,21,12,11,9, + 8,16,16,39,46,42,14,18,6,9,27,33,45,56,129,68,1,95,238,184,190,232,200,50,250,123,251,219,106,183,64,70,39,37,25,26,46,51,114,64, + 77,100,55,43,29,24,1,52,2,86,253,170,0,2,1,158,255,221,5,22,5,240,0,21,0,47,0,0,1,50,23,22,23,30,1,21,20,7,6,7, + 38,39,38,53,52,54,55,54,55,54,18,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55,3,90,160,121, + 42,44,38,39,136,178,130,134,174,136,39,38,37,49,93,126,124,52,53,44,45,43,43,45,44,53,52,124,52,53,44,45,43,43,45,44,53,5,240,40, + 14,43,38,97,52,124,100,131,206,206,131,102,122,52,97,38,36,21,40,252,70,22,24,42,46,106,61,60,106,46,42,24,22,22,24,42,46,106,60,61, + 106,46,42,24,0,2,1,78,255,221,5,102,5,240,0,33,0,59,0,0,1,38,37,38,53,52,54,55,54,55,54,50,23,22,23,30,1,21,52,54, + 55,54,55,54,50,23,22,23,30,1,21,20,7,4,2,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,55, + 3,90,123,254,247,136,39,38,37,49,45,108,46,47,38,37,40,40,37,38,47,46,108,45,49,37,38,39,136,254,246,184,124,52,53,44,45,43,43,45, + 44,53,52,124,52,53,44,45,43,43,45,44,53,2,173,196,161,83,131,52,97,38,36,21,20,20,20,37,37,96,54,54,96,37,37,20,20,20,21,36, + 38,97,52,132,82,161,254,197,22,24,42,46,106,61,60,106,46,42,24,22,22,24,42,46,106,60,61,106,46,42,24,0,0,1,0,110,0,171,6,70, + 5,40,0,33,0,0,37,38,37,38,53,52,54,55,54,55,54,50,23,22,23,30,1,21,52,54,55,54,55,54,50,23,22,23,30,1,21,20,7,4, + 3,90,137,254,95,194,55,55,53,69,65,154,65,68,54,53,57,57,53,54,68,65,154,65,69,53,55,55,194,254,95,171,239,242,113,178,75,138,54,52, + 30,28,28,29,53,52,137,78,78,137,52,53,29,28,28,30,52,54,138,75,180,111,242,0,0,1,1,88,255,254,5,212,5,214,0,35,0,0,1,6, + 3,6,35,34,38,39,38,39,38,53,52,55,54,55,62,1,51,34,38,39,38,39,38,53,52,55,54,55,62,1,51,50,23,18,5,212,238,242,114,178, + 74,138,54,52,30,28,28,28,54,52,136,78,78,136,52,54,28,28,28,30,52,54,138,74,180,112,242,2,234,138,254,96,194,54,56,52,70,64,78,76, + 66,68,54,52,58,56,54,54,68,64,78,76,66,68,54,54,56,194,254,94,0,2,0,126,0,42,5,203,5,158,0,13,0,105,0,0,1,54,53,52, + 39,38,35,34,7,6,21,20,23,22,23,6,7,54,51,50,23,22,21,20,5,6,21,20,51,50,55,54,51,50,21,20,33,34,39,38,53,16,33,50, + 23,54,55,38,39,38,35,34,7,6,21,20,22,21,20,7,6,35,34,39,38,53,52,55,54,51,50,31,1,52,55,54,51,50,23,22,21,20,7,22, + 51,50,55,54,53,52,39,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34,3,151,10,29,24,54,30,22,19,43,74,111,21,46,94,86,124,59, + 45,254,203,153,105,116,16,51,54,63,254,197,204,186,198,1,5,102,81,77,16,101,230,69,74,83,63,40,42,26,36,20,32,25,14,115,93,118,104,50, + 75,41,42,78,76,49,51,16,60,86,76,42,45,21,42,21,31,56,65,42,20,143,95,120,65,4,103,48,44,63,41,33,18,15,27,58,34,57,140,74, + 79,67,81,62,94,218,118,58,77,99,42,132,90,156,153,163,254,1,101,141,151,67,48,170,51,78,51,53,37,38,29,23,20,28,45,25,75,116,92,75, + 37,57,83,31,32,62,66,87,78,61,17,33,36,31,63,18,36,21,56,28,40,70,33,53,123,94,63,0,0,2,0,160,1,90,6,19,4,132,0,9, + 0,81,0,0,1,6,7,6,7,54,55,54,53,52,1,32,53,52,55,38,39,38,43,1,22,7,6,7,22,51,50,55,22,21,20,35,34,39,35,53, + 51,54,55,54,55,38,39,38,39,38,53,52,51,6,21,20,23,22,23,50,23,22,23,38,53,52,55,54,51,50,19,22,51,50,53,52,39,38,53,52, + 51,50,21,20,7,6,1,223,63,45,66,27,79,62,61,1,254,254,139,118,48,54,38,37,4,2,75,96,100,25,67,43,40,8,145,107,20,36,39,30, + 101,77,63,15,36,35,61,72,98,12,143,66,4,61,41,43,56,31,61,46,109,216,57,24,101,98,12,11,80,66,247,176,3,62,14,36,51,103,29,58, + 56,52,4,254,33,254,69,66,55,28,20,87,80,102,15,71,43,30,49,75,171,72,142,80,60,2,18,18,18,14,17,70,102,29,35,38,84,39,25,19, + 20,48,80,43,65,39,29,254,147,154,60,30,18,17,27,60,81,173,98,70,0,1,1,145,254,228,5,47,6,39,0,32,0,0,1,34,39,38,39,38, + 39,38,53,52,55,54,55,54,55,54,51,21,34,7,6,2,7,6,21,20,23,22,23,22,23,22,51,5,47,186,169,161,138,134,70,68,68,64,140,132, + 167,169,186,109,104,96,166,40,40,40,40,83,78,101,99,114,254,228,71,67,137,133,167,164,187,189,169,157,143,134,70,71,47,67,62,254,250,155,156,184, + 177,156,155,131,125,68,67,0,0,1,1,145,254,228,5,47,6,39,0,34,0,0,1,48,53,50,55,54,55,54,55,54,53,52,39,38,2,39,38,35, + 48,53,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,1,145,114,99,101,78,83,40,40,40,40,166,96,104,109,186,169,167,132,140,64,68,68, + 70,134,138,161,169,254,228,47,67,68,125,131,155,156,177,184,156,155,1,6,62,67,47,71,70,134,143,157,169,189,187,164,167,133,137,67,71,0,0,0, + 0,1,2,29,254,241,4,152,6,17,0,12,0,0,1,6,2,16,18,23,33,38,2,53,52,18,55,4,152,134,130,131,133,254,176,150,149,148,151,6, + 17,230,254,62,254,50,254,59,229,235,1,198,224,223,1,196,236,0,0,0,0,1,2,29,254,241,4,152,6,17,0,13,0,0,1,48,33,22,18,21, + 20,2,7,33,54,18,16,2,2,29,1,80,151,148,149,150,254,176,133,131,130,6,17,236,254,60,223,224,254,58,235,229,1,197,1,206,1,194,0,0, + 0,1,1,185,254,20,4,219,6,20,0,5,0,0,1,33,9,1,33,1,4,219,254,220,254,2,1,254,1,36,254,0,254,20,4,0,4,0,252,0, + 0,1,1,219,254,20,4,252,6,20,0,5,0,0,9,2,33,9,1,1,219,1,255,254,2,1,34,1,254,254,2,254,20,4,0,4,0,252,0,252, + 0,0,0,0,0,1,1,35,254,20,5,123,6,20,0,5,0,0,1,33,9,1,33,1,5,123,254,60,253,108,2,148,1,196,253,96,254,20,4,0, + 4,0,252,0,0,1,1,57,254,20,5,145,6,20,0,5,0,0,9,2,33,9,1,1,57,2,160,253,96,1,196,2,148,253,108,254,20,4,0,4, + 0,252,0,252,0,0,0,0,0,1,1,85,254,20,5,63,6,20,0,5,0,0,1,33,9,1,33,1,5,63,254,20,254,2,1,254,1,236,254,0, + 254,20,4,0,4,0,252,0,0,1,1,119,254,20,5,96,6,20,0,5,0,0,9,2,33,9,1,1,119,1,255,254,2,1,234,1,254,254,2,254, + 20,4,0,4,0,252,0,252,0,0,0,0,0,1,2,196,254,19,4,72,6,20,0,7,0,0,5,23,7,1,17,1,23,7,3,90,238,106,254,230, + 1,26,106,238,149,238,106,1,26,5,205,1,26,106,238,0,0,1,2,108,254,19,3,240,6,20,0,7,0,0,1,39,55,1,17,1,39,55,3,90, + 238,106,1,26,254,230,106,238,4,188,238,106,254,230,250,51,254,230,106,238,0,1,1,102,254,178,5,19,6,20,0,36,0,0,5,21,35,34,38,61, + 1,52,38,43,1,53,51,50,54,61,1,52,54,59,1,21,35,34,6,29,1,20,6,7,30,1,29,1,20,22,51,5,19,212,249,169,108,142,61,61, + 143,107,169,249,212,68,141,86,91,110,111,90,86,141,190,144,148,221,239,151,116,143,115,149,240,221,147,143,88,141,248,157,142,25,27,142,156,248,141,88, + 0,1,1,161,254,178,5,78,6,20,0,36,0,0,5,51,50,54,61,1,52,54,55,46,1,61,1,52,38,43,1,53,51,50,22,29,1,20,22,59, + 1,21,35,34,6,29,1,20,6,43,1,1,161,68,141,86,90,111,110,91,86,141,68,212,249,169,107,143,61,61,142,108,169,249,212,190,88,141,248,156, + 142,27,25,142,157,248,141,88,143,147,221,240,149,115,143,116,151,239,221,148,0,2,0,152,255,236,6,148,5,232,0,13,0,24,0,27,0,186,0,14, + 0,3,0,3,43,184,0,14,16,186,0,10,0,19,0,3,43,184,0,10,16,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,1,33,53, + 35,17,35,5,21,55,17,35,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,251,211,2,105,218,161,254,255,236,217,2,234,254,193, + 254,65,1,191,1,63,198,1,114,198,198,254,144,253,92,142,3,26,47,152,43,253,130,0,0,2,0,152,255,236,6,148,5,232,0,13,0,42,0,27, + 0,186,0,37,0,3,0,3,43,184,0,37,16,186,0,10,0,20,0,3,43,184,0,10,16,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4, + 18,5,62,1,53,52,38,35,34,6,7,21,62,1,51,50,22,21,20,6,7,6,4,7,21,33,53,33,62,1,6,148,254,63,254,194,254,196,254,63, + 206,1,113,190,193,1,113,205,253,230,62,48,197,163,61,145,97,115,132,59,78,95,47,62,33,254,250,82,2,164,254,76,125,178,2,234,254,193,254,65, + 1,191,1,63,198,1,114,198,198,254,144,233,70,105,58,125,151,31,36,171,58,38,78,63,40,85,63,34,241,77,129,142,116,167,0,0,0,2,0,152, + 255,236,6,148,5,232,0,13,0,54,0,153,186,0,0,0,14,0,3,43,65,5,0,234,0,14,0,250,0,14,0,2,93,65,27,0,25,0,14,0, + 41,0,14,0,57,0,14,0,73,0,14,0,89,0,14,0,105,0,14,0,121,0,14,0,137,0,14,0,153,0,14,0,169,0,14,0,185,0,14,0, + 201,0,14,0,217,0,14,0,13,93,184,0,49,220,0,186,0,46,0,3,0,3,43,184,0,46,16,186,0,10,0,17,0,3,43,184,0,10,16,186, + 0,33,0,39,0,3,43,184,0,33,16,186,0,24,0,30,0,3,43,184,0,24,16,186,0,21,0,30,0,24,17,18,57,186,0,42,0,39,0,33, + 17,18,57,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,37,52,38,35,34,6,7,21,62,1,51,50,22,21,20,6,43,1,21,51,50, + 22,21,20,6,35,34,38,39,21,30,1,51,50,54,53,52,38,39,50,54,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,254,124, + 193,161,61,136,95,107,121,52,91,92,88,90,145,140,99,107,115,117,68,125,91,88,136,64,195,216,118,13,4,104,2,234,254,193,254,65,1,191,1,63, + 198,1,114,198,198,254,144,24,115,137,20,24,151,32,21,63,60,58,60,140,78,71,76,79,28,48,168,27,23,156,141,93,129,3,114,0,0,3,0,152, + 255,236,6,148,5,232,0,13,0,16,0,27,0,27,0,186,0,20,0,3,0,3,43,184,0,20,16,186,0,10,0,27,0,3,43,184,0,10,16,48, + 49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,1,33,9,1,21,33,21,51,53,51,53,35,17,35,6,148,254,63,254,194,254,196,254,63,206, + 1,113,190,193,1,113,205,253,22,254,243,1,13,254,67,1,189,182,141,141,206,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,254,188, + 1,126,254,131,142,211,211,141,2,72,0,0,0,2,0,152,255,236,6,148,5,232,0,13,0,43,0,139,186,0,0,0,33,0,3,43,65,5,0,234, + 0,33,0,250,0,33,0,2,93,65,27,0,25,0,33,0,41,0,33,0,57,0,33,0,73,0,33,0,89,0,33,0,105,0,33,0,121,0,33,0, + 137,0,33,0,153,0,33,0,169,0,33,0,185,0,33,0,201,0,33,0,217,0,33,0,13,93,0,186,0,30,0,3,0,3,43,184,0,30,16,186, + 0,10,0,43,0,3,43,184,0,10,16,186,0,17,0,23,0,3,43,184,0,17,16,186,0,40,0,36,0,3,43,184,0,40,16,186,0,26,0,23, + 0,17,17,18,57,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,5,62,1,51,50,22,21,20,6,35,34,38,39,21,30,1,51,50,54, + 53,52,38,35,34,6,55,53,33,53,33,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,251,239,89,101,50,104,118,118,104,68,119, + 95,88,133,64,190,213,207,176,31,63,3,1,145,253,195,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,243,37,20,97,86,85,97,27, + 47,172,24,20,172,152,149,176,10,1,171,142,0,3,0,152,255,236,6,148,5,232,0,13,0,25,0,50,0,241,184,0,51,47,184,0,52,47,184,0, + 51,16,184,0,6,208,184,0,6,47,184,0,52,16,184,0,14,220,184,0,20,220,65,5,0,234,0,20,0,250,0,20,0,2,93,65,27,0,25,0, + 20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0,169,0,20,0,185,0, + 20,0,201,0,20,0,217,0,20,0,13,93,184,0,6,16,184,0,29,220,65,27,0,22,0,29,0,38,0,29,0,54,0,29,0,70,0,29,0,86, + 0,29,0,102,0,29,0,118,0,29,0,134,0,29,0,150,0,29,0,166,0,29,0,182,0,29,0,198,0,29,0,214,0,29,0,13,93,65,5,0, + 229,0,29,0,245,0,29,0,2,93,0,186,0,32,0,3,0,3,43,184,0,32,16,186,0,10,0,26,0,3,43,184,0,10,16,186,0,23,0,17, + 0,3,43,184,0,23,16,186,0,44,0,38,0,3,43,184,0,44,16,186,0,47,0,38,0,44,17,18,57,48,49,1,16,0,33,32,0,17,52,18, + 36,51,50,4,18,1,20,6,35,34,38,53,52,54,51,50,22,3,34,2,21,20,22,51,50,54,53,52,38,35,34,6,55,62,1,51,50,22,23,53, + 46,1,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,253,162,92,78,78,92,92,78,78,92,113,200,234,192,185,160,194,186,160,78, + 128,9,5,127,119,47,97,84,74,106,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,254,143,90,98,98,90,91,98,98,2,42,254,245, + 218,231,253,179,145,148,177,61,11,80,148,22,35,156,24,19,0,2,0,152,255,236,6,148,5,232,0,13,0,20,0,27,0,186,0,17,0,3,0,3, + 43,184,0,17,16,186,0,10,0,20,0,3,43,184,0,10,16,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,37,33,1,51,1,53,33, + 6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,251,194,1,207,254,175,193,1,108,253,85,2,234,254,193,254,65,1,191,1,63,198, + 1,114,198,198,254,144,118,252,230,3,93,75,0,4,0,152,255,236,6,148,5,232,0,13,0,25,0,49,0,61,1,139,186,0,26,0,6,0,3,43, + 184,0,26,16,186,0,14,0,20,0,3,43,184,0,14,16,186,0,0,0,32,0,3,43,184,0,0,16,65,5,0,234,0,20,0,250,0,20,0,2, + 93,65,27,0,25,0,20,0,41,0,20,0,57,0,20,0,73,0,20,0,89,0,20,0,105,0,20,0,121,0,20,0,137,0,20,0,153,0,20,0, + 169,0,20,0,185,0,20,0,201,0,20,0,217,0,20,0,13,93,65,27,0,22,0,26,0,38,0,26,0,54,0,26,0,70,0,26,0,86,0,26, + 0,102,0,26,0,118,0,26,0,134,0,26,0,150,0,26,0,166,0,26,0,182,0,26,0,198,0,26,0,214,0,26,0,13,93,65,5,0,229,0, + 26,0,245,0,26,0,2,93,65,5,0,234,0,32,0,250,0,32,0,2,93,65,27,0,25,0,32,0,41,0,32,0,57,0,32,0,73,0,32,0, + 89,0,32,0,105,0,32,0,121,0,32,0,137,0,32,0,153,0,32,0,169,0,32,0,185,0,32,0,201,0,32,0,217,0,32,0,13,93,186,0, + 47,0,6,0,0,17,18,57,186,0,59,0,20,0,14,17,18,57,184,0,59,47,65,5,0,234,0,59,0,250,0,59,0,2,93,65,27,0,25,0, + 59,0,41,0,59,0,57,0,59,0,73,0,59,0,89,0,59,0,105,0,59,0,121,0,59,0,137,0,59,0,153,0,59,0,169,0,59,0,185,0, + 59,0,201,0,59,0,217,0,59,0,13,93,184,0,53,220,0,186,0,29,0,3,0,3,43,184,0,29,16,186,0,10,0,41,0,3,43,184,0,10, + 16,186,0,23,0,17,0,3,43,184,0,23,16,186,0,50,0,56,0,3,43,184,0,50,16,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4, + 18,1,20,6,35,34,38,53,52,54,51,50,22,5,20,22,51,50,54,53,52,38,39,62,1,53,52,38,35,34,6,21,20,22,23,14,1,1,50,22, + 21,20,6,35,34,38,53,52,54,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205,253,185,95,84,84,95,95,84,84,95,253,226,190, + 173,173,190,118,15,4,105,182,157,157,183,106,4,15,118,1,107,75,82,82,75,77,81,81,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254, + 144,254,108,72,81,80,73,73,80,80,73,138,151,151,138,92,131,3,1,118,83,116,136,136,116,83,118,1,3,131,1,196,66,62,61,66,66,61,62,66, + 0,3,0,152,255,236,6,148,5,232,0,13,0,38,0,50,0,233,184,0,51,47,184,0,52,47,184,0,0,220,184,0,17,220,65,5,0,234,0,17, + 0,250,0,17,0,2,93,65,27,0,25,0,17,0,41,0,17,0,57,0,17,0,73,0,17,0,89,0,17,0,105,0,17,0,121,0,17,0,137,0, + 17,0,153,0,17,0,169,0,17,0,185,0,17,0,201,0,17,0,217,0,17,0,13,93,184,0,51,16,184,0,39,208,184,0,39,47,184,0,45,220, + 65,27,0,22,0,45,0,38,0,45,0,54,0,45,0,70,0,45,0,86,0,45,0,102,0,45,0,118,0,45,0,134,0,45,0,150,0,45,0,166, + 0,45,0,182,0,45,0,198,0,45,0,214,0,45,0,13,93,65,5,0,229,0,45,0,245,0,45,0,2,93,0,186,0,14,0,3,0,3,43,184, + 0,14,16,186,0,10,0,20,0,3,43,184,0,10,16,186,0,26,0,32,0,3,43,184,0,26,16,186,0,42,0,48,0,3,43,184,0,42,16,186, + 0,35,0,32,0,26,17,18,57,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4,18,1,50,18,53,52,38,35,34,6,21,20,22,51,50,54, + 7,14,1,35,34,38,39,21,30,1,3,52,54,51,50,22,21,20,6,35,34,38,6,148,254,63,254,194,254,196,254,63,206,1,113,190,193,1,113,205, + 252,209,200,233,191,185,160,194,186,159,79,128,10,5,127,119,46,97,85,74,107,60,92,78,78,91,91,78,78,92,2,234,254,193,254,65,1,191,1,63, + 198,1,114,198,198,254,144,253,75,1,10,218,232,253,180,145,148,175,60,13,79,147,21,36,156,24,19,2,132,91,98,98,91,91,98,98,0,4,0,152, + 255,236,6,148,5,232,0,13,0,24,0,36,0,48,0,211,186,0,37,0,17,0,3,43,184,0,37,16,186,0,25,0,31,0,3,43,184,0,25,16, + 186,0,0,0,43,0,3,43,184,0,0,16,65,5,0,234,0,31,0,250,0,31,0,2,93,65,27,0,25,0,31,0,41,0,31,0,57,0,31,0, + 73,0,31,0,89,0,31,0,105,0,31,0,121,0,31,0,137,0,31,0,153,0,31,0,169,0,31,0,185,0,31,0,201,0,31,0,217,0,31,0, + 13,93,65,5,0,234,0,43,0,250,0,43,0,2,93,65,27,0,25,0,43,0,41,0,43,0,57,0,43,0,73,0,43,0,89,0,43,0,105,0, + 43,0,121,0,43,0,137,0,43,0,153,0,43,0,169,0,43,0,185,0,43,0,201,0,43,0,217,0,43,0,13,93,0,186,0,15,0,3,0,3, + 43,184,0,15,16,186,0,10,0,46,0,3,43,184,0,10,16,184,0,3,16,184,0,40,220,48,49,1,16,0,33,32,0,17,52,18,36,51,50,4, + 18,1,33,53,35,17,35,7,21,55,17,35,1,20,6,35,34,38,53,52,54,51,50,22,5,20,22,51,50,54,53,52,38,35,34,6,6,148,254,63, + 254,194,254,196,254,63,206,1,113,190,193,1,113,205,251,36,1,194,159,117,188,172,158,3,137,70,63,64,69,69,64,63,70,254,112,136,131,130,136,136, + 130,131,136,2,234,254,193,254,65,1,191,1,63,198,1,114,198,198,254,144,253,169,128,2,202,42,137,39,253,194,1,36,162,151,151,162,163,151,151,163, + 208,228,228,208,209,228,228,0,0,3,0,9,255,150,6,171,6,61,0,25,0,36,0,62,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22, + 32,55,54,55,54,18,53,52,2,39,38,39,1,33,17,5,53,37,51,17,33,21,33,18,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38, + 39,38,2,53,52,18,55,54,55,3,244,254,204,134,132,109,111,109,109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,253,165,1,8,254,225, + 1,30,161,1,8,253,80,141,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,5,217,57,54,111,111,254,247,156, + 151,254,247,111,111,54,57,57,54,111,111,1,9,151,156,1,9,111,111,54,251,125,3,143,57,147,58,251,221,136,5,168,64,62,125,126,254,212,177,172, + 254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,3,0,9,255,150,6,171,6,61,0,25,0,54,0,80,0,0,0,32, + 7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18,53,52,2,39,38,39,1,33,21,33,53,54,0,55,62,1,53,52,38,35,34,6, + 7,53,62,1,51,50,22,21,20,6,7,14,1,2,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,3, + 244,254,204,134,132,109,111,109,109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,254,41,2,52,253,10,92,1,61,41,78,61,133,107,80,165, + 96,97,170,70,186,221,55,73,20,215,186,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,5,217,57,54,111,111, + 254,247,156,151,254,247,111,111,54,57,57,54,111,111,1,9,151,156,1,9,111,111,54,251,128,136,136,95,1,65,46,88,120,59,95,120,53,53,163,39, + 40,186,155,73,132,90,23,222,4,86,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0, + 0,3,0,9,255,150,6,171,6,61,0,25,0,66,0,92,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18,53,52, + 2,39,38,39,3,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51, + 50,22,21,20,6,0,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,3,244,254,204,134,132,109,111,109, + 109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,116,116,131,243,224,76,159,85,68,160,87,152,159,148,132,139,145,120,126,130,122,66,152,92, + 82,171,71,186,213,114,254,61,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,5,217,57,54,111,111,254,247,156, + 151,254,247,111,111,54,57,57,54,111,111,1,9,151,156,1,9,111,111,54,253,121,25,156,116,176,194,30,29,156,39,40,120,114,106,119,133,95,90,92, + 98,29,30,144,23,28,167,142,100,136,3,9,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0, + 0,4,0,9,255,150,6,171,6,61,0,25,0,28,0,39,0,65,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18, + 53,52,2,39,38,39,7,1,33,3,51,17,51,21,35,17,35,17,33,53,0,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2, + 53,52,18,55,54,55,3,244,254,204,134,132,109,111,109,109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,222,254,104,1,152,42,203,170,170, + 161,253,229,1,43,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,5,217,57,54,111,111,254,247,156,151,254,247, + 111,111,54,57,57,54,111,111,1,9,151,156,1,9,111,111,54,237,253,130,3,11,252,245,134,254,230,1,26,156,3,242,64,62,125,126,254,212,177,172, + 254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,3,0,9,255,150,6,171,6,61,0,25,0,55,0,81,0,0,0,32, + 7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18,53,52,2,39,38,39,5,33,21,33,17,62,1,51,50,22,21,20,6,35,34,38, + 39,53,30,1,51,50,54,53,52,38,35,34,6,7,18,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55, + 3,244,254,204,134,132,109,111,109,109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,253,163,2,122,254,26,35,71,35,200,233,240,218,75,156, + 83,76,149,86,138,162,162,138,65,129,67,143,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,5,217,57,54,111, + 111,254,247,156,151,254,247,111,111,54,57,57,54,111,111,1,9,151,156,1,9,111,111,54,99,136,254,219,12,12,219,187,193,214,26,25,163,41,37,146, + 125,124,146,29,30,3,88,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0,4,0,9, + 255,150,6,171,6,61,0,25,0,37,0,62,0,88,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18,53,52,2,39, + 38,39,1,34,6,21,20,22,51,50,54,53,52,38,19,21,46,1,35,34,6,7,62,1,51,50,22,21,20,6,35,34,2,17,16,0,51,50,22,0, + 32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,3,244,254,204,134,132,109,111,109,109,111,109,132,134,1, + 52,134,132,109,111,109,109,111,109,132,254,214,108,128,128,108,109,127,127,212,61,124,60,160,169,12,47,142,86,180,209,218,181,207,219,1,13,226,61,124, + 254,94,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,5,217,57,54,111,111,254,247,156,151,254,247,111,111,54, + 57,57,54,111,111,1,9,151,156,1,9,111,111,54,253,139,149,130,128,150,150,128,130,149,1,250,147,29,30,216,218,69,75,219,188,184,222,1,62,1, + 45,1,29,1,79,24,1,0,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,3,0,9, + 255,150,6,171,6,61,0,25,0,32,0,58,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18,53,52,2,39,38,39, + 5,33,21,1,35,1,33,18,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,3,244,254,204,134,132,109, + 111,109,109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,253,92,3,0,254,78,168,1,152,253,194,214,1,92,152,150,124,126,123,123,126,124, + 150,152,254,164,152,150,124,126,123,123,126,124,150,5,217,57,54,111,111,254,247,156,151,254,247,111,111,54,57,57,54,111,111,1,9,151,156,1,9,111, + 111,54,96,69,251,154,4,35,1,133,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0, + 0,5,0,9,255,150,6,171,6,61,0,25,0,35,0,57,0,69,0,95,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55, + 54,18,53,52,2,39,38,39,1,34,6,20,22,50,54,53,52,38,37,46,1,53,52,54,32,22,21,20,6,7,30,1,21,20,6,32,38,53,52,54, + 19,20,22,51,50,54,53,52,38,35,34,6,18,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,3,244, + 254,204,134,132,109,111,109,109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,254,223,115,132,132,230,133,132,254,234,104,116,204,1,100,204,116, + 104,117,131,212,254,116,212,132,57,116,105,104,118,118,104,105,116,48,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124, + 150,5,217,57,54,111,111,254,247,156,151,254,247,111,111,54,57,57,54,111,111,1,9,151,156,1,9,111,111,54,253,44,123,216,123,124,107,108,123,69, + 26,142,103,143,166,166,143,103,142,26,27,158,115,173,186,186,173,115,158,1,26,92,104,104,92,93,104,104,1,208,64,62,125,126,254,212,177,172,254,212, + 126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0,0,4,0,9,255,150,6,171,6,61,0,25,0,50,0,62,0,88,0,0, + 0,32,7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18,53,52,2,39,38,39,1,53,30,1,51,50,54,55,14,1,35,34,38,53, + 52,54,51,50,18,17,16,0,35,34,38,19,50,54,53,52,38,35,34,6,21,20,22,2,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38, + 39,38,2,53,52,18,55,54,55,3,244,254,204,134,132,109,111,109,109,111,109,132,134,1,52,134,132,109,111,109,109,111,109,132,253,167,61,124,60,160, + 169,12,46,143,86,181,207,218,180,208,218,254,244,226,61,125,254,109,127,127,109,108,128,128,74,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152, + 150,124,126,123,123,126,124,150,5,217,57,54,111,111,254,247,156,151,254,247,111,111,54,57,57,54,111,111,1,9,151,156,1,9,111,111,54,251,14,147, + 29,30,215,219,68,74,217,188,184,222,254,195,254,209,254,230,254,175,24,2,18,149,130,129,149,149,129,130,149,3,149,64,62,125,126,254,212,177,172,254, + 212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0,5,0,9,255,150,6,171,6,61,0,29,0,43,0,56,0,67,0,97, + 0,0,0,32,7,6,7,6,7,6,21,20,23,22,23,22,23,22,32,55,54,55,54,55,54,53,52,39,38,39,38,39,7,34,7,6,21,20,22,51, + 50,54,53,52,39,46,1,32,23,22,17,16,7,6,32,2,17,16,55,1,51,17,7,53,55,51,17,51,21,33,0,32,23,22,23,22,23,22,21,20, + 7,6,7,6,7,6,32,39,38,39,38,39,38,53,52,55,54,55,54,55,3,244,254,204,134,132,109,111,53,56,56,53,111,109,132,134,1,52,134,132, + 109,111,53,56,56,53,111,109,132,29,84,44,43,86,85,86,86,43,43,239,1,50,81,80,80,81,254,206,160,80,254,51,141,150,149,129,131,254,112,1, + 5,1,92,152,150,124,126,60,63,63,60,126,124,150,152,254,164,152,150,124,126,60,63,63,60,126,124,150,5,217,57,54,111,111,131,134,156,151,134,131, + 111,111,54,57,57,54,111,111,131,134,151,156,134,131,111,111,54,203,123,122,247,245,246,246,245,243,126,123,128,159,158,254,209,254,211,159,159,1,62,1, + 45,1,44,161,252,103,3,143,37,147,38,251,221,136,5,168,64,62,125,126,149,151,177,172,151,149,126,125,62,64,64,62,125,126,149,151,172,177,151,149, + 126,125,62,0,0,2,0,9,255,150,6,171,6,61,0,10,0,36,0,0,1,21,33,53,33,17,35,5,21,37,17,2,32,23,22,23,22,18,21,20, + 2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,2,31,2,176,254,248,161,254,226,1,31,123,1,92,152,150,124,126,123,123,126,124,150, + 152,254,164,152,150,124,126,123,123,126,124,150,1,29,136,136,4,35,58,147,57,252,113,5,32,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64, + 62,125,126,1,44,172,177,1,44,126,125,62,0,2,0,9,255,150,6,171,6,61,0,28,0,54,0,0,1,62,1,55,62,1,53,52,38,35,34,6, + 7,21,62,1,51,50,22,21,20,6,7,6,0,7,21,33,53,0,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18, + 55,54,55,2,163,195,215,20,73,55,221,186,70,170,97,96,169,76,107,133,61,78,41,254,195,92,2,246,253,213,1,92,152,150,124,126,123,123,126,124, + 150,152,254,164,152,150,124,126,123,123,126,124,150,1,32,199,222,23,90,132,73,155,186,40,39,163,53,53,120,95,59,120,88,46,254,191,95,136,136,5, + 29,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,2,0,9,255,150,6,171,6,61,0,40, + 0,66,0,0,1,62,1,53,52,38,35,34,6,7,21,62,1,51,50,22,21,20,6,43,1,21,51,50,22,21,20,6,35,34,38,39,21,30,1,51, + 50,54,53,52,38,0,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,4,6,105,114,215,184,71,161,92, + 92,152,66,122,130,126,120,145,139,132,148,159,152,87,160,68,85,159,76,224,243,131,254,50,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150, + 124,126,123,123,126,124,150,3,25,27,136,100,142,167,25,26,144,30,29,98,92,90,95,133,119,106,114,120,40,39,156,29,30,194,176,116,156,3,61,64, + 62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0,3,0,9,255,150,6,171,6,61,0,2, + 0,13,0,39,0,0,1,17,33,9,1,21,33,17,51,17,51,53,35,17,36,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2, + 53,52,18,55,54,55,3,156,254,104,1,110,254,15,2,27,161,170,170,254,111,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123, + 123,126,124,150,4,179,253,130,3,11,253,11,156,254,230,1,26,134,3,11,253,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1, + 44,172,177,1,44,126,125,62,0,2,0,9,255,150,6,171,6,61,0,29,0,55,0,0,1,17,62,1,51,50,22,21,20,6,35,34,38,39,21,30, + 1,51,50,54,53,52,38,35,34,6,7,17,33,53,0,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55, + 2,29,67,129,65,138,162,162,138,86,153,72,83,156,75,218,240,233,200,35,71,35,1,230,254,21,1,92,152,150,124,126,123,123,126,124,150,152,254,164, + 152,150,124,126,123,123,126,124,150,5,61,253,168,30,29,146,124,125,146,39,39,163,25,26,214,193,187,219,12,12,1,37,136,1,0,64,62,125,126,254, + 212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0,3,0,9,255,150,6,171,6,61,0,11,0,36,0,62, + 0,0,1,50,22,21,20,6,35,34,38,53,52,54,1,46,1,35,34,0,17,16,18,51,50,54,53,52,38,35,34,6,7,62,1,51,50,22,23,0, + 32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,3,80,109,127,127,109,108,128,128,1,173,67,124,61,226, + 254,243,219,207,181,218,209,180,86,142,47,12,169,160,60,124,61,254,27,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126, + 124,150,3,43,149,130,128,150,150,128,130,149,1,250,24,24,254,175,254,229,254,211,254,194,222,184,188,219,75,69,218,216,30,29,1,171,64,62,125,126, + 254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,2,0,9,255,150,6,171,6,61,0,6,0,32,0,0, + 1,21,33,1,51,1,53,36,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,1,214,2,62,254,104,168, + 1,178,253,214,1,92,152,150,124,126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,5,64,136,251,221,4,102,69,253,64,62,125,126, + 254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,4,0,9,255,150,6,171,6,61,0,9,0,31,0,43, + 0,69,0,0,1,50,22,21,20,6,34,38,52,54,39,14,1,21,20,22,32,54,53,52,38,39,62,1,53,52,38,32,6,21,20,22,55,52,54,51, + 50,22,21,20,6,35,34,38,18,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,3,89,116,132,133,230, + 132,132,47,116,132,212,1,140,212,131,117,104,116,204,254,156,204,116,45,116,105,104,118,118,104,105,116,48,1,92,152,150,124,126,123,123,126,124,150,152, + 254,164,152,150,124,126,123,123,126,124,150,2,204,123,108,107,124,123,216,123,69,27,158,115,173,186,186,173,115,158,27,26,142,103,143,166,166,143,103,142, + 229,93,104,104,93,92,104,104,2,137,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0, + 0,3,0,9,255,150,6,171,6,61,0,24,0,36,0,62,0,0,37,30,1,51,50,0,17,16,2,35,34,6,21,20,22,51,50,54,55,14,1,35, + 34,38,39,1,34,38,53,52,54,51,50,22,21,20,6,0,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54, + 55,2,33,67,125,61,226,1,12,218,208,180,218,209,179,86,143,46,12,169,160,60,124,61,1,65,108,128,128,108,109,127,127,254,221,1,92,152,150,124, + 126,123,123,126,124,150,152,254,164,152,150,124,126,123,123,126,124,150,174,24,24,1,81,1,26,1,47,1,61,222,184,188,217,74,68,219,215,30,29,1, + 103,149,130,129,149,149,129,130,149,3,149,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0, + 0,4,0,9,255,150,6,171,6,61,0,11,0,21,0,32,0,58,0,0,1,50,22,21,20,6,35,34,38,53,52,54,36,32,2,17,16,18,32,18, + 17,16,1,21,33,53,35,17,35,7,21,55,17,18,32,23,22,23,22,18,21,20,2,7,6,7,6,32,39,38,39,38,2,53,52,18,55,54,55,4, + 153,101,100,100,101,100,100,100,1,5,254,190,169,169,1,66,170,251,145,1,194,161,129,179,180,150,1,92,152,150,124,126,123,123,126,124,150,152,254,164, + 152,150,124,126,123,123,126,124,150,4,213,245,247,245,246,246,245,247,245,128,254,195,254,209,254,211,254,194,1,62,1,45,1,47,253,5,136,136,4,35, + 38,147,37,252,113,5,32,64,62,125,126,254,212,177,172,254,212,126,125,62,64,64,62,125,126,1,44,172,177,1,44,126,125,62,0,0,0,1,0,117, + 0,154,6,80,4,106,0,8,0,0,9,1,33,1,33,53,33,1,33,6,80,254,24,254,192,1,112,251,221,4,35,254,144,1,64,2,130,254,24,1, + 112,240,1,112,0,1,0,252,0,112,5,116,4,233,0,6,0,0,9,1,55,1,27,1,37,3,247,253,5,169,2,181,212,70,253,78,1,139,2,180, + 170,253,5,1,52,253,78,71,0,1,0,117,0,204,6,80,4,56,0,6,0,0,1,5,53,5,3,9,1,4,122,251,251,4,5,68,2,26,253,230, + 2,60,50,240,50,1,112,254,74,254,74,0,0,1,0,252,0,27,5,116,4,148,0,6,0,0,9,1,39,1,45,1,3,4,90,253,75,169,2,251, + 254,203,2,178,70,3,22,253,5,170,2,180,212,71,253,78,0,1,0,117,1,8,6,80,3,252,0,8,0,0,19,33,3,4,5,4,5,19,33,117, + 2,187,168,1,92,2,108,253,148,254,164,168,253,69,2,190,1,62,252,126,126,252,1,62,0,1,0,117,0,117,6,29,4,143,0,43,0,0,0,20, + 6,7,1,6,7,6,34,38,39,46,1,53,52,54,63,1,33,34,46,2,52,62,2,51,33,39,46,1,53,52,54,55,62,1,50,23,22,23,1,22, + 6,29,20,17,254,112,16,24,22,52,44,18,18,19,20,17,186,252,128,26,44,36,19,19,36,44,26,3,128,186,17,20,19,18,18,44,52,22,24,16, + 1,144,19,2,155,50,46,17,254,112,16,11,10,20,17,19,44,25,26,46,17,186,20,34,46,50,46,34,20,186,17,46,26,25,44,19,17,20,10,11, + 16,254,112,19,0,1,0,117,0,204,6,80,4,56,0,6,0,0,1,33,53,33,17,9,1,4,154,251,219,4,37,1,182,254,74,2,90,80,1,142, + 254,74,254,74,0,1,0,117,0,204,6,80,4,56,0,6,0,0,1,33,53,33,17,9,1,4,154,251,219,4,37,1,182,254,74,2,20,220,1,72, + 254,74,254,74,0,4,0,117,0,204,6,80,4,56,0,3,0,7,0,11,0,18,0,0,1,35,17,51,1,35,17,51,3,35,17,51,1,33,17,33, + 53,9,1,2,185,240,240,254,192,120,120,200,60,60,3,233,254,111,1,145,1,182,254,74,1,186,1,144,254,112,1,144,254,112,1,144,254,112,1,144, + 238,254,74,254,74,0,0,0,0,4,0,117,0,204,6,80,4,56,0,8,0,12,0,16,0,20,0,0,1,53,18,23,6,3,53,33,17,3,35,17, + 51,1,35,17,51,3,35,17,51,4,154,184,254,254,184,254,111,80,240,240,254,192,120,120,200,60,60,3,174,138,254,206,132,132,254,206,138,2,88,253, + 168,2,88,253,168,2,88,253,168,2,88,0,0,1,0,117,0,134,6,125,4,126,0,6,0,0,9,2,17,33,17,33,4,129,1,252,254,4,251,244, + 4,12,4,126,254,4,254,4,1,17,1,214,0,2,0,228,0,192,6,80,4,68,0,2,0,6,0,0,1,33,1,19,9,2,3,30,2,54,252,188, + 150,254,62,5,108,250,148,2,130,1,15,254,241,1,194,254,62,254,62,0,0,2,0,228,0,192,6,80,4,68,0,2,0,6,0,0,9,2,33,9, + 2,3,30,254,242,3,68,253,82,254,62,5,108,250,148,2,130,254,241,1,15,1,194,254,62,254,62,0,0,1,0,228,255,248,6,80,5,12,0,3, + 0,0,9,3,2,66,254,162,5,108,250,148,2,130,2,138,253,118,253,118,0,1,0,117,0,204,6,80,4,98,0,20,0,0,19,17,20,22,23,22, + 23,22,51,33,53,9,1,53,33,32,39,38,39,46,1,117,36,35,35,43,42,12,3,90,1,182,254,74,254,77,254,77,42,43,35,35,36,2,130,1, + 224,48,85,37,33,19,18,198,254,74,254,74,198,18,19,33,37,85,0,0,0,1,0,117,0,162,6,80,4,56,0,20,0,0,19,52,54,55,54,55, + 54,51,33,53,9,1,53,33,32,7,6,7,14,1,21,117,36,35,35,43,42,12,3,90,1,182,254,74,254,77,254,77,42,43,35,35,36,2,130,48, + 85,37,33,19,18,198,254,74,254,74,198,18,19,33,37,85,48,0,0,0,0,1,1,236,255,241,4,217,5,19,0,6,0,0,1,33,17,33,17,9, + 1,3,94,254,142,1,114,1,123,254,133,1,86,2,88,1,101,253,111,253,111,0,0,0,0,1,0,117,0,204,6,80,4,56,0,8,0,0,1,53, + 18,5,4,3,53,33,17,4,4,144,1,188,254,68,144,252,113,3,154,158,254,206,132,132,254,206,158,2,48,0,0,0,0,2,0,117,0,154,6,30, + 4,106,0,8,0,15,0,0,37,53,33,17,33,53,51,9,1,3,21,9,1,21,33,17,3,60,253,57,2,199,250,1,232,254,24,170,1,152,254,104, + 253,57,154,238,1,244,238,254,24,254,24,1,62,238,1,152,1,152,238,254,172,0,0,0,0,2,0,117,0,154,6,30,4,106,0,8,0,15,0,0, + 37,53,33,17,33,53,51,9,1,3,21,9,1,21,33,17,3,60,253,57,2,199,250,1,232,254,24,20,1,152,254,104,253,57,154,238,1,244,238,254, + 24,254,24,1,62,238,1,152,1,152,238,254,172,0,0,0,0,2,0,43,0,24,6,90,4,176,0,11,0,18,0,0,19,1,33,55,51,19,21,1, + 35,53,55,33,1,7,1,3,7,33,3,43,1,32,3,73,138,100,216,253,38,150,22,253,43,3,209,138,2,132,172,138,252,183,196,1,206,1,244,238, + 253,254,200,254,50,200,38,1,24,238,1,152,1,152,238,254,172,0,0,0,0,2,0,43,0,24,6,90,4,176,0,11,0,18,0,0,19,53,33,39, + 53,51,1,21,3,35,39,33,1,33,19,33,23,19,1,43,2,213,22,150,2,218,216,100,138,252,183,2,177,252,183,196,3,73,138,172,253,124,2,250, + 200,38,200,254,50,200,253,254,238,1,164,254,172,238,1,152,1,152,0,0,0,2,1,21,0,0,6,50,4,152,0,10,0,17,0,0,33,39,33,39, + 17,33,53,51,1,23,1,3,21,9,1,21,33,17,3,220,79,253,236,100,2,99,110,1,232,100,254,24,130,1,152,254,104,253,157,158,200,2,148,158, + 254,24,200,254,24,1,182,158,1,152,1,152,158,254,12,0,0,2,1,21,0,0,6,50,4,152,0,10,0,17,0,0,1,51,1,7,1,35,53,33, + 17,55,33,19,33,17,33,21,9,1,3,220,110,1,232,100,254,24,110,253,157,100,2,20,59,253,157,2,99,1,152,254,104,4,152,254,24,200,254,24, + 158,2,148,200,254,232,254,12,158,1,152,1,152,0,0,0,0,2,0,127,0,100,6,100,4,152,0,12,0,20,0,0,1,3,33,53,51,1,23,1, + 35,39,53,33,39,19,7,33,21,9,1,21,33,1,21,150,3,93,110,1,232,50,254,24,110,50,252,213,50,242,114,3,45,1,152,254,104,252,211,2, + 176,1,74,158,254,24,100,254,24,99,59,100,1,74,250,158,1,152,1,152,158,0,0,0,0,2,0,127,0,100,6,100,4,152,0,12,0,20,0,0, + 1,3,55,33,53,55,51,1,7,1,35,53,33,19,7,33,21,9,1,21,33,1,21,150,50,3,43,50,110,1,232,50,254,24,110,252,163,242,114,3, + 45,1,152,254,104,252,211,2,76,1,74,100,59,99,254,24,100,254,24,158,1,74,250,158,1,152,1,152,158,0,0,0,0,1,1,60,255,216,5,196, + 4,175,0,30,0,0,1,54,55,54,55,54,51,50,23,22,23,30,1,21,20,6,7,6,7,6,34,39,38,39,38,39,33,21,9,1,21,1,60,39, + 67,90,109,111,126,121,116,105,94,90,92,88,94,86,113,111,247,116,105,94,63,41,2,88,1,202,254,54,3,110,71,67,90,46,47,47,43,93,89,221, + 128,122,218,95,88,48,47,47,43,93,62,73,158,1,202,1,202,158,0,0,0,9,0,130,1,66,6,80,3,194,0,3,0,7,0,11,0,15,0,30, + 0,34,0,38,0,42,0,46,0,0,1,7,51,55,35,7,51,55,35,7,51,55,35,7,51,55,35,53,3,33,19,33,17,22,23,6,7,17,33,3, + 33,1,51,39,35,23,51,39,35,23,51,39,35,23,51,39,35,2,225,160,60,160,180,160,60,160,180,160,60,160,180,160,60,160,120,187,2,28,187,1, + 135,173,195,195,173,254,121,187,253,228,2,95,60,160,60,40,60,160,60,40,60,160,60,40,60,160,60,2,90,240,240,240,240,240,240,240,240,80,1,24, + 254,232,1,22,188,130,130,188,1,22,254,232,1,104,240,240,240,240,240,240,240,0,0,0,0,3,0,165,0,112,5,116,5,62,0,12,0,16,0,20, + 0,0,1,55,6,21,20,23,38,35,34,7,55,39,55,9,1,33,1,37,17,1,17,4,162,175,7,42,142,164,66,70,175,254,56,254,29,1,169,254, + 229,254,87,1,85,1,168,1,123,176,70,67,163,143,42,7,176,254,57,1,111,254,88,1,168,58,1,27,254,87,254,230,0,3,0,117,1,98,6,80, + 3,162,0,8,0,12,0,16,0,0,1,53,22,23,6,7,53,33,53,5,33,7,33,19,39,33,23,4,254,154,184,184,154,254,152,253,167,2,88,200, + 253,168,200,200,2,88,200,2,170,248,188,100,100,188,248,80,82,200,1,26,200,200,0,0,0,3,0,167,255,197,5,116,4,148,0,12,0,16,0,20, + 0,0,1,39,22,51,50,55,6,21,20,23,39,7,39,9,1,17,1,3,33,1,33,4,105,175,70,66,164,142,42,7,175,255,56,254,145,1,168,254, + 88,58,254,229,1,168,1,27,3,193,176,7,42,144,162,67,70,176,255,57,254,29,1,168,254,229,254,88,1,85,1,168,0,1,0,167,0,112,5,116, + 5,62,0,42,0,0,37,38,35,34,7,62,1,55,39,38,39,38,34,6,7,1,62,1,51,50,31,1,55,38,53,52,54,55,1,14,1,21,20,23, + 22,23,1,62,1,55,6,21,20,5,116,143,165,66,69,72,128,24,166,166,35,38,78,75,28,254,88,36,87,47,44,48,21,5,19,36,34,1,168,32, + 25,14,15,7,1,68,4,53,72,7,112,42,7,71,54,3,166,166,14,15,30,28,1,168,36,34,18,8,33,48,44,48,89,34,254,87,33,70,38,39, + 38,35,7,254,187,23,129,71,71,67,163,0,0,1,0,117,1,97,6,80,3,163,0,39,0,0,1,6,7,52,54,55,35,34,7,6,7,14,1,21, + 33,52,54,55,54,63,1,39,38,39,46,1,53,33,20,22,23,22,23,22,51,33,46,1,53,22,6,80,183,155,53,14,235,234,35,36,29,28,31,253, + 168,37,34,31,47,21,21,47,31,34,37,2,88,31,28,29,36,35,10,1,203,14,53,155,2,130,101,188,101,129,19,15,16,28,27,74,40,48,89,33, + 31,21,9,27,21,31,34,88,48,40,74,27,28,16,15,19,129,101,188,0,0,1,0,167,255,198,5,116,4,148,0,42,0,0,1,6,21,20,23,46, + 1,39,7,6,7,6,21,20,22,23,1,46,1,53,52,63,1,39,6,35,34,38,39,1,30,1,50,55,54,55,1,46,1,39,22,51,50,5,116,41, + 7,72,53,4,167,167,12,14,29,28,254,88,34,36,19,9,35,48,44,48,88,34,1,168,28,75,78,38,35,7,1,69,24,128,72,69,66,165,4,148, + 142,163,67,71,71,129,23,168,168,31,38,39,38,75,28,254,87,34,89,48,44,48,21,4,18,36,34,1,168,28,30,15,14,7,1,69,3,54,71,7, + 0,3,0,115,0,172,6,80,4,88,0,20,0,39,0,60,0,0,1,54,37,6,3,6,7,6,7,6,34,39,38,39,46,1,53,52,54,55,54,36, + 52,54,55,54,55,54,50,23,4,5,4,5,6,34,39,38,39,38,1,38,39,46,1,53,52,54,55,54,55,54,50,23,22,23,22,23,18,23,36,4, + 47,246,1,43,227,122,12,21,22,27,26,62,26,27,22,21,23,23,21,22,252,95,32,27,29,36,35,82,35,1,97,3,102,252,130,254,183,35,82,35, + 41,24,29,3,158,27,22,21,23,23,21,22,27,26,62,26,27,22,18,15,120,229,254,148,1,206,98,81,117,254,253,29,20,21,12,11,11,12,21,20, + 56,31,30,56,20,21,151,82,75,26,28,16,15,14,133,54,56,131,14,15,18,26,31,1,35,12,21,20,56,30,31,56,20,21,12,11,11,12,21,17, + 32,254,254,118,99,0,0,0,0,2,0,150,1,31,6,60,3,229,0,26,0,42,0,0,19,54,55,54,55,54,55,54,51,50,23,22,23,22,5,4, + 7,14,1,35,34,39,38,39,38,39,38,37,46,1,53,52,54,55,22,23,6,7,46,1,53,52,54,150,65,30,32,20,39,39,43,47,53,52,60,51, + 162,1,145,254,111,162,56,110,50,51,39,57,21,29,23,29,4,6,37,37,37,37,98,252,252,98,37,37,37,2,130,38,58,63,19,36,18,19,19,22, + 32,102,76,76,102,35,38,19,29,25,35,47,58,38,39,88,50,51,88,39,241,114,114,241,39,88,51,50,88,0,0,0,0,1,0,162,1,86,6,50, + 3,174,0,99,0,0,0,20,6,15,1,6,7,6,34,39,38,39,46,1,53,52,63,1,54,53,52,38,39,38,39,38,35,33,34,7,6,7,6,15, + 1,6,7,6,7,6,35,33,34,46,2,52,63,1,54,52,47,1,38,52,54,55,54,55,54,51,33,50,23,22,23,22,31,1,22,23,22,23,22,51, + 33,50,55,54,55,62,1,53,52,47,1,38,53,52,54,55,54,55,54,50,23,22,31,1,22,6,50,6,6,240,4,9,7,16,7,7,6,6,6,3, + 27,3,6,6,5,8,8,7,254,230,8,7,7,6,5,4,90,5,3,6,8,6,8,253,156,8,14,12,6,3,59,58,1,116,3,6,6,6,7,7, + 8,2,100,8,6,9,5,3,5,90,4,5,6,7,7,8,1,26,7,8,8,5,6,6,3,27,3,6,6,6,7,7,16,7,9,4,240,6,2,139, + 18,14,6,240,4,5,3,3,4,5,6,14,9,4,11,99,11,5,7,15,6,5,3,4,3,4,5,5,8,180,10,3,5,4,3,6,12,14,18,6, + 117,117,20,2,232,6,18,14,6,5,4,3,3,3,6,3,10,180,8,5,5,4,3,4,3,5,6,15,7,5,11,99,11,4,9,14,6,5,4,3, + 3,5,4,240,6,0,0,0,0,1,0,162,0,241,6,50,4,19,0,99,0,0,0,20,6,7,1,6,7,6,34,39,38,39,46,1,53,52,63,1, + 54,53,52,38,39,38,39,38,43,1,34,7,6,7,6,15,1,6,7,6,7,6,35,33,34,46,2,52,63,1,54,52,39,3,38,52,54,55,54,55, + 54,51,33,50,23,22,23,22,23,19,22,23,22,23,22,59,1,50,55,54,55,62,1,53,52,47,1,38,53,52,54,55,54,55,54,50,23,22,23,1, + 22,6,50,6,6,254,112,5,8,7,16,7,7,6,6,6,3,87,3,6,6,5,8,8,7,92,8,7,7,6,5,4,120,5,3,6,8,6,8,253, + 106,8,14,12,6,3,73,74,1,156,3,6,6,6,7,7,8,2,150,8,6,9,5,3,5,130,4,5,6,7,7,8,92,7,8,8,5,6,6,3, + 87,3,6,6,6,7,7,16,7,8,5,1,144,6,2,139,18,15,5,254,152,5,4,3,3,4,5,6,14,9,7,8,219,8,8,7,15,6,5,3, + 4,3,4,5,5,8,240,10,3,5,4,3,6,12,14,18,6,147,147,20,2,1,56,6,18,14,6,5,4,3,3,3,6,3,10,254,252,8,5,5, + 4,3,4,3,5,6,15,7,8,8,219,8,7,9,14,6,5,4,3,3,4,5,254,152,5,0,0,0,0,3,0,117,0,166,6,80,4,94,0,19, + 0,29,0,39,0,0,1,6,7,6,7,35,55,54,55,54,55,38,39,38,47,1,51,22,23,22,1,35,62,1,55,33,53,33,14,1,3,30,1,23, + 33,53,33,46,1,39,6,80,136,83,140,74,108,46,46,160,38,71,71,38,160,21,71,108,72,142,83,253,204,105,19,55,42,252,214,3,229,110,75,13, + 13,75,110,252,27,3,42,42,55,19,2,130,79,85,143,169,110,109,164,39,54,54,39,164,49,170,164,148,85,253,213,61,133,72,100,142,183,3,143,41, + 183,142,100,72,133,61,0,0,0,1,0,110,254,178,2,208,6,38,0,25,0,0,1,42,1,39,36,3,38,0,39,38,35,34,7,39,54,55,54,21, + 20,0,7,6,5,22,54,55,2,208,9,104,55,254,72,2,1,1,109,4,3,94,58,45,136,51,213,222,254,176,7,12,1,28,82,69,20,254,178,11, + 83,1,82,174,3,245,81,79,137,49,216,1,1,204,161,252,76,143,220,72,21,1,2,0,0,1,0,79,254,178,2,177,6,38,0,25,0,0,19,53, + 30,1,55,36,39,38,0,53,52,23,22,23,7,38,35,34,7,6,0,7,2,5,6,34,79,20,69,82,1,28,12,7,254,176,222,213,51,136,45,58, + 94,3,4,1,109,1,2,254,72,55,104,254,178,143,2,1,21,72,220,143,3,180,161,204,1,1,216,49,137,79,81,252,11,174,254,174,83,11,0,0, + 0,3,0,6,254,35,3,238,6,117,0,3,0,6,0,9,0,0,9,5,33,9,1,33,1,249,1,245,254,11,254,13,1,243,254,152,2,210,254,150, + 1,106,253,46,6,117,251,219,251,211,4,45,3,49,253,8,252,142,3,0,0,2,0,176,254,242,3,48,6,20,0,3,0,11,0,0,1,17,51,17, + 37,33,21,35,17,51,21,33,1,20,200,254,212,2,128,240,240,253,128,5,176,249,166,6,90,100,100,249,166,100,0,0,0,2,0,175,254,242,3,47, + 6,20,0,3,0,11,0,0,1,35,17,51,19,17,33,53,51,17,35,53,2,203,200,200,100,253,128,240,240,5,176,249,166,6,190,248,222,100,6,90, + 100,0,0,0,0,1,0,183,254,242,2,123,6,18,0,5,0,0,19,1,51,9,1,35,183,1,26,170,254,230,1,26,170,2,130,3,144,252,112,252, + 112,0,0,0,0,1,0,164,254,242,2,104,6,18,0,5,0,0,9,1,35,9,1,51,2,104,254,230,170,1,26,254,230,170,2,130,252,112,3,144, + 3,144,0,0,255,255,0,183,254,242,3,207,6,18,16,38,16,64,0,0,16,7,16,64,1,84,0,0,255,255,0,164,254,242,3,188,6,18,16,38, + 16,65,0,0,16,7,16,65,1,84,0,0,0,1,0,91,0,0,6,91,5,220,0,22,0,0,9,1,7,39,17,35,17,39,17,35,17,39,7,17, + 35,17,7,17,35,17,7,39,1,3,137,2,210,120,92,120,210,120,106,106,120,210,120,92,120,2,210,5,220,253,44,120,92,253,20,3,101,211,251,200, + 4,176,104,104,251,80,4,56,211,252,155,2,236,92,120,2,212,0,0,0,0,1,0,89,255,249,6,89,5,213,0,22,0,0,5,1,55,23,17,51, + 17,23,17,51,17,23,55,17,51,17,55,17,51,17,55,23,1,3,43,253,46,120,92,120,210,120,106,106,120,210,120,92,120,253,46,7,2,212,120,92, + 2,236,252,155,211,4,56,251,80,104,104,4,176,251,200,211,3,101,253,20,92,120,253,44,0,1,0,79,0,108,6,132,5,68,0,61,0,0,1,48, + 55,22,23,22,50,55,54,55,62,1,53,52,39,38,39,38,39,38,34,7,6,7,6,7,6,7,55,23,1,35,1,55,23,54,55,54,55,54,55,54, + 51,50,23,22,23,22,23,22,21,20,7,6,7,6,7,6,35,34,39,38,2,101,119,64,82,78,190,74,86,60,66,66,33,35,64,64,82,78,190,74, + 86,60,66,33,23,7,232,120,254,120,90,254,118,120,233,8,36,48,89,84,116,103,133,128,108,113,87,90,47,46,46,47,90,83,117,103,133,128,108,106, + 1,33,120,63,35,33,33,39,59,66,162,93,89,81,83,64,63,35,33,33,39,59,66,81,57,63,234,120,254,118,1,138,120,233,96,88,113,89,83,52, + 46,46,48,87,89,113,112,123,127,112,113,89,83,52,46,46,45,0,0,0,0,1,0,79,0,124,6,132,5,84,0,60,0,0,1,6,7,6,35,34, + 39,38,39,38,39,38,53,52,55,54,55,54,55,54,51,50,23,22,23,22,23,22,23,55,23,1,35,1,55,23,38,39,38,39,38,39,38,34,7,6, + 7,6,7,6,21,20,22,23,22,23,22,50,55,54,55,4,110,94,106,108,128,133,103,116,84,89,48,46,46,48,89,88,112,108,128,133,103,116,84,89, + 48,36,8,233,120,254,118,90,254,120,120,232,7,23,33,66,60,86,74,190,78,82,64,64,35,33,66,66,60,86,74,190,78,82,64,1,49,90,45,46, + 46,52,83,89,113,112,127,123,112,113,89,87,48,46,46,52,83,89,113,88,96,233,120,254,118,1,138,120,234,63,57,81,66,59,39,33,33,35,63,64, + 83,81,89,93,162,66,59,39,33,33,35,63,0,3,0,117,255,227,8,222,5,36,0,37,0,57,0,77,0,0,1,21,1,39,55,33,6,7,6,7, + 14,1,32,38,39,38,39,38,39,35,53,51,54,55,54,55,62,1,32,22,23,22,23,22,23,33,39,55,36,34,7,6,7,6,7,6,7,33,17,51, + 17,33,38,39,38,39,38,39,1,33,17,35,17,33,22,23,22,23,22,23,22,50,55,54,55,54,55,54,8,222,254,119,120,233,254,160,11,33,49,99, + 98,238,254,236,238,98,99,49,33,11,189,189,10,34,49,99,98,238,1,20,238,98,99,49,34,10,1,96,233,120,252,226,214,93,92,76,77,38,23,9, + 1,174,170,1,174,9,23,38,77,76,92,1,59,254,82,170,254,82,10,22,38,77,76,92,93,214,93,92,76,77,38,22,2,175,90,254,119,120,233,90, + 81,118,99,98,100,100,98,99,118,81,90,170,91,82,119,99,98,100,100,98,99,119,82,91,233,120,86,39,39,76,77,92,55,61,1,101,254,155,61,55, + 92,77,76,39,253,198,254,155,1,101,59,54,92,77,76,39,39,39,39,76,77,92,54,0,0,1,0,100,0,204,11,3,4,56,0,9,0,129,180,2, + 9,6,0,10,16,212,212,204,50,64,9,64,2,64,9,48,2,48,9,4,93,49,64,10,2,5,9,1,0,6,5,156,6,10,0,16,212,236,17,57, + 57,204,16,204,48,64,12,8,9,9,0,8,7,8,7,156,0,9,0,7,5,16,252,60,8,6,16,60,64,12,3,2,2,1,3,4,3,4,156,1, + 2,1,7,5,16,252,60,8,6,16,60,176,16,75,83,88,0,179,3,2,8,9,16,60,16,60,180,8,156,9,9,0,7,5,16,236,180,3,156,2, + 2,1,7,5,16,236,89,19,53,1,23,7,33,21,33,23,7,100,1,137,120,233,9,135,246,121,233,120,2,85,90,1,137,120,233,170,233,120,0,0, + 0,1,0,117,0,204,11,20,4,56,0,9,0,129,180,2,9,0,6,10,16,212,212,204,50,64,9,79,2,79,9,95,2,95,9,4,93,49,64,10, + 9,6,2,1,0,5,6,156,5,10,0,16,212,236,17,57,57,204,16,204,48,64,12,8,9,9,0,8,7,8,7,156,0,9,0,7,5,16,252,60, + 8,6,16,60,64,12,3,2,2,1,3,4,3,4,156,1,2,1,7,5,16,252,60,8,6,16,60,176,16,75,83,88,0,179,3,2,8,9,16,60, + 16,60,180,8,156,9,9,0,7,5,16,236,180,3,156,2,2,1,7,5,16,236,89,1,21,1,39,55,33,53,33,39,55,11,20,254,119,120,233,246, + 121,9,135,233,120,2,175,90,254,119,120,233,170,233,120,0,0,1,0,100,0,204,11,20,4,56,0,15,0,218,182,7,10,9,2,15,0,16,16,212, + 204,50,212,204,50,64,13,80,2,80,15,95,10,95,7,79,10,79,7,6,93,49,0,64,15,7,2,4,10,15,0,1,8,9,4,13,4,156,13,16, + 16,212,236,17,23,57,204,50,16,204,50,48,64,12,14,15,15,0,14,13,14,13,156,0,15,0,7,5,16,252,60,8,6,16,60,64,12,3,2,2, + 1,3,4,3,4,156,1,2,1,7,5,16,252,60,8,6,16,60,64,12,11,10,10,9,11,12,11,12,156,9,9,10,7,5,16,252,60,8,6,16, + 60,64,12,6,7,7,8,6,5,6,5,156,8,7,8,7,5,16,252,60,8,6,16,60,176,16,75,83,88,0,183,11,10,6,7,3,2,14,15,16, + 60,16,60,16,60,16,60,180,14,156,15,15,0,7,5,16,236,180,3,156,2,2,1,7,5,16,236,180,11,156,10,10,9,7,5,16,236,180,6,156, + 7,7,8,7,5,16,236,89,19,53,1,23,7,33,39,55,1,21,1,39,55,33,23,7,100,1,137,120,233,8,128,233,120,1,137,254,119,120,233,247, + 128,233,120,2,85,90,1,137,120,233,233,120,254,119,90,254,119,120,233,233,120,0,0,0,0,1,0,100,0,204,11,3,4,56,0,14,0,0,1,33, + 21,33,23,7,1,53,1,23,7,33,21,33,7,1,144,9,115,247,5,93,120,254,119,1,137,120,93,8,251,246,141,105,2,25,120,93,120,1,137,90, + 1,137,120,93,120,105,0,0,0,1,0,117,0,204,11,20,4,56,0,14,0,0,1,55,39,33,53,33,39,55,1,21,1,39,55,33,53,9,232,105, + 105,246,141,8,251,93,120,1,137,254,119,120,93,247,5,2,25,105,105,120,93,120,254,119,90,254,119,120,93,120,0,0,0,2,0,100,0,204,11,20, + 4,56,0,5,0,21,0,0,1,33,55,39,33,7,5,33,23,7,1,53,1,23,7,33,39,55,1,21,1,39,1,144,8,88,105,105,247,168,105,8, + 73,248,152,93,120,254,119,1,137,120,93,7,104,93,120,1,137,254,119,120,2,25,105,105,105,225,93,120,1,137,90,1,137,120,93,93,120,254,119,90, + 254,119,120,0,0,1,0,100,0,204,11,3,4,56,0,13,0,0,1,33,23,7,1,53,1,23,7,33,17,51,17,35,10,89,247,35,233,120,254,119, + 1,137,120,233,8,221,170,170,2,45,233,120,1,137,90,1,137,120,233,1,89,252,164,0,0,1,0,117,0,204,11,20,4,56,0,13,0,0,1,17, + 35,17,51,17,33,39,55,1,21,1,39,55,1,31,170,170,8,221,233,120,1,137,254,119,120,233,2,45,254,167,3,92,254,167,233,120,254,119,90,254, + 119,120,233,0,0,2,0,100,0,204,11,3,4,56,0,13,0,18,0,0,1,33,23,7,1,53,1,23,7,33,53,51,17,35,17,53,33,7,23,10, + 89,247,175,93,120,254,119,1,137,120,93,8,81,170,170,247,55,105,105,1,161,93,120,1,137,90,1,137,120,93,205,252,164,1,69,210,105,105,0,0, + 0,2,0,117,0,204,11,20,4,56,0,13,0,18,0,0,1,33,39,55,1,21,1,39,55,33,21,35,17,51,17,21,33,55,39,1,31,8,81,93, + 120,1,137,254,119,120,93,247,175,170,170,8,201,105,105,3,99,93,120,254,119,90,254,119,120,93,205,3,92,254,187,210,105,105,0,0,0,1,0,117, + 0,204,11,20,4,56,0,37,0,0,19,23,55,23,55,23,55,23,55,23,55,23,55,23,55,51,39,55,1,21,1,39,55,35,7,39,7,39,7,39, + 7,39,7,39,7,39,7,39,117,70,180,180,180,180,180,180,180,180,180,180,180,180,70,139,233,120,1,137,254,119,120,233,99,110,180,180,180,180,180,180, + 180,180,180,180,180,180,70,2,215,70,180,180,180,180,180,180,180,180,180,180,180,180,70,233,120,254,119,90,254,119,120,233,110,180,180,180,180,180,180,180, + 180,180,180,180,180,70,0,0,255,255,1,44,5,20,2,88,6,64,16,7,23,1,1,44,5,20,0,0,255,255,1,44,2,221,2,88,4,9,16,7, + 23,1,1,44,2,221,0,0,255,255,1,44,2,221,2,88,6,64,16,39,23,1,1,44,5,20,16,7,23,1,1,44,2,221,0,0,255,255,1,44, + 0,167,2,88,1,211,16,7,23,1,1,44,0,167,0,0,255,255,1,44,0,167,2,88,6,64,16,39,23,1,1,44,5,20,16,7,23,1,1,44, + 0,167,0,0,255,255,1,44,0,167,2,88,4,9,16,39,23,1,1,44,2,221,16,7,23,1,1,44,0,167,0,0,255,255,1,44,0,167,2,88, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,7,23,1,1,44,0,167,0,0,255,255,3,132,5,20,4,176,6,64,16,7, + 23,1,3,132,5,20,0,0,255,255,1,44,5,20,4,176,6,64,16,39,23,1,1,44,5,20,16,7,23,1,3,132,5,20,0,0,255,255,1,44, + 2,221,4,176,6,64,16,39,23,1,1,44,2,221,16,7,23,1,3,132,5,20,0,0,255,255,1,44,2,221,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,7,23,1,3,132,5,20,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,0,167,16,7, + 23,1,3,132,5,20,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,7,23,1,3,132, + 5,20,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,7,23,1,3,132,5,20,0,0, + 255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,7,23,1,3,132, + 5,20,0,0,255,255,3,132,2,221,4,176,4,9,16,7,23,1,3,132,2,221,0,0,255,255,1,44,2,221,4,176,6,64,16,39,23,1,1,44, + 5,20,16,7,23,1,3,132,2,221,0,0,255,255,1,44,2,221,4,176,4,9,16,39,23,1,1,44,2,221,16,7,23,1,3,132,2,221,0,0, + 255,255,1,44,2,221,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,7,23,1,3,132,2,221,0,0,255,255,1,44, + 0,167,4,176,4,9,16,39,23,1,1,44,0,167,16,7,23,1,3,132,2,221,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,0,167,16,7,23,1,3,132,2,221,0,0,255,255,1,44,0,167,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,7,23,1,3,132,2,221,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,1,44,0,167,16,7,23,1,3,132,2,221,0,0,255,255,3,132,2,221,4,176,6,64,16,39,23,1,3,132,5,20,16,7, + 23,1,3,132,2,221,0,0,255,255,1,44,2,221,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,7,23,1,3,132, + 2,221,0,0,255,255,1,44,2,221,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,7,23,1,3,132,2,221,0,0, + 255,255,1,44,2,221,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,7,23,1,3,132, + 2,221,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,2,221,0,0, + 255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132, + 2,221,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7, + 23,1,3,132,2,221,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,2,221,0,0,255,255,3,132,0,167,4,176,1,211,16,7,23,1,3,132,0,167,0,0, + 255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,4,9,16,39, + 23,1,1,44,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,1,211,16,39,23,1,1,44,0,167,16,7,23,1,3,132,0,167,0,0, + 255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,7,23,1,3,132,0,167,0,0,255,255,1,44, + 0,167,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,7,23,1,3,132,0,167,0,0,255,255,3,132, + 0,167,4,176,6,64,16,39,23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,0,167,0,0,255,255,3,132, + 0,167,4,176,4,9,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,4,9,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,3,132, + 0,167,4,176,6,64,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44, + 0,167,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0, + 255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,0,167,4,176,6,64,16,39, + 23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0, + 255,255,1,44,0,167,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,0,167,0,0,255,255,1,44,254,112,2,88,255,156,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,2,88,6,64,16,39,23,1,1,44,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,2,88,4,9,16,39, + 23,1,1,44,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,2,88,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,2,88,1,211,16,39,23,1,1,44,0,167,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,2,88,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,2,88,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,2,88, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,2,221,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,1,211,16,39,23,1,3,132,0,167,16,7, + 23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,0,167,16,7,23,1,1,44, + 254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44, + 254,112,0,0,255,255,1,44,254,112,4,176,1,211,16,39,23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,7,23,1,1,44, + 254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,7, + 23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,1,44, + 254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44, + 254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7, + 23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132, + 2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7, + 23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44, + 254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39, + 23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7, + 23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7, + 23,1,1,44,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,1,44,254,112,0,0,255,255,3,132, + 254,112,4,176,255,156,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,7,23,1,3,132, + 254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,1,211,16,39, + 23,1,1,44,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44, + 0,167,16,7,23,1,3,132,254,112,0,0,255,255,3,132,254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 5,20,16,7,23,1,3,132,254,112,0,0,255,255,3,132,254,112,4,176,4,9,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 2,221,16,7,23,1,3,132,254,112,0,0,255,255,3,132,254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132, + 254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,7,23,1,3,132,254,112,0,0,255,255,3,132, + 254,112,4,176,1,211,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,1,211,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,3,132, + 254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,3,132,254,112,4,176,4,9,16,39,23,1,3,132,2,221,16,39, + 23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132, + 2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132, + 0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132, + 254,112,0,0,255,255,3,132,254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132, + 0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132, + 254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132, + 0,167,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,255,156,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,1,211,16,39,23,1,1,44,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,1,44, + 254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39,23,1,1,44,254,112,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,1,44, + 254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39, + 23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,3,132,5,20,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,1,44,254,112,16,7,23,1,3,132, + 254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39, + 23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,2,221,16,39,23,1,1,44, + 254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39, + 23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44, + 0,167,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39, + 23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39, + 23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,2,221,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,1,211,16,39, + 23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39, + 23,1,1,44,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132, + 254,112,0,0,255,255,1,44,254,112,4,176,1,211,16,39,23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,0,167,16,39,23,1,1,44, + 254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,39, + 23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,39,23,1,1,44, + 254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176, + 6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,3,132,2,221,16,39, + 23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132, + 2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132, + 0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,4,9,16,39,23,1,1,44,2,221,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132, + 0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39, + 23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0, + 255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,2,221,16,39,23,1,3,132,5,20,16,39,23,1,3,132, + 2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39, + 23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7, + 23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44,5,20,16,39,23,1,1,44,0,167,16,39,23,1,3,132, + 5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44, + 254,112,4,176,6,64,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39, + 23,1,3,132,0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,255,255,1,44,254,112,4,176,6,64,16,39,23,1,1,44, + 5,20,16,39,23,1,1,44,2,221,16,39,23,1,1,44,0,167,16,39,23,1,3,132,5,20,16,39,23,1,3,132,2,221,16,39,23,1,3,132, + 0,167,16,39,23,1,1,44,254,112,16,7,23,1,3,132,254,112,0,0,0,2,0,100,0,204,6,63,4,56,0,13,0,18,0,0,1,33,23,7, + 1,53,1,23,7,33,53,51,17,35,17,53,33,7,23,5,149,252,115,93,120,254,119,1,137,120,93,3,141,170,170,251,251,105,105,1,161,93,120,1, + 137,90,1,137,120,93,205,252,164,1,69,210,105,105,0,0,0,2,0,117,0,204,6,80,4,56,0,13,0,18,0,0,1,33,39,55,1,21,1,39, + 55,33,21,35,17,51,17,21,33,55,39,1,31,3,141,93,120,1,137,254,119,120,93,252,115,170,170,4,5,105,105,3,99,93,120,254,119,90,254,119, + 120,93,205,3,92,254,187,210,105,105,0,0,0,1,1,0,0,0,5,180,5,220,0,17,0,0,9,1,51,1,7,39,17,35,17,39,17,35,17,7, + 17,35,17,7,1,0,2,45,90,2,45,120,92,120,210,120,210,120,92,3,174,2,46,253,210,120,92,252,110,4,10,211,251,35,4,221,211,251,246,3, + 146,92,0,0,0,1,1,0,255,249,5,180,5,213,0,17,0,0,1,55,23,17,51,17,23,17,51,17,55,17,51,17,55,23,1,35,1,0,120,92, + 120,210,120,210,120,92,120,253,211,90,2,39,120,92,3,146,251,246,211,4,221,251,35,211,4,10,252,110,92,120,253,210,0,2,0,79,0,128,5,39, + 6,181,0,30,0,61,0,0,37,34,39,38,39,38,39,38,16,55,54,55,54,55,1,23,7,22,23,22,23,22,23,22,16,7,6,7,6,7,6,3, + 48,23,7,1,6,7,6,7,6,20,23,22,23,30,1,51,50,55,54,55,54,55,54,52,39,38,39,38,39,38,2,189,127,112,107,95,86,49,46,46, + 49,86,98,114,1,137,120,233,96,88,107,95,86,49,46,46,49,86,95,107,112,73,234,120,254,184,88,69,63,35,33,33,39,59,66,162,93,89,81,83, + 64,63,35,33,33,39,59,66,81,57,128,46,45,92,90,110,108,1,0,108,110,90,95,46,1,137,120,233,8,36,45,92,90,110,108,255,0,108,110,90, + 92,45,46,4,41,232,120,1,70,33,70,64,82,78,190,74,86,60,66,66,33,35,64,64,82,78,190,74,86,60,66,33,23,0,0,0,0,2,0,79, + 0,128,5,39,6,181,0,30,0,60,0,0,37,34,39,38,39,38,39,38,16,55,54,55,54,55,54,55,39,55,1,22,23,22,23,22,16,7,6,7, + 6,7,6,3,6,7,6,7,6,7,6,20,23,22,23,22,23,22,51,50,54,55,54,55,54,52,39,38,39,38,39,1,39,2,185,123,112,107,95,86, + 49,46,46,49,86,95,107,88,96,233,120,1,137,114,98,86,49,46,46,49,86,95,107,112,177,63,57,81,66,59,39,33,33,35,63,64,83,81,89,93, + 162,66,59,39,33,33,35,63,69,88,254,184,120,128,46,45,92,90,110,108,1,0,108,110,90,92,45,36,8,233,120,254,119,46,95,90,110,108,255,0, + 108,110,90,92,45,46,4,41,7,23,33,66,60,86,74,190,78,82,64,64,35,33,66,66,60,86,74,190,78,82,64,70,33,254,186,120,0,2,1,0, + 254,178,4,223,6,20,0,16,0,46,0,92,64,18,46,29,32,19,26,17,27,22,6,13,0,39,36,15,37,43,32,47,16,220,178,0,32,1,93,75, + 176,12,84,88,185,0,32,0,64,56,89,60,204,57,57,57,204,50,220,180,15,6,31,6,2,93,220,204,50,57,57,17,57,57,49,0,64,14,15,39, + 169,37,4,26,28,192,37,9,19,17,177,47,16,244,204,50,196,244,204,50,16,236,57,48,1,21,20,22,23,38,53,17,52,55,14,1,29,1,16,7, + 22,1,21,35,34,6,21,17,20,22,59,1,21,33,34,38,61,1,52,38,43,1,53,51,50,54,61,1,52,54,51,2,156,75,176,50,48,176,73,173, + 173,2,67,53,140,85,85,140,53,254,249,249,167,108,142,62,62,142,108,167,249,1,18,239,152,109,7,71,157,4,208,161,66,7,107,152,240,254,238,62, + 68,3,244,100,87,142,251,48,141,88,100,148,221,239,151,116,143,115,149,240,221,147,0,0,0,2,1,0,254,178,4,223,6,20,0,16,0,46,0,87, + 64,18,18,35,46,28,25,2,27,22,32,5,0,10,45,38,46,37,41,47,16,220,75,176,10,84,88,185,0,41,255,192,56,89,204,50,57,57,204,220, + 180,15,0,31,0,2,93,60,220,60,204,57,57,57,17,57,57,49,0,64,14,2,25,169,27,13,38,36,192,27,8,45,17,177,47,16,244,204,50,196, + 244,204,50,16,236,57,48,1,16,55,38,17,53,52,38,39,22,21,17,20,7,62,1,53,1,33,50,22,29,1,20,22,59,1,21,35,34,6,29,1, + 20,6,35,33,53,51,50,54,53,17,52,38,43,1,3,67,173,173,73,176,48,50,176,75,253,189,1,7,249,167,108,142,62,62,142,108,167,249,254,249, + 53,140,85,85,140,53,1,18,1,14,68,62,1,18,240,152,107,7,66,161,251,48,157,71,7,109,152,5,241,147,221,240,149,115,143,116,151,239,221,148, + 100,88,141,4,208,142,87,0,0,4,0,217,254,50,5,219,5,249,0,2,0,6,0,9,0,13,0,0,5,17,9,2,53,1,5,9,1,3,17,1, + 21,5,49,252,170,4,0,250,254,5,2,251,168,3,86,252,170,170,5,2,204,2,100,254,206,253,204,1,225,166,1,225,7,1,50,1,50,252,154,4, + 104,254,31,166,0,3,0,217,0,30,7,39,4,230,0,3,0,6,0,10,0,0,37,35,17,51,1,17,9,2,53,1,7,39,170,170,254,10,252,162, + 4,8,250,254,5,2,30,4,200,252,58,2,196,254,158,253,156,2,17,166,2,17,0,0,0,3,0,217,0,30,7,39,4,230,0,3,0,6,0,10, + 0,0,55,17,51,17,9,2,3,17,1,21,217,170,1,76,3,94,252,162,170,5,2,30,4,200,251,56,1,2,1,98,1,98,252,58,4,200,253,239, + 166,0,0,0,0,2,0,217,255,194,7,39,5,66,0,5,0,8,0,0,23,17,9,1,17,1,55,1,17,217,3,39,3,39,252,217,155,1,226,62, + 5,128,253,176,2,80,250,128,2,78,113,254,162,2,198,0,0,2,0,217,255,194,7,39,5,66,0,5,0,8,0,0,23,17,9,1,17,1,39,1, + 17,217,3,39,3,39,252,217,155,254,30,62,5,128,253,176,2,80,250,128,2,78,113,1,94,253,68,0,0,1,0,217,255,194,7,39,5,66,0,5, + 0,0,23,17,9,1,17,1,217,3,39,3,39,252,217,62,5,128,253,176,2,80,250,128,2,78,0,0,0,1,0,217,255,194,7,39,5,66,0,8, + 0,0,37,21,9,1,17,9,1,21,1,7,39,252,217,252,217,3,39,3,39,253,116,162,224,2,78,253,178,5,128,253,176,2,80,221,254,28,0,0, + 0,1,0,217,255,194,7,39,5,66,0,8,0,0,19,53,9,1,17,9,1,53,1,217,3,39,3,39,252,217,252,217,2,140,4,98,224,253,178,2, + 78,250,128,2,80,253,176,221,1,228,0,0,0,1,0,6,254,35,3,238,6,117,0,3,0,0,9,3,1,250,1,244,254,12,254,12,6,117,251,219, + 251,211,4,45,0,1,0,217,0,0,5,219,5,4,0,19,0,0,1,17,51,17,33,17,51,17,33,21,33,17,35,17,33,17,35,17,33,53,2,12, + 168,1,76,168,1,51,254,205,168,254,180,168,254,205,2,215,2,45,253,211,2,45,253,211,170,253,211,2,45,253,211,2,45,170,0,0,0,1,0,217, + 0,0,5,219,5,4,0,27,0,0,1,17,51,17,51,17,51,17,51,17,51,17,51,21,35,17,35,17,35,17,35,17,35,17,35,17,35,53,1,168, + 168,182,168,182,168,207,207,168,182,168,182,168,207,2,215,2,45,253,211,2,45,253,211,2,45,253,211,170,253,211,2,45,253,211,2,45,253,211,2,45, + 170,0,0,0,0,3,0,58,254,107,7,198,5,251,0,3,0,29,0,55,0,0,1,33,17,33,0,32,7,6,7,6,2,21,20,18,23,22,23,22, + 32,55,54,55,54,18,53,52,2,39,38,39,36,32,4,23,22,23,22,21,20,7,6,7,6,4,32,36,39,38,39,38,53,52,55,54,55,54,3,104, + 1,48,254,208,1,56,254,192,140,137,114,116,114,114,116,114,137,140,1,64,140,137,114,116,114,114,116,114,137,254,13,1,142,1,86,142,142,71,70,70, + 71,142,142,254,170,254,114,254,170,142,142,71,70,70,71,142,142,2,232,254,146,3,200,59,58,114,115,254,236,163,159,254,236,115,114,58,59,59,58,114, + 115,1,20,159,163,1,20,115,114,58,244,144,141,142,172,170,201,197,172,170,142,141,144,144,141,142,170,172,197,201,170,172,142,141,0,0,0,3,0,58, + 254,107,7,198,5,251,0,25,0,51,0,63,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22,32,55,54,55,54,18,53,52,2,39,38,39, + 36,32,4,23,22,23,22,21,20,7,6,7,6,4,32,36,39,38,39,38,53,52,55,54,55,54,5,17,33,21,33,17,35,17,33,53,33,17,4,160, + 254,192,140,137,114,116,114,114,116,114,137,140,1,64,140,137,114,116,114,114,116,114,137,254,13,1,142,1,86,142,142,71,70,70,71,142,142,254,170,254, + 114,254,170,142,142,71,70,70,71,142,128,2,127,2,141,253,115,168,253,115,2,141,5,66,59,58,114,115,254,236,163,159,254,236,115,114,58,59,59,58, + 114,115,1,20,159,163,1,20,115,114,58,244,144,141,142,172,170,201,197,172,170,142,141,144,144,141,142,170,172,197,201,170,172,142,128,75,253,115,170,253, + 115,2,141,170,2,141,0,0,0,3,0,58,254,107,7,198,5,251,0,25,0,51,0,63,0,0,0,32,7,6,7,6,2,21,20,18,23,22,23,22, + 32,55,54,55,54,18,53,52,2,39,38,39,36,32,4,23,22,23,22,21,20,7,6,7,6,4,32,36,39,38,39,38,53,52,55,54,55,54,23,9, + 1,23,9,1,7,9,1,39,9,1,4,160,254,192,140,137,114,116,114,114,116,114,137,140,1,64,140,137,114,116,114,114,116,114,137,254,13,1,142,1, + 86,142,142,71,70,70,71,142,142,254,170,254,114,254,170,142,142,71,70,70,71,142,128,93,1,205,1,206,120,254,51,1,205,119,254,51,254,50,120,1, + 205,254,51,5,66,59,58,114,115,254,236,163,159,254,236,115,114,58,59,59,58,114,115,1,20,159,163,1,20,115,114,58,244,144,141,142,172,170,201,197, + 172,170,142,141,144,144,141,142,170,172,197,201,170,172,142,128,232,254,51,1,205,120,254,50,254,51,119,1,205,254,51,120,1,206,1,205,255,255,0,117, + 254,77,10,37,6,14,16,39,12,176,6,111,0,0,16,38,12,176,0,0,16,39,12,176,2,37,0,0,16,7,12,176,4,74,0,0,0,1,0,117, + 254,77,3,182,6,14,0,29,0,0,5,22,51,50,55,19,33,53,33,19,62,1,50,22,23,7,38,35,34,7,3,33,21,33,3,14,1,34,38,39, + 1,9,17,59,69,8,32,254,238,1,26,25,8,159,152,128,20,148,16,60,69,8,24,1,18,254,230,33,8,159,152,128,20,155,130,175,2,154,170,2, + 12,165,135,122,143,15,130,175,254,13,170,253,77,165,135,122,143,0,0,0,0,1,0,117,254,77,3,182,6,14,0,37,0,0,5,22,51,50,55,19, + 33,53,33,55,33,53,33,19,62,1,50,22,23,7,38,35,34,7,3,33,21,33,7,33,21,33,3,14,1,34,38,39,1,9,17,59,69,8,22,254, + 248,1,16,12,254,228,1,36,15,8,159,152,128,20,148,17,59,69,8,14,1,8,254,240,12,1,28,254,220,23,8,159,152,128,20,155,130,175,1,206, + 170,240,168,1,64,165,135,122,143,15,130,175,254,217,168,240,170,254,25,165,135,122,143,0,0,1,0,117,254,77,3,182,6,14,0,29,0,0,1,38, + 35,34,7,3,37,21,5,3,14,1,34,38,39,55,22,51,50,55,19,5,53,37,19,62,1,50,22,23,3,34,17,59,69,8,26,1,67,254,181,31, + 8,159,152,128,20,148,17,59,69,8,26,254,190,1,74,31,8,159,152,128,20,4,246,130,175,253,231,182,160,186,253,109,165,135,122,143,15,130,175,2, + 25,182,160,186,2,147,165,135,122,143,0,0,0,2,0,117,254,77,3,182,6,14,0,42,0,51,0,0,1,38,35,34,7,3,22,23,7,38,39,3, + 54,55,23,6,7,3,14,1,34,38,39,55,22,51,50,55,19,38,39,38,53,52,55,54,55,19,62,1,50,22,23,1,19,6,7,6,21,20,23,22, + 3,34,17,59,69,8,14,153,73,113,40,80,22,32,21,62,54,68,15,8,159,152,128,20,148,17,59,69,8,15,93,73,110,111,83,117,15,8,159,152, + 128,20,254,1,22,61,44,72,75,37,4,246,130,175,254,214,41,136,65,72,33,254,43,6,17,112,36,9,254,190,165,135,122,143,15,130,175,1,49,24, + 73,111,155,156,115,86,19,1,60,164,136,122,143,252,69,1,214,17,46,74,103,104,72,36,0,1,0,117,254,77,4,45,6,14,0,50,0,0,1,38, + 35,34,7,3,54,55,54,61,1,7,39,55,51,23,7,39,21,20,7,6,7,3,14,1,34,38,39,55,22,51,50,55,19,38,39,38,53,51,20,23, + 22,23,19,62,1,50,23,22,23,3,34,17,59,69,8,43,64,47,86,93,72,189,54,188,72,92,110,85,109,17,8,160,151,128,20,148,17,59,68,9, + 16,91,62,119,102,80,51,44,44,8,160,151,73,54,21,4,246,130,175,252,120,16,47,85,114,30,93,72,189,189,72,93,30,156,108,86,17,254,161,165, + 135,122,143,15,130,175,1,77,25,62,119,154,114,78,51,11,3,153,165,135,70,52,143,0,0,2,0,117,254,77,3,182,6,14,0,3,0,33,0,0, + 1,51,21,35,3,19,33,17,33,19,62,1,50,22,23,7,38,35,34,7,3,33,17,33,3,14,1,34,38,39,55,22,51,50,1,178,211,211,16,17, + 1,119,254,165,20,8,162,151,126,20,148,17,57,70,9,14,1,57,254,161,13,8,169,145,125,20,148,17,57,71,2,166,254,253,234,1,114,2,48,1, + 174,167,133,125,140,15,130,175,254,245,252,188,254,255,173,127,125,140,15,130,0,2,0,117,254,77,3,182,6,14,0,3,0,43,0,0,1,51,21,35, + 19,6,7,19,62,1,50,22,23,7,38,35,34,7,3,22,23,22,16,7,6,7,3,14,1,34,38,39,55,22,51,50,55,19,22,51,50,54,52,38, + 1,178,211,211,99,41,31,22,8,162,151,126,20,148,17,57,71,8,14,99,66,110,110,86,115,15,8,162,151,126,20,148,17,57,70,9,22,40,54,111, + 135,148,2,166,254,1,126,2,5,1,195,167,133,124,141,15,130,175,254,214,24,75,124,254,210,111,85,19,254,190,167,133,125,140,15,130,175,1,182,16, + 147,216,127,0,0,2,0,117,254,77,4,112,6,14,0,3,0,46,0,0,1,51,21,35,1,22,51,50,55,19,22,23,22,50,54,52,38,35,34,7, + 19,62,1,50,22,23,7,38,35,34,7,3,54,51,50,22,16,6,35,34,39,3,14,1,34,38,39,2,143,211,211,254,122,17,59,69,8,27,45,56, + 112,198,150,138,113,213,83,24,6,162,151,128,20,148,17,59,69,8,15,59,68,169,206,220,155,87,73,17,8,160,151,128,20,2,174,254,253,181,130,175, + 2,51,62,28,54,145,209,143,161,2,93,164,136,122,143,15,130,175,254,203,19,233,254,210,219,33,254,163,165,135,122,143,0,3,0,117,254,77,3,182, + 6,14,0,3,0,11,0,49,0,0,1,51,21,35,22,54,52,38,34,6,20,22,3,22,51,50,55,19,38,39,38,16,55,54,55,19,62,1,50,22, + 23,7,38,35,34,7,3,22,23,22,16,7,6,7,3,14,1,34,38,39,1,173,211,211,203,148,138,214,144,143,162,17,59,69,8,15,93,73,110,111, + 83,117,15,8,159,152,128,20,148,17,59,69,8,14,99,66,110,110,86,115,15,8,159,152,128,20,2,176,254,122,144,209,143,145,207,144,254,45,130,175, + 1,49,24,73,111,1,55,115,86,19,1,60,164,136,122,143,15,130,175,254,214,24,75,124,254,210,111,85,19,254,190,165,135,122,143,0,0,3,0,117, + 254,77,3,182,6,14,0,29,0,33,0,37,0,0,55,17,33,19,62,1,50,22,23,7,38,35,34,7,3,33,17,33,3,14,1,34,38,39,55,22, + 51,50,55,27,1,3,51,17,33,35,17,51,152,1,59,16,8,162,151,126,20,148,17,57,71,8,15,1,24,254,196,14,8,169,143,127,20,148,17,57, + 71,8,13,197,24,172,254,197,171,147,155,2,254,1,73,167,133,125,140,15,130,175,254,208,253,2,254,222,173,127,123,142,15,130,175,1,9,2,116,254, + 22,1,234,254,22,0,0,0,0,1,255,190,254,77,4,109,6,14,0,45,0,0,1,38,35,34,7,3,33,50,22,20,6,35,53,54,55,38,39,33, + 3,14,1,34,38,39,55,22,51,50,55,19,33,23,7,1,53,1,23,7,33,19,62,1,50,23,22,23,3,34,17,59,69,8,25,1,14,100,139,144, + 95,96,8,8,96,254,235,33,8,159,152,128,20,148,17,59,68,9,32,254,220,187,96,254,197,1,59,96,187,1,42,27,8,159,152,73,54,21,4,246, + 130,175,253,239,143,198,140,136,4,101,98,6,253,73,165,135,122,143,15,130,175,2,158,186,96,1,58,72,1,58,96,186,2,42,165,135,70,52,143,0, + 0,1,0,117,254,77,3,182,6,14,0,35,0,0,1,38,35,34,7,3,55,23,7,23,7,39,3,14,1,34,38,39,55,22,51,50,55,19,7,39, + 55,39,55,23,19,62,1,50,22,23,3,34,17,59,69,8,20,157,120,252,252,120,177,25,8,159,152,128,20,148,17,59,69,8,23,159,122,254,252,120, + 178,23,8,159,152,128,20,4,246,130,175,254,88,157,121,252,252,120,176,253,244,165,135,122,143,15,130,175,1,226,160,121,252,252,120,179,1,216,165,135, + 122,143,0,0,0,1,0,117,254,77,3,182,6,14,0,42,0,0,5,22,51,50,55,19,6,7,6,21,17,35,17,52,54,55,19,62,1,50,22,23, + 7,38,35,34,7,3,22,23,22,21,17,35,17,52,39,3,14,1,34,38,39,1,9,17,59,69,8,45,65,32,52,121,155,121,14,8,159,152,128,20, + 148,17,59,69,8,13,90,62,86,121,124,45,8,159,152,128,20,155,130,175,3,166,16,50,80,156,254,200,1,73,207,188,17,1,43,165,135,122,143,15, + 130,175,254,230,24,69,97,214,254,183,1,56,243,50,252,74,165,135,122,143,0,1,0,117,254,77,3,182,6,14,0,39,0,0,1,38,35,34,7,3, + 54,25,1,51,17,16,5,3,14,1,34,38,39,55,22,51,50,55,19,38,39,38,53,17,51,17,20,23,19,62,1,50,22,23,3,34,17,59,69,8, + 42,146,121,254,239,17,8,159,152,128,20,148,17,59,69,8,16,92,63,86,121,126,43,8,159,152,128,20,4,246,130,175,252,141,38,1,7,1,56,254, + 183,254,140,39,254,162,165,135,122,143,15,130,175,1,76,23,70,97,214,1,73,254,200,245,49,3,133,165,135,122,143,0,0,2,0,117,254,77,3,192, + 6,249,0,23,0,27,0,0,1,62,1,51,50,22,23,7,38,35,34,7,3,14,1,35,34,38,39,55,22,51,50,55,1,21,33,53,1,227,8,162, + 75,76,126,20,148,17,57,71,8,65,8,162,76,75,126,20,148,17,57,71,8,2,30,252,239,4,226,167,133,125,140,15,130,175,250,176,167,133,125,140, + 15,130,175,7,103,160,160,0,0,2,0,107,253,98,3,182,6,14,0,23,0,27,0,0,1,62,1,51,50,22,23,7,38,35,34,7,3,14,1,35, + 34,38,39,55,22,51,50,55,1,53,33,21,1,227,8,162,75,76,126,20,148,17,57,71,8,65,8,162,76,75,126,20,148,17,57,71,8,254,201,3, + 17,4,226,167,133,125,140,15,130,175,250,176,167,133,125,140,15,130,175,253,208,160,160,0,255,255,1,25,0,63,5,156,4,197,16,6,0,153,0,0, + 255,255,0,217,1,211,5,219,4,106,16,38,12,193,0,0,16,7,13,74,2,20,1,36,255,255,0,217,0,159,5,219,4,106,16,38,12,193,0,0, + 16,39,13,74,0,231,254,87,16,7,13,74,3,64,1,36,0,2,0,217,255,4,5,219,4,166,0,3,0,10,0,0,5,21,1,53,9,2,21,1, + 53,1,5,219,250,254,5,2,251,248,4,8,250,254,5,2,70,182,1,209,182,2,101,254,145,254,147,182,1,209,166,1,209,0,0,0,0,2,0,217, + 255,4,5,219,4,166,0,3,0,10,0,0,23,1,21,1,17,53,1,21,1,53,1,217,5,2,250,254,5,2,250,254,4,8,70,1,209,182,254,47, + 4,236,182,254,47,166,254,47,182,1,109,0,255,255,0,217,255,4,5,221,4,166,16,39,13,74,4,47,255,187,16,6,17,126,0,0,255,255,0,217, + 255,4,5,219,4,166,16,38,13,74,254,187,16,6,17,127,0,0,0,0,255,255,0,217,255,4,5,219,5,39,16,39,13,74,1,15,1,225,16,6, + 17,126,0,0,255,255,0,217,255,4,5,219,5,39,16,39,13,74,3,29,1,225,16,6,17,127,0,0,255,255,0,217,255,4,5,221,6,18,16,39, + 13,74,4,47,2,204,16,6,17,126,0,0,255,255,0,217,255,4,5,219,6,13,16,39,13,74,255,254,2,199,16,6,17,127,0,0,0,3,0,217, + 254,241,5,220,5,78,0,28,0,58,0,65,0,0,37,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,30,1,23,22, + 51,50,54,19,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50,54,19,9,1,21,1,53,1, + 5,220,106,178,98,110,146,10,6,6,16,154,94,88,172,98,104,180,96,110,148,10,12,14,156,94,86,168,104,106,178,98,110,146,10,6,6,16,154,94, + 88,172,98,104,180,96,110,148,10,4,8,14,156,94,86,168,103,252,64,3,192,250,254,5,2,80,179,78,69,59,4,3,2,6,61,76,84,179,78,69, + 59,5,4,6,61,75,1,155,178,80,68,58,4,4,2,6,60,76,82,178,78,68,58,4,2,4,6,60,74,3,94,254,235,254,238,178,1,112,170,1, + 111,0,0,0,0,3,0,217,254,241,5,220,5,78,0,28,0,58,0,65,0,0,37,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62, + 1,51,50,23,30,1,23,22,51,50,54,19,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,51,50, + 54,1,53,1,21,1,53,1,5,220,106,178,98,110,146,10,6,6,16,154,94,88,172,98,104,180,96,110,148,10,12,14,156,94,86,168,104,106,178,98, + 110,146,10,6,6,16,154,94,88,172,98,104,180,96,110,148,10,4,8,14,156,94,86,168,251,101,5,2,250,254,3,192,80,179,78,69,59,4,3,2, + 6,61,76,84,179,78,69,59,5,4,6,61,75,1,155,178,80,68,58,4,4,2,6,60,76,82,178,78,68,58,4,2,4,6,60,74,3,94,176,254, + 145,170,254,144,178,1,18,0,0,2,0,217,255,8,5,219,4,168,0,11,0,18,0,0,1,23,7,33,21,33,7,39,55,33,53,33,9,2,21,1, + 53,1,3,172,150,90,1,243,253,178,133,150,90,254,13,2,78,2,180,252,64,3,192,250,254,5,2,1,162,80,168,170,248,80,168,170,3,78,254,235, + 254,238,178,1,112,170,1,111,0,2,0,217,255,8,5,219,4,168,0,11,0,18,0,0,1,23,7,33,21,33,7,39,55,33,53,33,1,53,1,21, + 1,53,1,3,172,150,90,1,243,253,178,133,150,90,254,13,2,78,253,178,5,2,250,254,3,192,1,162,80,168,170,248,80,168,170,3,78,176,254,145, + 170,254,144,178,1,18,0,0,0,2,0,217,254,95,5,220,5,78,0,54,0,61,0,0,1,21,14,1,35,34,39,7,22,51,50,54,55,21,14,1, + 35,34,47,1,7,39,55,38,35,34,6,7,53,62,1,51,50,23,55,38,35,34,6,7,53,54,55,54,23,22,31,1,55,23,7,22,51,50,54,19, + 9,1,21,1,53,1,5,220,106,178,98,68,83,52,140,87,86,168,104,106,178,98,109,147,8,92,164,89,64,47,88,172,98,104,180,96,69,83,51,139, + 86,88,172,98,104,90,109,77,146,112,7,91,164,89,64,49,86,168,103,252,64,3,192,250,254,5,2,1,150,178,80,68,23,131,52,75,85,179,78,69, + 59,3,233,64,226,16,76,84,179,78,69,23,130,52,76,82,178,78,34,42,8,14,44,3,233,64,227,15,74,3,94,254,235,254,238,178,1,112,170,1, + 111,0,0,0,0,2,0,217,254,95,5,220,5,78,0,53,0,60,0,0,1,21,14,1,35,34,39,7,22,51,50,54,55,21,14,1,35,34,47,1, + 7,39,55,38,35,34,6,7,53,62,1,51,50,23,55,38,35,34,6,7,53,62,1,51,50,31,1,55,23,7,22,51,50,54,1,53,1,21,1,53, + 1,5,220,106,178,98,68,83,52,140,87,86,168,104,106,178,98,109,147,8,92,164,89,64,47,88,172,98,104,180,96,69,83,51,139,86,88,172,98,104, + 180,96,110,148,7,91,164,89,64,49,86,168,251,101,5,2,250,254,3,192,1,150,178,80,68,23,131,52,75,85,179,78,69,59,3,233,64,226,16,76, + 84,179,78,69,23,130,52,76,82,178,78,68,58,3,233,64,227,15,74,3,94,176,254,145,170,254,144,178,1,18,0,0,0,4,0,217,253,132,5,219, + 6,84,0,6,0,10,0,17,0,21,0,0,1,21,1,53,1,21,5,1,33,53,33,1,45,1,53,1,21,9,1,33,53,33,5,219,250,254,5,2, + 252,139,3,117,250,254,5,2,250,254,3,117,252,139,5,2,250,254,5,2,250,254,5,2,3,251,176,1,47,170,1,48,178,210,253,92,170,251,94,213, + 210,178,254,208,170,254,209,3,126,170,0,0,0,4,0,217,253,132,5,219,6,84,0,6,0,10,0,17,0,21,0,0,19,45,1,53,1,21,1,17, + 53,33,21,17,21,1,53,1,21,5,1,53,33,21,217,3,117,252,139,5,2,250,254,5,2,250,254,5,2,252,139,254,115,5,2,3,251,213,210,178, + 254,208,170,254,209,254,225,170,170,252,8,176,1,47,170,1,48,178,210,1,249,170,170,0,0,3,0,217,255,2,5,220,5,78,0,26,0,30,0,37, + 0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,1,33,21,33,9,2,21,1,53,1,5,220, + 106,179,97,110,146,16,6,16,154,94,88,172,98,104,180,96,110,148,14,22,156,94,86,168,251,102,5,2,250,254,5,1,252,64,3,192,250,254,5,2, + 1,150,178,80,68,58,8,2,6,60,75,83,178,78,68,58,6,10,60,74,254,108,170,5,156,254,235,254,238,178,1,112,170,1,111,0,0,3,0,217, + 255,2,5,220,5,78,0,26,0,30,0,37,0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54, + 1,33,21,33,3,53,1,21,1,53,1,5,220,106,179,97,110,146,16,6,16,154,94,88,172,98,104,180,96,110,148,14,22,156,94,86,168,251,102,5, + 2,250,254,1,5,2,250,254,3,192,1,150,178,80,68,58,8,2,6,60,75,83,178,78,68,58,6,10,60,74,254,108,170,5,156,176,254,145,170,254, + 144,178,1,18,0,3,0,217,254,18,5,219,6,12,0,26,0,33,0,40,0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1, + 51,50,31,2,22,51,50,54,19,21,1,53,1,21,5,1,45,1,53,1,21,1,5,219,105,179,97,110,146,17,6,15,155,94,88,172,98,105,179,97, + 110,147,15,22,155,94,86,169,103,250,254,5,2,252,139,254,115,3,117,252,139,5,2,250,254,2,190,178,79,69,59,7,2,6,61,76,83,178,78,69, + 59,6,9,61,75,1,74,176,1,47,170,1,48,178,210,250,58,213,210,178,254,208,170,254,209,0,0,0,0,3,0,217,254,18,5,219,6,12,0,26, + 0,33,0,40,0,0,1,21,14,1,35,34,47,1,38,39,38,35,34,6,7,53,62,1,51,50,31,2,22,51,50,54,1,45,1,53,1,21,9,1, + 21,1,53,1,21,5,5,219,105,179,97,110,146,17,6,15,155,94,88,172,98,105,179,97,110,147,15,22,155,94,86,169,251,101,3,117,252,139,5,2, + 250,254,5,2,250,254,5,2,252,139,2,190,178,79,69,59,7,2,6,61,76,83,178,78,69,59,6,9,61,75,1,74,213,210,178,254,208,170,254,209, + 251,191,176,1,47,170,1,48,178,210,0,0,0,4,0,217,254,44,5,219,5,215,0,6,0,10,0,17,0,21,0,0,19,45,1,53,1,21,1,17, + 53,33,21,17,21,1,53,1,21,5,1,53,33,21,217,3,117,252,139,5,2,250,254,5,2,250,254,5,2,252,139,254,115,5,2,1,37,213,210,178, + 254,208,170,254,209,254,225,170,170,4,40,176,1,47,170,1,48,178,210,249,217,170,170,0,0,4,0,217,254,44,5,219,5,215,0,6,0,10,0,17, + 0,21,0,0,1,21,1,53,1,21,5,1,33,53,33,1,45,1,53,1,21,9,1,33,53,33,5,219,250,254,5,2,252,139,3,117,250,254,5,2, + 250,254,3,117,252,139,5,2,250,254,5,2,250,254,5,2,1,37,176,1,47,170,1,48,178,210,253,92,170,3,126,213,210,178,254,208,170,254,209,251, + 94,170,0,0,0,4,0,217,254,54,5,219,5,238,0,6,0,10,0,17,0,21,0,0,1,21,1,53,1,21,5,9,1,53,9,1,45,1,53,1, + 21,1,17,53,1,21,5,219,250,254,5,2,252,139,3,117,250,254,5,2,250,254,3,117,252,139,5,2,250,254,5,2,3,149,176,1,47,170,1,48, + 178,210,253,86,1,47,176,254,209,253,166,213,210,178,254,208,170,254,209,254,208,176,1,47,176,0,0,0,0,4,0,217,254,54,5,219,5,238,0,6, + 0,10,0,17,0,21,0,0,19,45,1,53,1,21,1,17,53,1,21,17,21,1,53,1,21,5,9,1,53,1,217,3,117,252,139,5,2,250,254,5, + 2,250,254,5,2,252,139,3,117,250,254,5,2,3,149,213,210,178,254,208,170,254,209,254,219,176,1,47,176,253,39,176,1,47,170,1,48,178,210,253, + 75,1,47,176,254,209,0,0,0,2,0,217,255,132,5,219,5,38,0,3,0,10,0,0,9,1,53,1,17,21,1,53,1,21,1,5,219,250,254,5, + 2,250,254,5,2,251,248,4,112,254,47,182,1,209,251,20,182,1,209,166,1,209,182,254,147,0,0,0,0,2,0,217,255,132,5,219,5,38,0,3, + 0,10,0,0,19,53,1,21,9,2,53,1,21,1,217,5,2,250,254,4,8,251,248,5,2,250,254,4,112,182,254,47,182,253,155,1,111,1,109,182, + 254,47,166,254,47,0,0,0,255,255,0,217,255,132,5,221,5,38,16,39,13,74,4,47,254,238,16,6,17,150,0,0,255,255,0,217,255,132,5,219, + 5,38,16,39,13,74,255,254,254,228,16,6,17,151,0,0,0,3,0,218,255,182,5,220,5,123,0,3,0,10,0,14,0,0,19,53,33,21,17,21, + 1,53,1,21,9,1,53,33,21,218,5,2,250,254,5,2,252,64,254,190,5,2,4,209,170,170,251,149,176,1,111,170,1,112,178,254,238,2,57,170, + 170,0,0,0,0,3,0,218,255,182,5,220,5,123,0,3,0,10,0,14,0,0,1,33,53,33,9,2,53,1,21,9,1,33,53,33,5,220,250,254, + 5,2,250,254,3,192,252,64,5,2,250,254,5,2,250,254,5,2,4,209,170,250,235,1,21,1,18,178,254,144,170,254,145,3,254,170,0,3,0,217, + 255,192,5,219,5,205,0,3,0,7,0,14,0,0,19,53,1,21,1,53,1,21,17,21,1,53,1,21,1,217,5,2,250,254,5,2,250,254,5,2, + 252,64,3,171,178,1,112,178,253,78,178,1,112,178,252,151,176,1,111,170,1,112,178,254,238,0,0,0,0,3,0,217,255,192,5,219,5,205,0,3, + 0,7,0,14,0,0,9,1,53,1,17,1,53,9,3,53,1,21,1,5,219,250,254,5,2,250,254,5,2,250,254,3,192,252,64,5,2,250,254,3, + 171,1,112,178,254,144,254,12,1,112,178,254,144,253,85,1,21,1,18,178,254,144,170,254,145,0,0,0,0,2,0,217,0,17,5,220,5,40,0,27, + 0,34,0,0,1,46,1,35,34,7,14,1,7,6,35,34,38,39,53,30,1,51,50,55,62,1,55,54,51,50,22,23,3,21,1,53,1,21,1,5, + 220,104,168,86,94,156,14,12,10,148,110,96,180,104,98,172,88,94,154,16,12,10,146,110,98,178,106,1,250,254,5,2,252,64,3,202,84,76,62,6, + 4,4,60,70,78,178,84,76,62,6,4,4,60,70,78,252,69,176,1,111,170,1,112,178,254,238,0,0,0,2,0,217,0,48,5,220,5,40,0,27, + 0,34,0,0,1,46,1,35,34,7,14,1,7,6,35,34,38,39,53,30,1,51,50,55,62,1,55,54,51,50,22,23,9,2,53,1,21,1,5,220, + 104,168,86,94,156,14,12,10,148,110,96,180,104,98,172,88,94,154,16,12,10,146,110,98,178,106,250,253,3,193,252,63,5,2,250,254,3,202,84,76, + 62,6,4,4,60,70,78,178,84,76,62,6,4,4,60,70,78,252,100,1,21,1,18,178,254,144,170,254,145,0,0,0,0,4,0,217,254,152,5,220, + 5,212,0,3,0,7,0,36,0,43,0,0,23,53,33,21,1,53,33,21,19,46,1,35,34,7,14,1,7,6,35,34,38,39,53,30,1,51,50,55, + 54,55,54,55,54,51,50,22,23,3,21,1,53,1,21,1,217,5,2,250,254,5,2,1,104,168,86,94,156,14,12,10,148,110,96,180,104,98,172,88, + 94,154,16,6,6,10,146,110,98,178,106,1,250,254,5,2,252,64,62,170,170,254,214,170,170,5,220,86,74,60,6,4,6,58,68,78,180,84,76,60, + 6,2,4,4,58,68,78,252,68,176,1,111,170,1,112,178,254,238,0,0,0,4,0,217,254,152,5,220,5,212,0,3,0,7,0,36,0,43,0,0, + 23,53,33,21,1,53,33,21,19,46,1,35,34,7,14,1,7,6,35,34,38,39,53,30,1,51,50,55,54,55,54,55,54,51,50,22,23,9,2,53, + 1,21,1,217,5,2,250,254,5,2,1,104,168,86,94,156,14,12,10,148,110,96,180,104,98,172,88,94,154,16,6,6,10,146,110,98,178,106,250,253, + 3,192,252,64,5,2,250,254,62,170,170,254,214,170,170,5,220,86,74,60,6,4,6,58,68,78,180,84,76,60,6,2,4,4,58,68,78,252,68,1, + 21,1,18,178,254,144,170,254,145,0,0,0,0,3,0,217,0,102,5,219,4,206,0,3,0,32,0,36,0,0,19,33,21,33,1,6,7,6,7,6, + 7,33,53,33,54,55,54,55,54,50,23,22,23,22,23,33,21,33,38,39,38,39,38,1,33,21,33,217,5,2,250,254,2,130,67,46,56,30,27,4, + 254,100,1,10,12,30,54,87,89,206,89,86,55,28,14,1,10,254,101,4,27,30,56,45,253,59,5,2,250,254,2,90,170,2,123,4,30,43,68,68, + 92,168,57,51,91,50,51,51,50,91,48,60,168,91,69,67,44,30,252,233,170,0,0,0,0,2,0,217,255,207,5,219,5,87,0,3,0,14,0,0, + 55,33,21,33,1,0,5,4,1,21,0,37,53,36,1,217,5,2,250,254,5,2,254,129,254,36,1,220,1,127,254,129,252,125,3,131,1,127,121,170, + 4,177,254,229,93,93,254,229,215,1,120,132,166,124,1,128,0,2,0,217,255,207,5,219,5,87,0,3,0,15,0,0,37,21,33,53,17,53,0,5, + 48,21,4,1,53,0,37,36,5,219,250,254,1,127,3,131,252,125,254,129,1,127,1,220,254,36,121,170,170,4,7,215,254,128,124,166,132,254,136,215, + 1,27,93,93,0,2,0,217,254,215,5,219,5,87,0,11,0,22,0,0,1,23,7,33,21,33,7,39,55,33,53,33,1,0,5,4,1,21,0,37, + 53,36,1,3,172,150,90,1,243,253,178,133,150,90,254,13,2,78,2,180,254,129,254,36,1,220,1,127,254,129,252,125,3,131,1,127,1,113,80,168, + 170,248,80,168,170,4,7,254,229,93,93,254,229,215,1,120,132,166,124,1,128,0,0,0,0,2,0,217,254,215,5,219,5,87,0,11,0,22,0,0, + 1,23,7,33,21,33,7,39,55,33,53,33,1,53,0,5,21,4,1,53,0,37,36,3,172,150,90,1,243,253,178,133,150,90,254,13,2,78,253,178, + 1,127,3,131,252,125,254,129,1,127,1,220,254,36,1,113,80,168,170,248,80,168,170,4,7,215,254,128,124,166,132,254,136,215,1,27,93,93,0,0, + 0,3,0,217,255,9,5,219,5,75,0,3,0,7,0,18,0,0,55,53,33,21,1,53,33,21,17,0,5,4,5,21,0,37,53,36,1,217,5,2, + 250,254,5,2,254,205,253,216,2,33,1,58,254,163,252,91,3,165,1,93,51,170,170,254,214,170,170,5,107,254,229,45,81,247,215,1,116,88,166,86, + 1,118,0,0,0,3,0,217,255,9,5,219,5,75,0,3,0,7,0,18,0,0,55,53,33,21,1,53,33,21,1,53,0,5,21,4,1,53,36,37, + 36,217,5,2,250,254,5,2,250,254,1,93,3,165,252,91,254,163,1,58,2,33,253,216,51,170,170,254,214,170,170,5,107,215,254,138,86,166,88,254, + 140,215,247,81,45,0,0,0,0,2,0,217,254,113,5,219,5,75,0,19,0,30,0,0,5,33,53,33,55,33,53,33,55,23,7,33,21,33,7,33, + 21,33,7,39,1,0,5,4,5,21,0,37,53,36,1,2,38,254,179,1,218,96,253,198,2,200,137,138,41,1,80,254,34,95,2,61,253,54,138,138, + 3,222,254,205,253,216,2,33,1,58,254,163,252,91,3,165,1,93,234,170,115,170,164,115,49,170,115,170,165,116,5,143,254,229,45,81,247,215,1,116, + 88,166,86,1,118,0,0,0,0,2,0,217,254,113,5,219,5,75,0,19,0,30,0,0,5,33,53,33,55,33,53,33,55,23,7,33,21,33,7,33, + 21,33,7,39,1,53,0,5,21,4,1,53,36,37,36,2,38,254,179,1,218,96,253,198,2,200,137,138,41,1,80,254,34,95,2,61,253,54,138,138, + 254,220,1,93,3,165,252,91,254,163,1,58,2,33,253,216,234,170,115,170,164,115,49,170,115,170,165,116,5,143,215,254,138,86,166,88,254,140,215,247, + 81,45,0,0,0,3,0,217,254,121,5,219,5,139,0,29,0,58,0,69,0,0,5,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62, + 1,55,54,23,22,23,22,23,22,51,50,54,19,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,62, + 1,19,0,5,4,5,21,0,37,53,36,1,5,219,105,179,97,110,146,10,7,6,15,155,94,88,172,98,105,178,98,96,161,11,5,6,15,155,94,86, + 169,103,105,179,97,110,146,10,7,6,15,155,94,88,172,98,105,179,97,110,147,10,5,7,15,170,158,176,103,254,205,253,216,2,33,1,58,254,163,252, + 91,3,165,1,93,40,179,78,69,59,4,3,2,6,61,76,84,179,78,57,12,6,65,5,2,2,6,61,75,1,154,178,79,69,59,4,3,2,6,61, + 76,83,178,78,69,59,4,2,3,6,67,12,69,3,236,254,229,45,81,247,215,1,116,88,166,86,1,118,0,3,0,217,254,121,5,219,5,139,0,29, + 0,58,0,69,0,0,5,21,14,1,35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,55,54,23,22,23,22,23,22,51,50,54,19,21,14,1, + 35,34,39,38,39,38,39,38,35,34,6,7,53,62,1,51,50,23,22,23,22,23,22,62,1,1,53,0,5,21,4,1,53,36,37,36,5,219,105,179, + 97,110,146,10,7,6,15,155,94,88,172,98,105,178,98,96,161,11,5,6,15,155,94,86,169,103,105,179,97,110,146,10,7,6,15,155,94,88,172,98, + 105,179,97,110,147,10,5,7,15,170,158,176,251,101,1,93,3,165,252,91,254,163,1,58,2,33,253,216,40,179,78,69,59,4,3,2,6,61,76,84, + 179,78,57,12,6,65,5,2,2,6,61,75,1,154,178,79,69,59,4,3,2,6,61,76,83,178,78,69,59,4,2,3,6,67,12,69,3,236,215,254, + 138,86,166,88,254,140,215,247,81,45,0,0,0,2,0,217,253,237,5,220,5,139,0,54,0,65,0,0,1,21,14,1,35,34,39,7,22,51,50,54, + 55,21,14,1,35,34,47,1,7,39,55,38,35,34,6,7,53,62,1,51,50,23,55,38,35,34,6,7,53,54,55,54,23,22,31,1,55,23,7,22, + 51,50,54,19,0,5,4,5,21,0,37,53,36,1,5,220,106,178,98,68,83,52,140,87,86,168,104,106,178,98,109,147,8,92,164,89,64,47,88,172, + 98,104,180,96,69,83,51,139,86,88,172,98,104,90,109,77,146,112,7,91,164,89,64,49,86,168,103,254,205,253,216,2,33,1,58,254,163,252,91,3, + 165,1,93,1,36,178,80,68,23,131,52,75,85,179,78,69,59,3,233,64,226,16,76,84,179,78,69,23,130,52,76,82,178,78,34,42,8,14,44,3, + 233,64,227,15,74,3,230,254,229,45,81,247,215,1,116,88,166,86,1,118,0,2,0,217,253,237,5,220,5,139,0,54,0,65,0,0,1,21,14,1, + 35,34,39,7,22,51,50,54,55,21,14,1,35,34,47,1,7,39,55,38,35,34,6,7,53,62,1,51,50,23,55,38,35,34,6,7,53,54,55,54, + 23,22,31,1,55,23,7,22,51,50,54,1,53,0,5,21,4,1,53,36,37,36,5,220,106,178,98,68,83,52,140,87,86,168,104,106,178,98,109,147, + 8,92,164,89,64,47,88,172,98,104,180,96,69,83,51,139,86,88,172,98,104,90,109,77,146,112,7,91,164,89,64,49,86,168,251,101,1,93,3,165, + 252,91,254,163,1,58,2,33,253,216,1,36,178,80,68,23,131,52,75,85,179,78,69,59,3,233,64,226,16,76,84,179,78,69,23,130,52,76,82,178, + 78,34,42,8,14,44,3,233,64,227,15,74,3,230,215,254,138,86,166,88,254,140,215,247,81,45,0,0,0,3,0,217,254,161,5,219,4,174,0,3, + 0,7,0,14,0,0,55,1,21,1,17,1,21,9,3,21,1,53,1,217,5,2,250,254,5,2,250,254,5,2,252,64,3,192,250,254,5,2,195,254, + 144,178,1,112,1,244,254,144,178,1,112,2,171,254,235,254,238,178,1,112,170,1,111,0,0,3,0,217,254,161,5,219,4,174,0,3,0,7,0,14, + 0,0,37,21,1,53,1,21,1,53,17,53,1,21,1,53,1,5,219,250,254,5,2,250,254,5,2,250,254,3,192,195,178,254,144,178,2,178,178,254, + 144,178,3,105,176,254,145,170,254,144,178,1,18,0,0,0,0,2,0,181,255,201,5,159,4,179,0,6,0,13,0,0,1,23,1,23,1,23,17,19, + 39,9,2,39,33,3,194,93,253,35,191,2,221,92,101,193,253,35,254,180,2,221,194,2,207,4,78,92,253,35,191,2,221,93,1,120,253,150,194,253, + 35,1,76,2,221,193,0,0,0,2,1,32,255,201,6,10,4,179,0,6,0,13,0,0,1,33,17,55,1,55,9,1,17,33,7,9,2,2,253,254, + 136,92,2,221,191,253,35,254,128,2,207,194,2,221,254,180,253,35,4,78,254,136,93,253,35,191,2,221,253,242,2,207,193,253,35,254,180,2,221,0, + 0,2,0,181,0,52,5,159,5,30,0,6,0,13,0,0,1,7,1,7,1,7,33,5,55,9,2,55,17,5,58,92,253,35,191,2,221,93,1,120, + 253,150,194,253,35,1,76,2,221,193,2,17,93,2,221,191,253,35,92,101,193,2,221,1,76,253,35,194,253,49,0,0,0,2,1,32,0,52,6,10, + 5,30,0,6,0,13,0,0,37,39,1,39,1,39,17,3,23,9,2,23,33,2,253,93,2,221,191,253,35,92,101,193,2,221,1,76,253,35,194,253, + 49,153,92,2,221,191,253,35,93,254,136,2,106,194,2,221,254,180,253,35,193,0,0,0,0,2,0,55,0,134,6,80,4,126,0,9,0,19,0,0, + 37,9,1,17,33,17,9,1,17,33,1,21,33,53,9,1,53,33,21,1,2,51,254,4,1,252,2,33,1,252,254,4,253,223,2,133,253,23,254,246, + 1,10,2,233,1,10,134,1,252,1,252,254,239,1,17,254,4,254,4,1,17,1,245,131,131,254,246,254,246,131,131,1,10,0,0,0,0,1,0,55, + 0,134,6,63,4,126,0,6,0,0,37,9,1,17,33,17,33,2,51,254,4,1,252,4,12,251,244,134,1,252,1,252,254,239,254,42,0,1,1,94, + 0,0,5,86,6,8,0,6,0,0,9,2,33,17,33,17,1,94,1,252,1,252,254,239,254,42,4,12,1,252,254,4,251,244,4,12,0,1,1,94, + 255,205,5,86,5,213,0,6,0,0,1,33,17,33,17,33,1,1,94,1,17,1,214,1,17,254,4,1,201,4,12,251,244,254,4,0,0,1,0,181, + 255,201,5,159,4,179,0,6,0,0,1,39,9,2,39,33,5,159,193,253,35,254,180,2,221,194,2,207,1,228,194,253,35,1,76,2,221,193,0,0, + 0,1,1,32,255,201,6,10,4,179,0,6,0,0,1,17,33,7,9,2,1,32,2,207,194,2,221,254,180,253,35,1,228,2,207,193,253,35,254,180, + 2,221,0,0,0,1,0,181,0,52,5,159,5,30,0,6,0,0,37,55,9,2,55,17,2,208,194,253,35,1,76,2,221,193,52,193,2,221,1,76, + 253,35,194,253,49,0,0,0,0,1,1,32,0,52,6,10,5,30,0,6,0,0,1,23,9,2,23,33,1,32,193,2,221,1,76,253,35,194,253,49, + 3,3,194,2,221,254,180,253,35,193,0,0,0,1,0,55,0,134,6,80,4,126,0,9,0,0,37,9,1,17,33,17,9,1,17,33,2,51,254,4, + 1,252,2,33,1,252,254,4,253,223,134,1,252,1,252,254,239,1,17,254,4,254,4,1,17,0,0,0,0,1,1,94,255,205,5,86,6,8,0,9, + 0,0,1,33,9,1,33,17,33,9,1,33,4,69,1,17,254,4,254,4,1,17,254,239,1,252,1,252,254,239,1,201,254,4,1,252,2,67,1,252, + 254,4,0,0,0,1,0,117,255,249,6,82,2,215,0,11,0,0,5,35,1,55,23,17,33,53,33,17,55,23,4,200,90,254,120,120,232,252,47,4, + 123,234,120,7,1,138,120,234,1,28,170,254,58,234,120,0,0,1,0,117,2,45,6,82,5,11,0,11,0,0,9,1,7,39,17,33,53,33,17,7, + 39,1,4,200,1,138,120,234,251,133,3,209,232,120,1,136,5,11,254,118,120,234,254,58,170,1,28,234,120,1,138,0,0,1,0,72,255,249,6,37, + 2,215,0,11,0,0,5,1,55,23,17,33,21,33,17,55,23,1,1,210,254,118,120,234,4,123,252,47,232,120,254,120,7,1,138,120,234,1,198,170, + 254,228,234,120,254,118,0,0,0,1,0,72,2,45,6,37,5,11,0,11,0,0,1,51,1,7,39,17,33,21,33,17,7,39,1,210,90,1,136,120, + 232,3,209,251,133,234,120,5,11,254,118,120,234,254,228,170,1,198,234,120,0,2,0,186,255,4,6,213,5,36,0,3,0,7,0,0,23,17,33,17, + 37,33,17,33,186,6,27,250,87,5,55,250,201,252,6,32,249,224,114,2,158,0,0,0,0,2,0,186,255,4,6,213,5,36,0,3,0,7,0,0, + 23,17,33,17,1,33,17,33,186,6,27,250,87,5,55,250,201,252,6,32,249,224,3,16,2,158,0,0,0,2,0,186,255,4,6,213,5,36,0,2, + 0,6,0,0,5,33,1,3,17,33,17,1,44,5,55,250,201,114,6,27,138,5,60,250,82,6,32,249,224,0,0,0,0,2,0,186,255,4,6,213, + 5,36,0,2,0,6,0,0,5,17,33,3,17,33,17,6,99,250,201,114,6,27,138,5,60,250,82,6,32,249,224,0,0,2,0,6,255,4,6,33, + 5,36,0,2,0,6,0,0,5,9,5,3,19,2,118,253,138,252,243,3,13,3,14,252,242,100,2,120,2,120,253,136,3,16,252,240,252,240,0,0, + 0,2,0,6,255,4,6,33,5,36,0,2,0,6,0,0,19,1,17,9,3,158,2,117,252,243,3,13,3,14,252,242,2,20,253,136,4,240,253,136, + 3,16,252,240,252,240,0,0,0,2,0,6,255,4,6,33,5,36,0,2,0,6,0,0,19,9,1,33,9,2,158,2,117,2,118,250,125,3,13,3, + 14,252,242,2,20,253,136,2,120,3,16,252,240,252,240,0,0,2,0,6,255,4,6,33,5,36,0,2,0,6,0,0,19,33,9,4,158,4,235,253, + 138,252,243,3,13,3,14,252,242,2,20,2,120,253,136,3,16,252,240,252,240,0,0,0,0,12,0,186,255,4,6,213,5,36,0,5,0,9,0,13, + 0,17,0,21,0,27,0,31,0,35,0,41,0,45,0,49,0,55,0,0,5,21,35,53,51,53,19,21,35,53,19,21,35,53,1,21,35,53,35,21, + 35,53,1,21,35,53,35,53,35,21,35,53,35,21,35,53,1,21,51,21,35,53,19,21,35,53,19,21,35,53,19,21,35,21,35,53,6,213,227,113, + 114,114,114,114,254,165,204,234,202,4,77,114,113,234,204,234,202,254,164,114,228,114,114,114,114,228,114,114,22,230,116,114,1,182,204,204,1,180,202,202, + 252,36,116,116,116,116,5,172,230,114,116,116,116,116,116,250,198,114,116,230,1,182,204,204,1,180,202,202,1,208,116,114,230,0,0,0,0,1,0,36, + 255,202,6,208,6,35,0,4,0,0,19,9,2,33,36,3,86,3,86,254,186,251,224,3,182,2,109,253,147,252,20,0,0,2,0,36,255,202,6,208, + 6,35,0,4,0,9,0,0,19,1,33,9,5,33,170,1,19,3,122,1,19,253,48,252,170,3,86,3,86,254,186,251,224,3,139,252,177,3,79,2, + 12,254,31,2,109,253,147,252,20,0,0,0,0,2,0,150,255,70,6,102,5,252,0,5,0,11,0,0,9,2,17,9,1,3,17,9,1,17,1,1, + 8,2,118,2,118,253,138,253,138,114,2,232,2,232,253,24,1,53,254,149,1,107,2,216,1,107,254,149,252,230,3,92,1,173,254,83,252,164,254,83, + 0,1,0,150,255,70,6,102,5,252,0,5,0,0,55,17,9,1,17,1,150,2,232,2,232,253,24,243,3,92,1,173,254,83,252,164,254,83,0,0, + 0,1,0,34,255,185,6,217,5,137,0,5,0,0,5,9,1,33,9,1,1,208,254,82,1,174,3,91,1,174,254,82,71,2,232,2,232,253,24,253, + 24,0,0,0,0,1,0,112,254,0,8,132,6,40,0,11,0,0,22,16,1,36,32,5,0,16,1,4,32,37,112,2,5,1,3,2,4,1,3,2, + 5,253,251,254,253,253,252,254,253,64,4,168,1,42,150,150,254,214,251,88,254,214,150,150,0,1,0,77,255,160,6,167,6,77,0,4,0,0,9,3, + 17,4,58,2,108,253,148,252,20,6,76,252,170,252,170,1,70,4,32,0,0,2,0,77,255,160,6,167,6,77,0,4,0,9,0,0,9,1,17,9, + 5,17,4,14,252,178,3,78,2,12,254,32,2,108,253,148,252,20,5,198,254,238,252,134,254,236,2,208,3,86,252,170,252,170,1,70,4,32,0,0, + 0,1,0,10,0,0,4,106,5,213,0,21,0,0,19,51,17,33,21,33,21,33,21,33,17,33,21,33,17,35,53,51,53,35,53,51,201,202,1,91, + 254,165,1,91,254,165,2,215,252,95,191,191,191,191,5,213,254,7,144,144,144,254,126,170,2,44,144,144,144,0,0,0,0,1,0,10,0,0,2,42, + 6,20,0,19,0,0,1,51,21,35,17,35,17,35,53,51,53,35,53,51,17,51,17,51,21,35,1,121,177,177,184,183,183,183,183,184,177,177,2,188, + 144,253,212,2,44,144,144,144,2,56,253,200,144,0,0,0,0,1,255,215,0,0,4,106,5,213,0,35,0,0,19,51,17,22,23,22,51,50,55,54, + 55,51,14,1,35,34,39,17,33,21,33,17,38,39,38,35,34,7,6,7,35,62,1,51,50,23,201,202,2,1,17,13,38,18,18,2,125,2,102,91, + 20,19,2,215,252,95,6,5,17,13,38,18,18,2,125,2,102,91,25,22,5,213,253,44,1,1,9,37,36,82,134,148,4,254,47,170,3,2,4,3, + 9,37,36,82,134,148,6,0,0,2,0,10,0,0,4,141,5,213,0,16,0,29,0,0,19,33,50,23,22,21,20,7,6,43,1,17,35,17,35,53, + 51,23,21,51,50,54,53,52,38,43,1,21,33,21,201,1,200,251,128,129,129,128,251,254,202,191,191,202,254,141,154,154,141,254,1,91,5,213,113,114, + 219,221,113,113,253,168,3,207,144,144,209,146,135,134,146,208,144,0,0,0,0,2,0,201,254,102,5,84,5,213,0,27,0,36,0,199,64,26,17,14, + 15,11,5,6,3,25,9,0,36,30,22,5,10,33,25,4,25,63,28,10,28,20,4,37,16,252,236,50,252,196,236,17,23,57,17,57,57,57,16,204, + 57,57,49,0,64,38,9,8,7,3,10,6,17,3,4,3,5,17,4,4,3,66,20,11,10,14,149,17,176,4,6,4,0,29,3,4,29,149,9,36, + 149,21,129,4,47,244,236,212,236,18,57,18,57,18,57,16,244,236,17,57,57,48,75,83,88,7,16,5,237,7,16,5,237,17,23,57,89,34,178,64, + 38,1,1,93,64,66,122,27,1,5,0,5,1,5,2,6,3,7,4,21,0,21,1,20,2,22,3,23,4,37,0,37,1,37,2,38,3,39,6,38, + 7,38,8,38,9,32,38,54,1,54,2,70,1,70,2,104,5,117,4,117,5,119,27,136,6,136,7,152,6,152,7,31,93,0,93,1,30,1,23,19, + 35,3,46,1,43,1,17,20,22,59,1,21,35,34,38,25,1,33,32,22,21,20,6,1,17,51,50,54,53,52,38,35,3,141,65,123,62,205,217,191, + 74,139,120,220,110,134,63,77,227,205,1,200,1,0,252,131,253,137,254,146,149,149,146,2,188,22,144,126,254,104,1,127,150,98,253,241,194,150,170,244, + 1,14,5,109,214,216,141,186,2,79,253,238,135,131,131,133,0,4,0,72,255,162,4,156,4,188,0,35,0,40,0,48,0,55,0,0,1,17,35,53, + 14,1,35,34,39,7,39,55,38,53,52,54,59,1,55,38,39,38,35,34,6,7,53,62,1,51,50,23,55,23,7,22,15,1,51,53,52,7,1,22, + 51,50,54,61,1,1,19,6,7,6,21,20,4,45,184,63,188,136,135,92,103,96,110,59,253,251,41,158,11,13,84,151,96,182,84,101,190,90,231,120, + 148,95,168,57,187,53,56,175,254,188,62,99,153,185,253,197,229,99,51,86,2,127,253,129,170,102,97,60,125,78,133,86,123,189,192,191,12,12,69,46, + 46,170,39,39,114,179,79,203,115,43,65,18,24,186,254,120,46,217,180,41,254,226,1,21,12,30,51,123,32,0,0,0,0,1,255,232,255,66,3,18, + 6,147,0,28,0,0,1,17,51,19,51,3,51,21,35,3,21,20,22,59,1,21,35,34,39,38,39,3,35,19,17,35,53,51,17,1,119,49,192,170, + 192,160,209,170,75,115,189,189,213,81,13,10,102,170,214,135,135,5,158,254,194,2,51,253,205,143,254,15,111,137,78,154,80,12,16,254,214,2,114,2, + 29,143,1,62,255,255,0,201,254,191,6,4,5,213,16,6,4,54,0,0,0,1,0,186,254,229,5,28,6,20,0,25,0,0,33,35,17,52,38,35, + 34,6,21,17,35,17,51,17,54,55,54,51,50,23,22,21,17,51,17,35,4,100,184,124,124,149,172,185,185,66,89,90,117,193,99,99,184,184,2,158, + 159,158,190,164,253,135,6,20,253,158,101,50,50,119,120,232,253,245,254,76,0,1,0,201,254,191,5,106,5,213,0,14,0,0,37,51,17,35,17,35, + 1,17,35,17,51,17,1,33,1,4,193,169,197,69,253,51,202,202,2,158,1,4,253,27,170,254,21,1,65,2,207,253,49,5,213,253,137,2,119,253, + 72,0,0,0,0,1,0,186,254,229,4,156,6,20,0,14,0,0,19,51,17,1,51,9,1,51,17,35,17,35,1,17,35,186,185,2,37,235,253,174, + 1,204,159,184,56,253,199,185,6,20,252,105,1,227,253,244,254,69,254,76,1,27,2,35,253,221,0,0,0,1,0,92,254,191,5,232,5,213,0,11, + 0,0,19,33,21,1,33,17,35,17,33,53,1,33,115,4,149,252,80,4,144,201,251,61,3,176,252,103,5,213,154,251,111,254,21,1,65,154,4,145, + 0,1,0,88,254,229,4,147,4,96,0,11,0,0,19,33,21,1,33,17,35,17,33,53,1,33,113,3,106,253,76,3,108,184,252,125,2,180,253,101, + 4,96,168,252,219,254,82,1,27,168,3,37,0,2,0,115,255,227,5,119,5,241,0,16,0,28,0,45,64,24,26,149,0,14,20,149,5,8,140,14, + 145,1,175,3,23,4,0,28,2,17,25,11,16,29,16,252,236,212,236,50,50,49,0,47,236,228,244,196,236,16,196,238,48,1,53,51,17,35,53,14, + 1,35,32,0,17,16,0,33,50,22,1,16,18,51,50,18,17,16,2,35,34,2,4,179,196,196,77,236,165,254,242,254,172,1,84,1,14,165,236,252, + 223,234,204,205,235,235,205,204,234,4,237,232,250,43,231,132,128,1,171,1,92,1,92,1,171,128,253,120,254,227,254,187,1,69,1,29,1,29,1,69, + 254,187,0,0,0,1,0,201,254,102,6,31,5,213,0,20,0,0,19,33,9,1,33,17,16,6,43,1,53,51,50,54,53,17,1,35,1,17,35,201, + 1,45,1,125,1,127,1,45,205,227,77,68,134,110,254,127,203,254,127,196,5,213,252,8,3,248,250,147,254,242,244,170,150,194,4,183,252,0,4,0, + 250,225,0,0,0,2,0,16,0,0,5,104,5,213,0,2,0,10,0,0,37,1,33,1,35,1,51,19,33,19,51,2,188,1,18,253,219,1,133,229, + 253,199,210,136,2,161,136,213,199,2,231,252,82,5,213,254,129,1,127,0,0,2,0,115,255,227,5,119,5,241,0,15,0,24,0,0,37,21,35,17, + 51,21,62,1,51,32,0,16,0,33,34,38,0,16,2,35,34,2,16,18,32,1,55,196,196,77,236,165,1,14,1,84,254,172,254,242,165,236,3,33, + 234,204,205,235,235,1,154,231,232,5,213,231,132,128,254,85,253,72,254,85,128,1,107,2,58,1,69,254,187,253,198,254,187,0,0,0,0,1,0,61, + 0,0,5,224,4,123,0,20,0,0,1,48,1,35,1,51,9,1,54,51,50,22,29,1,35,53,52,38,34,7,6,4,36,254,183,250,254,92,195,1, + 94,1,20,84,222,131,185,178,81,114,41,21,3,109,252,147,4,96,252,84,2,230,225,191,134,114,114,58,84,42,21,0,0,1,0,68,0,0,9,6, + 5,240,0,29,0,0,9,1,35,9,1,35,1,51,9,1,51,9,1,54,55,54,51,50,23,22,29,1,35,53,52,38,35,34,7,6,7,102,254,201, + 254,254,197,254,194,254,254,138,204,1,58,1,57,227,1,58,1,7,18,60,86,137,136,85,85,170,81,46,42,40,28,4,225,251,31,5,16,250,240,5, + 213,251,18,4,238,251,18,4,38,71,64,92,92,91,110,131,121,54,80,40,28,0,0,0,0,1,0,86,0,0,7,177,4,123,0,27,0,0,1,54, + 55,54,51,50,22,29,1,35,53,52,38,34,7,6,7,3,35,11,1,35,1,51,27,1,51,19,5,70,23,57,91,132,131,185,178,81,114,41,24,6, + 229,217,241,242,217,254,219,184,230,229,217,230,3,136,86,61,96,191,134,114,114,58,84,42,25,20,252,147,3,150,252,106,4,96,252,150,3,106,252,150, + 0,2,0,104,0,0,4,127,4,179,0,19,0,27,0,0,19,16,37,54,51,50,21,20,15,1,19,1,51,1,35,3,7,53,54,63,1,54,53,38, + 35,34,21,20,200,1,84,20,18,168,184,127,171,1,94,195,254,92,250,209,168,49,60,165,216,1,45,175,3,77,1,50,49,3,248,153,93,64,254,47, + 3,172,251,160,2,50,85,196,20,28,80,110,52,52,160,37,0,1,0,201,0,0,4,113,5,213,0,7,0,0,1,33,17,35,17,51,17,33,4,113, + 253,34,202,202,2,222,2,199,253,57,5,213,253,156,0,0,0,1,0,193,0,0,3,208,4,96,0,7,0,0,1,33,17,35,17,51,17,33,3,208, + 253,169,184,184,2,87,2,4,253,252,4,96,254,51,0,0,0,2,0,112,255,231,4,209,4,104,0,10,0,39,0,0,1,34,21,17,50,55,54,53, + 52,39,38,39,50,23,22,17,16,7,6,35,7,34,39,38,17,16,55,54,55,21,6,7,6,21,20,23,22,51,17,16,3,61,65,95,95,85,86,70, + 54,139,128,137,137,129,203,183,200,133,136,136,101,167,66,58,86,86,77,112,3,203,145,253,82,104,93,223,208,112,91,157,132,141,254,217,254,241,161,152, + 1,153,156,1,19,1,30,146,109,28,163,23,78,115,190,202,115,103,2,175,1,46,0,0,0,1,0,0,255,229,2,144,6,20,0,23,0,0,33,53, + 6,33,34,47,1,22,51,50,54,53,17,52,38,43,1,53,51,50,23,22,21,17,1,215,114,254,249,37,56,1,60,88,156,167,77,105,231,254,183,79, + 82,174,201,10,189,35,203,190,2,108,153,97,156,96,98,212,251,130,0,0,0,3,0,113,255,227,4,117,4,123,0,7,0,15,0,32,0,0,0,38, + 34,6,20,22,50,54,8,1,32,0,16,0,32,8,1,38,32,6,21,20,23,54,55,54,51,50,23,22,23,54,53,3,22,94,135,93,93,136,93,253, + 91,1,17,1,225,1,18,254,238,254,31,254,239,3,65,172,254,217,172,20,22,55,92,133,136,89,51,23,18,1,97,95,94,135,92,92,2,104,1,56, + 254,200,253,217,254,199,1,57,1,218,233,231,201,96,77,71,56,93,95,50,66,73,91,0,0,1,0,98,0,0,3,51,4,96,0,11,0,0,1,17, + 33,53,33,17,33,53,33,17,33,53,3,51,253,47,2,23,254,13,1,243,253,246,4,96,251,160,147,1,120,148,1,45,148,0,0,0,255,255,255,233, + 255,17,0,238,3,103,18,7,2,116,0,0,253,100,0,0,0,1,0,10,2,156,3,104,5,224,0,6,0,0,9,1,51,9,1,51,1,1,113,254, + 153,133,1,42,1,43,132,254,153,2,156,3,68,253,64,2,192,252,188,0,0,1,0,135,254,16,4,200,5,240,0,58,0,0,1,21,46,1,35,34, + 6,21,20,23,22,31,1,22,23,22,21,20,7,6,7,23,30,1,59,1,21,35,34,46,2,47,1,38,39,38,39,38,39,53,30,1,51,50,54,53, + 52,38,47,1,46,1,53,52,36,51,50,22,4,72,115,204,95,165,179,60,54,171,122,230,103,108,146,115,201,135,124,147,70,24,63,34,78,103,123,60, + 223,49,14,50,39,119,128,123,236,114,173,188,135,154,123,226,202,1,23,245,105,218,5,164,197,55,54,128,118,99,51,46,35,25,47,105,108,182,217,112, + 89,18,119,110,73,170,16,39,79,56,206,45,10,33,7,24,47,208,69,70,136,126,110,124,31,24,45,192,171,198,228,38,0,1,0,92,254,16,5,31, + 5,213,0,24,0,0,1,51,21,35,34,46,2,39,37,38,43,1,53,1,33,53,33,21,1,22,31,1,30,1,4,179,108,147,39,89,118,140,69,254, + 211,78,113,125,3,176,252,103,4,149,252,85,114,117,252,136,159,254,186,170,16,39,79,56,243,63,154,4,145,170,154,251,111,13,95,205,110,73,0,0, + 0,1,0,123,255,126,4,91,4,96,0,31,0,0,1,35,55,54,35,34,5,3,6,51,50,54,51,50,3,7,35,55,54,35,14,1,35,34,27,1, + 51,7,36,51,50,7,4,56,192,19,25,106,144,254,214,69,27,115,128,220,90,183,43,18,191,18,19,52,89,245,150,192,42,116,191,24,1,122,146,210, + 25,2,173,129,172,172,254,4,174,154,254,226,130,130,132,1,131,1,49,3,47,177,177,177,0,1,0,50,254,30,4,114,4,95,0,32,0,0,1,6, + 22,7,6,4,35,32,36,55,51,6,22,51,62,1,55,54,38,55,4,35,34,55,19,51,3,6,51,22,37,19,51,3,250,15,104,26,27,254,244,210, + 254,255,254,221,22,186,11,147,217,107,192,25,19,106,8,254,119,148,211,25,152,188,132,24,114,157,1,16,113,191,1,45,120,209,158,135,161,171,150,68, + 124,1,72,118,96,211,81,176,175,3,126,253,5,174,2,176,2,251,0,0,0,1,0,80,254,30,4,72,4,95,0,35,0,0,1,6,22,21,20,4, + 35,34,36,39,53,51,21,30,1,51,50,54,53,52,38,55,19,54,35,34,7,3,35,19,51,7,36,51,50,7,3,168,31,191,254,190,210,176,254,216, + 12,187,7,159,148,149,183,199,36,90,25,104,145,252,57,190,100,189,23,1,82,143,212,24,1,153,141,182,176,189,203,159,172,89,80,91,121,129,131,132, + 232,184,1,102,174,174,253,227,3,80,176,176,176,0,0,0,0,2,0,127,255,235,4,148,6,117,0,9,0,46,0,0,1,54,7,4,7,3,6,51, + 32,63,1,6,7,6,35,32,27,1,54,37,19,14,1,35,34,63,1,51,7,6,51,50,55,54,51,50,29,1,35,53,38,15,1,19,55,36,3,3, + 170,27,249,254,212,39,69,27,158,1,139,32,194,24,219,219,172,254,156,57,57,32,1,133,4,90,133,46,164,2,10,196,10,10,73,66,202,209,97,161, + 117,2,121,164,7,104,1,36,52,3,81,180,24,32,202,254,40,188,215,12,160,100,99,1,142,1,127,225,90,1,101,20,21,126,136,80,65,52,53,71, + 120,61,37,19,39,254,148,9,27,254,131,0,0,1,0,105,254,30,4,75,4,95,0,17,0,0,1,35,3,19,54,35,34,5,3,35,19,51,7,36, + 51,50,7,3,4,52,209,82,104,25,105,135,254,209,70,196,117,191,25,1,126,143,210,24,117,254,30,2,102,2,168,174,174,253,131,3,176,176,176,176, + 252,213,0,0,0,1,0,80,254,29,6,229,4,95,0,28,0,0,1,35,3,19,54,35,34,5,3,35,19,51,7,36,51,50,7,36,51,50,7,3, + 35,19,54,35,34,5,3,4,18,203,85,108,25,104,146,254,226,81,190,116,192,20,1,120,141,202,23,1,108,147,213,23,158,193,137,25,111,145,254,236, + 107,254,29,2,103,2,168,174,174,252,212,4,95,176,176,176,176,176,252,81,3,44,174,174,253,88,0,0,0,2,0,0,255,239,4,154,6,135,0,11, + 0,36,0,0,1,54,35,34,5,3,6,55,50,55,54,55,23,6,5,4,35,34,55,27,1,35,34,39,53,51,21,22,59,1,55,51,3,36,51,50, + 7,3,201,25,105,144,254,217,79,21,95,212,123,107,20,191,39,254,205,254,248,136,211,24,106,104,182,176,17,198,9,106,87,15,176,122,1,123,144,211, + 25,3,43,174,174,253,206,134,1,56,66,126,3,247,66,65,175,2,214,1,68,230,233,253,107,54,254,89,177,177,0,0,0,2,0,108,0,0,7,52, + 4,95,0,9,0,34,0,0,1,54,35,34,5,3,6,51,22,37,1,36,51,50,7,3,35,19,54,35,34,5,3,35,55,4,35,34,55,19,51,7, + 36,51,50,3,169,28,101,143,254,187,82,26,114,141,1,59,1,39,1,105,142,212,24,155,190,135,24,104,144,254,236,130,184,30,254,123,171,218,36,144, + 191,27,1,153,143,214,3,44,174,178,254,10,174,2,176,2,125,176,176,252,81,3,44,174,174,252,212,200,200,175,3,176,180,180,0,0,0,1,0,142, + 0,0,4,87,4,95,0,15,0,0,33,35,19,54,35,34,5,3,35,19,51,7,36,51,50,7,3,190,191,136,25,104,147,254,220,53,190,94,192,23, + 1,129,137,216,32,3,44,174,174,254,145,2,162,176,176,192,0,2,0,104,254,30,4,115,6,135,0,9,0,26,0,0,1,54,35,34,5,3,6,51, + 50,37,23,19,35,3,4,35,34,55,19,3,51,19,7,36,51,50,7,3,161,31,111,144,254,199,78,24,113,175,1,22,170,109,205,93,254,138,172,211, + 24,144,73,211,52,29,1,146,141,211,24,3,44,174,174,253,245,174,191,157,253,137,2,145,192,175,3,227,2,6,253,239,199,176,176,0,0,2,0,80, + 0,0,7,57,4,95,0,9,0,34,0,0,1,54,35,34,5,3,6,51,50,37,19,35,55,4,35,34,55,19,54,35,6,5,3,35,19,51,7,36, + 51,50,7,36,51,54,7,6,101,25,111,130,254,180,78,26,109,136,1,73,144,193,28,254,121,187,183,24,91,25,102,121,254,184,95,191,136,193,25,1, + 144,142,200,23,1,150,176,194,30,3,44,174,157,253,245,174,174,254,206,191,191,175,2,125,174,2,172,252,212,4,95,176,176,179,179,1,177,0,0,0, + 0,2,0,109,255,239,4,195,6,135,0,9,0,41,0,0,1,4,7,3,6,51,50,55,54,55,1,3,6,7,6,7,36,55,19,54,37,3,38,35, + 34,6,35,34,61,1,51,21,20,51,50,54,51,50,23,19,51,21,3,162,253,239,20,69,29,182,115,121,120,13,1,31,99,24,192,187,210,254,183,29, + 86,25,2,207,38,20,74,93,213,122,129,195,55,83,178,114,172,35,49,88,3,219,45,131,254,27,245,59,61,109,2,164,253,59,160,64,64,6,6,251, + 2,93,166,107,1,1,114,129,149,162,119,63,124,192,254,211,134,0,0,0,0,1,0,80,0,0,4,91,6,135,0,27,0,0,33,35,19,54,35,34, + 5,3,35,19,39,16,33,32,23,21,35,53,38,35,34,21,19,7,36,51,54,7,3,182,192,147,24,105,144,254,218,115,191,153,34,1,160,1,133,2, + 188,2,173,254,32,17,1,126,142,219,32,3,44,174,174,252,212,4,56,211,1,124,161,123,97,65,163,254,185,116,176,1,177,0,0,0,0,1,0,104, + 0,0,7,25,4,95,0,26,0,0,37,4,35,34,55,19,51,3,6,51,50,37,19,51,3,6,51,50,37,19,51,3,35,55,4,35,34,3,44,254, + 146,156,210,24,166,190,147,26,114,157,1,7,135,192,138,21,92,157,1,26,105,192,147,193,25,254,128,138,190,175,175,175,3,176,252,211,174,174,3,45, + 252,211,174,174,3,45,251,161,175,175,0,0,0,1,0,104,0,0,4,114,4,95,0,15,0,0,37,4,35,34,55,19,51,3,6,51,50,37,19,51, + 3,35,3,44,254,146,156,210,24,154,192,137,26,114,157,1,17,115,192,156,194,175,175,175,3,176,252,211,174,174,3,45,251,161,0,0,0,1,0,142, + 254,30,6,35,6,135,0,30,0,0,1,35,3,55,4,35,34,55,19,4,35,34,55,19,51,3,6,51,50,55,51,3,6,51,50,37,19,3,51,19, + 3,6,2,210,76,15,254,189,144,202,28,66,254,236,127,169,22,92,206,78,30,116,50,214,190,81,13,66,127,1,23,105,122,204,104,127,254,30,2,24, + 78,132,193,1,186,136,151,1,215,254,186,143,115,253,227,94,121,2,220,2,174,253,39,252,142,0,0,0,0,1,0,104,0,0,7,11,6,135,0,29, + 0,0,1,19,3,51,19,7,36,51,50,7,3,35,19,54,35,34,5,3,35,55,4,35,34,55,19,51,3,6,51,50,3,53,109,84,205,64,12,1, + 114,141,213,24,156,190,135,24,104,144,254,230,115,192,23,254,156,156,210,24,152,195,138,26,114,157,1,50,3,0,2,85,253,161,121,176,176,252,81,3, + 44,174,174,252,212,175,175,175,3,176,252,211,174,0,0,0,0,1,0,104,0,0,4,93,6,135,0,17,0,0,19,3,51,19,3,6,51,50,37,19, + 51,3,35,55,4,35,34,55,237,77,220,55,112,26,104,157,1,7,94,202,136,202,23,254,156,156,210,24,4,97,2,38,253,215,252,212,174,174,3,45, + 251,161,175,175,175,0,0,0,0,2,0,102,254,30,4,74,4,95,0,7,0,28,0,0,1,54,35,34,5,3,36,55,23,6,5,6,22,51,50,55, + 23,6,33,32,2,27,1,51,7,36,51,54,3,3,136,27,106,143,254,217,101,1,252,23,188,33,253,68,27,117,152,142,206,99,194,254,224,254,250,165, + 50,138,189,21,1,120,145,214,45,3,43,174,174,253,57,75,158,27,236,70,155,198,186,133,182,1,70,1,52,3,199,177,177,1,254,203,0,1,0,104, + 254,30,7,19,5,74,0,29,0,0,37,4,35,34,55,4,35,34,55,19,51,3,6,51,50,37,19,51,3,6,51,50,37,19,39,51,19,3,19,35, + 5,222,254,128,138,200,22,254,156,156,210,24,164,192,147,26,114,157,1,7,135,192,138,21,92,157,1,26,104,36,203,20,120,109,208,175,175,175,175,175, + 3,176,252,211,174,174,3,45,252,211,174,174,3,44,236,254,231,252,105,253,132,0,0,0,0,3,0,123,254,30,7,34,4,95,0,9,0,19,0,45, + 0,0,1,54,7,38,5,3,6,51,50,37,1,54,35,6,5,3,6,23,50,37,19,35,55,4,35,39,7,19,35,3,55,4,33,34,27,1,51,7, + 36,51,50,7,36,51,50,3,3,157,14,111,158,254,231,71,26,112,175,1,10,3,21,25,125,89,254,175,72,24,141,149,1,3,149,183,26,254,214,150, + 116,9,85,206,64,26,254,253,254,241,212,44,116,191,24,1,83,212,192,24,1,80,215,195,45,3,109,110,2,1,176,254,7,173,174,1,250,175,1,175, + 254,6,174,1,175,254,207,175,175,45,59,254,44,1,204,197,175,1,49,3,46,177,177,177,177,254,205,0,0,1,0,100,254,30,6,69,6,135,0,23, + 0,0,37,19,35,3,19,5,7,35,19,51,3,37,19,3,51,19,3,37,55,51,3,35,19,5,3,109,103,206,81,54,254,90,29,196,123,199,79,1, + 166,66,85,194,69,51,1,160,28,203,123,204,80,254,92,111,253,175,2,82,1,132,123,237,3,111,253,248,134,1,187,2,83,253,123,254,171,120,192,252, + 159,2,28,126,0,1,0,80,0,0,4,92,4,95,0,15,0,0,1,36,51,50,7,3,35,19,54,35,34,5,3,35,19,51,1,150,1,123,142,213, + 24,155,201,135,24,94,144,254,217,113,193,158,191,3,175,176,176,252,81,3,44,174,174,252,212,4,95,0,0,1,0,104,254,30,4,114,4,96,0,16, + 0,0,37,4,35,34,55,19,51,3,6,51,50,55,19,51,3,19,35,3,14,254,175,155,210,24,148,190,129,26,114,157,243,136,201,156,131,218,175,175, + 175,3,176,252,211,174,174,3,46,252,64,253,126,0,0,0,0,1,0,104,254,30,4,104,4,95,0,22,0,0,37,4,35,34,55,19,51,3,6,51, + 50,37,19,51,3,2,0,33,35,53,51,50,36,3,31,254,156,153,210,24,152,194,137,26,114,157,1,17,105,192,114,59,254,46,254,219,85,73,231,1, + 89,165,165,175,3,176,252,211,174,174,3,45,252,145,254,87,254,215,139,223,0,1,0,80,254,30,4,84,6,135,0,19,0,0,1,3,19,35,3,19, + 3,51,19,7,36,51,50,7,3,35,19,54,35,34,1,124,106,99,218,75,151,74,196,61,15,1,123,141,213,24,139,189,116,24,104,144,3,44,253,26, + 253,216,2,21,4,56,2,28,253,179,139,176,176,252,81,3,44,174,0,0,0,1,0,86,254,30,4,65,4,96,0,25,0,0,1,50,55,23,6,35, + 6,0,55,19,51,7,36,51,50,11,1,35,19,54,35,34,5,3,6,22,2,91,119,203,88,208,218,251,254,226,36,146,189,27,1,40,230,212,43,130, + 190,126,25,163,115,254,247,101,30,161,254,157,173,122,178,2,1,51,246,4,27,177,176,254,205,253,26,2,230,174,174,253,25,206,218,0,0,2,0,122, + 255,238,4,197,6,135,0,7,0,21,0,0,1,4,7,3,6,51,32,55,1,35,3,2,5,32,27,1,18,37,3,51,19,51,3,150,253,252,24,67, + 31,205,1,56,25,1,143,105,100,44,253,219,254,169,42,62,39,2,194,106,210,75,112,3,240,39,181,254,50,214,178,2,183,253,92,254,230,45,1,88, + 1,186,1,27,67,2,41,253,217,0,0,0,0,1,0,80,254,30,6,246,4,96,0,28,0,0,33,19,54,35,34,5,3,19,35,3,19,51,7,36, + 51,50,7,36,51,50,7,3,35,19,54,35,34,5,3,2,244,115,27,95,145,254,224,96,92,218,68,136,192,20,1,117,144,201,22,1,105,150,209,22, + 155,194,137,27,113,144,254,235,116,3,44,174,174,252,245,253,253,1,226,4,96,177,177,177,177,177,252,81,3,44,174,174,252,212,0,0,0,1,0,60, + 254,30,4,92,4,95,0,32,0,0,1,35,19,54,35,34,5,3,54,23,32,17,16,37,6,39,55,22,51,32,17,38,33,34,7,35,19,51,7,36, + 23,54,3,4,34,192,41,21,103,144,254,220,93,234,151,1,179,253,180,233,235,30,221,229,1,160,7,254,216,179,197,197,157,198,29,1,44,223,208,42, + 2,35,1,8,174,177,253,151,115,1,254,141,254,94,2,1,81,190,122,1,20,223,110,4,40,177,178,1,1,254,203,0,0,1,0,96,254,30,4,97, + 4,95,0,14,0,0,1,4,27,1,51,3,32,55,19,51,3,2,5,2,33,2,200,253,56,96,148,190,139,2,5,33,84,192,94,36,253,57,55,1, + 231,254,30,1,2,67,3,255,252,37,240,2,235,252,211,254,255,29,254,139,0,1,0,70,254,30,4,96,4,137,0,30,0,0,1,22,23,36,19,4, + 35,32,47,1,51,23,22,51,32,55,51,2,1,22,23,7,36,39,6,19,35,18,37,38,39,1,82,36,119,1,173,1,254,203,242,254,232,16,6,216, + 8,6,161,1,97,145,161,21,253,245,214,176,59,254,255,185,203,34,194,2,1,20,155,44,2,131,171,216,220,1,210,100,237,82,109,81,148,253,114,254, + 190,174,60,137,122,176,190,254,150,1,215,191,203,248,0,0,0,1,0,80,0,0,7,0,4,95,0,27,0,0,33,35,55,4,35,34,27,1,54,35, + 34,5,3,35,19,51,7,36,51,50,7,3,6,51,50,37,19,51,6,120,194,24,254,150,159,202,44,73,23,107,131,254,224,102,195,142,191,22,1,32, + 228,208,25,90,24,103,105,1,67,94,191,175,175,1,50,1,249,174,174,252,214,4,94,177,177,177,253,132,174,174,3,45,0,1,0,100,254,30,4,91, + 6,135,0,23,0,0,1,54,35,34,5,3,1,35,1,19,18,33,51,21,35,34,7,3,36,55,22,7,3,35,3,136,27,105,124,254,198,93,2,2, + 246,254,49,179,42,1,112,174,234,145,27,50,1,120,154,203,25,94,192,3,44,174,170,253,127,253,111,2,102,4,192,1,67,138,185,254,120,163,1,2, + 175,253,224,0,0,1,0,122,0,0,4,78,5,2,0,24,0,0,1,2,33,32,27,1,51,3,6,51,32,55,19,54,4,55,53,51,21,6,55,54, + 51,50,7,3,255,44,253,172,254,209,42,35,203,38,26,197,1,56,27,79,22,253,124,1,208,2,134,133,134,241,36,1,50,254,206,1,50,1,8,254, + 247,173,185,2,50,154,194,231,212,164,118,59,60,252,0,0,0,1,0,124,254,30,4,109,6,135,0,19,0,0,37,19,35,3,55,4,35,34,27,1, + 51,3,6,51,22,37,19,3,51,19,3,227,110,220,79,2,254,144,155,205,44,138,190,140,23,135,104,1,42,115,78,211,59,132,253,154,2,37,108,175, + 1,49,3,46,252,210,173,2,175,3,33,2,53,253,205,0,0,1,0,104,254,30,4,210,4,95,0,19,0,0,37,35,55,7,19,35,3,6,35,34, + 55,19,51,3,6,51,50,37,19,51,4,69,189,8,212,109,203,74,197,64,191,24,144,194,134,20,143,127,1,114,111,195,70,95,69,253,190,2,21,51, + 175,3,176,252,180,143,153,3,66,0,0,0,0,2,0,122,255,239,6,187,6,136,0,7,0,37,0,0,1,4,7,3,6,51,32,55,5,35,19,54, + 7,5,3,2,33,32,27,1,54,37,17,2,33,4,23,21,35,53,38,7,34,23,17,37,32,3,3,149,253,254,26,66,24,171,1,71,28,3,23,189, + 115,28,101,254,159,102,41,253,185,254,214,42,73,28,2,196,2,1,141,1,87,1,202,1,169,192,2,1,94,1,51,42,3,217,43,189,254,48,178,178, + 179,2,189,202,9,21,253,74,254,206,1,50,2,25,193,57,1,82,1,2,2,190,77,63,91,1,150,254,186,39,254,224,0,2,0,113,255,227,4,187, + 3,11,0,11,0,23,0,36,64,10,25,69,9,18,15,3,18,21,69,24,16,252,236,212,236,236,49,0,64,8,0,185,12,6,185,18,140,24,16,244, + 236,212,236,48,1,34,6,21,20,22,51,50,54,53,52,38,39,50,4,21,20,4,35,34,36,53,52,36,2,150,153,183,183,153,153,183,183,153,249,1, + 44,254,212,249,249,254,212,1,44,2,103,125,115,115,125,125,115,115,125,164,211,193,193,211,211,193,193,211,0,3,0,115,255,227,6,167,5,240,0,19, + 0,31,0,43,0,50,64,13,45,16,33,20,25,10,145,32,21,25,0,16,44,16,252,236,50,244,236,50,236,49,0,64,14,21,149,32,173,26,149,15, + 38,149,5,145,15,140,44,16,228,244,236,16,236,244,236,48,19,52,18,54,36,51,50,4,22,18,21,20,2,6,4,35,34,36,38,2,37,33,22,23, + 30,1,51,50,55,54,55,54,37,33,38,39,46,1,35,34,7,6,7,6,115,126,212,1,38,162,162,1,38,212,126,126,212,254,218,162,162,254,218,212, + 126,5,89,251,129,27,138,78,214,119,119,107,216,93,30,251,140,4,126,26,138,78,214,119,119,107,216,93,30,2,234,157,1,30,209,122,122,209,254,226, + 157,158,254,226,209,122,122,209,1,30,73,202,145,83,96,48,97,228,74,249,201,146,82,96,48,97,229,73,0,5,0,115,255,227,6,167,5,240,0,19, + 0,24,0,29,0,34,0,39,0,73,64,21,26,34,149,24,36,36,30,35,41,16,30,25,25,10,145,35,20,25,0,16,40,16,252,236,50,244,236,50, + 236,17,18,57,47,60,236,50,49,0,64,18,26,20,149,34,35,173,27,23,149,15,33,37,149,5,145,15,140,40,16,228,244,236,50,16,236,50,244,60, + 236,50,48,19,52,18,54,36,51,50,4,22,18,21,20,2,6,4,35,34,36,38,2,55,22,0,23,17,41,1,17,54,0,19,38,0,39,17,41,1, + 17,6,0,115,126,212,1,38,162,162,1,38,212,126,126,212,254,218,162,162,254,218,212,126,219,26,1,11,181,2,164,254,38,181,1,11,26,26,254,245, + 181,253,92,1,218,181,254,245,2,234,157,1,30,209,122,122,209,254,226,157,158,254,226,209,122,122,209,1,30,73,201,254,230,33,2,4,253,251,33,1, + 26,1,116,201,1,26,33,253,252,2,4,33,254,230,0,0,0,2,0,64,0,0,5,53,5,213,0,10,0,13,0,99,64,13,3,0,12,149,1,129, + 6,9,3,5,0,9,14,16,220,196,212,196,49,0,47,60,244,236,57,57,48,64,21,13,17,0,6,0,6,17,5,13,5,12,17,3,8,3,8,17, + 9,10,9,66,75,83,88,7,16,1,237,7,16,1,237,7,16,1,237,7,16,1,237,64,20,11,9,12,13,5,10,9,12,0,6,7,0,6,8,3, + 4,3,8,13,5,15,15,15,15,89,34,19,53,33,21,9,1,35,9,1,35,1,55,1,33,118,4,149,254,40,2,2,240,254,118,254,117,240,2,2, + 121,1,84,253,87,5,43,170,154,253,127,253,70,2,23,253,233,2,186,163,1,206,0,0,0,2,0,67,0,0,5,56,5,213,0,10,0,13,0,99, + 64,13,3,0,12,149,7,5,129,2,0,7,3,5,14,16,220,196,212,196,49,0,47,228,50,236,57,57,48,64,21,13,17,0,6,0,6,17,5,13, + 5,12,17,3,8,3,8,17,9,10,9,66,75,83,88,7,16,1,237,7,16,1,237,7,16,1,237,7,16,1,237,64,20,11,9,12,13,5,10,9, + 12,0,6,7,0,6,8,3,4,3,8,13,5,15,15,15,15,89,34,37,21,33,53,9,1,51,9,1,51,1,7,1,33,5,14,251,107,1,204,253, + 254,240,1,139,1,138,240,253,254,120,254,171,2,169,154,154,170,2,113,2,186,253,233,2,23,253,70,163,254,50,0,0,0,3,0,64,0,0,4,213, + 5,213,0,2,0,5,0,15,0,106,64,17,12,15,1,149,13,129,10,7,3,149,9,17,15,7,10,12,16,16,220,60,212,60,204,49,0,47,236,57, + 57,244,236,57,57,48,64,21,0,17,15,3,15,1,17,12,4,12,4,17,7,1,7,3,17,10,0,10,66,75,83,88,7,16,1,237,7,16,1,237, + 7,16,1,237,7,16,1,237,64,20,2,1,7,10,0,6,1,7,15,3,5,3,15,4,12,11,12,4,10,0,15,15,15,15,89,34,1,33,9,1, + 33,1,55,1,21,33,53,9,1,53,33,21,3,217,253,87,1,88,254,180,2,169,254,168,119,1,209,251,107,1,209,254,47,4,149,5,43,254,87,253, + 40,1,169,150,253,193,170,160,2,76,2,63,170,160,0,0,0,3,0,150,0,0,3,232,5,213,0,3,0,7,0,11,0,35,64,17,3,7,0,8, + 4,145,11,1,28,0,9,28,8,5,28,4,12,16,220,252,220,252,220,236,49,0,47,244,60,60,204,50,48,1,51,21,35,1,51,21,35,1,51,17, + 35,3,28,204,204,253,122,204,204,1,68,202,202,5,213,255,0,255,255,0,255,250,43,0,255,255,0,16,0,0,5,104,5,213,16,6,3,48,0,0, + 255,255,0,16,0,0,5,104,5,213,16,6,0,57,0,0,255,255,0,201,0,0,4,139,5,213,16,6,0,40,0,0,255,255,0,131,0,0,4,69, + 5,213,16,6,1,80,0,0,0,5,0,150,255,227,4,224,5,240,0,11,0,23,0,35,0,47,0,51,0,72,64,16,53,69,49,3,27,18,21,45, + 48,9,33,18,15,39,69,52,16,252,60,236,50,196,212,60,236,50,196,236,49,0,64,22,51,185,48,48,42,12,0,185,12,6,185,18,145,52,30,185, + 42,24,185,36,140,52,16,244,236,212,236,16,244,236,212,236,17,18,57,47,236,48,1,50,54,53,52,38,35,34,6,21,20,22,23,34,36,53,52,36, + 51,50,4,21,20,4,3,50,54,53,52,38,35,34,6,21,20,22,23,34,36,53,52,36,51,50,4,21,20,4,1,33,21,33,2,187,153,185,185,153, + 153,185,185,153,249,254,212,1,44,249,249,1,44,254,212,249,153,185,185,153,153,185,185,153,249,254,212,1,44,249,249,1,44,254,212,253,55,3,160,252, + 96,4,115,57,52,52,56,56,52,52,57,164,142,131,130,142,142,130,131,142,252,184,57,52,52,56,56,52,52,57,164,142,131,130,142,142,130,131,142,3, + 92,170,0,0,0,1,0,219,0,0,6,125,5,213,0,19,0,58,64,13,5,9,12,3,28,7,13,2,28,0,16,18,20,16,220,204,50,236,50,220, + 236,50,204,50,49,0,64,16,7,18,149,0,13,149,2,173,0,4,145,17,8,149,11,15,47,60,236,50,228,50,244,236,16,236,50,48,19,33,17,33, + 17,33,21,33,17,33,21,33,17,33,17,33,53,33,17,33,219,2,11,1,139,2,11,254,191,1,65,253,245,254,117,253,245,1,65,254,191,5,213,253, + 156,2,100,170,251,127,170,2,199,253,57,170,4,129,0,0,0,2,0,92,0,0,5,82,5,213,0,8,0,11,0,84,64,16,11,149,2,129,7,0, + 10,2,4,6,0,11,28,2,4,12,16,244,236,50,212,196,17,57,49,0,47,60,244,236,48,64,25,5,17,0,4,8,7,8,9,17,0,4,0,7, + 17,6,5,6,5,8,10,17,4,0,4,66,75,83,88,7,16,5,237,60,60,7,16,5,237,0,7,16,4,237,7,16,8,237,89,34,33,35,17,33, + 21,9,1,35,1,5,1,33,1,38,202,4,172,254,30,2,44,239,254,80,254,115,2,230,253,26,5,213,154,253,118,253,79,2,23,211,3,231,0,0, + 0,3,0,150,0,0,3,126,5,213,0,3,0,7,0,11,0,45,64,19,11,149,8,175,7,3,149,0,173,4,149,7,1,0,9,5,8,4,12,16, + 220,60,204,50,220,204,180,63,13,63,1,2,93,49,0,47,236,252,236,16,252,236,48,1,51,21,35,1,51,21,35,17,51,21,35,2,128,254,254,254, + 22,254,254,254,254,3,81,205,254,73,205,5,213,205,0,0,0,2,0,92,0,0,5,82,5,213,0,8,0,11,0,84,64,16,0,6,129,11,149,5, + 11,6,4,1,7,10,28,6,4,12,16,244,236,50,212,196,17,57,49,0,47,236,244,60,48,64,25,2,17,7,3,8,0,8,9,17,7,3,7,0, + 17,1,2,1,2,8,11,17,3,7,3,66,75,83,88,7,16,5,237,60,60,7,16,5,237,0,7,16,4,237,7,16,8,237,89,34,1,51,9,1, + 21,33,17,51,1,37,17,33,4,99,239,253,212,1,226,251,84,202,1,141,254,115,2,230,5,213,253,79,253,118,154,5,213,253,233,211,252,25,0,0, + 0,3,0,115,255,227,6,167,5,240,0,19,0,31,0,43,0,55,64,17,32,149,27,27,20,38,45,16,38,25,10,145,20,25,0,16,44,16,252,236, + 244,236,236,17,18,57,47,236,49,0,64,12,26,33,149,15,27,32,149,5,145,15,140,44,16,228,244,236,50,16,236,50,48,19,52,18,54,36,51,50, + 4,22,18,21,20,2,6,4,35,34,36,38,2,55,20,23,22,23,22,23,17,6,7,14,1,1,17,54,55,62,1,53,52,39,38,39,38,115,126,212, + 1,38,162,162,1,38,212,126,126,212,254,218,162,162,254,218,212,126,213,46,93,216,61,64,181,129,78,92,2,170,181,129,78,92,46,93,216,61,2,234, + 157,1,30,209,122,122,209,254,226,157,158,254,226,209,122,122,209,1,30,158,125,113,228,97,27,12,4,179,33,136,83,225,1,221,251,77,33,137,82,225, + 125,124,112,229,97,27,0,0,0,3,0,115,255,149,6,167,6,63,0,25,0,35,0,45,0,110,64,30,22,46,21,23,0,26,10,8,13,28,29,39, + 38,7,20,6,26,36,9,47,16,36,25,13,145,26,25,0,16,46,16,252,236,244,236,236,196,17,18,23,57,18,57,57,17,18,57,57,17,57,49,0, + 64,30,7,9,5,31,22,46,28,29,39,38,4,31,20,18,10,23,31,41,21,10,41,149,18,31,149,5,145,18,140,46,16,228,244,236,16,236,47,196, + 17,18,57,57,18,57,18,23,57,18,57,17,18,57,57,48,19,52,18,54,36,51,50,23,55,23,7,22,18,21,20,2,6,4,35,34,39,7,39,55, + 38,2,55,20,23,1,38,35,34,14,2,5,52,39,1,22,51,50,62,2,115,126,212,1,38,162,227,196,160,130,157,110,128,126,212,254,218,162,228,196, + 160,129,156,110,127,213,145,2,234,143,167,119,214,156,92,4,138,145,253,21,144,167,119,214,156,92,2,234,157,1,30,209,122,118,196,105,194,106,254,222, + 157,158,254,226,209,122,119,197,107,193,106,1,33,158,230,174,3,152,94,96,165,225,124,229,175,252,103,94,96,165,225,0,0,4,0,150,0,0,1,148, + 5,213,0,3,0,7,0,11,0,15,0,46,64,23,7,149,4,3,149,0,8,149,11,12,149,0,175,15,13,9,5,1,12,8,4,0,16,16,220,60, + 60,60,204,50,50,50,49,0,47,228,236,220,236,16,236,220,236,48,19,51,21,35,21,51,21,35,21,51,21,35,21,51,21,35,150,254,254,254,254,254, + 254,254,254,5,213,205,223,205,225,205,225,205,0,1,0,41,0,0,4,225,5,213,0,7,0,58,64,9,7,175,1,5,9,7,1,5,8,16,220,220, + 196,204,49,0,47,60,228,48,64,20,3,17,0,7,4,2,17,1,0,1,0,3,7,17,6,4,17,5,6,5,7,1,16,237,16,237,50,50,7,16, + 237,8,16,237,9,1,35,9,1,35,1,51,2,178,2,46,232,254,93,254,186,230,3,127,232,2,186,253,70,2,30,253,226,5,213,0,0,1,0,201, + 0,0,5,59,5,213,0,11,0,45,64,13,13,4,3,28,6,2,28,11,7,28,10,4,12,16,252,252,220,252,220,252,252,49,0,64,10,0,145,5, + 7,149,2,11,173,9,5,47,60,244,60,236,16,228,48,1,51,17,33,17,35,17,33,17,35,17,33,2,157,202,1,212,202,253,34,202,1,212,5,213, + 253,156,252,143,2,199,253,57,3,113,0,0,0,1,0,62,0,0,5,60,5,213,0,14,0,129,64,12,3,28,4,4,7,0,15,7,9,0,13,15, + 16,212,196,220,196,196,17,18,57,47,236,49,180,128,0,127,13,2,93,0,64,6,6,3,0,175,12,9,47,60,236,50,50,48,75,176,66,80,88,64, + 20,10,17,9,8,9,12,17,13,14,13,6,17,7,8,7,1,17,0,14,0,5,7,16,236,7,16,236,7,16,236,7,16,236,64,15,8,1,9,12, + 7,11,12,7,10,0,14,13,6,0,10,15,15,15,64,10,5,17,8,8,7,2,17,14,0,14,7,0,16,237,7,0,16,237,89,19,51,1,17,51, + 17,1,51,9,1,35,9,1,35,1,130,218,1,19,202,1,11,216,254,32,2,0,216,254,92,254,88,218,2,22,5,213,254,100,1,156,254,115,1,141, + 253,51,252,248,2,123,253,133,3,29,0,0,0,4,0,150,0,0,3,162,5,213,0,3,0,7,0,11,0,15,0,49,64,20,15,7,149,12,4,175, + 8,0,149,11,3,5,1,4,0,13,9,12,8,16,16,220,60,204,50,220,60,204,50,180,63,5,63,1,2,93,49,0,47,60,236,50,244,60,236,50, + 48,37,51,21,35,17,51,21,35,1,51,21,35,17,51,21,35,2,164,254,254,254,254,253,242,254,254,254,254,205,205,5,213,205,251,197,205,5,213,205, + 0,2,0,92,0,0,5,8,5,213,0,2,0,9,0,55,64,16,2,149,5,129,8,149,4,1,5,9,6,0,28,5,4,10,16,244,236,212,196,17, + 57,49,0,47,236,244,236,48,64,9,0,17,8,1,17,7,8,7,66,75,83,88,7,16,5,237,4,16,237,89,34,9,1,33,1,33,17,33,21,1, + 33,1,38,2,230,253,26,3,226,251,84,4,172,252,156,3,100,1,68,3,231,250,213,5,213,154,251,111,0,3,0,150,2,104,4,146,3,104,0,3, + 0,7,0,11,0,36,64,17,3,7,11,0,4,8,13,1,28,0,5,28,4,9,28,8,12,16,220,236,220,236,220,236,204,49,0,47,60,60,204,50, + 50,48,1,51,17,35,1,51,17,35,1,51,17,35,3,198,204,204,254,104,204,204,254,104,204,204,3,104,255,0,1,0,255,0,1,0,255,0,0,0, + 255,255,0,201,0,0,4,139,5,213,16,6,3,55,0,0,0,1,0,111,0,0,3,150,5,213,0,11,0,33,64,16,11,3,149,0,175,4,8,149, + 7,5,1,3,28,0,8,9,47,204,50,252,204,50,49,0,47,236,50,244,236,50,48,19,33,21,33,17,33,21,33,53,33,17,33,111,3,38,254,211, + 1,46,252,218,1,45,254,210,5,213,170,251,127,170,170,4,129,0,0,0,0,1,0,111,255,226,7,49,5,240,0,47,0,44,64,22,15,33,149,20, + 28,145,9,39,149,44,4,140,48,49,30,42,36,25,12,18,6,48,16,204,50,220,236,220,50,204,49,0,16,228,50,236,50,244,60,236,50,48,1,6, + 7,6,33,34,39,53,22,51,32,0,17,16,0,33,34,7,53,54,51,32,23,22,23,54,55,54,33,50,23,21,38,35,32,0,17,16,0,33,50,55, + 21,6,35,32,39,38,3,208,37,52,194,254,172,128,114,109,121,1,0,1,16,254,240,255,0,121,109,114,128,1,79,199,52,37,37,52,194,1,84,128, + 114,109,121,255,0,254,240,1,16,1,0,121,109,114,128,254,178,200,52,1,42,66,54,208,33,175,42,1,58,1,39,1,40,1,56,41,175,32,207,54, + 65,66,54,207,32,175,41,254,200,254,216,254,217,254,198,42,175,33,208,54,0,2,0,111,0,0,5,204,5,213,0,27,0,31,0,80,64,19,11,7, + 9,13,5,28,16,31,4,17,29,1,28,22,26,24,20,0,32,16,212,60,60,204,50,236,50,50,212,60,60,252,60,60,204,50,49,0,64,20,9,28, + 24,149,6,2,27,0,10,29,23,149,13,17,20,4,0,175,15,19,47,60,228,50,220,60,60,236,50,50,16,220,60,60,236,50,50,48,1,51,17,33, + 17,51,17,33,21,33,17,33,21,33,17,35,17,33,17,35,17,33,53,33,17,33,53,33,23,17,33,17,1,145,202,1,146,202,1,21,254,235,1,21, + 254,235,202,254,110,202,254,222,1,34,254,222,1,34,202,1,146,5,213,254,120,1,136,254,120,170,254,142,170,254,121,1,135,254,121,1,135,170,1,114, + 170,170,254,142,1,114,0,0,255,255,0,201,0,0,5,51,5,213,16,6,3,172,0,0,0,1,0,204,0,0,4,136,5,213,0,7,0,28,64,14, + 4,149,1,175,5,149,0,6,2,5,28,0,4,8,16,252,236,196,50,49,0,47,236,252,236,48,51,17,33,21,33,17,33,21,204,3,188,253,14,2, + 242,5,213,170,251,127,170,0,255,255,0,201,0,0,1,147,5,213,16,6,0,44,0,0,0,1,0,111,0,0,5,204,5,213,0,19,0,55,64,12, + 7,3,5,9,1,28,18,14,12,16,0,20,16,47,60,60,204,50,252,60,60,204,50,49,0,64,14,16,5,149,2,19,0,6,15,149,9,12,0,175, + 11,47,228,220,60,236,50,16,220,60,236,50,48,1,51,17,33,21,33,17,33,21,33,17,35,17,33,53,33,17,33,53,33,2,191,202,2,67,253,189, + 2,67,253,189,202,253,176,2,80,253,176,2,80,5,213,254,120,170,254,142,170,254,121,1,135,170,1,114,170,0,0,0,0,2,0,201,0,0,1,149, + 5,213,0,3,0,7,0,55,64,12,7,0,4,175,2,5,1,28,4,0,4,8,16,252,75,176,16,84,88,185,0,0,0,64,56,89,50,236,50,49, + 0,47,236,204,204,48,1,64,13,48,9,64,9,80,9,96,9,143,9,159,9,6,93,55,51,21,35,19,51,17,35,201,204,204,2,202,202,205,205,5, + 213,251,166,0,0,1,0,159,255,227,5,164,5,213,0,28,0,62,64,24,21,15,149,26,4,149,7,145,26,140,29,20,25,21,18,25,7,23,12,25, + 6,0,16,29,16,252,196,236,212,196,236,212,236,49,0,16,228,244,236,16,236,196,48,64,6,4,17,8,9,8,66,75,83,88,7,16,1,237,89,34, + 19,52,18,55,1,33,53,33,21,1,14,1,21,20,22,51,50,54,53,52,39,51,22,21,20,4,33,32,36,159,190,187,2,16,252,164,4,172,253,120, + 183,197,219,201,226,213,203,191,225,254,187,254,185,254,206,254,185,1,195,159,1,4,119,1,78,170,170,254,101,116,228,119,150,164,136,136,179,206,224,161, + 206,230,249,0,0,4,0,99,255,227,4,173,5,240,0,11,0,23,0,35,0,47,0,57,64,14,49,69,3,27,18,21,45,9,33,18,15,39,69,48, + 16,252,60,236,50,212,60,236,50,236,49,0,64,16,0,185,12,6,185,18,145,48,30,185,42,24,185,36,140,48,16,244,236,212,236,16,244,236,212,236, + 48,1,50,54,53,52,38,35,34,6,21,20,22,23,34,36,53,52,36,51,50,4,21,20,4,3,50,54,53,52,38,35,34,6,21,20,22,23,34,36, + 53,52,36,51,50,4,21,20,4,2,136,153,183,183,153,153,183,183,153,249,254,212,1,44,249,249,1,44,254,212,249,153,183,183,153,153,183,183,153,249, + 254,212,1,44,249,249,1,44,254,212,4,26,80,73,73,80,80,73,73,80,164,165,152,151,166,166,151,152,165,253,17,80,73,73,80,80,73,73,80,164, + 166,151,152,165,165,152,151,166,0,2,0,115,255,227,6,167,5,240,0,19,0,39,0,40,64,11,41,16,30,25,10,145,20,25,0,16,40,16,252,236, + 244,236,236,49,0,64,10,25,149,15,35,149,5,145,15,140,40,16,228,244,236,16,236,48,19,52,18,54,36,51,50,4,22,18,21,20,2,6,4,35, + 34,36,38,2,55,20,30,2,51,50,62,2,53,52,46,2,35,34,14,2,115,126,212,1,38,162,162,1,38,212,126,126,212,254,218,162,162,254,218,212, + 126,213,92,156,214,119,119,214,156,92,92,156,214,119,119,214,156,92,2,234,157,1,30,209,122,122,209,254,226,157,158,254,226,209,122,122,209,1,30,158, + 125,225,165,96,96,165,225,125,124,225,165,96,96,165,225,0,0,2,0,115,255,145,6,167,5,240,0,22,0,44,0,80,64,24,15,14,10,31,32,33, + 30,13,16,6,23,35,14,46,16,35,25,10,145,23,25,0,16,45,16,252,236,244,236,236,196,17,18,23,57,18,57,57,49,0,64,22,15,18,32,31, + 33,30,16,13,6,40,28,15,28,149,18,40,149,5,145,18,140,45,16,228,244,236,16,236,192,17,18,23,57,18,57,48,19,52,18,54,36,51,50,4, + 22,18,21,20,2,7,23,7,39,6,35,34,36,38,2,55,20,30,2,51,50,55,1,55,1,54,53,52,46,2,35,34,14,2,115,126,212,1,38,162, + 162,1,38,212,126,127,108,162,129,167,196,229,162,254,218,212,126,213,92,156,214,119,167,144,254,145,131,1,106,144,92,156,214,119,119,214,156,92,2,234, + 158,1,30,208,122,122,208,254,226,158,158,254,224,105,199,107,202,119,122,208,1,30,158,124,226,164,96,94,1,190,106,254,73,174,229,124,226,164,96,96, + 164,226,0,0,0,1,0,201,0,0,5,59,5,213,0,11,0,45,64,13,13,4,6,28,4,8,28,11,2,28,0,4,12,16,252,252,220,252,220,252, + 252,49,0,64,10,5,1,145,10,11,8,149,3,173,10,47,244,236,50,16,228,50,48,19,17,51,17,33,17,51,17,33,17,35,17,201,202,2,222,202, + 254,44,202,2,100,3,113,253,57,2,199,252,143,253,156,2,100,0,0,0,0,3,0,201,0,0,1,199,5,213,0,3,0,7,0,11,0,40,64,20, + 11,149,8,175,7,3,149,0,173,4,149,7,13,9,1,5,0,4,8,12,16,220,60,60,220,60,60,204,49,0,47,236,252,236,16,252,236,48,19,51, + 21,35,17,51,21,35,17,51,21,35,201,254,254,254,254,254,254,3,81,205,254,73,205,5,213,205,0,0,0,5,0,150,0,0,5,104,5,213,0,3, + 0,7,0,11,0,15,0,19,0,63,64,27,19,1,149,2,16,175,15,11,149,8,173,12,6,149,5,15,3,7,2,6,9,8,13,17,12,16,20,16, + 220,60,204,50,220,204,220,60,204,50,182,63,7,63,3,63,9,3,93,49,0,47,60,236,50,252,236,16,252,60,236,50,48,1,35,53,51,17,35,53, + 51,1,51,21,35,1,51,21,35,17,51,21,35,5,104,254,254,254,254,253,24,254,254,254,22,254,254,254,254,5,8,205,250,43,205,2,132,205,254,73, + 205,5,213,205,0,3,0,115,255,227,6,167,5,240,0,19,0,39,0,43,0,62,64,16,45,16,10,41,40,40,20,30,25,10,145,20,25,0,16,44, + 16,252,236,244,236,17,57,47,204,16,236,178,47,41,1,93,49,0,64,14,43,206,40,173,25,149,15,35,149,5,145,15,140,44,16,228,244,236,16,236, + 244,236,48,1,19,52,18,54,36,51,50,4,22,18,21,20,2,6,4,35,34,36,38,2,55,20,30,2,51,50,62,2,53,52,46,2,35,34,14,2, + 5,51,21,35,115,126,212,1,38,162,162,1,38,212,126,126,212,254,218,162,162,254,218,212,126,213,92,156,214,119,119,214,156,92,92,156,214,119,119,214, + 156,92,1,198,254,254,2,234,157,1,30,209,122,122,209,254,226,157,158,254,226,209,122,122,209,1,30,158,125,225,165,96,96,165,225,125,124,225,165,96, + 96,165,225,21,205,0,0,0,0,2,0,115,255,228,6,167,6,62,0,22,0,44,0,80,64,24,9,8,13,37,36,35,38,10,7,6,23,33,8,46, + 16,33,25,13,145,23,25,0,16,45,16,252,236,244,236,236,196,17,18,23,57,18,57,57,49,0,64,22,8,5,10,7,35,38,36,37,6,40,28,8, + 28,149,18,40,149,5,145,18,140,45,16,228,244,236,16,236,196,17,18,23,57,18,57,48,19,52,18,54,36,51,50,23,55,23,7,22,18,21,20,2, + 6,4,35,34,36,38,2,55,20,30,2,51,50,62,2,53,52,39,1,39,1,38,35,34,14,2,115,126,212,1,38,162,228,196,160,131,158,110,127,126, + 212,254,218,162,162,254,218,212,126,213,92,156,214,119,119,214,156,92,144,254,148,130,1,112,144,167,119,214,156,92,2,234,158,1,30,208,122,118,196,105, + 194,107,254,224,158,158,254,226,208,122,122,208,1,30,158,124,226,164,96,96,164,226,124,229,174,254,63,108,1,198,94,96,164,226,0,0,0,3,0,115, + 255,227,5,114,5,239,0,37,0,49,0,61,0,71,64,16,56,38,25,14,24,30,8,25,44,50,48,19,25,0,16,62,16,252,236,244,60,236,50,220, + 60,236,50,49,0,64,23,47,149,27,59,149,11,53,11,27,41,4,22,16,22,149,35,16,149,3,145,35,140,62,16,228,244,236,16,236,17,18,23,57, + 47,236,47,236,48,19,16,0,33,32,23,30,1,21,20,6,35,34,38,53,52,55,32,0,17,16,0,33,38,53,52,54,51,50,22,21,20,6,7,6, + 33,32,0,5,20,22,51,50,54,53,52,38,35,34,6,19,52,38,35,34,6,21,20,22,51,50,54,115,1,134,1,83,1,147,95,32,20,153,133,132, + 153,24,254,254,254,251,1,5,1,2,24,153,132,133,153,20,32,95,254,109,254,173,254,122,3,153,44,28,28,44,44,28,28,44,144,44,28,28,44,44, + 28,28,44,2,233,1,103,1,159,115,39,79,59,129,145,145,129,72,54,254,190,254,226,254,226,254,190,54,72,129,145,145,129,59,79,39,115,1,159,122, + 60,49,49,60,59,50,50,3,135,60,49,49,60,59,47,47,0,1,0,100,0,0,5,192,5,213,0,11,0,35,64,17,5,8,149,2,11,173,0,175, + 7,3,5,2,28,10,8,11,12,16,212,60,196,252,60,196,49,0,47,228,244,60,236,50,48,1,51,17,33,21,33,17,35,17,33,53,33,2,173,202, + 2,73,253,183,202,253,183,2,73,5,213,253,106,170,253,107,2,149,170,0,255,255,0,61,0,0,5,59,5,213,16,6,0,59,0,0,0,3,0,115, + 255,227,5,114,5,239,0,51,0,63,0,75,0,102,64,25,25,24,27,149,21,30,30,31,70,52,25,14,37,43,8,25,54,58,48,31,20,25,0,16, + 76,16,252,236,50,244,60,236,50,220,60,236,50,17,57,47,60,252,60,204,49,0,64,31,23,28,20,24,149,30,26,61,149,40,73,149,11,26,67,11, + 40,55,5,35,16,35,149,49,16,149,3,145,49,140,76,16,228,244,236,16,236,17,18,23,57,47,236,47,236,47,60,236,50,204,196,48,19,16,0,33, + 32,23,30,1,21,20,6,35,34,38,53,52,55,34,7,6,21,51,17,51,21,51,21,35,21,35,17,35,20,23,22,51,38,53,52,54,51,50,22,21, + 20,14,1,7,6,33,32,0,5,20,22,51,50,54,53,52,38,35,34,6,19,52,38,35,34,6,21,20,22,51,50,54,115,1,134,1,83,1,147,95, + 32,20,153,133,132,153,24,238,151,127,187,204,233,233,204,187,127,151,238,24,153,132,133,153,20,65,59,133,254,239,254,173,254,122,3,153,44,28,28,44, + 44,28,28,44,144,44,28,28,44,44,28,28,44,2,233,1,103,1,159,115,39,79,59,129,145,145,129,72,54,162,138,223,0,255,255,170,255,0,255,223, + 138,162,54,72,129,145,145,129,59,79,79,23,52,1,159,122,60,49,49,60,59,50,50,3,135,60,49,49,60,59,47,47,0,1,0,201,0,0,4,139, + 5,213,0,19,0,59,64,28,14,11,149,4,2,149,0,129,16,149,8,4,173,18,5,14,149,11,8,9,1,17,15,3,28,0,4,20,16,252,236,50, + 212,196,196,220,60,236,50,49,0,47,236,50,236,244,236,16,238,50,48,178,31,20,1,1,93,19,33,21,33,17,33,17,51,21,51,21,35,21,35,17, + 33,17,33,21,33,201,3,176,253,26,1,17,204,234,234,204,254,239,2,248,252,62,5,213,170,254,70,0,255,255,170,255,0,255,253,227,170,0,0,0, + 255,255,0,16,0,0,5,104,5,213,16,6,3,41,0,0,0,1,0,201,0,0,5,59,5,213,0,7,0,31,64,16,6,2,129,4,149,0,9,4, + 5,28,0,4,28,1,4,8,16,252,236,212,236,236,49,0,47,236,244,60,48,41,1,17,51,17,33,17,51,5,59,251,142,202,2,222,202,5,213,250, + 213,5,43,0,0,1,0,201,0,0,4,121,5,213,0,8,0,61,64,12,66,7,3,149,4,129,1,5,1,4,4,9,16,252,60,212,49,0,47,244, + 236,50,48,75,83,88,64,18,8,17,2,2,1,7,17,3,3,2,8,17,2,0,17,1,2,1,5,7,16,236,16,236,7,16,236,8,16,236,89,33, + 35,9,1,53,33,21,33,1,1,177,232,1,223,254,33,3,176,253,56,1,223,2,192,2,107,170,170,253,154,0,0,0,0,1,0,115,0,0,5,219, + 5,213,0,35,0,79,64,22,37,16,6,15,25,7,14,2,36,16,33,24,25,32,25,19,10,2,28,20,29,1,47,60,60,236,50,50,212,60,236,50, + 236,16,212,60,236,50,236,49,0,64,18,0,3,149,29,10,32,1,6,129,15,21,18,149,28,11,25,20,15,47,60,60,212,60,236,50,16,244,60,60, + 212,60,236,50,48,1,17,51,17,50,54,53,51,16,0,35,17,50,0,17,35,52,38,35,17,35,17,34,6,21,35,16,0,51,17,34,0,17,51,20, + 22,2,194,202,138,242,211,254,135,214,214,1,121,211,242,138,202,138,242,211,1,121,214,214,254,135,211,242,4,43,1,170,254,86,226,200,254,238,254,186, + 254,219,254,186,254,238,200,226,254,86,1,170,226,200,1,18,1,70,1,37,1,70,1,18,200,226,0,0,0,1,0,201,0,0,3,246,5,213,0,6, + 0,46,64,11,3,0,175,6,1,3,4,28,0,4,7,16,252,75,176,16,84,88,185,0,0,0,64,56,89,236,196,196,49,0,47,236,196,48,180,2, + 17,3,3,4,7,1,16,237,19,33,1,35,1,17,35,201,1,26,2,19,222,254,117,196,5,213,253,45,2,29,250,225,0,1,0,115,0,0,5,219, + 5,213,0,43,0,102,64,26,22,45,16,29,16,25,28,17,12,44,16,1,7,38,25,6,39,32,24,20,12,28,35,43,3,11,47,60,60,60,236,50, + 50,50,212,60,236,50,196,236,16,212,60,236,50,236,196,49,0,64,26,24,43,185,21,1,1,42,3,13,10,149,20,3,16,11,6,129,29,32,35,149, + 25,42,39,34,29,47,60,60,212,60,236,50,16,244,60,60,212,60,236,50,17,18,57,47,60,236,50,48,1,53,33,53,34,0,17,51,20,22,51,17, + 51,17,50,54,53,51,16,0,35,21,33,21,33,21,50,0,17,35,52,38,35,17,35,17,34,6,21,35,16,0,51,53,1,1,1,193,214,254,135,211, + 242,138,202,138,242,211,254,135,214,1,191,254,65,214,1,121,211,242,138,202,138,242,211,1,121,214,2,149,170,62,1,70,1,18,200,226,1,170,254,86, + 226,200,254,238,254,186,62,170,61,254,186,254,238,200,226,254,86,1,170,226,200,1,18,1,70,61,0,0,0,1,0,54,4,45,3,233,5,213,0,7, + 0,23,64,9,6,2,4,1,0,5,4,1,8,16,220,204,220,204,49,0,47,204,196,50,48,1,33,17,51,17,33,17,51,3,233,252,77,143,2,149, + 143,4,45,1,168,254,251,1,5,0,0,0,0,3,0,143,255,227,3,172,5,211,0,23,0,27,0,36,0,0,1,51,17,54,55,54,55,21,14,1, + 35,34,38,53,52,54,63,1,62,1,55,62,1,53,19,35,53,51,3,17,7,14,1,21,20,23,22,1,243,191,31,33,89,97,94,193,103,184,223,72, + 90,88,47,39,8,6,6,197,203,203,197,45,57,51,66,36,4,66,252,83,8,13,35,67,188,57,56,194,159,76,137,86,86,47,53,25,21,60,52,1, + 14,254,250,190,1,173,44,53,94,49,89,55,31,0,0,0,255,255,0,217,0,159,5,219,3,50,16,38,12,193,0,0,16,7,13,74,2,19,254,87, + 0,1,0,176,3,58,2,88,6,20,0,5,0,0,19,33,21,35,17,35,176,1,168,240,184,6,20,143,253,181,0,0,0,1,0,199,3,58,2,111, + 6,20,0,5,0,0,1,35,53,33,17,35,1,182,239,1,168,185,5,133,143,253,38,0,0,1,0,176,254,242,2,88,1,204,0,5,0,0,5,51, + 21,33,17,51,1,104,240,254,88,184,127,143,2,218,0,0,0,1,0,199,254,242,2,111,1,204,0,5,0,0,1,33,53,51,17,51,2,111,254,88, + 239,185,254,242,143,2,75,0,255,255,0,147,0,0,3,176,5,240,16,6,5,77,0,0,255,255,0,170,254,188,6,130,5,213,16,39,23,123,0,0, + 252,54,16,6,23,123,0,0,255,255,0,170,254,188,6,130,5,213,16,39,23,130,0,0,252,54,16,6,23,130,0,0,255,255,0,170,254,188,6,130, + 5,213,16,39,23,126,0,0,252,54,16,6,23,128,0,0,255,255,0,170,254,188,6,130,5,213,16,39,23,128,0,0,252,54,16,6,23,129,0,0, + 255,255,0,170,254,188,6,130,5,213,16,39,23,123,0,0,252,54,16,6,23,128,0,0,255,255,0,170,254,188,6,130,5,213,16,38,23,123,0,0, + 16,7,23,128,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,39,23,128,0,0,252,54,16,6,23,130,0,0,255,255,0,170,254,188,6,130, + 5,213,16,38,23,128,0,0,16,7,23,130,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,39,23,123,0,0,252,54,16,6,23,127,0,0, + 255,255,0,170,254,188,6,131,5,213,16,38,23,123,0,0,16,7,23,124,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,130,0,0, + 16,7,23,123,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,39,23,130,0,0,252,54,16,6,23,123,0,0,255,255,0,170,254,188,6,130, + 5,213,16,38,23,123,0,0,16,7,23,125,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,39,23,123,0,0,252,54,16,6,23,125,0,0, + 255,255,0,170,254,188,6,130,5,213,16,38,23,130,0,0,16,7,23,129,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,126,0,0, + 16,7,23,130,0,0,252,54,255,255,0,170,254,188,6,131,5,213,16,39,23,126,0,0,252,54,16,6,23,124,0,0,255,255,0,170,254,188,6,130, + 5,213,16,39,23,127,0,0,252,54,16,6,23,129,0,0,255,255,0,170,254,188,6,131,5,213,16,39,23,124,0,0,252,54,16,6,23,130,0,0, + 255,255,0,170,254,188,6,130,5,213,16,38,23,127,0,0,16,7,23,130,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,39,23,126,0,0, + 252,54,16,6,23,125,0,0,255,255,0,170,254,188,6,130,5,213,16,38,23,129,0,0,16,7,23,125,0,0,252,54,255,255,0,170,254,188,6,130, + 5,213,16,38,23,129,0,0,16,7,23,130,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,39,23,126,0,0,252,54,16,6,23,130,0,0, + 255,255,0,170,254,188,6,130,5,213,16,39,23,126,0,0,252,54,16,6,23,123,0,0,255,255,0,170,254,188,6,130,5,213,16,38,23,129,0,0, + 16,7,23,123,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,129,0,0,16,7,23,126,0,0,252,54,255,255,0,170,254,188,6,131, + 5,213,16,38,23,124,0,0,16,7,23,127,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,128,0,0,16,7,23,128,0,0,252,54, + 255,255,0,170,254,188,6,130,5,213,16,38,23,125,0,0,16,7,23,125,0,0,252,54,255,255,0,170,254,188,6,131,5,213,16,38,23,124,0,0, + 16,7,23,129,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,126,0,0,16,7,23,127,0,0,252,54,255,255,0,170,254,188,6,130, + 5,213,16,39,23,129,0,0,252,54,16,6,23,123,0,0,255,255,0,170,254,188,6,130,5,213,16,38,23,126,0,0,16,7,23,123,0,0,252,54, + 255,255,0,170,254,188,6,130,5,213,16,39,23,130,0,0,252,54,16,6,23,125,0,0,255,255,0,170,254,188,6,130,5,213,16,38,23,130,0,0, + 16,7,23,125,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,127,0,0,16,7,23,125,0,0,252,54,255,255,0,170,254,188,6,131, + 5,213,16,38,23,125,0,0,16,7,23,124,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,128,0,0,16,7,23,129,0,0,252,54, + 255,255,0,170,254,188,6,130,5,213,16,39,23,128,0,0,252,54,16,6,23,126,0,0,255,255,0,170,254,188,6,131,5,213,16,38,23,129,0,0, + 16,7,23,124,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,127,0,0,16,7,23,126,0,0,252,54,255,255,0,170,254,188,6,131, + 5,213,16,38,23,124,0,0,16,7,23,123,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,123,0,0,16,7,23,127,0,0,252,54, + 255,255,0,170,254,188,6,131,5,213,16,38,23,124,0,0,16,7,23,130,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,130,0,0, + 16,7,23,127,0,0,252,54,255,255,0,170,254,188,6,131,5,213,16,39,23,128,0,0,252,54,16,6,23,124,0,0,255,255,0,170,254,188,6,130, + 5,213,16,38,23,128,0,0,16,7,23,127,0,0,252,54,255,255,0,170,254,188,6,131,5,213,16,38,23,124,0,0,16,7,23,125,0,0,252,54, + 255,255,0,170,254,188,6,130,5,213,16,38,23,125,0,0,16,7,23,127,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,126,0,0, + 16,7,23,126,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,129,0,0,16,7,23,129,0,0,252,54,255,255,0,170,254,188,6,130, + 5,213,16,38,23,127,0,0,16,7,23,129,0,0,252,54,255,255,0,170,254,188,6,131,5,213,16,38,23,126,0,0,16,7,23,124,0,0,252,54, + 255,255,0,170,254,188,6,130,5,213,16,38,23,126,0,0,16,7,23,125,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,125,0,0, + 16,7,23,129,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,127,0,0,16,7,23,127,0,0,252,54,255,255,0,170,254,188,6,131, + 5,213,16,38,23,124,0,0,16,7,23,124,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,127,0,0,16,7,23,128,0,0,252,54, + 255,255,0,170,254,188,6,131,5,213,16,38,23,128,0,0,16,7,23,124,0,0,252,54,255,255,0,170,254,188,6,131,5,213,16,38,23,127,0,0, + 16,7,23,124,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,38,23,126,0,0,16,7,23,129,0,0,252,54,255,255,0,170,254,188,6,130, + 5,213,16,38,23,128,0,0,16,7,23,125,0,0,252,54,255,255,0,170,254,188,6,130,5,213,16,39,23,128,0,0,252,54,16,6,23,125,0,0, + 255,255,0,201,0,0,4,236,5,213,18,6,0,37,0,0,255,255,0,201,0,0,4,141,5,213,18,6,0,51,0,0,0,2,0,70,0,0,4,10, + 5,213,0,8,0,19,0,0,37,17,35,34,6,21,20,22,51,5,33,34,36,53,52,36,59,1,17,51,3,64,254,141,154,154,141,1,200,254,56,251, + 254,255,1,1,251,254,202,166,2,49,146,135,134,146,166,227,219,221,226,2,88,0,0,0,255,255,0,201,0,0,5,176,5,213,18,6,0,39,0,0, + 255,255,255,250,0,0,4,233,5,213,18,6,0,55,0,0,0,1,255,250,0,0,4,233,5,213,0,7,0,0,41,1,53,33,17,51,17,33,4,233, + 251,17,2,18,203,2,18,170,5,43,250,213,255,255,0,115,255,227,5,139,5,240,18,6,0,42,0,0,255,255,0,201,0,0,5,106,5,213,18,6, + 0,46,0,0,0,1,255,213,0,0,4,118,5,213,0,10,0,0,33,35,17,1,33,9,1,33,1,17,51,4,118,202,253,98,254,252,2,229,252,230, + 1,10,2,205,202,2,119,253,137,2,184,3,29,253,49,2,207,0,0,0,255,255,0,0,255,227,3,79,5,213,18,6,23,2,0,0,255,255,0,115, + 255,227,5,39,5,240,18,6,0,38,0,0,255,255,0,115,255,227,5,39,5,240,18,6,1,72,0,0,255,255,0,92,0,0,5,31,5,213,18,6, + 0,61,0,0,255,255,0,201,0,0,4,35,5,213,18,6,0,41,0,0,255,255,0,201,0,0,4,35,5,213,18,6,11,196,0,0,255,255,0,201, + 0,0,6,31,5,213,18,6,0,48,0,0,255,255,0,201,0,0,5,51,5,213,18,6,0,49,0,0,255,255,0,201,0,0,4,106,5,213,18,6, + 0,47,0,0,255,255,0,135,255,227,4,162,5,240,18,6,0,54,0,0,255,255,0,201,0,0,5,84,5,213,18,6,0,53,0,0,0,2,0,59, + 0,0,4,198,5,213,0,19,0,27,0,0,1,46,1,39,3,51,19,30,1,59,1,17,51,17,33,32,38,53,52,54,1,17,35,34,6,16,22,51, + 2,2,65,123,62,205,217,191,74,139,120,220,202,254,56,255,0,252,131,2,119,254,146,149,149,146,3,25,22,144,126,1,152,254,129,150,98,2,119,250, + 43,214,216,141,186,253,177,2,18,135,254,250,133,0,0,0,255,255,0,16,0,0,5,104,5,213,18,6,2,7,0,0,255,255,0,16,0,0,5,104, + 5,213,18,6,0,57,0,0,255,255,0,201,0,0,5,59,5,213,18,6,0,43,0,0,255,255,0,163,255,227,5,187,5,240,18,6,11,211,0,0, + 0,1,0,201,0,0,4,24,5,242,0,15,0,0,1,21,46,1,35,34,6,21,17,35,17,16,54,51,50,22,4,24,91,194,104,143,113,202,211,247, + 96,190,5,152,236,81,81,149,203,252,18,3,238,1,26,234,44,0,0,0,255,255,0,68,0,0,7,166,5,213,18,6,0,58,0,0,255,255,0,61, + 0,0,5,59,5,213,18,6,0,59,0,0,255,255,255,252,0,0,4,231,5,213,18,6,0,60,0,0,0,3,0,145,0,0,4,180,5,213,0,8, + 0,17,0,32,0,0,1,17,33,34,6,21,20,22,51,1,17,33,34,6,21,20,22,51,5,33,34,38,53,52,54,55,46,1,53,52,36,51,33,3, + 234,254,188,163,157,157,163,1,68,254,213,148,145,145,148,1,245,253,252,231,250,128,124,149,165,1,16,251,2,24,3,12,2,35,135,139,140,133,253,154, + 1,194,111,114,113,112,166,192,177,137,162,20,32,203,152,200,218,0,0,0,255,255,0,16,0,0,5,104,5,213,18,6,0,36,0,0,255,255,0,16, + 0,0,5,104,5,213,18,6,17,227,0,0,255,255,0,201,0,0,4,139,5,213,18,6,0,40,0,0,0,1,0,131,0,0,4,69,5,213,0,11, + 0,0,41,1,53,33,17,33,53,33,17,33,53,33,4,69,252,80,2,230,253,57,2,199,253,8,3,194,170,1,186,170,2,29,170,0,255,255,0,201, + 0,0,1,147,5,213,18,6,0,44,0,0,255,255,0,115,255,227,5,217,5,240,18,6,0,50,0,0,255,255,0,178,255,227,5,41,5,213,18,6, + 0,56,0,0,0,1,0,178,0,0,5,41,5,242,0,17,0,42,64,9,10,28,8,56,17,28,0,65,18,16,252,75,176,16,84,88,185,0,0,255, + 192,56,89,236,252,236,49,0,181,13,149,4,145,9,0,47,60,244,236,48,51,17,16,0,33,32,0,25,1,35,17,52,38,35,34,6,21,17,178,1, + 33,1,27,1,26,1,33,203,174,194,195,174,3,164,1,36,1,42,254,214,254,220,252,92,3,139,240,211,211,240,252,117,255,255,0,8,0,0,3,169, + 5,213,18,6,11,212,0,0,0,2,0,115,0,0,5,90,5,213,0,8,0,17,0,31,64,9,0,28,10,50,4,25,14,16,18,16,252,236,244,236, + 49,0,182,0,149,9,129,7,149,11,47,236,244,236,48,1,35,32,0,17,16,0,33,51,19,17,33,32,0,17,16,0,33,4,144,244,254,203,254,225, + 1,31,1,53,244,202,254,97,254,80,254,104,1,150,1,178,5,47,254,233,254,212,254,210,254,232,5,47,250,43,1,106,1,130,1,128,1,105,0,0, + 0,1,0,175,0,0,1,183,1,62,0,3,0,0,19,33,17,33,175,1,8,254,248,1,62,254,194,0,0,1,0,146,254,192,1,183,1,62,0,6, + 0,0,19,33,17,3,35,19,35,175,1,8,164,129,164,135,1,62,254,194,254,192,1,64,255,255,0,175,0,0,4,22,1,62,16,39,18,191,2,95, + 0,0,16,6,18,191,0,0,255,255,0,175,254,192,4,22,1,62,16,39,18,192,2,95,0,0,16,6,18,191,0,0,0,2,0,146,254,192,1,183, + 4,35,0,6,0,10,0,0,19,33,17,3,35,19,35,17,33,17,33,175,1,8,164,129,164,135,1,8,254,248,1,62,254,194,254,192,1,64,4,35, + 254,194,0,0,0,2,0,175,0,0,1,183,4,35,0,3,0,7,0,0,19,33,17,33,17,33,17,33,175,1,8,254,248,1,8,254,248,1,62,254, + 194,4,35,254,194,0,0,0,0,2,0,175,0,0,4,5,2,214,0,3,0,7,0,0,1,33,17,33,1,33,21,33,2,253,1,8,254,248,253,178, + 3,86,252,170,1,62,254,194,2,214,168,0,0,2,0,175,1,96,4,5,3,162,0,3,0,7,0,0,19,33,21,33,21,33,21,33,175,3,86,252, + 170,3,86,252,170,3,162,168,240,170,0,0,255,255,0,114,255,227,4,141,5,240,16,6,1,105,0,0,255,255,0,100,255,227,3,188,4,123,16,6, + 1,106,0,0,255,255,0,201,0,0,2,198,5,213,16,6,1,88,0,0,255,255,0,166,0,0,2,110,4,96,16,6,2,43,0,0,0,1,0,118, + 255,227,8,250,5,41,0,52,0,62,64,21,48,49,44,28,0,24,23,4,10,15,42,36,30,6,0,54,28,28,19,69,53,16,252,236,204,204,23,57, + 212,204,16,236,212,204,49,0,64,12,36,149,10,42,30,149,4,15,140,48,23,53,16,204,50,244,50,236,50,220,236,48,1,20,7,6,35,34,39,38, + 39,38,35,34,15,1,6,35,34,39,38,53,52,55,54,55,51,6,7,6,21,16,33,50,55,54,55,54,51,50,23,22,23,22,51,32,17,52,39,38, + 39,51,22,23,22,8,250,102,116,234,91,110,97,96,122,120,122,123,194,110,91,234,116,102,67,71,111,249,126,91,85,1,0,138,93,76,75,102,157,155, + 100,75,74,93,138,1,0,85,91,126,250,111,70,67,1,254,242,139,158,68,64,64,68,68,128,68,157,139,242,198,226,236,152,107,243,226,182,254,186,54, + 51,51,54,54,51,51,54,1,70,182,226,243,107,152,236,226,0,1,0,152,255,227,7,161,3,197,0,33,0,60,64,19,33,0,31,8,2,14,13,4, + 9,29,18,4,2,35,16,8,11,69,34,16,252,236,204,204,23,57,212,204,16,236,212,204,49,0,64,12,23,169,7,29,18,169,4,9,140,33,13,34, + 16,204,50,244,50,236,50,220,236,48,1,18,17,16,33,34,36,34,4,35,32,17,16,19,51,2,21,16,51,50,55,54,55,54,50,23,22,23,22,51, + 50,17,52,3,7,23,138,254,114,84,254,213,240,254,212,82,254,114,138,198,146,208,62,73,120,21,100,252,100,20,121,73,63,208,146,3,197,254,227,254, + 235,254,80,226,226,1,177,1,20,1,29,254,185,250,254,251,56,91,12,55,55,12,91,56,1,7,248,1,71,0,0,0,255,255,0,60,0,0,7,114, + 5,213,16,38,3,190,0,0,16,7,0,44,5,223,0,0,255,255,0,62,0,0,6,138,4,123,16,38,3,222,0,0,16,7,0,243,5,17,0,0, + 0,2,0,115,255,227,7,208,5,240,0,9,0,28,0,0,0,32,0,17,16,0,32,0,17,16,23,33,17,51,17,35,17,33,2,0,33,32,0,17, + 16,0,33,32,0,4,1,254,72,254,255,1,1,1,184,1,3,210,1,48,202,202,254,208,14,254,152,254,197,254,198,254,136,1,120,1,58,1,59,1, + 104,5,76,254,184,254,229,254,230,254,184,1,72,1,26,1,27,197,2,150,250,43,2,149,254,232,254,102,1,165,1,97,1,98,1,165,254,103,0,0, + 0,2,0,112,255,227,5,251,4,123,0,10,0,28,0,0,1,34,6,21,20,22,51,50,54,16,38,1,51,17,51,17,35,17,35,6,0,35,34,0, + 17,16,0,32,18,2,114,147,172,172,147,149,171,172,1,104,213,184,184,208,9,254,249,241,240,254,238,1,18,1,224,249,3,223,233,199,200,232,231,1, + 146,231,254,194,1,191,251,160,2,9,248,254,210,1,57,1,19,1,20,1,56,254,228,0,0,2,0,211,0,0,7,191,5,213,0,15,0,18,0,0, + 1,51,1,35,3,33,3,35,19,33,17,35,17,51,17,33,9,1,33,4,161,229,2,57,210,136,253,95,136,213,252,254,58,202,202,2,7,1,111,254, + 238,2,37,5,213,250,43,1,127,254,129,2,149,253,107,5,213,253,106,1,207,253,25,0,0,2,0,193,255,227,6,4,4,123,0,34,0,45,0,0, + 1,17,35,53,14,1,35,34,38,53,52,55,33,17,35,17,51,17,33,54,51,33,53,52,38,35,34,6,7,53,62,1,51,50,22,1,34,6,21,20, + 22,51,50,54,61,1,6,4,184,63,188,136,172,203,47,254,248,184,184,1,210,106,149,1,2,167,151,96,182,84,101,190,90,243,240,254,145,223,172,129, + 111,153,185,2,127,253,129,170,102,97,193,162,115,80,253,247,4,96,254,65,34,18,127,139,46,46,170,39,39,252,254,180,102,123,98,115,217,180,41,0, + 0,2,0,101,254,191,8,8,5,213,0,18,0,26,0,0,55,54,55,18,25,1,33,21,33,17,51,17,35,17,35,33,17,35,17,1,33,21,16,3, + 6,7,33,172,134,38,97,6,79,253,41,170,170,202,252,168,170,4,2,254,27,112,23,40,2,148,170,63,120,1,52,2,38,1,26,170,251,127,254,21, + 1,65,254,191,1,235,4,129,212,254,13,254,181,68,43,0,0,2,0,107,254,229,6,231,4,96,0,18,0,25,0,0,55,54,55,54,17,53,33,21, + 33,17,51,17,35,17,35,33,17,35,17,1,33,21,16,15,1,33,176,91,40,98,5,82,253,163,147,147,185,253,45,147,3,102,254,125,118,29,2,22, + 147,40,85,211,1,169,212,147,252,198,254,82,1,27,254,229,1,174,3,58,140,254,100,220,54,0,0,0,0,1,0,84,0,0,8,17,5,213,0,17, + 0,0,51,53,54,55,54,17,53,33,21,33,17,35,17,33,21,16,3,6,84,221,58,87,6,79,253,41,202,254,27,102,98,170,48,163,246,2,100,254, + 170,250,213,5,43,184,253,202,254,248,253,0,0,1,0,76,0,0,6,209,4,96,0,18,0,0,51,53,54,55,54,17,53,33,21,33,17,43,1,17, + 33,21,16,7,6,76,187,51,68,5,83,253,163,1,184,254,123,88,94,153,29,125,166,1,208,183,147,252,51,3,205,111,254,80,194,207,0,1,0,201, + 0,0,8,246,5,213,0,15,0,0,19,33,9,1,33,21,33,17,43,1,17,1,35,1,17,35,201,1,45,1,125,1,127,4,4,253,41,197,5,254, + 132,203,254,127,196,5,213,252,8,3,248,170,250,213,5,18,252,13,4,0,250,225,0,0,0,1,0,186,0,0,7,172,4,96,0,14,0,0,19,33, + 9,1,33,21,33,17,35,17,1,35,1,17,35,186,1,13,1,62,1,63,3,104,253,163,185,254,203,184,254,202,185,4,96,253,18,2,238,147,252,51, + 3,176,253,39,2,217,252,80,255,255,0,115,255,227,5,217,5,240,16,39,0,121,1,226,0,0,16,6,0,50,0,0,255,255,0,113,255,227,4,117, + 4,123,16,38,0,82,0,0,16,7,0,121,1,46,255,132,0,4,0,115,255,227,6,101,5,240,0,3,0,7,0,19,0,29,0,0,1,51,21,35, + 37,51,21,35,18,32,39,38,16,55,54,32,23,22,16,7,0,32,0,17,16,0,32,0,17,16,2,49,211,211,1,164,211,211,241,253,76,208,207,207, + 208,2,180,208,207,207,254,200,254,26,254,224,1,32,1,230,1,32,3,70,254,254,254,253,155,210,210,2,196,211,210,210,211,253,60,210,4,151,254,184, + 254,229,254,230,254,184,1,72,1,26,1,27,0,4,0,113,255,227,5,67,4,123,0,3,0,7,0,18,0,30,0,0,1,51,21,35,37,51,21,35, + 3,34,6,16,22,51,50,54,53,52,38,39,32,0,17,16,0,33,32,0,17,16,0,1,188,211,211,1,104,211,211,74,195,227,225,197,194,227,227,194, + 1,32,1,73,254,183,254,224,254,223,254,184,1,72,2,202,254,254,254,2,19,231,254,110,231,232,200,199,233,156,254,200,254,236,254,237,254,199,1,57, + 1,19,1,20,1,56,0,0,255,255,0,115,255,227,10,106,5,240,16,38,19,28,0,0,16,39,0,121,6,114,0,0,16,7,0,121,1,226,0,0, + 255,255,0,113,255,227,7,182,4,123,16,39,0,121,4,111,255,132,16,39,0,121,1,46,255,132,16,6,19,29,0,0,0,15,0,58,254,87,6,206, + 5,241,0,3,0,7,0,11,0,15,0,19,0,23,0,31,0,39,0,47,0,55,0,63,0,71,0,79,0,128,0,132,0,0,37,51,21,35,37,51, + 21,35,1,51,21,35,37,51,21,35,1,51,21,35,37,51,21,35,0,34,6,20,22,50,54,52,18,34,6,20,22,50,54,52,36,34,6,20,22,50, + 54,52,18,34,6,20,22,50,54,52,36,34,6,20,22,50,54,52,0,34,6,20,22,50,54,52,36,34,6,20,22,50,54,52,19,50,22,21,20,6, + 43,1,22,21,20,6,32,39,38,39,6,7,6,32,38,53,52,55,34,35,34,38,53,52,54,59,1,38,53,52,54,32,23,22,23,54,55,54,32,22, + 21,20,7,1,51,21,35,4,74,134,134,253,239,134,134,2,17,134,134,253,239,134,134,254,248,134,134,4,34,134,134,252,123,180,105,105,180,104,160,180, + 105,105,180,104,1,169,180,105,105,180,104,161,180,105,105,180,104,253,134,180,105,105,180,104,254,144,180,105,105,180,104,1,169,180,105,105,180,104,71,141, + 171,171,141,4,52,171,254,227,85,22,15,15,21,85,254,226,169,51,2,1,143,171,171,143,2,50,169,1,30,85,21,15,15,22,85,1,29,171,52,253, + 175,134,134,22,156,156,156,5,73,156,156,156,254,70,156,156,156,1,93,142,247,142,142,247,2,228,143,246,142,142,246,143,143,246,142,142,246,254,57,142, + 247,142,142,247,142,142,247,142,142,247,254,55,142,247,142,142,247,142,142,247,142,142,247,3,82,204,172,169,204,92,133,171,203,100,27,29,29,25,102,202, + 172,133,92,202,171,172,204,90,133,171,204,101,26,29,29,26,101,204,171,133,90,254,210,156,0,1,255,250,254,102,6,16,5,213,0,29,0,0,3,33, + 21,33,17,33,50,23,22,21,17,16,6,43,1,53,51,50,55,54,53,17,52,38,35,33,17,35,17,33,6,4,239,253,238,1,161,186,113,109,204,228, + 76,62,134,56,55,124,124,254,136,203,253,238,5,213,170,254,70,119,114,238,254,206,254,242,244,170,75,75,194,1,34,159,158,253,57,5,43,0,0,0, + 0,1,0,60,254,86,5,72,4,96,0,31,0,0,19,33,21,33,17,51,32,23,22,21,17,20,7,6,43,1,53,51,50,55,54,53,17,52,39,38, + 35,33,17,35,17,33,60,4,49,254,66,250,1,7,70,82,82,81,181,193,172,110,33,38,38,44,139,254,252,181,254,66,4,96,147,254,170,71,81,229, + 254,242,213,97,96,156,48,55,147,1,8,166,36,41,254,25,3,205,0,0,0,1,255,250,0,0,4,233,5,213,0,15,0,0,3,33,21,33,17,20, + 22,59,1,21,35,34,38,25,1,33,6,4,239,253,238,109,134,63,77,227,205,253,238,5,213,170,252,215,194,150,170,244,1,14,3,41,0,1,0,60, + 0,0,4,109,4,96,0,17,0,0,19,33,21,33,17,20,23,22,59,1,21,35,34,39,38,53,17,33,60,4,49,254,70,35,35,109,88,110,182,80, + 83,254,69,4,96,147,253,190,145,46,48,156,96,98,212,2,55,0,0,0,0,1,0,175,0,0,4,179,5,213,0,23,0,42,64,11,25,8,28,6, + 19,12,0,28,15,4,24,16,252,236,50,204,212,236,204,49,0,64,10,2,149,11,173,21,149,18,129,7,14,47,60,244,236,244,236,48,1,21,33,50, + 22,21,17,35,17,52,38,35,33,17,35,17,52,54,51,33,21,35,34,6,1,122,1,161,186,222,201,124,124,254,136,203,163,181,1,9,224,105,77,4, + 63,206,233,238,254,102,1,138,159,158,253,57,4,63,214,192,156,97,0,0,255,255,0,186,0,0,4,100,6,20,16,6,2,40,0,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,19,51,21,35,1,17,51,17,214,170,170,1,191,136,5,88,136,251,48,5,88,250,168,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,19,51,21,35,1,17,51,17,214,170,170,1,191,136,4,36,136,252,100,5,88,250,168,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,19,51,21,35,1,17,51,17,214,170,170,1,191,136,2,240,136,253,152,5,88,250,168,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,19,51,21,35,1,17,51,17,214,170,170,1,191,136,1,188,136,254,204,5,88,250,168,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,55,51,21,35,1,51,17,35,214,170,170,1,191,136,136,136,136,5,88,250,168,0,0,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,115,170,170,254,235,136,136,5,88,136,251,48,5,88,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,115,170,170,254,235,136,136,4,36,136,252,100,5,88,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,115,170,170,254,235,136,136,2,240,136,253,152,5,88,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,1,51,21,35,1,35,17,51,2,115,170,170,254,235,136,136,1,188,136,254,204,5,88,0,0,2,0,214, + 0,0,3,29,5,88,0,3,0,7,0,0,37,51,21,35,33,35,17,51,2,115,170,170,254,235,136,136,136,136,5,88,0,1,0,214,0,0,3,29, + 5,88,0,5,0,0,33,35,17,33,21,33,1,94,136,2,71,254,65,5,88,136,0,0,0,1,0,214,0,0,3,29,5,88,0,7,0,0,33,35, + 17,51,17,33,21,33,1,94,136,136,1,191,254,65,5,88,254,204,136,0,0,1,0,214,0,0,3,29,5,88,0,7,0,0,33,35,17,51,17,33, + 21,33,1,94,136,136,1,191,254,65,5,88,253,152,136,0,0,1,0,214,0,0,3,29,5,88,0,7,0,0,33,35,17,51,17,33,21,33,1,94, + 136,136,1,191,254,65,5,88,252,100,136,0,0,1,0,214,0,0,3,29,5,88,0,5,0,0,37,33,21,33,17,51,1,94,1,191,253,185,136,136, + 136,5,88,0,0,1,0,102,2,156,2,142,5,228,0,9,0,0,1,51,23,7,39,17,35,17,7,39,1,94,57,247,76,146,107,147,76,5,228,221, + 67,131,253,85,2,171,131,67,0,1,0,102,2,152,2,142,5,224,0,9,0,0,1,35,39,55,23,17,51,17,55,23,1,151,57,248,76,147,107,146, + 76,2,152,221,67,131,2,171,253,85,131,67,0,2,0,195,2,156,1,67,5,224,0,3,0,9,0,0,19,51,21,35,17,51,17,7,35,39,195,128, + 128,128,13,102,13,3,42,142,3,68,254,145,200,200,0,0,0,2,0,195,2,156,1,67,5,224,0,3,0,9,0,0,1,35,53,51,17,35,17,55, + 51,23,1,67,128,128,128,12,102,14,5,82,142,252,188,1,111,200,200,0,255,255,0,195,0,0,1,67,3,68,16,7,18,248,0,0,253,100,0,0, + 0,1,0,137,0,0,2,205,5,212,0,16,0,0,51,53,32,2,33,53,32,2,33,53,32,19,22,7,22,19,18,207,1,74,20,254,182,1,74,30, + 254,162,2,29,14,9,174,184,6,10,163,2,39,163,1,197,162,254,140,229,99,109,254,251,254,90,0,0,0,1,0,137,0,0,2,145,4,96,0,16, + 0,0,51,53,32,2,33,53,32,2,33,53,32,19,22,7,22,23,18,187,1,44,20,254,212,1,44,30,254,212,1,225,14,8,132,143,6,10,153,1, + 124,153,1,26,152,254,232,158,77,89,188,254,184,0,0,0,0,1,0,115,1,203,3,74,5,240,0,9,0,0,1,16,23,7,2,53,16,33,21,32, + 1,45,117,164,139,2,215,253,227,3,205,254,254,210,46,1,49,212,2,32,219,0,0,0,0,1,0,115,0,86,3,74,4,123,0,9,0,0,1,16, + 23,7,2,53,16,33,21,32,1,45,117,164,139,2,215,253,227,2,88,254,254,210,46,1,49,212,2,32,189,0,0,0,0,1,0,201,254,102,5,59, + 5,213,0,19,0,0,19,51,17,33,17,51,17,16,6,43,1,53,51,50,54,53,17,33,17,35,201,202,2,222,202,205,227,77,63,134,110,253,34,202, + 5,213,253,156,2,100,250,147,254,242,244,170,150,194,2,95,253,57,0,0,0,1,0,186,254,86,4,100,6,20,0,28,0,0,1,52,38,35,34,6, + 21,17,35,17,51,17,62,1,51,50,22,21,17,20,6,43,1,53,51,50,55,54,53,3,172,124,124,149,172,185,185,66,179,117,193,198,163,181,70,49, + 110,33,38,2,158,159,158,190,164,253,135,6,20,253,158,101,100,239,232,253,72,214,192,156,48,56,146,0,0,1,255,250,254,76,6,141,5,213,0,42, + 0,0,3,33,21,33,21,33,21,1,50,23,22,23,22,21,20,7,6,33,34,39,38,39,53,22,23,22,51,50,55,54,53,52,39,38,43,1,53,1, + 33,17,35,17,33,6,4,239,253,238,3,94,254,101,105,129,99,85,81,152,152,254,232,115,129,130,130,106,127,126,137,192,99,100,92,93,165,174,1,129, + 253,158,203,253,238,5,213,170,203,154,254,22,56,43,108,104,138,220,122,121,19,19,36,195,49,25,25,75,75,143,134,73,74,152,1,234,252,74,5,43, + 0,1,0,55,254,76,5,52,5,158,0,48,0,0,1,50,23,22,23,22,21,20,4,33,34,39,38,39,53,30,1,51,50,55,54,53,52,39,38,43, + 1,53,1,33,17,20,22,59,1,21,35,34,38,53,17,35,53,51,17,51,17,33,21,3,65,105,129,99,85,81,254,208,254,232,94,99,100,106,84,200, + 109,190,99,100,92,91,167,174,1,174,253,106,75,115,189,189,213,162,135,135,185,3,101,1,220,56,43,108,104,138,221,242,18,19,37,195,49,50,75,75, + 143,132,75,74,166,1,243,253,164,137,78,154,159,210,2,96,143,1,62,254,194,168,0,0,255,255,0,164,255,227,4,123,5,240,16,6,1,82,0,0, + 0,1,0,133,254,103,3,200,4,124,0,49,0,0,1,38,39,38,53,52,55,54,51,50,22,23,21,38,39,38,35,34,7,6,21,20,23,22,59,1, + 21,35,34,7,6,21,20,23,22,51,50,55,54,55,21,6,7,6,35,34,36,53,52,54,1,139,112,60,60,114,113,196,76,170,98,97,80,81,71,129, + 59,70,68,67,116,155,148,137,72,78,84,85,151,97,81,85,71,90,84,85,80,238,254,254,138,1,172,32,86,85,123,186,104,104,26,38,182,45,20,21, + 62,72,109,109,70,69,152,77,85,133,136,85,85,28,28,56,190,37,19,18,240,229,143,193,0,1,0,186,0,0,3,126,4,96,0,9,0,0,19,33, + 21,33,17,33,21,33,17,35,186,2,196,253,246,1,213,254,43,186,4,96,148,254,211,148,253,245,0,0,255,255,0,111,255,227,3,199,4,123,16,6, + 0,86,0,0,0,3,0,16,0,0,9,238,5,213,0,15,0,18,0,21,0,0,1,51,9,1,51,1,35,3,33,3,43,1,3,33,3,35,9,1, + 33,9,1,33,2,74,229,1,208,1,209,229,2,57,210,136,253,95,136,3,210,136,253,95,136,213,2,172,254,238,2,37,3,115,254,238,2,37,5,213, + 251,62,4,194,250,43,1,127,254,129,1,127,254,129,5,14,253,25,2,231,253,25,0,0,0,4,0,123,255,227,7,39,4,123,0,10,0,53,0,64, + 0,77,0,0,1,34,6,21,20,22,51,50,54,61,1,37,17,35,53,14,1,35,34,39,21,35,53,14,1,35,34,38,53,52,54,51,33,53,52,38, + 35,34,6,7,53,62,1,51,50,23,48,23,53,62,1,51,50,22,1,34,6,21,20,22,51,50,54,61,1,1,22,23,54,51,33,53,52,38,35,34, + 7,6,2,190,223,172,129,111,153,185,3,178,184,63,188,136,110,81,184,63,188,136,172,203,253,251,1,2,167,151,96,182,84,101,190,90,243,120,18,101, + 190,90,243,240,254,145,223,172,129,111,153,185,253,136,53,1,121,199,1,2,167,151,96,91,65,2,51,102,123,98,115,217,180,41,76,253,129,170,102,97, + 39,10,170,102,97,193,162,189,192,18,127,139,46,46,170,39,39,126,20,68,39,39,252,254,180,102,123,98,115,217,180,41,1,104,110,166,60,18,127,139, + 23,16,0,0,0,3,0,16,255,227,9,45,5,240,0,19,0,22,0,32,0,0,1,51,19,54,55,54,33,32,0,17,16,0,33,32,39,38,39,33, + 3,35,9,1,33,0,32,0,17,16,0,32,0,17,16,2,74,229,184,45,112,188,1,59,1,58,1,120,254,136,254,198,254,197,188,80,46,253,103,136, + 213,2,172,254,238,2,37,3,136,254,72,254,253,1,3,1,184,1,1,5,213,254,30,174,125,210,254,91,254,158,254,159,254,91,210,88,114,254,129,5, + 14,253,25,3,37,254,184,254,229,254,230,254,184,1,72,1,26,1,27,0,0,3,0,123,255,227,7,123,4,123,0,34,0,45,0,56,0,0,1,50, + 0,17,16,0,32,39,38,39,14,2,35,34,38,53,52,54,51,33,53,52,38,35,34,6,7,53,62,1,51,32,23,54,1,34,6,21,20,22,51,50, + 54,61,1,1,34,6,16,22,51,50,54,53,52,38,5,121,240,1,18,254,238,254,31,136,55,33,18,96,140,178,177,204,253,251,1,2,167,151,96,182, + 84,101,190,90,1,42,113,138,254,79,223,172,129,111,153,185,2,4,148,172,171,149,147,172,172,4,123,254,200,254,236,254,237,254,199,157,62,82,69,135, + 97,193,162,189,192,18,127,139,46,46,170,39,39,189,189,253,184,102,123,98,115,217,180,41,1,172,231,254,110,231,232,200,199,233,0,0,0,2,0,16, + 255,227,8,113,5,213,0,2,0,22,0,0,9,1,33,1,51,1,22,33,50,54,53,17,51,17,16,0,33,32,3,39,33,3,35,2,188,254,238,2, + 37,254,123,229,1,188,74,1,1,194,174,203,254,223,254,230,254,115,118,37,253,95,136,213,5,14,253,25,3,174,251,114,192,211,240,3,139,252,92,254, + 220,254,214,1,52,104,254,129,0,2,0,123,255,227,7,31,4,123,0,40,0,51,0,0,37,14,1,35,34,38,53,52,54,51,33,53,52,38,35,34, + 6,7,53,62,1,51,50,22,17,21,20,22,51,50,54,53,17,51,17,35,53,14,1,35,32,1,34,6,21,20,22,51,50,54,61,1,3,147,72,162, + 178,177,203,253,251,1,2,167,151,96,182,84,101,190,90,243,240,124,124,149,173,184,184,67,177,117,254,229,254,219,223,172,129,111,153,185,223,141,111,193, + 162,189,192,18,127,139,46,46,170,39,39,252,255,0,190,159,159,190,164,2,123,251,160,172,102,99,2,80,102,123,98,115,217,180,41,0,0,2,0,16, + 0,0,7,180,5,213,0,2,0,13,0,0,9,1,33,19,3,33,3,35,1,51,9,1,51,1,2,188,254,238,2,37,199,136,253,95,136,213,2,58, + 229,1,220,1,215,210,253,199,5,14,253,25,253,217,1,127,254,129,5,213,251,31,4,225,250,43,0,0,0,2,0,123,255,227,6,78,4,123,0,10, + 0,40,0,0,1,34,6,21,20,22,51,50,54,61,1,17,53,14,1,35,34,38,53,52,54,51,33,53,52,38,35,34,6,7,53,62,1,51,50,22, + 25,1,1,51,1,2,190,223,172,129,111,153,185,63,188,136,172,203,253,251,1,2,167,151,96,182,84,101,190,90,243,240,1,94,195,254,92,2,51,102, + 123,98,115,217,180,41,253,205,170,102,97,193,162,189,192,18,127,139,46,46,170,39,39,252,255,0,254,53,3,172,251,160,0,3,0,16,0,0,7,180, + 5,213,0,2,0,18,0,21,0,0,9,1,41,2,21,33,3,35,3,33,3,35,1,51,1,51,1,51,1,35,23,2,188,254,238,2,37,2,126,1, + 103,254,89,146,229,136,253,95,136,213,2,58,229,1,103,233,1,99,210,253,139,105,53,5,14,253,25,168,254,129,1,127,254,129,5,213,252,82,3,174, + 251,170,139,0,0,3,0,123,255,227,6,78,4,123,0,34,0,45,0,48,0,0,33,53,14,1,35,34,38,53,52,54,51,33,53,52,38,35,34,6, + 7,53,62,1,51,50,23,22,23,51,19,51,3,51,21,35,3,1,34,6,21,20,22,51,50,54,61,1,33,35,17,3,117,63,188,136,172,203,253,251, + 1,2,167,151,96,182,84,101,190,90,243,120,103,15,198,154,195,155,155,209,211,254,20,223,172,129,111,153,185,1,71,143,170,102,97,193,162,189,192,18, + 127,139,46,46,170,39,39,126,109,205,1,157,254,99,144,253,205,2,51,102,123,98,115,217,180,41,254,129,0,2,0,16,254,86,7,155,5,213,0,2, + 0,24,0,0,9,1,33,1,6,7,6,43,1,53,51,50,55,54,63,1,3,33,3,35,1,51,9,1,51,2,188,254,238,2,37,1,108,75,77,74, + 124,216,171,76,42,43,50,19,136,253,95,136,213,2,58,229,1,207,1,203,210,5,14,253,25,253,113,198,63,61,170,36,37,133,50,1,127,254,129,5, + 213,251,64,4,192,0,0,0,0,2,0,123,254,86,6,78,4,123,0,39,0,50,0,0,33,53,14,1,35,34,38,53,52,54,51,33,53,52,38,35, + 34,6,7,53,62,1,51,50,22,25,1,1,51,1,14,1,43,1,53,51,50,54,63,1,1,34,6,21,20,22,51,50,54,61,1,3,117,63,188,136, + 172,203,253,251,1,2,167,151,96,182,84,101,190,90,243,240,1,94,195,254,20,78,148,124,147,108,76,84,51,26,254,244,223,172,129,111,153,185,170,102, + 97,193,162,189,192,18,127,139,46,46,170,39,39,252,255,0,254,119,3,106,251,56,200,122,154,72,134,66,2,51,102,123,98,115,217,180,41,0,0,0, + 255,255,0,115,255,227,5,39,5,240,16,6,3,147,0,0,255,255,0,127,255,227,3,245,4,123,16,6,3,25,0,0,0,1,0,10,0,0,5,106, + 5,213,0,18,0,0,19,51,21,51,21,35,17,1,33,9,1,33,1,17,35,17,35,53,51,201,202,191,191,2,158,1,4,253,27,3,26,254,246,253, + 51,202,191,191,5,213,185,170,254,236,2,119,253,72,252,227,2,207,253,49,4,114,170,0,0,1,0,14,0,0,4,164,6,20,0,18,0,0,19,51, + 21,33,21,33,17,1,51,9,1,35,1,17,35,17,35,53,51,194,185,1,34,254,222,2,37,235,253,174,2,107,240,253,199,185,180,180,6,20,172,164, + 253,185,1,227,253,244,253,172,2,35,253,221,4,196,164,0,0,1,0,201,0,0,5,102,5,213,0,9,0,0,19,17,51,17,55,17,33,21,33,17, + 201,202,252,2,215,252,95,2,173,3,40,253,94,77,253,42,170,2,250,0,0,1,0,193,0,0,2,99,6,20,0,7,0,0,19,17,51,17,55,17, + 35,17,193,184,234,184,2,156,3,120,253,5,73,252,158,2,229,0,0,0,0,1,0,83,0,0,4,156,5,213,0,13,0,0,19,51,21,51,21,35, + 17,33,21,33,17,35,53,51,251,202,168,168,2,215,252,95,168,168,5,213,224,164,252,89,170,4,81,164,0,1,0,120,0,0,2,242,6,20,0,11, + 0,0,1,51,17,51,21,35,17,35,17,35,53,51,1,89,184,225,225,184,225,225,6,20,254,226,164,251,174,4,82,164,0,3,0,10,255,227,6,106, + 5,240,0,21,0,29,0,37,0,0,1,32,23,22,19,51,21,35,2,7,6,33,32,39,38,3,35,53,51,18,55,54,4,32,7,6,7,33,38,39, + 19,33,22,23,22,32,55,54,3,59,1,58,188,161,23,129,126,11,176,188,254,198,254,197,188,177,11,126,129,23,162,188,2,23,254,72,129,106,20,3, + 180,19,105,127,252,70,10,119,129,1,184,129,118,5,240,210,181,254,227,144,254,190,196,211,210,196,1,67,144,1,29,181,210,164,164,134,214,214,134,254, + 20,250,151,164,164,151,0,0,0,3,0,10,255,227,5,142,4,123,0,21,0,30,0,39,0,0,1,50,23,22,23,51,21,35,6,7,6,35,34,39, + 38,39,35,53,51,54,55,54,23,34,7,6,7,33,38,39,38,19,33,22,23,22,51,50,55,54,2,205,240,137,111,21,196,192,10,126,137,240,241,136, + 126,10,194,198,21,111,136,241,148,86,63,17,2,115,17,63,86,171,253,131,8,76,86,149,147,86,77,4,123,156,126,205,144,244,144,157,157,144,244,144, + 205,126,156,156,115,85,131,129,85,117,254,37,171,103,115,116,103,0,0,0,0,3,0,115,255,227,10,106,5,240,0,26,0,36,0,46,0,0,1,32, + 23,22,23,54,55,54,33,32,0,17,16,0,33,32,39,38,39,6,7,6,33,32,0,16,0,4,32,0,17,16,0,32,0,17,16,0,32,0,17,16, + 0,32,0,17,16,3,39,1,58,188,47,35,35,46,189,1,59,1,58,1,120,254,136,254,198,254,197,189,46,36,35,46,188,254,198,254,197,254,135,1, + 121,2,23,254,72,254,253,1,3,1,184,1,1,3,144,254,72,254,253,1,3,1,184,1,1,5,240,210,53,61,61,53,210,254,91,254,158,254,159,254, + 91,210,52,61,60,52,211,1,164,2,196,1,165,164,254,184,254,229,254,230,254,184,1,72,1,26,1,27,1,72,254,184,254,229,254,230,254,184,1,72, + 1,26,1,27,0,3,0,113,255,227,7,182,4,123,0,10,0,21,0,49,0,0,1,34,6,16,22,51,50,54,53,52,38,33,34,6,16,22,51,50, + 54,53,52,38,39,50,23,22,23,54,55,54,51,50,0,17,16,0,35,34,39,38,39,6,7,6,35,34,0,17,16,0,5,180,148,172,171,149,147,172, + 172,252,44,148,172,171,149,147,172,172,147,240,137,21,18,18,21,137,241,240,1,18,254,238,240,241,137,21,18,18,21,137,240,241,254,239,1,17,3,223, + 231,254,110,231,232,200,199,233,231,254,110,231,232,200,199,233,156,156,24,27,27,24,156,254,200,254,236,254,237,254,199,157,24,27,27,24,157,1,57,1, + 19,1,20,1,56,0,0,0,0,2,0,10,0,0,4,141,5,213,0,8,0,29,0,0,1,17,51,50,54,53,52,38,35,37,33,50,23,22,21,20, + 7,6,43,1,21,51,21,35,17,35,17,35,53,51,1,147,254,141,154,154,141,254,56,1,200,251,128,129,129,128,251,254,237,237,202,191,191,5,47,253, + 207,146,135,134,146,166,113,114,219,221,113,113,196,144,254,252,1,4,144,0,0,2,255,251,254,86,4,164,4,123,0,7,0,31,0,0,0,16,38,32, + 6,16,22,32,1,53,51,17,51,21,62,1,51,50,0,16,2,35,34,38,39,17,51,21,35,21,35,53,3,229,167,254,220,167,167,1,36,252,189,191, + 185,58,177,123,204,0,255,255,204,123,177,58,254,254,185,1,100,1,150,231,231,254,106,231,254,103,144,4,236,170,100,97,254,188,253,240,254,188,97,100, + 254,204,144,142,142,0,0,0,0,2,0,50,0,0,5,153,5,213,0,30,0,39,0,0,1,33,50,4,21,20,4,43,1,17,35,17,35,34,7,6, + 21,22,23,22,23,7,38,39,38,53,52,55,54,59,3,50,54,53,52,38,43,1,1,213,1,200,251,1,1,254,255,251,254,202,45,92,48,58,1,26, + 23,60,68,79,69,70,127,97,162,33,202,254,141,154,154,141,254,5,213,227,219,221,226,253,168,2,88,24,31,61,53,39,32,24,148,23,73,75,125,147, + 76,59,146,135,134,146,0,0,0,2,0,50,254,86,5,194,4,123,0,12,0,49,0,0,1,23,22,51,50,55,54,53,52,38,32,6,21,3,38,35, + 34,7,6,21,20,23,22,23,7,38,39,38,53,52,55,54,51,50,23,17,51,21,62,1,51,50,0,16,2,35,34,39,17,35,2,145,10,157,146,142, + 88,83,167,254,220,167,185,51,41,44,52,58,27,23,60,68,79,69,70,127,84,103,53,55,185,58,177,123,204,0,255,255,202,192,168,185,1,50,11,170, + 115,112,207,203,231,231,203,254,227,25,24,27,65,52,40,32,24,148,23,73,75,125,134,89,59,23,2,166,170,100,97,254,188,253,240,254,188,162,253,209, + 0,2,0,115,254,148,5,217,5,240,0,9,0,35,0,0,0,32,0,17,16,0,32,0,17,16,1,39,55,39,7,6,35,32,0,17,16,0,33,32, + 0,17,16,2,7,23,55,23,7,23,35,39,4,3,254,72,254,253,1,3,1,184,1,1,254,128,72,170,107,51,18,15,254,197,254,135,1,121,1,59, + 1,58,1,120,209,198,69,215,72,188,98,244,14,5,76,254,184,254,229,254,230,254,184,1,72,1,26,1,27,250,144,125,98,116,3,1,1,165,1,97, + 1,98,1,165,254,91,254,158,254,252,254,142,88,75,124,125,108,107,15,0,0,2,0,113,254,86,5,25,4,123,0,23,0,31,0,0,37,14,1,35, + 34,2,16,0,51,50,22,23,53,51,17,51,21,35,21,35,53,35,53,33,0,16,22,32,54,16,38,32,3,162,58,177,124,203,255,0,255,203,124,177, + 58,184,191,191,184,255,0,255,253,141,167,1,36,168,168,254,220,168,100,97,1,68,2,16,1,68,97,100,170,251,20,144,142,142,144,3,134,254,106,231, + 231,1,150,231,0,2,0,10,0,0,4,141,5,213,0,7,0,27,0,0,1,17,51,50,54,16,38,35,1,51,21,51,21,35,21,51,50,4,16,4, + 43,1,17,35,17,35,53,51,1,147,254,141,154,153,142,254,56,202,237,237,254,251,1,1,254,255,251,254,202,191,191,4,39,253,209,146,1,12,145,1, + 174,45,144,75,225,254,72,226,254,174,5,24,144,0,0,0,0,2,255,251,254,86,4,164,6,20,0,7,0,31,0,0,0,16,38,32,6,16,22,32, + 37,17,35,17,35,53,51,53,51,21,51,21,35,17,62,1,51,50,0,16,2,35,34,38,3,229,167,254,220,167,167,1,36,254,53,185,191,191,185,254, + 254,58,177,123,204,0,255,255,204,123,177,1,100,1,150,231,231,254,106,231,43,253,174,6,155,144,147,147,144,254,197,100,97,254,188,253,240,254,188,97, + 0,2,0,10,0,0,4,141,5,213,0,7,0,27,0,0,1,17,51,50,54,16,38,35,1,51,17,51,50,4,16,4,43,1,21,51,21,35,21,35, + 53,35,53,51,1,147,254,141,154,153,142,254,56,202,254,251,1,1,254,255,251,254,237,237,202,191,191,4,39,253,209,146,1,12,145,1,174,254,248,225, + 254,72,226,94,144,100,100,144,0,2,255,251,254,86,4,164,6,20,0,7,0,31,0,0,0,16,38,32,6,16,22,32,1,53,51,17,51,17,62,1, + 51,50,0,16,2,35,34,38,39,17,51,21,35,21,35,53,3,229,167,254,220,167,167,1,36,252,189,191,185,58,177,123,204,0,255,255,204,123,177,58, + 254,254,185,1,100,1,150,231,231,254,106,231,254,103,144,6,160,253,162,100,97,254,188,253,240,254,188,97,100,254,204,144,142,142,0,0,0,1,0,11, + 0,0,3,172,5,213,0,5,0,0,33,35,17,33,53,33,3,172,202,253,41,3,161,5,43,170,0,0,0,2,0,193,254,86,1,121,4,123,0,0, + 0,4,0,0,1,7,51,17,35,1,29,92,184,184,4,123,27,249,246,0,0,1,0,201,254,86,5,25,5,240,0,20,0,0,1,52,38,35,34,6, + 21,17,35,17,51,21,54,55,54,51,50,18,25,1,35,4,80,154,153,179,215,202,202,81,102,101,158,227,233,201,3,127,215,213,255,222,251,8,7,127, + 241,135,67,66,254,193,254,204,252,131,0,0,0,1,0,186,254,86,4,100,4,123,0,19,0,0,1,17,35,17,52,38,35,34,6,21,17,35,17,51, + 21,62,1,51,50,22,4,100,184,124,124,149,172,185,185,66,179,117,193,198,2,164,253,92,2,158,159,158,190,164,251,221,6,10,174,101,100,239,0,0, + 255,255,0,240,0,0,1,195,4,35,18,6,0,29,0,0,0,2,0,160,1,73,2,98,3,11,0,3,0,7,0,0,1,33,53,33,53,33,53,33, + 2,98,254,62,1,194,254,62,1,194,1,73,150,150,150,0,0,1,1,53,1,225,2,0,5,213,0,5,0,58,64,11,3,0,129,6,4,3,1,3, + 0,0,6,16,252,75,176,11,84,88,185,0,0,255,192,56,89,236,57,57,49,0,16,228,204,64,9,32,3,95,3,176,3,239,3,4,93,48,1,182, + 0,7,32,7,80,7,3,93,1,51,17,3,35,3,1,53,203,20,162,21,5,213,253,113,254,155,1,101,0,1,0,197,3,170,1,111,5,213,0,3, + 0,55,64,10,1,132,0,129,4,0,5,2,4,4,16,252,75,176,18,84,75,176,19,84,91,88,185,0,2,255,192,56,89,236,49,0,16,244,236,48, + 1,64,13,64,5,80,5,96,5,112,5,144,5,160,5,6,93,1,17,35,17,1,111,170,5,213,253,213,2,43,0,0,255,255,0,175,0,0,4,179, + 5,213,18,6,3,187,0,0,0,2,0,77,254,86,3,84,6,20,0,6,0,31,0,0,1,38,35,34,7,20,51,55,17,51,17,51,21,35,17,20, + 22,59,1,21,35,34,38,53,48,3,35,32,55,54,51,50,1,146,23,55,77,1,92,80,184,250,250,61,120,49,70,191,153,2,60,254,232,1,1,245, + 53,3,18,132,75,57,250,2,8,252,254,160,253,112,124,116,156,204,202,2,134,189,246,0,0,1,0,201,254,191,5,221,5,213,0,13,0,0,19,33, + 1,17,51,17,51,17,35,17,33,1,17,35,201,1,16,2,150,196,170,170,254,240,253,106,196,5,213,251,31,4,225,250,213,254,21,1,65,4,225,251, + 31,0,0,0,0,1,0,186,254,229,4,247,4,123,0,23,0,0,1,17,51,17,35,17,35,17,52,38,35,34,6,21,17,35,17,51,21,62,1,51, + 50,22,4,100,147,147,184,124,124,149,172,185,185,66,179,117,193,198,2,164,253,239,254,82,1,27,2,158,159,158,190,164,253,135,4,96,174,101,100,239, + 0,1,0,4,255,227,6,57,5,240,0,40,0,0,37,17,33,53,33,17,6,4,35,36,39,38,39,7,39,55,38,53,16,0,33,50,4,23,21,46, + 1,35,32,7,6,3,1,23,1,22,23,22,33,50,54,4,195,254,182,2,18,117,254,230,160,254,162,198,141,40,84,43,112,1,1,139,1,94,146,1, + 7,111,112,252,139,254,239,138,135,3,4,198,43,251,22,25,106,138,1,17,107,168,213,1,145,166,253,127,83,85,1,204,146,226,28,127,37,30,31,1, + 110,1,153,72,70,215,95,96,153,151,254,217,1,149,127,254,95,207,119,153,37,0,0,0,0,3,0,4,254,86,5,16,4,123,0,38,0,48,0,58, + 0,0,37,16,2,33,34,38,39,53,30,1,51,50,54,61,1,14,1,35,34,39,38,39,7,39,55,38,53,16,18,51,50,22,23,53,51,17,55,23, + 15,1,5,22,23,22,51,50,54,53,52,39,38,39,38,35,34,6,21,20,23,4,90,254,254,250,97,172,81,81,158,82,181,180,57,178,124,206,126,67, + 31,104,33,116,7,252,206,124,178,57,184,149,33,182,185,253,159,20,46,82,148,149,165,13,19,50,82,150,148,165,2,139,254,226,254,233,29,30,179,44, + 42,189,191,91,99,98,157,83,112,35,99,39,56,62,1,4,1,58,98,99,170,254,177,50,99,61,61,203,87,60,110,220,199,21,126,98,65,110,220,200, + 29,28,0,0,0,2,0,4,0,0,5,106,5,213,0,19,0,22,0,0,19,51,17,1,33,1,23,37,23,5,1,33,1,7,17,35,17,7,39,55, + 37,39,21,201,202,2,158,1,4,253,27,121,2,82,43,253,237,2,55,254,246,254,11,216,202,154,43,197,1,56,110,5,213,253,137,2,119,253,72,122, + 197,127,176,253,199,1,247,72,254,81,1,108,51,127,65,104,110,147,0,0,0,2,0,4,0,0,4,158,6,20,0,19,0,22,0,0,19,51,17,1, + 51,1,23,37,23,5,1,35,1,7,17,35,53,7,39,55,37,39,21,186,185,2,37,235,253,174,94,1,238,33,254,70,1,184,240,254,133,190,185,149, + 33,182,1,34,105,6,20,252,105,1,227,253,244,91,164,98,147,254,88,1,108,63,254,211,240,50,99,60,97,101,136,0,0,3,0,4,0,0,5,248, + 5,213,0,19,0,22,0,25,0,0,19,33,1,37,17,51,17,55,23,7,17,33,1,5,17,35,17,7,39,55,37,3,17,37,19,17,201,1,16,1, + 94,1,56,196,154,43,197,254,240,254,166,254,196,196,154,43,197,1,192,252,1,234,248,5,213,253,107,103,2,46,254,19,51,127,65,252,165,2,142,105, + 253,219,1,228,51,127,65,149,1,219,253,209,22,254,44,2,38,0,0,0,0,2,0,4,0,0,5,16,4,123,0,23,0,32,0,0,1,17,35,17, + 5,17,35,17,7,39,55,17,51,21,62,1,51,54,23,22,23,55,23,7,39,38,39,38,35,34,6,29,1,4,100,184,253,199,185,149,33,182,185,66, + 179,117,193,99,74,19,145,33,172,186,9,51,62,124,149,172,2,164,253,92,2,106,190,254,84,1,111,50,99,61,2,131,174,101,100,1,120,89,153,49, + 99,57,48,117,64,79,190,164,95,0,0,0,0,3,0,4,0,0,5,139,5,213,0,29,0,36,0,43,0,0,1,30,1,23,19,35,3,46,1,43, + 1,17,35,17,7,39,55,17,33,32,23,22,23,55,23,7,22,21,20,6,45,1,38,39,38,39,35,17,21,51,22,55,54,55,3,141,65,123,62,205, + 217,191,74,139,120,220,202,154,43,197,1,200,1,0,126,73,31,233,43,255,1,131,253,137,2,25,18,44,74,147,254,254,147,74,61,11,2,188,22,144, + 126,254,104,1,127,150,98,253,137,3,1,51,127,66,2,70,107,62,100,78,127,85,13,14,141,186,242,179,63,40,66,1,254,22,40,1,68,56,99,0, + 0,1,0,4,0,0,3,74,4,123,0,25,0,0,1,46,1,35,34,6,29,1,37,23,5,17,35,17,7,39,55,17,51,21,62,1,51,50,22,23, + 3,74,31,73,44,156,167,1,178,33,254,45,185,149,33,182,185,58,186,133,19,46,28,3,180,18,17,203,190,52,144,98,156,254,84,1,111,50,99,60, + 2,132,174,102,99,5,5,0,0,1,0,4,255,227,5,16,5,240,0,47,0,0,1,21,46,1,35,34,6,21,20,22,31,1,37,23,5,22,23,22, + 21,20,4,33,34,38,39,53,30,1,51,50,54,53,52,38,47,1,5,39,37,38,39,38,53,52,36,51,50,22,4,72,115,204,95,165,179,119,166,84, + 2,34,43,254,153,87,54,108,254,221,254,231,106,239,128,123,236,114,173,188,135,154,97,253,226,43,1,101,77,48,101,1,23,245,105,218,5,164,197,55, + 54,128,118,99,101,31,17,181,127,119,39,56,108,182,217,224,48,47,208,69,70,136,126,110,124,31,19,180,127,119,34,46,96,171,198,228,38,0,0,0, + 0,1,0,4,255,227,4,39,4,123,0,47,0,0,1,21,46,1,35,34,6,21,20,22,31,1,37,23,5,22,23,22,23,20,6,35,34,38,39,53, + 30,1,51,50,54,53,52,38,47,1,5,39,37,38,39,38,53,52,54,51,50,22,3,139,78,168,90,137,137,98,148,45,1,186,33,254,214,75,44,82, + 1,247,216,90,195,108,102,198,97,130,140,101,171,36,254,79,33,1,35,62,38,76,224,206,102,180,4,63,174,40,40,84,84,64,73,33,10,147,99,99, + 32,40,76,137,156,182,35,35,190,53,53,89,81,75,80,37,8,144,99,97,27,38,74,131,158,172,30,0,0,1,255,151,0,0,5,159,5,213,0,20, + 0,0,1,14,1,29,1,35,53,52,54,59,1,17,33,17,51,17,35,17,33,17,35,1,45,132,118,156,192,214,202,2,222,202,202,253,34,202,5,48, + 1,94,105,49,70,181,163,253,156,2,100,250,43,2,199,253,57,0,0,0,255,255,0,186,0,0,6,152,4,96,18,6,3,220,0,0,0,1,0,119, + 0,0,3,209,5,213,0,9,0,0,1,17,35,17,33,53,33,17,33,53,3,209,202,253,176,2,80,253,112,5,213,250,43,2,201,170,1,184,170,0, + 0,2,0,70,0,0,4,10,5,213,0,8,0,19,0,0,1,35,34,6,21,20,22,59,1,19,17,35,17,35,34,36,53,52,36,51,3,64,254,141, + 154,154,141,254,202,202,254,251,254,255,1,1,251,5,47,146,134,135,146,2,215,250,43,2,88,226,221,219,227,0,0,0,0,1,0,201,0,0,6,31, + 5,213,0,12,0,0,51,17,51,17,1,51,1,17,51,17,33,9,1,201,196,1,129,203,1,129,197,254,211,254,129,254,131,5,213,250,225,4,0,252, + 0,5,31,250,43,3,248,252,8,0,0,0,0,1,0,201,0,0,1,147,7,109,0,3,0,0,19,51,17,35,201,202,202,7,109,248,147,0,0,0, + 0,1,0,68,0,0,9,85,5,213,0,15,0,0,37,1,51,9,1,51,1,35,9,1,35,9,1,35,1,51,3,244,1,62,227,1,58,1,57,205, + 254,137,254,254,197,254,194,227,254,198,254,199,205,1,119,254,197,5,16,251,18,4,238,250,43,5,16,250,240,4,238,251,18,5,213,0,0,1,0,194, + 4,208,2,149,5,88,0,3,0,17,182,1,169,2,4,3,1,4,16,196,212,49,0,16,212,236,48,1,33,53,33,2,149,254,45,1,211,4,208,136, + 0,1,0,141,3,156,2,189,5,88,0,4,0,0,19,39,1,51,21,214,73,2,8,40,3,156,115,1,73,136,0,0,0,1,0,110,2,104,2,228, + 5,88,0,5,0,0,1,35,1,39,1,51,2,228,16,254,2,104,2,39,79,4,208,253,152,87,2,153,0,1,0,96,1,52,2,242,5,88,0,5, + 0,0,1,35,1,39,1,51,2,242,14,253,242,118,2,53,93,4,208,252,100,68,3,224,0,1,0,90,0,0,2,249,5,88,0,5,0,0,1,35, + 1,39,1,51,2,249,11,253,232,124,2,59,100,4,208,251,48,55,5,33,0,1,0,141,3,156,2,189,5,88,0,4,0,0,19,1,21,35,1,214, + 1,231,40,253,248,5,88,254,204,136,1,73,255,255,0,194,3,156,2,149,4,36,16,7,19,69,0,0,254,204,0,0,255,255,0,141,2,104,2,189, + 4,36,16,7,19,70,0,0,254,204,0,0,255,255,0,110,1,52,2,228,4,36,16,7,19,71,0,0,254,204,0,0,255,255,0,96,0,0,2,242, + 4,36,16,7,19,72,0,0,254,204,0,0,0,1,0,110,2,104,2,228,5,88,0,5,0,0,1,21,35,1,55,1,2,228,79,253,217,104,1,254, + 2,240,136,2,153,87,253,152,255,255,0,141,2,104,2,189,4,36,16,7,19,74,0,0,254,204,0,0,255,255,0,194,2,104,2,149,2,240,16,7, + 19,69,0,0,253,152,0,0,255,255,0,141,1,52,2,189,2,240,16,7,19,70,0,0,253,152,0,0,255,255,0,110,0,0,2,228,2,240,16,7, + 19,71,0,0,253,152,0,0,0,1,0,96,1,52,2,242,5,88,0,5,0,0,1,21,35,1,55,1,2,242,93,253,203,118,2,14,1,188,136,3, + 224,68,252,100,255,255,0,110,1,52,2,228,4,36,16,7,19,79,0,0,254,204,0,0,255,255,0,141,1,52,2,189,2,240,16,7,19,74,0,0, + 253,152,0,0,255,255,0,194,1,52,2,149,1,188,16,7,19,69,0,0,252,100,0,0,255,255,0,141,0,0,2,189,1,188,16,7,19,70,0,0, + 252,100,0,0,0,1,0,90,0,0,2,249,5,88,0,5,0,0,37,21,35,1,55,1,2,249,100,253,197,124,2,24,136,136,5,33,55,251,48,0, + 255,255,0,96,0,0,2,242,4,36,16,7,19,84,0,0,254,204,0,0,255,255,0,110,0,0,2,228,2,240,16,7,19,79,0,0,253,152,0,0, + 255,255,0,141,0,0,2,189,1,188,16,7,19,74,0,0,252,100,0,0,255,255,0,194,0,0,2,149,0,136,17,7,19,69,0,0,251,48,0,7, + 177,0,4,0,16,60,48,0,0,1,0,214,0,0,1,94,5,88,0,3,0,14,181,2,1,0,8,3,4,16,212,236,49,0,196,196,51,17,51,17, + 214,136,5,88,250,168,0,0,0,14,0,150,0,0,7,58,5,220,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43, + 0,47,0,51,0,55,1,218,183,47,36,48,40,55,44,52,56,16,220,60,220,60,60,60,60,182,31,35,43,32,51,28,39,220,60,60,60,60,220,60, + 182,20,12,27,19,8,16,24,220,60,220,60,60,60,60,182,3,7,15,4,23,0,11,220,60,60,60,60,220,60,176,57,204,176,88,75,82,88,176,56, + 16,75,176,10,98,102,32,176,0,84,88,177,51,48,60,60,89,32,176,64,84,88,64,10,51,48,47,44,55,52,43,40,39,36,60,60,60,60,60,60, + 60,60,60,60,89,32,176,128,84,88,179,35,32,47,44,60,60,60,60,89,32,176,192,84,88,179,55,52,47,44,60,60,60,60,89,32,184,1,0,84, + 88,181,43,40,39,36,55,52,60,60,60,60,60,60,89,32,184,1,64,84,88,179,55,52,31,28,60,60,60,60,89,32,184,1,128,84,88,177,31,28, + 60,60,89,32,184,1,192,84,88,183,43,40,51,48,55,52,47,44,60,60,60,60,60,60,60,60,89,184,16,0,98,184,2,128,99,75,35,97,32,176, + 0,84,88,177,23,20,60,60,89,32,176,1,84,88,64,10,15,12,27,24,23,20,19,16,11,8,60,60,60,60,60,60,60,60,60,60,89,32,176,2, + 84,88,179,7,4,19,16,60,60,60,60,89,32,176,3,84,88,179,19,16,27,24,60,60,60,60,89,32,176,4,84,88,181,27,24,11,8,15,12,60, + 60,60,60,60,60,89,32,176,5,84,88,179,3,0,27,24,60,60,60,60,89,32,176,6,84,88,177,3,0,60,60,89,32,176,7,84,88,183,19,16, + 23,20,27,24,15,12,60,60,60,60,60,60,60,60,89,176,9,84,88,177,27,24,60,60,89,27,182,15,12,43,40,39,36,56,16,60,60,60,60,60, + 60,183,7,4,3,0,11,8,23,20,60,60,60,60,60,60,60,60,89,49,0,183,4,13,24,32,52,41,12,40,47,60,220,60,60,60,60,60,181,5, + 20,25,33,48,53,220,60,60,60,60,60,181,0,21,16,28,49,44,220,60,60,60,60,60,183,9,37,1,8,17,29,36,45,220,60,60,60,60,60,220, + 60,48,1,17,51,17,3,17,51,17,1,53,33,21,1,53,33,21,1,17,51,17,21,53,33,21,1,17,51,17,1,17,51,17,3,17,51,17,1,53, + 33,21,1,53,33,21,1,17,51,17,21,53,33,21,1,17,51,17,6,214,100,100,100,253,118,2,38,253,218,2,38,253,118,100,2,38,253,118,100,254, + 112,100,100,100,253,118,2,38,253,218,2,38,253,118,100,2,38,253,118,100,3,37,2,78,253,178,253,68,2,78,253,178,5,15,100,100,250,136,100,100, + 3,37,2,78,253,178,105,100,100,253,173,2,78,253,178,2,188,2,78,253,178,253,68,2,78,253,178,5,15,100,100,250,136,100,100,3,37,2,78,253, + 178,105,100,100,253,173,2,78,253,178,0,0,0,14,0,150,0,0,7,58,5,220,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35, + 0,39,0,43,0,47,0,51,0,55,1,224,183,47,36,48,40,55,44,52,56,16,220,60,220,60,60,60,60,182,31,35,43,32,51,28,39,220,60,60, + 60,60,220,60,182,20,12,27,19,8,16,24,220,60,220,60,60,60,60,182,3,7,15,4,23,0,11,220,60,60,60,60,220,60,176,57,204,176,88,0, + 75,1,82,88,176,56,16,0,75,1,176,10,98,102,32,176,0,84,88,177,51,48,60,60,89,32,176,64,84,88,64,10,51,48,47,44,55,52,43,40, + 39,36,60,60,60,60,60,60,60,60,60,60,89,32,176,128,84,88,179,35,32,47,44,60,60,60,60,89,32,176,192,84,88,179,55,52,47,44,60,60, + 60,60,89,32,184,1,0,84,88,181,43,40,39,36,55,52,60,60,60,60,60,60,89,32,184,1,64,84,88,179,55,52,31,28,60,60,60,60,89,32, + 184,1,128,84,88,177,31,28,60,60,89,32,184,1,192,84,88,183,43,40,51,48,55,52,47,44,60,60,60,60,60,60,60,60,89,184,16,0,98,184, + 2,128,99,0,75,1,35,97,32,176,0,84,88,177,23,20,60,60,89,32,176,1,84,88,64,10,15,12,27,24,23,20,19,16,11,8,60,60,60,60, + 60,60,60,60,60,60,89,32,176,2,84,88,179,7,4,19,16,60,60,60,60,89,32,176,3,84,88,179,19,16,27,24,60,60,60,60,89,32,176,4, + 84,88,181,27,24,11,8,15,12,60,60,60,60,60,60,89,32,176,5,84,88,179,3,0,27,24,60,60,60,60,89,32,176,6,84,88,177,3,0,60, + 60,89,32,176,7,84,88,183,19,16,23,20,27,24,15,12,60,60,60,60,60,60,60,60,89,176,9,84,88,177,27,24,60,60,89,27,182,15,12,43, + 40,39,36,56,16,60,60,60,60,60,60,183,7,4,3,0,11,8,23,20,60,60,60,60,60,60,60,60,89,49,0,183,4,13,24,32,52,41,12,40, + 47,60,220,60,60,60,60,60,181,5,20,25,33,48,53,220,60,60,60,60,60,181,0,21,16,28,49,44,220,60,60,60,60,60,183,9,37,1,8,17, + 29,36,45,220,60,60,60,60,60,220,60,48,1,17,51,17,3,17,51,17,1,53,33,21,1,53,33,21,1,17,51,17,21,53,33,21,1,17,51,17, + 1,17,51,17,3,17,51,17,1,53,33,21,1,53,33,21,1,17,51,17,21,53,33,21,1,17,51,17,6,214,100,100,100,253,118,2,38,253,218,2, + 38,253,118,100,2,38,253,118,100,254,112,100,100,100,253,118,2,38,253,218,2,38,253,118,100,2,38,253,118,100,3,27,2,88,253,168,253,68,2,88, + 253,168,5,25,100,100,250,136,100,100,3,27,2,88,253,168,95,100,100,253,163,2,88,253,168,2,188,2,88,253,168,253,68,2,88,253,168,5,25,100, + 100,250,136,100,100,3,27,2,88,253,168,95,100,100,253,163,2,88,253,168,0,14,0,150,0,0,7,58,5,220,0,3,0,7,0,11,0,15,0,19, + 0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,1,218,183,47,36,48,40,55,44,52,56,16,220,60,220,60,60,60,60,182,31,35, + 43,32,51,28,39,220,60,60,60,60,220,60,182,20,12,27,19,8,16,24,220,60,220,60,60,60,60,182,3,7,15,4,23,0,11,220,60,60,60,60, + 220,60,176,57,204,176,88,76,82,88,176,56,16,76,176,10,98,102,32,176,0,84,88,177,51,48,60,60,89,32,176,64,84,88,64,10,51,48,47,44, + 55,52,43,40,39,36,60,60,60,60,60,60,60,60,60,60,89,32,176,128,84,88,179,35,32,47,44,60,60,60,60,89,32,176,192,84,88,179,55,52, + 47,44,60,60,60,60,89,32,184,1,0,84,88,181,43,40,39,36,55,52,60,60,60,60,60,60,89,32,184,1,64,84,88,179,55,52,31,28,60,60, + 60,60,89,32,184,1,128,84,88,177,31,28,60,60,89,32,184,1,192,84,88,183,43,40,51,48,55,52,47,44,60,60,60,60,60,60,60,60,89,184, + 16,0,98,184,2,128,99,76,35,97,32,176,0,84,88,177,23,20,60,60,89,32,176,1,84,88,64,10,15,12,27,24,23,20,19,16,11,8,60,60, + 60,60,60,60,60,60,60,60,89,32,176,2,84,88,179,7,4,19,16,60,60,60,60,89,32,176,3,84,88,179,19,16,27,24,60,60,60,60,89,32, + 176,4,84,88,181,27,24,11,8,15,12,60,60,60,60,60,60,89,32,176,5,84,88,179,3,0,27,24,60,60,60,60,89,32,176,6,84,88,177,3, + 0,60,60,89,32,176,7,84,88,183,19,16,23,20,27,24,15,12,60,60,60,60,60,60,60,60,89,176,9,84,88,177,27,24,60,60,89,27,182,15, + 12,43,40,39,36,56,16,60,60,60,60,60,60,183,7,4,3,0,11,8,23,20,60,60,60,60,60,60,60,60,89,49,0,183,4,13,24,32,52,41, + 12,40,47,60,220,60,60,60,60,60,181,5,20,25,33,48,53,220,60,60,60,60,60,181,0,21,16,28,49,44,220,60,60,60,60,60,183,9,37,1, + 8,17,29,36,45,220,60,60,60,60,60,220,60,48,1,17,51,17,3,17,51,17,1,53,33,21,1,53,33,21,1,17,51,17,21,53,33,21,1,17, + 51,17,1,17,51,17,3,17,51,17,1,53,33,21,1,53,33,21,1,17,51,17,21,53,33,21,1,17,51,17,6,214,100,100,100,253,118,2,38,253, + 218,2,38,253,118,100,2,38,253,118,100,254,112,100,100,100,253,118,2,38,253,218,2,38,253,118,100,2,38,253,118,100,3,37,2,78,253,178,253,68, + 2,78,253,178,5,15,100,100,250,136,100,100,3,37,2,78,253,178,105,100,100,253,173,2,78,253,178,2,188,2,78,253,178,253,68,2,78,253,178,5, + 15,100,100,250,136,100,100,3,37,2,78,253,178,105,100,100,253,173,2,78,253,178,0,0,0,14,0,150,0,0,7,58,5,220,0,3,0,7,0,11, + 0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,1,224,183,47,36,48,40,55,44,52,56,16,220,60,220,60,60,60, + 60,182,31,35,43,32,51,28,39,220,60,60,60,60,220,60,182,20,12,27,19,8,16,24,220,60,220,60,60,60,60,182,3,7,15,4,23,0,11,220, + 60,60,60,60,220,60,176,57,204,176,88,0,76,1,82,88,176,56,16,0,76,1,176,10,98,102,32,176,0,84,88,177,51,48,60,60,89,32,176,64, + 84,88,64,10,51,48,47,44,55,52,43,40,39,36,60,60,60,60,60,60,60,60,60,60,89,32,176,128,84,88,179,35,32,47,44,60,60,60,60,89, + 32,176,192,84,88,179,55,52,47,44,60,60,60,60,89,32,184,1,0,84,88,181,43,40,39,36,55,52,60,60,60,60,60,60,89,32,184,1,64,84, + 88,179,55,52,31,28,60,60,60,60,89,32,184,1,128,84,88,177,31,28,60,60,89,32,184,1,192,84,88,183,43,40,51,48,55,52,47,44,60,60, + 60,60,60,60,60,60,89,184,16,0,98,184,2,128,99,0,76,1,35,97,32,176,0,84,88,177,23,20,60,60,89,32,176,1,84,88,64,10,15,12, + 27,24,23,20,19,16,11,8,60,60,60,60,60,60,60,60,60,60,89,32,176,2,84,88,179,7,4,19,16,60,60,60,60,89,32,176,3,84,88,179, + 19,16,27,24,60,60,60,60,89,32,176,4,84,88,181,27,24,11,8,15,12,60,60,60,60,60,60,89,32,176,5,84,88,179,3,0,27,24,60,60, + 60,60,89,32,176,6,84,88,177,3,0,60,60,89,32,176,7,84,88,183,19,16,23,20,27,24,15,12,60,60,60,60,60,60,60,60,89,176,9,84, + 88,177,27,24,60,60,89,27,182,15,12,43,40,39,36,56,16,60,60,60,60,60,60,183,7,4,3,0,11,8,23,20,60,60,60,60,60,60,60,60, + 89,49,0,183,4,13,24,32,52,41,12,40,47,60,220,60,60,60,60,60,181,5,20,25,33,48,53,220,60,60,60,60,60,181,0,21,16,28,49,44, + 220,60,60,60,60,60,183,9,37,1,8,17,29,36,45,220,60,60,60,60,60,220,60,48,1,17,51,17,3,17,51,17,1,53,33,21,1,53,33,21, + 1,17,51,17,21,53,33,21,1,17,51,17,1,17,51,17,3,17,51,17,1,53,33,21,1,53,33,21,1,17,51,17,21,53,33,21,1,17,51,17, + 6,214,100,100,100,253,118,2,38,253,218,2,38,253,118,100,2,38,253,118,100,254,112,100,100,100,253,118,2,38,253,218,2,38,253,118,100,2,38,253, + 118,100,3,27,2,88,253,168,253,68,2,88,253,168,5,25,100,100,250,136,100,100,3,27,2,88,253,168,95,100,100,253,163,2,88,253,168,2,188,2, + 88,253,168,253,68,2,88,253,168,5,25,100,100,250,136,100,100,3,27,2,88,253,168,95,100,100,253,163,2,88,253,168,0,1,0,110,255,226,4,54, + 6,159,0,21,0,0,1,21,16,33,32,17,53,19,51,3,21,16,33,32,17,53,52,0,17,51,22,0,4,54,254,38,254,18,59,200,69,1,48,1, + 38,254,15,181,1,1,239,2,161,159,253,224,2,37,139,1,9,254,218,115,254,128,1,138,184,249,1,203,1,23,197,254,7,0,0,0,0,2,0,110, + 255,226,4,54,6,159,0,9,0,28,0,0,1,18,37,4,3,21,16,33,32,17,55,21,16,32,17,53,16,37,51,54,39,38,39,51,20,22,7,51, + 4,3,130,1,254,201,254,225,1,1,38,1,48,180,252,56,1,147,20,52,134,133,2,207,218,37,20,1,96,2,157,1,103,11,8,254,130,85,254,78, + 1,173,75,55,253,159,2,97,60,1,235,61,163,81,82,178,108,158,243,69,0,2,0,110,255,226,4,143,6,179,0,9,0,33,0,0,1,16,33,32, + 17,21,16,33,32,17,55,21,16,33,32,17,53,16,37,51,54,39,54,35,34,21,35,16,33,32,3,6,7,4,3,210,254,183,254,163,1,88,1,78, + 189,253,241,253,238,2,7,94,77,2,1,190,182,164,1,87,1,92,1,12,68,1,38,2,126,1,164,254,98,95,254,93,1,163,97,87,253,179,2,62, + 120,1,214,78,92,97,154,196,1,100,254,193,139,85,114,0,0,2,0,110,0,0,6,175,6,179,0,36,0,46,0,0,37,54,55,0,17,53,16,33, + 50,23,54,33,32,17,21,16,5,36,17,53,52,55,38,35,32,17,21,16,1,23,4,23,33,38,39,36,7,1,16,33,32,3,21,2,5,36,19,1, + 13,99,127,254,127,1,185,169,159,101,1,2,1,217,254,39,254,52,39,84,173,254,251,1,168,212,1,135,56,254,248,13,238,254,254,245,4,133,254,229, + 254,239,1,1,1,19,1,26,1,195,78,33,1,86,1,198,109,1,248,179,169,253,255,149,253,210,30,28,2,48,119,95,140,154,254,183,99,254,45,254, + 177,24,83,214,82,64,64,180,4,93,1,143,254,158,154,254,119,29,28,1,108,0,0,0,0,1,0,111,255,226,4,54,6,179,0,23,0,0,1,16, + 33,32,27,1,51,3,16,33,4,25,1,52,33,34,17,23,35,3,16,33,32,17,4,54,254,22,254,34,1,90,208,110,1,39,1,58,254,228,243,83, + 190,69,1,178,1,183,1,200,254,26,1,233,1,47,254,209,254,183,1,1,79,3,115,209,254,255,246,1,13,1,137,254,139,0,0,0,0,1,0,110, + 255,226,4,54,6,179,0,33,0,0,1,6,7,22,29,1,16,32,17,19,51,3,16,33,32,17,53,52,39,35,53,51,54,3,52,35,4,7,23,35, + 39,16,33,32,4,14,5,205,250,252,56,53,196,60,1,39,1,48,190,170,91,220,2,252,254,254,3,37,186,25,1,179,1,187,5,27,230,124,115,254, + 125,254,23,2,1,1,23,254,224,254,168,1,78,115,205,40,169,80,1,10,218,1,245,154,158,1,144,0,0,3,0,110,255,226,4,203,6,179,0,9, + 0,19,0,38,0,0,1,18,7,34,21,20,23,54,55,51,1,16,33,32,17,21,16,33,32,17,55,21,16,33,32,17,53,52,55,38,53,16,33,32, + 17,20,7,51,4,2,209,2,214,209,104,102,192,18,1,61,254,200,254,180,1,71,1,61,194,253,255,253,253,101,190,1,133,1,145,12,11,1,72,4, + 222,1,54,1,223,180,95,99,9,253,229,1,136,254,118,75,254,93,1,155,88,75,253,184,2,82,70,141,188,148,206,1,142,254,46,37,64,127,0,0, + 0,2,0,110,255,226,6,160,6,179,0,9,0,34,0,0,1,16,33,32,25,1,16,33,32,17,37,2,3,33,36,19,17,16,35,34,3,17,16,33, + 32,25,1,16,33,54,23,54,51,32,19,3,73,254,243,254,237,1,19,1,13,3,87,10,204,254,247,1,8,23,242,215,19,254,46,254,60,1,206,224, + 149,115,247,1,131,2,4,146,1,130,254,126,253,147,254,92,1,164,155,254,70,254,250,229,1,219,1,210,1,121,254,237,253,45,253,189,2,67,2,109, + 2,33,2,230,218,253,233,0,0,1,0,110,0,0,4,3,6,179,0,21,0,0,1,16,3,35,18,25,1,16,35,32,25,1,16,19,35,2,25,1, + 16,33,32,17,4,3,155,198,164,245,254,219,174,200,164,1,227,1,178,2,251,254,138,254,123,1,67,1,184,1,154,1,126,254,130,254,102,254,83,254, + 178,1,121,1,130,1,154,2,30,253,226,0,0,1,0,110,255,226,4,54,6,160,0,28,0,0,1,2,33,32,17,19,51,3,16,5,32,17,53,16, + 43,1,53,51,36,53,52,39,33,22,21,16,7,22,17,4,54,1,254,29,254,28,43,206,60,1,39,1,48,210,220,175,0,255,200,1,24,100,250,250, + 1,198,254,28,1,243,1,36,254,220,254,174,1,1,68,120,1,60,168,129,175,149,185,190,109,254,247,100,99,254,158,0,0,1,0,110,0,0,8,235, + 6,179,0,53,0,0,37,54,55,36,3,53,16,33,50,23,54,32,23,54,51,32,17,21,20,3,35,18,61,1,18,35,32,21,17,35,17,16,35,6, + 21,17,35,17,38,33,34,17,21,18,5,54,23,4,1,33,38,37,36,1,1,93,115,145,254,61,48,1,183,232,112,100,1,158,109,94,243,1,174,223, + 205,252,1,253,255,0,172,227,219,173,2,254,254,248,45,1,178,122,144,2,14,1,18,254,208,40,254,153,254,155,254,201,166,120,67,243,1,240,123,1, + 235,178,187,187,178,254,31,103,186,254,100,1,177,200,63,1,71,231,254,90,1,166,1,0,2,254,254,90,1,166,231,254,183,121,254,65,233,23,11,35, + 254,118,165,92,91,254,195,0,0,2,0,110,255,226,4,52,6,179,0,9,0,30,0,0,1,17,38,39,32,17,21,16,5,32,19,16,33,32,17,53, + 16,37,50,23,53,52,33,34,6,7,35,16,33,32,17,3,139,106,184,254,195,1,58,1,37,169,254,50,254,8,1,227,158,157,254,225,153,123,1,178, + 1,186,1,212,1,218,1,203,63,1,254,193,184,254,149,1,1,98,253,254,2,2,174,1,238,20,74,209,249,113,108,1,124,254,99,0,0,2,0,130, + 255,226,4,74,6,160,0,9,0,27,0,0,1,16,33,34,7,17,16,33,32,17,55,21,16,33,32,25,1,16,41,1,21,33,34,29,1,54,51,32, + 3,150,254,201,168,129,1,53,1,43,180,254,21,254,35,1,81,2,3,254,2,172,169,140,1,233,2,171,1,79,75,254,38,254,173,1,68,254,250,254, + 24,1,232,3,84,1,130,160,230,199,85,0,0,1,0,110,0,0,6,134,6,179,0,32,0,0,1,16,1,35,0,25,1,16,33,34,25,1,35,17, + 16,33,34,25,1,16,1,35,0,25,1,16,33,50,23,54,51,32,17,6,134,254,199,224,1,94,254,242,229,183,254,247,235,1,62,215,254,218,1,190, + 222,120,130,185,1,201,2,194,254,102,254,216,1,110,1,85,1,207,1,131,254,207,253,130,2,135,1,40,254,125,254,49,254,167,254,150,1,40,1,155, + 1,207,2,33,240,240,253,223,0,1,0,110,255,226,4,54,6,159,0,30,0,0,1,21,16,33,32,17,55,51,7,16,33,32,17,53,52,39,35,53, + 51,36,53,52,36,53,51,20,4,21,20,7,4,4,54,254,48,254,8,20,199,29,1,53,1,33,176,218,115,1,3,254,93,220,1,123,235,0,255,1, + 215,37,254,48,1,223,179,179,254,193,1,63,67,192,45,182,63,176,163,114,244,150,142,221,178,121,110,0,0,1,0,110,255,226,4,53,6,193,0,22, + 0,0,1,16,37,32,17,51,16,33,32,25,1,5,4,21,16,37,53,4,39,54,37,53,37,4,53,254,24,254,33,190,1,33,1,51,253,215,1,96, + 253,184,1,162,1,2,254,93,3,198,1,209,254,15,2,2,74,254,86,1,79,4,59,50,120,214,254,125,2,178,2,206,176,95,167,130,0,1,0,110, + 0,0,6,225,6,179,0,38,0,0,1,21,16,1,35,0,17,53,16,37,32,3,17,35,17,16,33,32,17,21,16,1,35,0,17,53,16,37,36,33, + 21,36,3,55,32,23,54,51,32,6,225,254,162,239,1,135,254,251,254,245,1,192,254,230,254,252,1,148,235,254,153,1,20,1,21,2,202,252,242,176, + 125,1,10,138,117,219,1,220,3,30,124,254,98,254,252,1,98,1,73,140,1,75,2,254,215,254,162,1,94,1,40,254,180,149,254,193,254,157,1,4, + 1,158,119,1,163,252,251,160,1,254,216,52,244,244,0,0,0,1,0,130,255,226,4,74,6,159,0,21,0,0,1,21,16,33,32,25,1,51,17,16, + 33,32,17,53,52,2,39,55,51,7,20,0,4,74,254,21,254,35,180,1,43,1,53,252,3,45,200,74,1,8,2,7,45,254,8,2,82,4,107,251, + 109,254,118,1,73,75,179,1,38,153,217,230,124,254,251,0,0,1,0,110,255,226,5,106,6,179,0,36,0,0,1,14,1,7,17,22,18,51,50,18, + 53,17,52,2,39,35,19,35,19,53,51,21,51,4,18,7,17,22,0,33,32,0,53,17,52,18,55,2,10,132,88,2,1,209,241,239,205,214,146,18, + 20,187,20,147,18,1,46,250,1,1,254,215,254,169,254,188,254,199,192,220,5,167,47,240,179,254,189,152,254,136,1,119,153,1,64,182,1,68,2,252, + 237,3,17,231,68,92,254,117,177,254,182,209,254,38,1,214,213,1,73,176,1,141,82,0,0,1,0,50,255,225,4,39,6,179,0,30,0,0,1,18, + 33,32,3,19,51,3,16,33,32,25,1,38,35,34,23,17,35,17,38,39,35,53,51,50,23,54,51,32,17,4,39,1,254,52,254,8,4,56,203,68, + 1,66,1,29,1,194,167,2,159,20,158,147,140,155,75,105,169,1,113,1,238,253,243,1,234,1,46,254,215,254,178,1,53,3,180,169,84,254,104,1, + 77,140,19,159,159,159,254,134,0,2,0,110,255,226,6,140,6,179,0,9,0,55,0,0,1,16,33,32,17,21,16,33,32,17,1,6,0,33,35,34, + 36,53,51,20,22,59,1,50,54,53,16,43,1,53,55,54,53,16,33,34,7,22,7,21,16,37,4,17,53,16,33,50,23,54,51,32,17,16,7,22, + 3,70,254,239,254,247,1,22,1,4,3,50,1,254,191,254,233,100,207,254,181,203,218,130,74,198,232,127,124,59,212,254,247,133,111,38,3,254,73,254, + 43,1,195,253,109,140,187,1,170,236,216,4,158,1,118,254,143,139,254,121,1,135,253,192,212,254,222,217,129,59,128,205,137,1,1,151,2,137,223,1, + 53,128,112,148,114,253,215,1,1,2,41,139,2,16,199,193,254,90,254,229,146,123,0,0,0,1,0,110,255,226,4,53,6,159,0,25,0,0,1,16, + 33,32,17,55,51,7,16,33,32,25,1,2,39,6,7,19,35,39,16,5,50,19,17,51,4,53,254,22,254,35,55,204,69,1,33,1,63,208,180,196, + 1,66,179,60,1,109,172,221,169,1,202,254,24,1,232,221,220,254,183,1,78,2,36,1,178,2,1,168,254,255,249,1,94,2,254,170,1,162,0,0, + 0,1,0,110,255,226,6,187,6,179,0,42,0,0,55,54,55,0,17,53,16,33,50,19,18,51,32,19,21,6,3,35,18,61,1,16,33,32,25,1, + 35,17,16,32,19,21,2,1,22,23,4,23,33,38,39,36,5,252,120,154,254,96,1,198,217,137,120,230,1,198,1,2,175,229,214,254,253,254,241,171, + 253,236,2,1,1,179,118,83,1,165,56,254,248,3,253,254,239,254,223,177,98,34,1,28,2,32,75,1,247,254,249,1,7,254,32,97,235,254,148,1, + 96,242,84,1,84,254,114,254,192,1,64,1,141,254,168,109,254,77,254,173,4,18,112,225,82,99,69,190,0,1,0,110,255,226,4,52,6,161,0,29, + 0,0,1,16,33,32,17,19,51,3,16,33,32,25,1,6,7,4,17,53,52,55,51,6,29,1,16,5,54,55,17,51,4,52,254,25,254,33,30,194, + 34,1,33,1,63,165,144,254,53,144,225,179,1,3,164,155,168,1,197,254,29,1,187,1,9,254,243,254,233,1,68,1,248,99,11,2,1,185,40,169, + 201,212,148,40,254,218,1,10,116,2,57,0,0,2,0,110,255,226,4,52,6,179,0,8,0,35,0,0,1,17,38,35,32,17,21,2,32,19,16,33, + 32,17,53,18,33,22,23,17,52,35,34,29,1,35,53,52,33,53,32,23,54,51,32,17,3,140,115,199,254,219,1,2,96,168,254,49,254,9,1,1, + 227,136,178,174,179,164,254,231,1,28,54,85,212,1,75,1,203,1,198,73,254,144,114,254,138,1,93,254,3,2,12,144,1,249,2,61,1,96,124,180, + 58,58,180,159,192,192,254,179,0,1,0,131,0,0,4,74,6,179,0,29,0,0,1,55,52,35,34,17,21,54,23,4,3,21,16,3,35,18,61,1, + 16,5,38,7,17,35,17,2,33,32,19,7,2,143,16,165,196,174,155,1,204,1,192,220,232,254,218,129,185,179,1,1,85,1,127,1,20,5,14,146, + 117,254,230,225,104,4,1,254,61,94,254,253,254,167,1,117,176,174,1,19,1,1,98,252,124,4,240,1,195,254,237,146,0,1,0,112,255,226,4,195, + 6,160,0,35,0,0,1,22,7,4,17,16,0,32,0,25,1,2,19,51,2,21,17,26,1,23,50,18,53,38,43,1,53,51,36,53,52,36,55,51, + 20,4,4,145,2,248,1,40,254,229,254,2,254,198,2,114,215,134,1,204,171,175,172,3,192,210,90,1,9,254,227,1,184,1,36,5,7,174,140,123, + 254,246,254,226,254,184,1,72,1,112,1,157,1,44,1,61,254,139,244,254,99,254,246,254,242,1,1,15,173,251,163,101,194,129,145,140,84,136,0,0, + 0,2,0,110,255,226,4,52,6,159,0,9,0,21,0,0,1,17,38,35,32,17,21,16,33,32,19,16,33,32,17,53,16,33,54,23,17,51,3,140, + 122,202,254,228,1,28,1,68,168,254,30,254,28,1,228,166,148,168,2,7,1,163,80,254,112,89,254,113,1,108,253,244,2,62,74,2,61,1,82,2, + 73,0,0,0,0,2,0,131,255,226,4,73,6,179,0,26,0,36,0,0,19,16,33,50,23,54,33,21,32,29,1,35,53,52,35,34,21,17,54,55, + 32,19,21,16,33,32,19,51,16,33,32,17,53,16,33,34,7,131,1,91,200,96,37,1,30,254,231,164,167,175,166,138,1,225,2,254,9,254,48,2, + 179,1,23,1,73,254,207,137,166,5,121,1,58,189,189,159,160,68,68,160,155,254,158,85,1,254,17,119,253,219,2,27,254,133,1,113,139,1,82,96, + 0,2,0,110,255,226,4,92,6,160,0,28,0,35,0,0,1,35,19,51,21,35,19,16,33,32,17,55,51,7,16,33,32,17,3,35,32,17,16,33, + 51,39,51,23,51,1,20,59,1,3,35,34,4,91,220,63,158,126,87,254,22,254,35,59,204,72,1,32,1,53,94,225,254,103,1,156,94,37,200,34, + 242,252,238,242,213,68,142,245,5,105,254,185,141,254,53,254,24,1,232,221,220,254,183,1,78,1,197,1,45,1,54,168,168,254,207,165,1,71,0,0, + 0,2,0,130,255,226,4,74,6,159,0,9,0,21,0,0,1,16,33,6,7,17,16,33,32,17,55,21,16,33,32,25,1,51,17,54,51,4,3,150, + 254,203,162,136,1,57,1,38,180,254,38,254,18,181,161,137,1,233,2,141,1,127,3,85,254,88,254,118,1,128,110,95,253,209,2,37,4,152,253,188, + 78,1,0,0,0,1,0,50,255,226,3,239,6,179,0,33,0,0,1,7,37,3,4,23,6,4,33,53,32,54,53,38,37,39,19,37,55,5,55,54, + 52,38,35,7,53,51,50,23,22,20,15,1,3,239,77,254,167,145,1,80,1,1,254,201,254,153,1,23,201,1,254,250,115,233,254,121,80,1,129,106, + 19,74,64,130,156,132,74,75,30,112,3,204,138,171,254,235,110,220,198,230,160,127,122,192,40,69,1,149,190,140,197,194,28,83,56,19,155,75,74,178, + 55,196,0,0,0,1,0,110,255,226,4,53,6,179,0,38,0,0,1,16,33,32,17,51,16,33,32,17,52,43,1,53,51,50,53,52,39,35,53,51, + 50,53,52,33,35,53,51,32,17,20,7,51,22,21,22,7,22,4,53,254,24,254,33,190,1,33,1,45,154,231,211,154,154,231,231,131,254,109,118,118, + 2,81,151,2,169,1,131,150,1,153,254,73,2,4,254,156,1,23,197,179,132,121,1,181,153,184,158,254,170,155,97,78,135,148,71,110,0,1,0,120, + 255,226,4,62,6,178,0,38,0,0,5,32,25,1,51,17,16,33,32,17,52,39,35,53,51,50,55,38,43,1,53,51,54,53,52,33,53,32,17,6, + 7,35,22,23,6,7,22,21,16,2,92,254,28,181,1,48,1,39,131,169,169,108,5,5,131,166,166,111,254,215,1,231,1,159,2,182,1,1,173,192, + 30,1,230,4,77,251,179,254,186,1,18,224,2,177,131,125,183,1,180,129,158,254,210,165,83,103,126,128,92,86,225,254,78,0,0,0,0,2,0,110, + 255,95,4,54,6,179,0,9,0,31,0,0,1,16,5,36,25,1,16,33,32,17,3,50,55,35,0,25,1,16,33,32,25,1,16,1,22,51,21,34, + 37,35,4,39,1,44,1,36,1,42,254,215,254,219,190,217,63,2,254,234,1,226,1,228,254,229,46,239,195,254,231,21,254,238,197,2,210,254,104,120, + 120,1,152,1,162,1,160,254,96,251,169,83,1,4,1,94,1,166,2,59,253,193,254,94,254,162,254,248,79,190,230,231,1,0,0,0,0,1,0,110, + 255,226,4,52,6,181,0,28,0,0,1,16,33,32,17,53,51,21,16,33,32,17,53,16,43,1,53,51,36,17,5,21,35,17,37,16,5,4,17,4, + 52,254,23,254,37,189,1,37,1,40,242,228,123,1,91,253,181,193,3,198,254,186,1,70,1,150,254,76,1,212,211,221,254,214,1,20,155,1,26,164, + 173,1,120,23,236,1,143,21,253,191,158,113,254,210,0,0,0,1,0,110,255,226,4,66,6,180,0,32,0,0,1,16,33,32,17,53,51,21,16,33, + 32,17,16,33,35,53,51,36,3,6,35,4,17,51,20,33,50,55,51,21,2,5,4,4,53,254,24,254,33,191,1,32,1,45,254,234,192,110,1,103, + 2,167,131,254,33,190,1,33,222,125,154,11,254,213,1,41,1,200,254,26,1,230,142,142,254,186,1,70,1,96,173,30,1,187,111,2,1,119,198,197, + 225,254,128,166,156,0,0,0,0,3,0,110,255,226,4,193,6,179,0,7,0,15,0,37,0,0,1,33,36,17,16,33,32,53,1,16,41,1,17,52, + 33,32,1,21,16,33,32,17,16,37,35,36,17,16,33,32,17,21,51,21,35,17,51,21,3,132,254,199,254,225,1,38,1,50,253,168,1,31,1,57, + 254,206,254,218,3,9,254,22,254,35,1,12,1,254,245,1,228,1,227,140,140,140,2,222,2,254,206,254,212,244,3,98,254,186,1,159,227,251,218,120, + 254,108,1,204,1,33,106,96,1,63,1,219,254,126,151,190,254,202,184,0,0,2,0,110,255,226,7,54,6,180,0,10,0,44,0,0,1,17,52,38, + 35,32,19,17,16,5,32,19,16,33,34,39,21,16,33,53,32,53,17,16,33,34,6,29,1,16,33,21,32,3,53,16,36,55,32,23,54,33,4,18, + 21,6,124,129,166,254,222,2,1,32,1,39,186,254,24,128,154,254,47,1,20,254,218,139,153,1,37,254,29,1,1,24,203,1,4,137,118,1,1,1, + 39,186,3,181,1,3,195,154,254,217,254,107,254,212,1,1,132,253,221,135,158,254,108,160,244,3,120,1,39,155,194,253,254,175,165,1,246,253,1,1, + 250,1,216,216,1,254,196,191,0,3,0,122,254,30,6,249,6,135,0,7,0,15,0,35,0,0,1,4,7,3,6,51,50,37,23,36,55,19,54,35, + 34,5,1,6,5,19,35,3,4,35,34,27,1,54,37,3,51,19,36,51,50,3,3,154,253,252,27,66,23,112,114,1,46,171,2,4,14,72,27,143, + 90,254,227,2,100,32,253,68,93,207,93,254,199,169,211,42,72,36,2,188,79,190,72,1,53,193,212,42,3,252,78,168,254,44,174,174,174,70,104,1, + 250,174,73,253,161,224,40,253,244,2,145,175,1,50,1,249,250,58,2,40,253,106,110,254,205,0,0,0,0,2,0,100,254,40,6,19,6,211,0,48, + 0,60,0,0,1,22,0,21,20,7,4,17,2,5,36,3,52,55,39,38,39,6,17,16,5,4,23,35,38,37,6,7,39,54,55,36,17,16,37,38, + 53,55,23,7,20,22,51,50,54,53,38,0,53,1,16,35,34,7,6,7,6,21,18,5,54,3,107,1,1,86,30,1,111,21,254,114,254,98,20,60, + 70,106,85,221,1,101,2,43,5,219,11,254,124,150,116,122,107,156,254,158,1,58,36,38,160,24,151,97,111,128,1,254,172,2,165,239,31,27,54,88, + 67,10,1,1,229,6,211,164,254,230,171,102,69,20,254,44,254,32,20,20,1,235,102,142,10,9,92,55,254,185,254,172,173,192,222,168,89,3,152,108, + 103,47,233,1,66,1,191,56,77,117,177,56,121,142,144,137,139,122,1,27,212,251,14,1,82,5,52,26,93,161,254,149,10,10,0,0,0,2,0,100, + 255,226,3,172,6,30,0,3,0,22,0,0,19,33,21,33,1,16,33,32,17,55,51,7,16,51,50,17,38,36,53,51,22,23,22,217,2,86,253,170, + 2,211,254,91,254,93,39,176,35,242,239,1,254,122,187,2,190,191,6,30,148,252,32,254,56,1,190,208,208,254,206,1,60,221,254,221,173,126,126,0, + 0,3,0,100,255,226,3,172,6,56,0,3,0,7,0,26,0,0,1,51,21,35,37,51,21,35,1,16,33,32,17,55,51,7,16,51,50,17,38,36, + 53,51,22,23,22,2,76,203,203,254,121,203,203,2,231,254,91,254,93,39,176,35,242,239,1,254,122,187,2,190,191,6,56,202,202,202,252,60,254,56, + 1,190,208,208,254,206,1,60,221,254,221,173,126,126,0,0,0,4,0,100,255,226,3,172,7,0,0,18,0,22,0,26,0,30,0,0,1,16,33,32, + 17,55,51,7,16,51,50,17,38,36,53,51,22,23,22,1,33,21,33,1,51,21,35,37,51,21,35,3,172,254,91,254,93,39,176,35,242,239,1,254, + 122,187,2,190,191,253,13,2,86,253,170,1,137,203,203,254,121,203,203,1,170,254,56,1,190,208,208,254,206,1,60,221,254,221,173,126,126,2,182,148, + 2,37,202,202,202,0,0,0,0,2,0,100,255,226,3,172,6,140,0,3,0,22,0,0,1,51,1,35,1,16,33,32,17,55,51,7,16,51,50,17, + 38,36,53,51,22,23,22,2,39,235,254,254,173,2,73,254,91,254,93,39,176,35,242,239,1,254,122,187,2,190,191,6,140,254,248,252,38,254,56,1, + 190,208,208,254,206,1,60,221,254,221,173,126,126,0,0,0,0,3,0,100,255,226,3,172,7,24,0,3,0,7,0,26,0,0,1,51,3,35,7,33, + 21,33,1,16,33,32,17,55,51,7,16,51,50,17,38,36,53,51,22,23,22,2,39,185,228,153,150,2,86,253,170,2,223,254,91,254,93,39,176,35, + 242,239,1,254,122,187,2,190,191,7,24,254,248,121,148,252,167,254,56,1,190,208,208,254,206,1,60,221,254,221,173,126,126,0,0,0,0,2,0,100, + 255,226,3,172,6,121,0,8,0,27,0,0,1,2,32,3,51,22,51,50,55,19,16,33,32,17,55,51,7,16,51,50,17,38,36,53,51,22,23,22, + 3,40,19,253,180,19,118,25,170,172,23,250,254,91,254,93,39,176,35,242,239,1,254,122,187,2,190,191,6,121,254,225,1,31,150,150,251,49,254,56, + 1,190,208,208,254,206,1,60,221,254,221,173,126,126,0,0,0,2,0,100,254,29,3,152,6,30,0,3,0,27,0,0,1,33,21,33,1,16,33,32, + 17,55,51,7,16,51,50,25,1,16,35,34,21,23,35,39,16,33,32,17,1,11,2,86,253,170,2,141,254,116,254,88,33,172,25,244,226,225,200,55, + 172,49,1,110,1,139,6,30,148,250,55,254,92,1,166,225,227,254,232,1,22,3,19,1,2,244,226,220,1,134,254,111,0,2,0,100,254,29,3,152, + 6,100,0,3,0,27,0,0,1,51,1,35,1,16,33,32,17,55,51,7,16,51,50,25,1,16,35,34,21,23,35,39,16,33,32,17,2,109,235,254, + 254,173,1,239,254,116,254,88,33,172,25,244,226,225,200,55,172,49,1,110,1,139,6,100,254,248,250,101,254,92,1,166,225,227,254,232,1,22,3,19, + 1,2,244,226,220,1,134,254,111,0,0,0,0,3,0,100,254,29,3,152,7,54,0,3,0,7,0,31,0,0,1,51,3,35,7,33,21,33,1,16, + 33,32,17,55,51,7,16,51,50,25,1,16,35,34,21,23,35,39,16,33,32,17,2,89,215,228,183,150,2,86,253,170,2,153,254,116,254,88,33,172, + 25,244,226,225,200,55,172,49,1,110,1,139,7,54,254,248,121,148,250,160,254,92,1,166,225,227,254,232,1,22,3,19,1,2,244,226,220,1,134,254, + 111,0,0,0,0,2,0,100,254,29,3,152,6,121,0,8,0,32,0,0,1,2,32,3,51,22,51,50,55,19,16,33,32,17,55,51,7,16,51,50, + 25,1,16,35,34,21,23,35,39,16,33,32,17,3,80,19,253,180,19,118,25,170,172,23,190,254,116,254,88,33,172,25,244,226,225,200,55,172,49,1, + 110,1,139,6,121,254,225,1,31,150,150,249,72,254,92,1,166,225,227,254,232,1,22,3,19,1,2,244,226,220,1,134,254,111,0,0,0,2,0,100, + 0,0,3,192,6,30,0,17,0,21,0,0,1,16,3,35,18,17,16,35,34,17,16,19,35,2,17,16,33,32,1,33,21,33,3,192,153,173,146,246, + 254,145,174,151,1,178,1,170,253,55,2,86,253,170,2,68,254,244,254,200,1,33,1,35,1,144,254,109,254,224,254,223,1,58,1,13,2,25,1,190, + 148,0,0,0,0,2,0,100,0,0,3,192,6,100,0,17,0,21,0,0,1,16,3,35,18,17,16,35,34,17,16,19,35,2,17,16,33,32,1,51, + 1,35,3,192,153,173,146,246,254,145,174,151,1,178,1,170,254,183,225,254,254,163,2,68,254,244,254,201,1,32,1,35,1,144,254,109,254,224,254,223, + 1,58,1,13,2,25,2,4,254,248,0,0,0,2,0,100,0,0,3,192,6,121,0,17,0,26,0,0,1,16,3,35,18,17,16,35,34,17,16,19, + 35,2,17,16,33,32,3,2,32,3,51,22,51,50,55,3,192,153,173,146,246,254,145,174,151,1,178,1,170,112,19,253,180,19,118,25,170,172,23,2, + 68,254,244,254,201,1,32,1,35,1,144,254,109,254,224,254,223,1,58,1,13,2,25,2,25,254,225,1,31,150,150,0,0,2,0,100,255,255,5,230, + 6,30,0,28,0,32,0,0,1,18,1,35,0,17,2,35,34,17,21,35,53,16,35,34,17,2,1,35,0,17,16,33,50,23,54,51,32,1,33,21, + 33,5,230,1,254,237,209,1,47,1,210,231,166,231,211,1,1,56,209,254,230,1,136,225,87,98,220,1,133,252,20,2,86,253,170,2,86,254,209,254, + 217,1,22,1,64,1,126,254,167,210,210,1,89,254,130,254,205,254,220,1,36,1,51,2,10,227,227,1,190,148,0,0,0,3,0,100,255,255,5,230, + 6,56,0,28,0,32,0,36,0,0,1,18,1,35,0,17,2,35,34,17,21,35,53,16,35,34,17,2,1,35,0,17,16,33,50,23,54,51,32,1, + 51,21,35,37,51,21,35,5,230,1,254,237,209,1,47,1,210,231,166,231,211,1,1,56,209,254,230,1,136,225,87,98,220,1,133,253,155,203,203,254, + 121,203,203,2,86,254,209,254,217,1,22,1,64,1,126,254,167,210,210,1,89,254,130,254,205,254,220,1,36,1,51,2,10,227,227,1,216,202,202,202, + 0,4,0,100,255,255,5,230,7,40,0,28,0,32,0,36,0,40,0,0,1,18,1,35,0,17,2,35,34,17,21,35,53,16,35,34,17,2,1,35, + 0,17,16,33,50,23,54,51,32,1,33,21,33,1,51,21,35,37,51,21,35,5,230,1,254,237,209,1,47,1,210,231,166,231,211,1,1,56,209,254, + 230,1,136,225,87,98,220,1,133,252,18,2,86,253,170,1,137,203,203,254,121,203,203,2,86,254,209,254,217,1,22,1,64,1,126,254,167,210,210,1, + 89,254,130,254,205,254,220,1,36,1,51,2,10,227,227,1,55,148,2,37,202,202,202,0,0,2,0,100,255,255,5,230,6,100,0,28,0,32,0,0, + 1,18,1,35,0,17,2,35,34,17,21,35,53,16,35,34,17,2,1,35,0,17,16,33,50,23,54,51,32,1,51,1,35,5,230,1,254,237,209,1, + 47,1,210,231,166,231,211,1,1,56,209,254,230,1,136,225,87,98,220,1,133,253,118,225,254,254,163,2,86,254,209,254,217,1,22,1,64,1,126,254, + 167,210,210,1,89,254,130,254,205,254,220,1,36,1,51,2,10,227,227,2,4,254,248,0,0,2,0,100,255,255,5,230,6,121,0,28,0,37,0,0, + 1,18,1,35,0,17,2,35,34,17,21,35,53,16,35,34,17,2,1,35,0,17,16,33,50,23,54,51,32,1,2,32,3,51,22,51,50,55,5,230, + 1,254,237,209,1,47,1,210,231,166,231,211,1,1,56,209,254,230,1,136,225,87,98,220,1,133,254,139,19,253,180,19,118,25,170,172,23,2,86,254, + 209,254,217,1,22,1,64,1,126,254,167,210,210,1,89,254,130,254,205,254,220,1,36,1,51,2,10,227,227,2,25,254,225,1,31,150,150,0,0,0, + 0,2,0,60,254,29,3,232,6,30,0,3,0,36,0,0,19,33,21,33,1,16,33,32,17,55,51,7,16,33,50,25,1,38,35,34,21,3,35,3, + 52,43,1,39,55,23,51,50,23,54,51,32,17,237,2,86,253,170,2,251,254,110,254,71,25,178,23,1,5,232,2,135,123,10,143,10,156,82,109,20, + 87,80,143,79,67,160,1,48,6,30,148,250,54,254,93,1,163,227,227,254,233,1,23,3,103,182,140,254,165,1,91,120,40,161,50,187,187,254,199,0, + 0,3,0,60,254,29,3,232,6,56,0,3,0,7,0,40,0,0,1,51,21,35,37,51,21,35,1,16,33,32,17,55,51,7,16,33,50,25,1,38, + 35,34,21,3,35,3,52,43,1,39,55,23,51,50,23,54,51,32,17,2,116,203,203,254,121,203,203,2,251,254,110,254,71,25,178,23,1,5,232,2, + 135,123,10,143,10,156,82,109,20,87,80,143,79,67,160,1,48,6,56,202,202,202,250,82,254,93,1,163,227,227,254,233,1,23,3,103,182,140,254,165, + 1,91,120,40,161,50,187,187,254,199,0,0,0,4,0,60,254,29,3,232,7,60,0,3,0,7,0,11,0,44,0,0,19,33,21,33,1,51,21,35, + 37,51,21,35,1,16,33,32,17,55,51,7,16,33,50,25,1,38,35,34,21,3,35,3,52,43,1,39,55,23,51,50,23,54,51,32,17,235,2,86, + 253,170,1,137,203,203,254,121,203,203,2,251,254,110,254,71,25,178,23,1,5,232,2,135,123,10,143,10,156,82,109,20,87,80,143,79,67,160,1,48, + 5,171,148,2,37,202,202,202,249,78,254,93,1,163,227,227,254,233,1,23,3,103,182,140,254,165,1,91,120,40,161,50,187,187,254,199,0,2,0,60, + 254,29,3,232,6,100,0,3,0,36,0,0,1,51,3,35,1,16,33,32,17,55,51,7,16,33,50,25,1,38,35,34,21,3,35,3,52,43,1,39, + 55,23,51,50,23,54,51,32,17,2,89,215,248,163,2,83,254,110,254,71,25,178,23,1,5,232,2,135,123,10,143,10,156,82,109,20,87,80,143,79, + 67,160,1,48,6,100,254,248,250,100,254,93,1,163,227,227,254,233,1,23,3,103,182,140,254,165,1,91,120,40,161,50,187,187,254,199,0,2,0,60, + 254,29,3,232,6,121,0,8,0,41,0,0,1,2,32,3,51,22,51,50,55,1,16,33,32,17,55,51,7,16,33,50,25,1,38,35,34,21,3,35, + 3,52,43,1,39,55,23,51,50,23,54,51,32,17,3,70,19,253,180,19,118,25,170,172,23,1,24,254,110,254,71,25,178,23,1,5,232,2,135,123, + 10,143,10,156,82,109,20,87,80,143,79,67,160,1,48,6,121,254,225,1,31,150,150,249,71,254,93,1,163,227,227,254,233,1,23,3,103,182,140,254, + 165,1,91,120,40,161,50,187,187,254,199,0,0,2,0,60,254,29,3,232,6,209,0,6,0,39,0,0,1,19,35,39,7,35,19,1,16,33,32,17, + 55,51,7,16,33,50,25,1,38,35,34,21,3,35,3,52,43,1,39,55,23,51,50,23,54,51,32,17,2,88,245,139,180,180,139,245,2,36,254,110, + 254,71,25,178,23,1,5,232,2,135,123,10,143,10,156,82,109,20,87,80,143,79,67,160,1,48,6,209,254,136,245,245,1,120,248,239,254,93,1,163, + 227,227,254,233,1,23,3,103,182,140,254,165,1,91,120,40,161,50,187,187,254,199,0,0,0,2,0,113,255,227,4,117,6,20,0,9,0,32,0,0, + 1,34,6,16,22,32,54,53,52,38,1,16,55,46,1,53,52,54,51,33,21,33,34,21,20,22,51,50,0,16,0,32,0,2,114,147,172,171,1,40, + 172,172,253,107,195,79,65,194,158,1,252,254,40,188,117,146,237,1,21,254,237,254,32,254,239,3,223,231,254,110,231,232,199,200,233,254,80,1,77,155, + 47,141,49,124,148,147,137,73,52,254,200,253,218,254,198,1,57,0,0,0,0,1,0,47,0,0,5,170,6,20,0,36,0,72,64,19,38,0,7,9, + 5,8,12,33,24,13,30,8,17,12,33,16,20,76,37,16,252,60,196,50,196,252,60,196,16,60,252,60,196,196,196,49,0,64,17,9,13,17,169,18, + 2,26,135,0,24,151,6,31,18,188,11,15,47,60,230,50,50,254,60,238,50,16,238,50,50,48,1,21,35,34,6,29,1,33,21,33,17,35,17,33, + 17,35,17,35,53,51,53,52,54,59,1,21,35,34,7,6,29,1,33,53,52,54,51,5,170,176,99,77,1,47,254,209,185,254,7,185,176,176,174,189, + 174,176,99,39,38,1,249,174,189,6,20,153,80,104,99,143,252,47,3,209,252,47,3,209,143,78,187,171,153,40,40,104,99,78,187,171,0,2,0,47, + 0,0,4,74,6,20,0,21,0,25,0,82,64,17,27,70,0,23,8,22,15,20,4,8,8,3,22,10,6,76,26,16,252,60,196,50,196,252,60,196, + 16,254,60,236,49,0,64,18,8,3,169,0,16,135,14,24,190,22,177,14,151,9,0,188,5,1,47,60,230,50,238,254,238,16,238,16,238,50,48,64, + 11,255,27,160,27,144,27,128,27,16,27,5,1,93,1,17,35,17,33,17,35,17,35,53,51,53,52,54,59,1,21,35,34,6,29,1,1,51,21,35, + 4,74,185,254,7,185,176,176,173,179,185,176,99,77,1,249,185,185,4,96,251,160,3,209,252,47,3,209,143,78,183,175,153,80,104,99,1,178,233,0, + 0,1,0,47,0,0,4,74,6,20,0,21,0,55,64,15,23,70,1,8,4,10,12,8,8,16,4,18,14,76,22,16,252,60,196,196,252,60,196,16, + 254,236,49,0,64,13,15,11,169,9,4,135,0,151,17,9,188,13,2,47,60,230,50,254,238,16,238,50,48,1,33,17,35,17,33,34,6,29,1,33, + 21,33,17,35,17,35,53,51,53,52,54,2,74,2,0,185,254,183,99,77,1,47,254,209,185,176,176,174,6,20,249,236,5,123,80,104,99,143,252,47, + 3,209,143,78,187,171,0,0,0,2,0,47,0,0,6,252,6,20,0,41,0,45,0,90,64,24,47,70,23,43,8,42,16,27,21,8,26,42,9,0, + 31,6,8,36,30,9,34,38,76,46,16,252,60,196,50,196,252,60,196,16,196,50,252,60,196,16,252,60,236,49,0,64,23,27,31,35,169,36,17,1, + 135,0,45,190,42,177,16,0,151,22,7,36,188,25,29,33,47,60,60,228,50,50,228,50,244,236,16,236,50,16,236,50,50,48,1,21,35,34,7,6, + 29,1,33,53,52,55,54,55,54,59,1,21,35,34,6,29,1,33,17,35,17,33,17,35,17,33,17,35,17,35,53,51,53,52,54,51,5,51,21,35, + 2,248,176,99,39,38,1,249,87,28,39,78,131,174,176,99,77,2,178,185,254,7,185,254,7,185,176,176,174,189,3,249,185,185,6,20,153,40,40,104, + 99,78,187,85,28,19,39,153,80,104,99,251,160,3,209,252,47,3,209,252,47,3,209,143,78,187,171,2,233,0,0,0,0,1,0,47,0,0,6,252, + 6,20,0,38,0,78,64,22,40,70,13,8,16,22,24,20,8,16,9,0,28,6,8,33,27,9,31,35,76,39,16,252,60,196,50,196,252,60,196,16, + 196,252,60,196,16,252,236,49,0,64,18,24,28,32,169,33,17,2,135,12,38,151,21,7,33,188,15,26,30,47,60,60,228,50,50,244,60,236,50,16, + 236,50,50,48,1,21,35,34,7,6,29,1,33,53,52,54,51,33,17,35,17,33,34,6,29,1,33,21,33,17,35,17,33,17,35,17,35,53,51,53, + 52,54,51,2,248,176,99,39,38,1,249,174,189,2,0,185,254,183,99,77,1,47,254,209,185,254,7,185,176,176,174,189,6,20,153,40,40,104,99,78, + 187,171,249,236,5,123,80,104,99,143,252,47,3,209,252,47,3,209,143,78,187,171,0,0,0,1,0,47,0,0,5,76,6,20,0,45,0,0,1,53, + 52,39,38,43,1,34,7,6,21,17,35,17,35,53,51,53,52,55,54,59,1,50,23,22,29,1,33,21,33,17,20,23,22,59,1,21,35,34,39,38, + 53,17,35,53,3,24,36,37,101,34,99,39,38,185,176,176,87,87,189,30,189,87,85,1,123,254,133,37,38,115,189,189,213,81,81,135,4,96,99,104, + 40,40,40,40,104,251,61,3,209,143,78,187,85,86,86,83,189,78,143,253,160,137,39,39,154,80,79,210,2,96,143,0,0,1,0,111,255,227,6,178, + 5,240,0,89,0,0,1,21,38,39,38,35,34,7,6,21,20,23,22,31,1,30,1,21,20,7,6,35,34,39,38,39,53,22,23,22,51,50,55,54, + 53,52,39,38,47,1,38,39,38,53,52,55,54,51,50,23,38,53,52,55,54,55,50,23,22,29,1,33,21,33,17,20,23,22,59,1,21,35,34,39, + 38,53,17,35,53,51,53,52,39,38,7,34,7,6,21,20,3,81,86,73,84,70,117,63,59,49,49,148,63,195,166,123,124,216,96,92,97,108,102,99, + 99,97,130,70,70,50,45,177,64,171,76,76,102,112,181,72,77,5,92,91,162,140,98,94,1,123,254,133,37,38,115,189,189,213,81,81,135,135,48,54, + 68,69,54,52,4,63,174,43,17,20,42,39,87,64,37,36,33,14,43,152,137,156,91,91,17,18,35,190,53,26,27,45,44,81,75,40,35,42,15,36, + 74,75,130,166,78,86,11,29,31,135,95,93,1,96,92,136,76,143,253,160,137,39,39,154,80,79,210,2,96,143,78,65,43,50,1,49,48,64,61,0, + 0,1,0,171,255,227,8,227,6,20,0,75,0,0,1,22,21,17,35,53,14,1,35,34,38,53,17,51,17,20,22,51,50,54,53,17,52,39,33,34, + 39,38,53,52,55,54,59,1,21,35,34,21,20,51,33,39,38,53,52,55,54,59,1,21,35,34,21,20,31,1,33,3,20,22,51,50,54,53,17,51, + 17,35,53,14,1,35,34,38,53,17,4,79,9,184,67,177,117,193,200,184,124,124,149,173,5,254,83,152,91,80,90,119,114,89,89,131,131,1,108,23, + 54,9,55,209,236,222,96,14,59,1,221,1,124,124,149,173,184,184,67,177,117,193,200,3,182,37,33,252,144,172,102,99,240,231,1,102,254,161,159,159, + 190,164,1,145,36,28,94,83,145,131,66,87,175,123,138,56,131,75,31,21,122,175,43,41,32,145,253,97,160,158,190,164,2,123,251,160,172,102,99,240, + 231,1,252,0,0,1,0,174,255,227,8,227,6,20,0,58,0,0,1,33,38,21,20,31,1,22,21,17,35,53,14,1,35,34,38,53,17,51,17,20, + 22,51,50,54,53,17,52,47,1,38,55,54,51,33,17,33,21,33,17,20,22,51,50,55,54,53,17,51,17,35,53,14,1,35,34,38,53,5,57,254, + 243,96,14,77,49,184,67,177,117,193,200,184,124,124,149,173,16,77,77,32,55,209,1,211,2,242,253,14,124,124,152,83,87,184,184,67,177,117,193,200, + 5,101,1,44,39,34,188,120,77,252,144,172,102,99,240,231,2,166,253,97,159,159,190,164,1,145,63,39,188,187,71,122,254,76,170,254,11,159,159,95, + 98,161,1,59,252,224,172,102,99,240,231,0,0,1,0,174,254,86,8,227,6,20,0,53,0,0,1,33,38,21,20,31,1,22,21,17,35,53,14,1, + 35,34,38,53,17,51,17,20,22,51,50,54,53,17,52,47,1,38,55,54,51,33,17,62,1,51,50,22,21,17,35,17,52,38,35,34,6,21,17,35, + 5,57,254,243,96,14,77,49,184,67,177,117,193,200,184,124,124,149,173,16,77,77,32,55,209,1,212,66,179,117,193,198,184,124,124,149,172,185,5,101, + 1,44,39,34,188,120,77,252,144,172,102,99,240,231,2,166,253,97,159,159,190,164,1,145,63,39,188,187,71,122,253,158,101,100,239,232,253,92,2,158, + 159,158,190,164,251,221,0,0,0,2,0,174,254,86,8,227,6,20,0,53,0,60,0,0,1,33,34,39,38,55,54,55,54,51,33,17,33,17,20,22, + 51,50,54,53,17,51,17,35,53,14,1,35,34,38,53,17,35,17,51,21,33,17,14,1,35,34,38,53,17,51,17,20,22,51,50,55,54,53,25,1, + 33,34,21,20,51,3,160,254,219,149,94,83,3,3,87,115,118,1,221,1,153,124,124,149,173,184,184,67,177,117,193,200,225,213,254,115,67,177,117,193, + 200,184,124,124,149,87,86,254,219,131,131,3,182,94,83,145,131,66,87,254,76,253,97,159,159,190,164,2,123,251,160,172,102,99,240,231,1,252,251,66, + 162,2,86,102,99,240,231,1,102,254,161,159,159,95,95,164,2,123,1,5,123,138,0,0,0,1,0,174,254,86,11,155,6,20,0,72,0,0,1,33, + 38,21,20,31,1,22,21,17,35,53,14,1,35,34,38,53,17,51,17,20,22,51,50,54,53,17,52,47,1,38,55,54,51,33,17,54,55,54,51,50, + 22,29,1,20,23,22,51,50,54,53,17,51,17,35,53,14,1,35,34,39,38,61,1,52,38,35,34,6,21,17,35,5,57,254,243,96,14,77,49,184, + 67,177,117,193,200,184,124,124,149,173,16,77,77,32,55,209,1,212,99,37,90,107,193,198,62,56,110,140,173,184,184,67,177,108,175,98,100,124,124,120, + 172,185,5,101,1,44,39,34,188,120,77,252,144,172,102,99,240,231,2,166,253,97,159,159,190,164,1,145,63,39,188,187,71,122,253,158,129,22,50,239, + 232,227,151,88,79,190,164,2,123,251,160,172,102,99,120,123,228,228,159,158,190,164,251,221,255,255,0,136,0,91,1,66,4,96,18,38,5,47,0,0, + 16,7,5,20,254,78,1,160,0,1,1,86,5,0,3,200,6,31,0,12,0,0,1,51,30,1,51,50,54,55,51,14,1,32,38,1,86,118,11,97, + 87,86,96,13,118,10,158,254,222,158,6,31,75,75,74,76,143,144,144,0,255,255,0,74,0,91,2,162,4,96,18,38,5,67,0,0,16,7,5,23, + 254,231,1,160,0,1,0,78,0,0,4,126,4,96,0,22,0,0,1,19,50,55,54,55,54,61,1,51,17,20,14,5,35,33,53,33,3,1,99,193, + 250,92,64,8,2,186,14,38,64,101,139,190,120,254,106,1,20,193,4,96,252,81,163,113,242,60,118,247,254,214,116,182,176,129,111,69,39,177,3,175, + 0,1,0,174,0,0,6,45,4,96,0,32,0,0,9,1,35,1,14,3,21,17,35,17,52,62,2,55,1,51,1,62,3,53,17,51,21,20,14,3, + 4,179,1,122,237,253,75,45,98,91,59,184,73,119,122,63,254,135,237,2,180,45,98,92,59,184,50,78,104,96,1,105,254,151,2,151,6,56,94,151, + 88,254,244,1,10,100,173,119,78,22,1,106,253,105,6,56,94,151,88,1,12,246,86,154,110,90,55,0,0,1,0,88,0,0,5,189,4,96,0,7, + 0,0,1,35,17,35,17,33,53,33,5,189,202,186,252,31,5,101,3,209,252,47,3,209,143,0,0,0,0,2,0,186,0,0,6,29,4,96,0,19, + 0,23,0,0,1,17,35,17,52,46,4,35,33,53,33,50,30,4,37,17,35,17,6,29,185,13,39,62,110,140,105,253,43,2,213,133,196,148,94,59, + 24,251,107,185,1,237,254,19,1,237,106,139,116,64,44,15,143,26,63,93,145,178,69,253,84,2,96,0,0,1,0,88,0,0,5,187,4,96,0,27, + 0,0,19,33,50,30,3,20,14,3,35,33,53,33,50,62,3,52,46,3,35,33,88,2,215,150,232,143,92,35,35,92,143,231,150,253,40,2,216,113, + 168,102,61,22,22,61,102,168,113,253,40,4,96,65,105,149,153,176,153,149,105,65,142,42,72,110,117,154,117,110,72,42,0,1,0,88,0,0,5,187, + 6,20,0,8,0,0,33,1,33,17,51,17,33,21,1,2,160,2,92,251,92,187,4,168,253,164,3,209,2,67,254,76,132,252,36,0,0,2,0,186, + 0,0,6,29,4,96,0,8,0,19,0,0,41,1,17,33,50,30,2,21,1,17,33,17,52,46,4,35,6,29,250,157,3,53,163,211,131,53,251,87, + 3,239,12,33,51,87,109,79,4,96,60,144,217,167,1,189,252,190,1,133,94,130,104,61,41,15,0,0,0,1,0,88,0,0,5,187,4,96,0,15, + 0,0,1,17,35,17,52,46,2,35,33,53,33,50,30,2,5,187,186,29,84,140,116,252,200,3,55,162,211,130,53,2,20,253,236,2,20,134,161,109, + 41,143,60,144,217,0,0,0,0,1,0,96,255,248,5,186,4,96,0,30,0,0,1,17,35,17,52,46,3,35,33,17,20,6,35,34,39,53,22,51, + 50,54,53,17,35,53,33,50,30,2,5,186,186,10,36,64,112,80,254,36,123,152,53,78,65,38,71,46,173,3,67,143,193,108,44,2,94,253,162,2, + 96,74,99,101,58,37,253,205,214,208,16,143,14,114,163,2,51,143,67,138,180,0,0,0,0,1,0,217,2,45,5,219,5,4,0,7,0,0,1,33, + 53,33,17,51,17,33,5,219,250,254,2,45,168,2,45,2,45,170,2,45,253,211,0,0,255,255,0,88,0,0,5,83,5,150,16,38,5,33,161,0, + 18,6,5,63,0,0,0,0,255,255,0,78,0,0,5,83,5,150,16,38,5,25,78,0,18,6,5,63,0,0,0,0,255,255,0,88,0,0,5,83, + 5,150,16,39,5,25,2,88,252,15,16,38,5,33,151,0,18,6,5,63,0,0,0,0,255,255,0,88,0,0,5,83,5,150,16,39,5,25,2,88, + 252,15,16,39,5,33,251,76,0,0,18,6,5,63,0,0,255,255,0,186,254,187,4,159,4,96,16,38,5,23,0,0,18,6,5,38,0,0,0,0, + 255,255,0,186,254,117,4,159,4,96,16,38,5,24,0,0,18,6,5,38,0,0,0,0,255,255,0,186,254,187,4,159,4,96,16,38,5,20,0,0, + 18,6,5,38,0,0,0,0,255,255,0,88,0,0,4,72,4,96,16,39,5,28,254,225,0,0,18,6,5,39,0,0,255,255,0,88,255,246,3,17, + 4,96,16,39,5,28,254,33,0,0,18,6,5,40,0,0,255,255,0,88,0,0,4,23,4,96,16,39,5,28,254,129,0,0,18,6,5,41,0,0, + 255,255,0,186,0,0,4,128,4,96,16,38,5,28,0,0,18,6,5,42,0,0,0,0,255,255,0,89,0,0,2,30,4,96,16,39,5,28,254,11, + 0,0,16,7,5,43,0,170,0,0,0,0,255,255,0,89,0,0,2,231,4,96,16,39,5,28,254,11,0,0,16,6,5,44,122,0,255,255,0,185, + 255,227,4,191,4,107,16,38,5,28,0,0,18,6,5,46,0,0,0,0,255,255,0,89,1,162,2,28,4,96,16,39,5,28,254,11,0,160,16,7, + 5,47,0,218,0,0,0,0,255,255,0,88,254,86,3,146,4,96,16,39,5,28,254,177,0,0,18,6,5,48,0,0,255,255,0,88,0,0,3,202, + 4,96,16,39,5,28,254,177,0,0,18,6,5,49,0,0,255,255,0,88,0,0,3,240,5,213,16,39,5,28,254,81,0,0,18,6,5,50,0,0, + 255,255,0,88,0,0,4,181,4,112,16,38,5,28,48,0,18,6,5,52,0,0,0,0,255,255,0,88,0,0,2,120,4,96,16,39,5,28,254,33, + 0,0,16,6,5,54,0,0,255,255,0,185,255,227,4,191,4,96,16,38,5,28,0,0,18,6,5,55,0,0,0,0,255,255,0,186,254,86,4,100, + 4,96,16,38,5,28,113,0,18,6,5,57,0,0,0,0,255,255,0,186,0,0,4,142,4,96,16,38,5,28,124,0,18,6,5,58,0,0,0,0, + 255,255,0,88,0,0,4,5,4,96,16,39,5,28,254,81,0,0,18,6,5,60,0,0,255,255,0,186,254,86,5,17,4,95,16,38,5,28,209,0, + 18,6,5,61,0,0,0,0,255,255,0,88,0,0,3,202,4,96,16,39,5,28,254,177,0,0,18,6,5,62,0,0,255,255,0,88,0,0,5,83, + 4,96,16,39,5,25,2,57,252,13,18,6,5,63,0,0,255,255,0,20,255,248,4,136,4,96,16,38,5,28,0,0,18,6,5,64,0,0,0,0, + 255,255,0,186,0,0,1,116,5,150,16,39,5,33,251,180,0,0,18,6,5,43,0,0,255,255,0,88,0,0,4,72,5,150,16,39,5,31,255,113, + 0,0,18,6,5,39,0,0,255,255,0,88,0,0,3,202,5,150,16,39,5,31,255,65,0,0,18,6,5,49,0,0,255,255,0,186,0,0,4,142, + 5,150,16,38,5,31,0,0,18,6,5,58,0,0,0,0,0,1,0,88,0,0,4,145,6,20,0,44,0,0,9,1,35,1,14,4,21,17,35,53, + 52,62,5,55,3,35,17,51,17,51,7,1,62,4,53,17,51,21,20,14,5,3,114,1,29,217,254,96,28,35,56,33,26,184,20,31,50,45,65,44, + 31,186,184,187,120,2,1,158,27,35,56,34,26,184,20,31,50,46,64,44,1,155,254,101,2,88,14,21,53,65,110,69,254,244,185,81,138,96,81,50, + 44,21,13,1,13,2,66,254,76,3,253,171,13,21,54,65,110,69,1,12,185,82,137,97,81,49,44,21,255,255,0,130,254,12,6,235,2,157,16,39, + 22,200,3,57,255,6,16,6,5,142,0,0,255,255,0,130,254,12,7,239,2,157,16,39,22,200,3,57,255,6,16,6,22,202,0,0,255,255,255,236, + 254,12,1,135,2,88,16,38,22,203,0,0,16,7,22,200,0,224,255,6,255,255,255,236,254,12,2,126,2,88,16,39,22,200,0,224,255,6,16,6, + 22,204,0,0,255,255,0,130,254,12,6,235,2,157,16,39,22,199,2,188,255,6,16,6,5,142,0,0,255,255,0,130,254,12,7,239,2,157,16,39, + 22,199,2,188,255,6,16,6,22,202,0,0,255,255,255,236,254,12,1,243,2,88,16,38,22,203,0,0,16,7,22,199,0,99,255,6,255,255,255,236, + 254,12,2,126,2,88,16,38,22,204,0,0,16,7,22,199,0,99,255,6,255,255,0,130,254,12,6,235,2,157,16,39,22,201,2,188,255,6,16,6, + 5,142,0,0,255,255,0,130,254,12,7,239,2,157,16,39,22,201,2,188,255,6,16,6,22,202,0,0,255,255,255,236,254,12,1,243,2,88,16,38, + 22,203,0,0,16,7,22,201,0,99,255,6,255,255,255,236,254,12,2,126,2,88,16,38,22,204,0,0,16,7,22,201,0,99,255,6,255,255,0,130, + 255,236,6,235,4,26,16,39,22,200,3,57,3,132,16,6,5,142,0,0,255,255,0,130,255,236,7,239,4,26,16,39,22,200,3,57,3,132,16,6, + 22,202,0,0,255,255,255,236,0,0,1,135,4,226,16,38,22,203,0,0,16,7,22,200,0,224,4,76,255,255,255,236,0,0,2,126,4,226,16,38, + 22,204,0,0,16,7,22,200,0,224,4,76,255,255,0,130,255,236,6,235,4,26,16,39,22,201,2,188,3,132,16,6,5,142,0,0,255,255,0,130, + 255,236,7,239,4,26,16,38,22,202,0,0,16,7,22,201,2,188,3,132,255,255,255,236,0,0,1,243,4,226,16,38,22,203,0,0,16,7,22,201, + 0,99,4,76,255,255,255,236,0,0,2,126,4,226,16,38,22,204,0,0,16,7,22,201,0,99,4,76,255,255,0,130,255,236,6,235,4,153,16,39, + 5,75,1,132,253,168,16,6,5,142,0,0,255,255,0,130,255,236,7,239,4,153,16,38,22,202,0,0,16,7,5,75,1,132,253,168,255,255,255,236, + 0,0,2,48,5,97,16,38,22,203,0,0,16,7,5,75,255,43,254,112,255,255,255,236,0,0,2,126,5,97,16,38,22,204,0,0,16,7,5,75, + 255,43,254,112,255,255,0,130,255,164,7,158,6,14,16,39,22,198,5,120,4,126,16,6,5,186,0,0,255,255,0,130,255,165,8,92,5,70,16,38, + 22,205,0,0,16,7,22,198,5,120,3,182,255,255,255,236,0,0,3,63,6,14,16,38,22,206,0,0,16,7,22,198,1,44,4,126,255,255,255,236, + 0,0,4,32,5,120,16,38,22,207,0,0,16,7,22,198,1,62,3,232,255,255,0,130,255,164,7,158,6,14,16,39,22,201,5,120,5,120,16,6, + 5,186,0,0,255,255,0,130,255,165,8,92,5,70,16,38,22,205,0,0,16,7,22,201,5,120,4,176,255,255,255,236,0,0,3,63,6,14,16,38, + 22,206,0,0,16,7,22,201,1,44,5,120,255,255,255,236,0,0,4,32,5,120,16,38,22,207,0,0,16,7,22,201,1,62,4,226,255,255,0,157, + 254,12,5,40,3,102,16,39,22,200,3,7,0,175,16,6,5,90,0,0,255,255,0,157,254,12,5,62,3,102,16,39,22,200,2,163,0,125,16,6, + 20,134,0,0,255,255,255,236,254,62,4,92,3,47,16,38,20,135,0,0,16,7,22,200,2,13,255,56,255,255,255,236,254,62,5,62,3,47,16,38, + 20,136,0,0,16,7,22,200,2,13,255,56,255,255,0,157,254,12,5,40,3,102,16,39,22,197,2,138,0,25,16,6,5,90,0,0,255,255,0,157, + 254,12,5,62,3,102,16,39,22,197,2,38,255,231,16,6,20,134,0,0,255,255,255,236,255,56,4,92,3,47,16,38,20,135,0,0,16,7,22,197, + 1,144,255,56,255,255,255,236,255,56,5,62,3,47,16,38,20,136,0,0,16,7,22,197,1,144,255,56,255,255,0,157,254,12,5,40,3,102,16,39, + 22,199,2,150,0,150,16,6,5,90,0,0,255,255,0,157,254,12,5,62,3,102,16,39,22,199,2,25,0,50,16,6,20,134,0,0,255,255,255,236, + 254,62,4,92,3,47,16,38,20,135,0,0,16,7,22,199,1,144,255,56,255,255,255,236,254,62,5,62,3,47,16,38,20,136,0,0,16,7,22,199, + 1,144,255,56,255,255,0,157,254,12,5,40,3,102,16,39,22,201,2,150,0,175,16,6,5,90,0,0,255,255,0,157,254,12,5,62,3,102,16,39, + 22,201,2,25,0,50,16,6,20,134,0,0,255,255,255,236,254,62,4,92,3,47,16,38,20,135,0,0,16,7,22,201,1,144,255,56,255,255,255,236, + 254,62,5,62,3,47,16,38,20,136,0,0,16,7,22,201,1,144,255,56,255,255,0,125,254,212,3,27,3,82,16,39,22,197,1,43,254,212,16,6, + 5,92,0,0,255,255,0,125,254,212,4,71,3,82,16,39,22,197,1,43,254,212,16,6,20,142,0,0,255,255,0,125,255,218,3,27,4,176,16,39, + 22,197,0,250,4,26,16,6,5,92,0,0,255,255,0,125,255,218,4,71,4,176,16,39,22,197,0,250,4,26,16,6,20,142,0,0,255,255,0,125, + 255,218,3,27,5,170,16,39,22,198,0,250,4,26,16,6,5,92,0,0,255,255,0,125,255,218,4,71,5,170,16,39,22,198,0,250,4,26,16,6, + 20,142,0,0,255,255,0,125,255,218,3,27,5,247,16,39,5,75,255,194,255,6,16,6,5,92,0,0,255,255,0,125,255,218,4,71,5,247,16,39, + 5,75,255,194,255,6,16,6,20,142,0,0,255,255,255,171,254,12,3,132,4,176,16,39,22,198,1,244,3,32,16,6,5,94,0,0,255,255,255,171, + 254,12,4,126,4,176,16,38,20,146,0,0,16,7,22,198,1,244,3,32,255,255,255,171,254,12,3,193,5,47,16,38,5,94,0,0,16,7,5,75, + 0,188,254,62,255,255,255,171,254,12,4,126,5,47,16,38,20,146,0,0,16,7,5,75,0,188,254,62,255,255,0,130,255,167,7,41,6,20,16,6, + 5,194,0,0,0,1,0,130,255,167,7,217,6,20,0,55,0,0,37,6,7,6,35,34,39,36,17,52,55,51,6,21,20,23,22,51,50,55,54,55, + 54,53,52,39,1,38,53,52,55,54,55,1,21,5,6,7,6,21,20,23,1,22,23,22,59,1,21,35,34,39,38,47,1,6,5,156,99,169,205,183, + 192,128,254,182,63,184,65,203,104,151,184,194,158,35,16,54,254,202,50,10,35,100,2,233,253,173,71,21,6,31,2,71,22,38,43,64,88,132,65,58, + 103,33,97,25,120,76,60,73,38,98,1,11,138,92,94,136,126,66,34,80,65,55,26,46,69,66,1,124,61,81,35,33,119,42,1,54,186,250,30,40, + 11,25,32,37,253,63,26,14,16,184,24,43,41,120,64,0,255,255,255,236,0,0,3,207,6,20,16,6,20,191,0,0,255,255,255,236,0,0,4,127, + 6,20,16,6,20,192,0,0,255,255,0,130,255,167,7,41,7,43,16,39,22,232,3,202,0,0,16,6,5,194,0,0,255,255,0,130,255,167,7,217, + 7,43,16,38,20,28,0,0,16,7,22,232,3,202,0,0,255,255,255,236,0,0,3,207,7,43,16,38,20,29,0,0,16,6,22,232,112,0,0,0, + 255,255,255,236,0,0,4,127,7,43,16,38,20,30,0,0,16,6,22,232,112,0,0,0,255,255,0,130,253,168,7,41,7,43,16,39,22,200,2,213, + 254,162,16,6,5,200,0,0,255,255,0,130,253,168,7,217,7,43,16,38,20,32,0,0,16,7,22,200,2,213,254,162,255,255,255,236,253,218,3,207, + 7,43,16,38,20,33,0,0,16,7,22,200,1,69,254,212,255,255,255,236,253,218,4,127,7,43,16,38,20,34,0,0,16,7,22,200,1,69,254,212, + 255,255,0,130,255,167,7,41,7,58,16,39,22,197,3,132,6,164,16,6,5,200,0,0,255,255,0,130,255,167,7,217,7,58,16,38,20,32,0,0, + 16,7,22,197,3,132,6,164,255,255,255,236,0,0,3,207,7,58,16,38,20,33,0,0,16,7,22,197,0,75,6,164,255,255,255,236,0,0,4,127, + 7,58,16,38,20,34,0,0,16,7,22,197,0,75,6,164,255,255,0,147,254,181,5,72,2,238,16,6,5,211,0,0,0,1,0,147,254,12,6,43, + 2,69,0,38,0,0,1,22,23,22,23,22,59,1,21,35,34,39,6,7,6,7,6,35,34,39,36,17,52,55,51,6,21,20,23,22,51,50,55,54, + 55,54,53,52,39,4,224,44,27,22,50,53,60,75,130,71,34,3,89,120,239,97,92,116,113,254,184,47,184,49,201,90,76,88,79,194,75,33,101,2, + 69,97,96,80,60,64,184,48,109,147,199,66,27,37,107,1,99,175,141,137,179,236,53,24,20,48,227,101,112,184,203,0,255,255,0,147,254,181,5,72, + 5,22,16,39,5,75,0,200,254,37,16,6,5,211,0,0,255,255,0,147,254,12,6,43,4,28,16,38,20,44,0,0,16,7,5,75,0,200,253,43, + 255,255,255,236,0,0,2,48,5,97,16,38,22,203,0,0,16,7,5,75,255,43,254,112,255,255,255,236,0,0,2,126,5,97,16,38,22,204,0,0, + 16,7,5,75,255,43,254,112,255,255,0,144,255,189,5,27,3,229,16,6,5,215,0,0,0,3,0,144,254,13,5,34,2,171,0,9,0,43,0,54, + 0,0,37,62,1,53,52,35,34,7,6,21,37,52,55,51,6,21,20,22,51,48,51,53,16,55,54,32,23,22,21,6,7,33,21,33,22,20,7,6, + 32,38,53,34,39,38,5,20,23,22,51,50,53,52,38,39,6,2,177,63,208,84,75,74,38,253,223,16,184,14,124,20,31,138,116,1,4,68,46,21, + 94,1,40,254,168,163,46,69,254,244,242,58,113,193,2,33,38,80,69,84,191,42,19,159,27,164,52,112,141,72,117,26,74,54,62,40,69,38,55,1, + 9,127,107,99,67,114,121,98,184,108,226,66,99,222,223,31,53,47,105,67,141,112,52,151,12,7,0,0,255,255,255,236,255,189,3,189,3,229,16,6, + 20,207,0,0,255,255,255,236,254,13,3,196,2,171,16,6,20,208,0,0,255,255,0,144,255,201,5,199,6,214,16,39,22,198,2,113,5,70,16,6, + 5,107,0,0,255,255,0,144,255,201,6,210,6,214,16,38,20,190,0,0,16,7,22,198,2,113,5,70,255,255,255,236,0,0,3,207,7,108,16,38, + 20,191,0,0,16,7,22,198,0,75,5,220,255,255,255,236,0,0,4,127,7,108,16,38,20,192,0,0,16,7,22,198,0,75,5,220,255,255,255,171, + 254,12,3,64,4,114,16,39,5,127,255,244,254,62,16,6,5,112,0,0,255,255,255,171,254,12,4,54,4,114,16,39,5,127,255,244,254,62,16,6, + 20,210,0,0,0,1,255,236,0,0,1,135,2,88,0,13,0,0,37,6,43,1,53,51,50,55,54,61,1,51,21,20,1,43,72,157,90,35,99,44, + 49,184,86,86,184,44,49,106,217,217,187,0,0,1,255,236,0,0,2,126,2,88,0,20,0,0,37,6,43,1,53,51,50,55,54,61,1,51,21,20, + 23,22,59,1,21,35,34,1,43,77,152,90,35,99,44,49,184,49,44,99,55,110,150,86,86,184,44,49,106,217,217,106,49,44,184,0,255,255,0,130, + 254,243,5,192,3,74,16,6,5,113,0,0,255,255,0,130,254,240,6,191,2,2,16,6,20,212,0,0,255,255,255,236,254,212,1,243,2,88,16,38, + 20,59,0,0,16,7,22,197,0,99,254,212,255,255,255,236,254,212,2,126,2,88,16,38,20,60,0,0,16,7,22,197,0,99,254,212,0,1,252,112, + 6,4,0,0,7,110,0,7,0,0,17,34,4,7,53,54,36,51,231,254,61,230,236,1,197,223,6,212,103,105,126,119,117,0,0,0,0,1,0,0, + 6,4,3,144,7,110,0,7,0,0,17,53,50,4,23,21,38,36,223,1,197,236,230,254,61,6,212,154,117,119,126,105,103,0,0,0,0,1,253,42, + 6,13,0,0,7,39,0,19,0,0,17,47,1,38,39,38,35,34,7,6,7,35,54,55,54,51,50,23,22,23,4,144,28,79,44,36,101,53,70,5, + 162,4,113,112,200,91,63,56,87,6,72,2,55,11,18,10,36,48,71,135,74,73,14,13,32,0,0,0,0,1,0,0,6,13,2,214,7,39,0,19, + 0,0,17,31,1,22,23,22,51,50,55,54,55,51,6,7,6,35,34,39,38,39,4,144,28,79,44,36,97,57,71,4,162,4,113,112,200,91,63,56, + 87,6,236,2,55,11,18,10,36,44,75,135,74,73,14,13,32,0,0,0,255,255,0,8,4,186,2,80,6,154,16,7,5,115,255,44,0,0,0,0, + 255,255,255,236,0,0,2,108,6,154,16,38,5,104,0,0,16,7,5,115,255,44,0,0,255,255,0,8,4,186,2,80,6,253,16,7,5,116,255,44, + 0,0,0,0,0,1,0,105,0,0,2,44,1,107,0,13,0,0,1,20,23,22,59,1,21,35,34,39,38,61,1,51,1,33,49,44,99,75,130,142, + 92,87,184,1,76,55,49,44,184,92,87,141,43,0,0,0,255,255,0,8,254,22,2,80,255,246,16,7,5,117,255,44,0,0,0,0,255,255,0,8, + 4,186,2,80,5,170,16,7,5,118,255,44,0,0,0,0,255,255,255,236,0,0,2,108,5,170,16,39,5,118,255,44,0,0,16,6,5,104,0,0, + 255,255,0,8,4,185,2,80,6,253,16,7,5,119,255,44,0,0,0,0,255,255,255,236,0,0,2,108,6,253,16,39,5,119,255,44,0,0,16,6, + 5,104,0,0,255,255,0,8,254,232,2,80,255,216,16,7,5,120,255,44,0,0,0,0,255,255,255,236,254,232,2,108,0,184,16,39,5,120,255,44, + 0,0,16,6,5,104,0,0,255,255,255,244,4,203,2,100,6,244,16,7,5,121,255,44,0,0,0,0,255,255,255,236,0,0,2,108,6,244,16,39, + 5,121,255,44,0,0,16,6,5,104,0,0,255,255,0,24,4,225,2,60,7,6,16,7,5,122,255,44,0,0,0,0,255,255,255,236,0,0,2,108, + 7,6,16,38,5,104,0,0,16,7,5,122,255,44,0,0,255,255,0,163,0,85,3,30,3,222,16,6,5,78,0,0,255,255,255,181,0,0,2,133, + 7,131,16,39,5,123,255,29,1,194,16,6,5,84,0,0,255,255,255,181,0,0,2,133,7,131,16,38,20,114,0,0,16,7,5,123,255,29,1,194, + 255,255,0,108,0,0,1,195,8,57,16,39,5,124,255,29,1,194,16,6,5,84,0,0,255,255,0,108,0,0,2,132,8,57,16,38,20,114,0,0, + 16,7,5,124,255,29,1,194,255,255,255,171,254,12,3,64,4,181,16,39,5,124,255,194,254,62,16,6,5,112,0,0,255,255,255,171,254,12,4,54, + 4,181,16,38,20,210,0,0,16,7,5,124,255,194,254,62,255,255,0,108,254,12,1,195,6,20,16,39,5,125,255,29,0,0,16,6,5,84,0,0, + 255,255,0,108,254,12,2,132,6,20,16,38,20,114,0,0,16,7,5,125,255,29,0,0,255,255,0,130,254,243,5,192,4,181,16,39,5,124,255,244, + 254,62,16,6,5,113,0,0,255,255,0,130,254,240,6,191,3,187,16,38,20,212,0,0,16,7,5,124,0,88,253,68,255,255,255,236,0,0,1,209, + 4,231,16,38,20,59,0,0,16,7,5,124,255,43,254,112,255,255,255,236,0,0,2,126,4,231,16,38,20,60,0,0,16,7,5,124,255,43,254,112, + 255,255,0,193,0,0,1,121,6,20,16,6,5,84,0,0,0,1,0,193,0,0,2,132,6,20,0,13,0,0,19,17,51,17,20,23,22,59,1,21, + 35,34,39,38,193,184,49,44,99,75,130,154,80,87,1,115,4,161,251,107,106,49,44,184,92,101,0,0,255,255,0,130,254,162,6,235,2,157,16,39, + 22,196,3,57,254,162,16,6,5,142,0,0,255,255,0,130,254,162,7,239,2,157,16,38,22,202,0,0,16,7,22,196,3,57,254,162,255,255,255,236, + 254,212,1,135,2,88,16,38,22,203,0,0,16,7,22,196,0,224,254,212,255,255,255,236,254,212,2,126,2,88,16,38,22,204,0,0,16,7,22,196, + 0,224,254,212,255,255,0,139,255,198,3,160,4,26,16,39,22,197,0,250,3,132,16,6,5,111,0,0,255,255,0,145,0,0,4,94,4,26,16,38, + 20,206,0,0,16,7,22,197,1,94,3,132,255,255,0,130,255,236,6,235,3,32,16,39,22,197,2,188,2,138,16,6,5,142,0,0,255,255,0,130, + 255,236,7,239,3,32,16,38,22,202,0,0,16,7,22,197,2,188,2,138,255,255,255,236,0,0,1,243,3,232,16,38,22,203,0,0,16,7,22,197, + 0,99,3,82,255,255,255,236,0,0,2,126,3,232,16,38,22,204,0,0,16,7,22,197,0,99,3,82,255,255,0,130,255,236,6,235,4,26,16,39, + 22,198,2,188,2,138,16,6,5,142,0,0,255,255,0,130,255,236,7,239,4,26,16,38,22,202,0,0,16,7,22,198,2,188,2,138,255,255,255,236, + 0,0,1,243,4,226,16,38,22,203,0,0,16,7,22,198,0,99,3,82,255,255,255,236,0,0,2,126,4,226,16,38,22,204,0,0,16,7,22,198, + 0,99,3,82,255,255,0,157,254,12,5,40,3,102,16,39,22,196,3,7,0,25,16,6,5,90,0,0,255,255,0,157,254,12,5,62,3,102,16,38, + 20,134,0,0,16,7,22,196,2,188,255,206,255,255,255,236,254,212,4,92,3,47,16,38,20,135,0,0,16,7,22,196,2,13,254,212,255,255,255,236, + 254,212,5,62,3,47,16,38,20,136,0,0,16,7,22,196,2,13,254,212,255,255,0,157,254,12,5,40,3,102,16,6,5,90,0,0,0,1,0,157, + 254,12,5,62,3,102,0,48,0,0,37,51,21,35,34,39,38,39,38,39,6,7,6,21,20,23,22,33,50,55,21,6,35,32,39,38,53,16,55,54, + 55,34,35,34,7,6,7,53,36,51,32,23,21,34,7,23,22,23,22,5,22,40,49,129,123,82,61,6,73,114,98,224,74,129,1,73,193,212,150,250, + 254,94,169,131,212,96,137,12,13,95,140,135,95,1,16,193,1,38,200,109,31,29,51,72,90,184,184,150,100,156,15,178,24,80,183,252,137,94,164,118, + 184,99,194,150,224,1,2,223,101,52,19,19,41,184,63,54,154,13,91,160,95,119,0,0,0,1,255,236,0,0,4,92,3,47,0,30,0,0,1,38, + 39,38,39,38,7,53,54,55,50,23,4,23,21,6,7,6,7,6,7,6,43,1,53,51,50,55,54,55,54,3,83,83,103,85,180,82,161,72,75,162, + 172,1,2,220,76,88,166,74,145,75,221,163,128,100,227,129,104,116,94,2,29,23,23,19,16,7,6,184,7,1,35,52,98,154,24,52,98,66,129,27, + 80,184,72,58,106,86,0,0,0,1,255,236,0,0,5,62,3,47,0,41,0,0,1,4,23,21,6,7,22,23,22,59,1,21,35,34,39,38,39,6, + 7,6,7,6,43,1,53,51,50,55,54,55,54,55,38,39,38,39,38,7,53,54,55,50,2,126,1,2,220,65,73,50,30,104,114,66,86,209,126,40, + 59,69,41,145,75,221,163,128,100,227,129,104,116,94,101,83,103,85,180,82,161,72,75,162,3,12,52,98,154,20,41,78,34,119,184,168,54,97,46,37, + 129,27,80,184,72,58,106,86,35,23,23,19,16,7,6,184,7,1,0,0,255,255,0,157,254,12,5,40,4,176,16,39,22,196,2,63,4,26,16,6, + 5,90,0,0,255,255,0,157,254,12,5,62,4,176,16,38,20,134,0,0,16,7,22,196,2,63,4,26,255,255,255,236,0,0,4,92,4,76,16,38, + 20,135,0,0,16,7,22,196,2,13,3,182,255,255,255,236,0,0,5,62,4,76,16,38,20,136,0,0,16,7,22,196,2,13,3,182,255,255,0,125, + 255,218,3,27,3,82,16,6,5,92,0,0,0,1,0,125,255,218,4,71,3,82,0,32,0,0,1,38,39,51,22,23,22,21,20,23,22,59,1,21, + 35,34,39,6,7,6,35,34,39,53,22,51,50,55,54,55,54,53,52,2,34,57,182,227,97,82,81,83,44,99,75,130,147,97,93,207,46,45,102,103, + 115,84,33,34,172,35,8,2,63,122,153,78,137,134,117,73,83,44,184,130,128,33,7,38,184,42,9,49,112,27,42,68,255,255,0,125,255,218,3,27, + 4,176,16,39,22,196,1,69,4,26,16,6,5,92,0,0,255,255,0,125,255,218,4,71,4,176,16,38,20,142,0,0,16,7,22,196,1,69,4,26, + 255,255,255,171,254,12,3,98,2,38,16,6,5,94,0,0,0,1,255,171,254,12,4,126,2,38,0,24,0,0,1,51,22,23,22,23,22,59,1,21, + 35,34,39,2,7,4,33,53,32,55,54,55,54,53,52,2,120,184,30,3,10,73,42,101,75,130,130,50,68,251,254,228,254,190,1,48,203,218,35,10, + 2,38,112,30,103,77,44,184,62,254,234,133,151,184,128,138,208,58,72,126,255,255,255,171,254,12,3,98,3,182,16,39,22,196,2,113,3,32,16,6, + 5,94,0,0,255,255,255,171,254,12,4,126,3,182,16,38,20,146,0,0,16,7,22,196,2,113,3,32,255,255,0,130,254,12,9,26,2,238,16,6, + 5,96,0,0,0,1,0,130,254,12,10,71,2,238,0,70,0,0,37,22,55,54,53,51,20,23,22,51,50,25,1,51,17,20,23,22,59,1,21,35, + 34,39,6,7,6,35,34,39,38,39,6,7,6,39,38,39,6,7,6,7,6,35,38,39,36,17,52,55,51,6,23,22,23,22,51,50,55,54,55,54, + 39,38,47,1,51,23,22,23,22,5,184,78,48,37,184,19,64,110,142,184,83,44,99,75,130,145,118,68,109,37,32,73,48,138,17,49,95,64,56,137, + 39,24,84,133,193,80,120,128,109,254,237,105,184,108,1,1,147,95,81,98,95,121,94,64,1,1,16,64,184,36,16,28,58,181,2,124,95,202,205,50, + 169,1,24,1,38,254,170,97,83,44,184,96,91,25,9,25,70,123,159,30,20,2,2,60,179,107,170,62,26,1,28,71,1,72,246,180,206,220,179,38, + 24,37,48,158,108,142,125,61,234,156,74,60,126,0,0,0,0,1,255,236,255,227,6,10,2,238,0,49,0,0,37,6,7,6,43,1,53,51,50,55, + 54,61,1,51,21,20,23,22,51,50,55,54,53,51,20,23,22,55,54,25,1,51,17,20,7,6,7,6,35,34,39,38,39,6,7,6,35,34,39,38, + 1,128,43,56,76,99,130,75,99,44,80,184,44,43,104,109,44,37,184,19,64,110,142,184,92,75,102,37,35,63,55,137,18,48,96,68,65,98,72,60, + 138,59,33,46,184,44,80,100,192,156,64,100,99,122,103,194,205,50,170,1,2,1,22,1,38,254,170,199,113,92,24,9,25,61,132,156,33,24,49,40, + 0,1,255,236,255,227,7,55,2,238,0,56,0,0,5,6,35,34,39,38,39,6,7,6,35,34,39,38,39,6,7,6,43,1,53,51,50,55,54,61, + 1,51,21,20,23,22,51,50,55,54,53,51,20,23,22,55,54,25,1,51,17,20,23,22,59,1,21,35,34,39,6,4,253,37,35,63,55,137,18,48, + 96,68,65,98,72,60,41,43,56,76,99,130,75,99,44,80,184,44,43,104,109,44,37,184,19,64,110,142,184,83,44,99,75,130,145,118,68,20,9,25, + 61,132,156,33,24,49,40,73,59,33,46,184,44,80,100,192,156,64,100,99,122,103,194,205,50,170,1,2,1,22,1,38,254,170,97,83,44,184,96,90, + 255,255,0,130,254,12,9,26,4,176,16,39,22,198,4,226,3,32,16,6,5,96,0,0,255,255,0,130,254,12,10,71,4,176,16,38,20,150,0,0, + 16,7,22,198,4,226,3,32,255,255,255,236,255,227,6,10,4,176,16,38,20,151,0,0,16,7,22,198,2,138,3,32,255,255,255,236,255,227,7,55, + 4,176,16,38,20,152,0,0,16,7,22,198,2,138,3,32,255,255,0,130,254,12,9,19,2,229,16,6,5,98,0,0,0,2,0,130,254,12,9,225, + 2,229,0,60,0,73,0,0,41,1,34,39,38,53,20,7,6,7,6,35,38,39,36,17,52,55,51,6,23,22,23,22,51,50,55,54,55,54,53,52, + 39,51,6,23,22,23,54,55,54,55,54,23,22,23,22,21,20,7,22,23,22,59,1,21,35,34,47,1,6,3,34,7,6,7,51,50,55,54,39,38, + 39,38,6,117,254,236,38,52,45,74,88,238,80,120,128,109,254,237,105,184,108,1,1,147,95,81,102,91,162,43,33,39,171,1,14,10,40,115,123,108, + 147,72,88,125,97,186,42,14,16,61,82,75,130,131,103,28,204,18,76,126,168,145,187,237,129,187,1,2,137,37,30,26,16,186,128,155,77,26,1,28, + 71,1,72,246,180,206,220,179,38,24,37,68,138,108,127,147,138,15,55,40,50,146,108,94,70,34,1,2,37,71,233,77,70,12,11,44,184,92,26,118, + 2,55,81,108,194,63,91,70,135,19,5,0,0,2,255,236,0,0,6,50,2,229,0,12,0,46,0,0,1,6,7,51,50,55,54,53,52,39,38,35, + 34,3,33,34,39,38,39,6,43,1,53,51,50,55,54,61,1,51,21,20,22,23,54,55,54,55,54,51,50,23,22,21,20,7,6,3,208,168,145,187, + 237,129,186,139,37,48,76,186,254,236,74,78,65,39,102,172,130,75,99,44,80,184,18,45,101,95,153,144,75,85,115,107,186,184,202,1,230,108,194,63, + 91,70,135,19,5,253,201,42,35,61,138,184,44,80,100,114,78,24,80,50,134,84,137,63,33,39,68,236,169,109,120,0,0,2,255,236,0,0,7,4, + 2,229,0,43,0,56,0,0,41,1,34,39,38,39,6,43,1,53,51,50,55,54,61,1,51,21,20,22,23,54,55,54,55,54,51,50,23,22,21,20, + 7,22,23,22,59,1,21,35,34,47,1,6,3,6,7,51,50,55,54,53,52,39,38,35,34,3,152,254,232,74,78,65,39,102,172,130,75,99,44,80, + 184,18,45,101,95,153,144,75,85,113,109,190,42,14,16,61,82,75,130,131,103,28,204,224,168,145,187,237,129,186,139,37,48,76,42,35,61,138,184,44, + 80,100,114,78,24,80,50,134,84,137,63,33,39,68,236,75,72,12,11,44,184,92,26,118,1,230,108,194,63,91,70,135,19,5,0,0,255,255,0,130, + 254,12,9,19,3,182,16,39,22,196,4,251,3,32,16,6,5,98,0,0,255,255,0,130,254,12,9,225,3,182,16,38,20,158,0,0,16,7,22,196, + 4,251,3,32,255,255,255,236,0,0,6,50,3,182,16,38,20,159,0,0,16,7,22,196,1,219,3,32,255,255,255,236,0,0,7,4,3,182,16,38, + 20,160,0,0,16,7,22,196,1,219,3,32,255,255,0,144,0,0,6,220,6,20,16,6,5,100,0,0,0,2,0,144,0,0,7,172,6,20,0,28, + 0,41,0,0,41,2,53,33,17,51,17,18,37,54,51,50,23,22,21,20,7,22,23,22,59,1,21,35,34,47,1,6,37,51,50,55,54,39,38,39, + 38,35,34,7,6,4,64,253,191,254,145,1,111,184,217,1,20,92,68,117,105,188,42,14,16,61,82,75,130,131,103,28,204,253,233,187,237,129,187,1, + 2,137,37,48,80,122,177,184,5,92,251,14,1,63,99,33,39,69,235,77,70,12,11,44,184,92,26,118,184,63,93,68,135,19,5,81,120,0,0,0, + 0,2,255,236,0,0,5,212,6,20,0,12,0,31,0,0,37,51,50,55,54,39,38,39,38,35,34,7,6,19,41,1,53,33,17,51,17,18,37,54, + 51,50,23,22,21,20,7,6,2,57,187,237,129,187,1,2,137,37,48,80,122,177,117,253,193,254,245,1,11,184,217,1,20,92,68,117,105,186,184,202, + 184,63,93,68,135,19,5,81,120,254,146,184,5,92,251,14,1,63,99,33,39,69,235,169,109,120,0,0,0,2,255,236,0,0,6,164,6,20,0,28, + 0,41,0,0,41,2,53,33,17,51,17,18,37,54,51,50,23,22,21,20,7,22,23,22,59,1,21,35,34,47,1,6,37,51,50,55,54,39,38,39, + 38,35,34,7,6,3,56,253,191,254,245,1,11,184,217,1,20,92,68,117,105,188,42,14,16,61,82,75,130,131,103,28,204,253,233,187,237,129,187,1, + 2,137,37,48,80,122,177,184,5,92,251,14,1,63,99,33,39,69,235,77,70,12,11,44,184,92,26,118,184,63,93,68,135,19,5,81,120,0,0,0, + 255,255,0,144,0,0,6,220,6,20,16,39,22,196,3,207,3,82,16,6,5,100,0,0,255,255,0,144,0,0,7,172,6,20,16,38,20,166,0,0, + 16,7,22,196,3,207,3,82,255,255,255,236,0,0,5,212,6,20,16,38,20,167,0,0,16,7,22,196,2,199,3,82,255,255,255,236,0,0,6,164, + 6,20,16,38,20,168,0,0,16,7,22,196,2,199,3,82,255,255,0,117,254,12,4,178,4,42,16,6,5,102,0,0,0,2,0,117,254,12,4,178, + 3,14,0,37,0,43,0,0,1,6,33,32,39,38,16,55,46,1,53,52,55,54,50,23,22,21,20,7,6,7,30,1,59,1,21,35,32,39,6,21, + 20,23,22,33,50,55,1,54,52,34,21,20,4,178,152,254,255,254,91,157,98,187,61,68,125,97,238,95,127,91,57,94,68,182,85,160,144,254,246,248, + 154,41,107,1,95,193,212,253,49,136,206,254,111,99,188,122,1,146,140,50,116,42,110,64,48,48,64,112,91,67,43,32,64,77,184,228,129,107,108,61, + 158,118,2,150,56,96,51,36,0,1,255,236,0,0,3,248,4,42,0,26,0,0,55,50,55,38,39,38,53,16,55,54,51,21,34,6,20,23,22,51, + 50,55,37,21,5,4,43,1,53,60,161,202,75,52,88,204,125,251,218,186,62,83,70,55,74,1,32,254,92,254,162,178,88,184,93,24,59,100,140,1, + 8,125,77,169,137,255,52,70,33,129,184,197,164,184,0,0,0,2,255,236,0,0,3,240,3,14,0,36,0,47,0,0,37,6,43,1,53,51,50,55, + 54,55,38,39,38,53,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,22,23,22,59,1,21,35,34,2,34,7,6,21,20,23,54,53,52,39, + 1,238,194,202,118,96,107,66,59,40,97,68,30,13,16,104,89,238,89,104,16,13,30,77,88,31,68,61,112,96,118,202,168,52,30,47,103,103,47,185, + 185,184,40,36,39,85,90,39,45,31,41,55,52,45,45,52,55,41,31,45,39,98,77,31,44,40,184,2,85,7,12,32,29,95,95,29,32,12,0,0, + 255,255,0,117,254,12,4,178,5,70,16,39,22,196,1,119,4,176,16,6,5,102,0,0,255,255,0,117,254,12,4,178,4,76,16,38,20,174,0,0, + 16,7,22,196,1,169,3,182,255,255,255,236,0,0,3,248,5,70,16,38,20,175,0,0,16,7,22,196,1,119,4,176,255,255,255,236,0,0,3,240, + 4,76,16,38,20,176,0,0,16,7,22,196,1,163,3,182,255,255,0,130,255,164,7,158,5,20,16,39,22,196,5,245,4,126,16,6,5,186,0,0, + 255,255,0,130,255,165,8,92,4,76,16,38,22,205,0,0,16,7,22,196,5,245,3,182,255,255,255,236,0,0,3,63,5,20,16,38,22,206,0,0, + 16,7,22,196,1,169,4,126,255,255,255,236,0,0,4,32,4,126,16,38,22,207,0,0,16,7,22,196,1,187,3,232,255,255,0,107,254,72,5,155, + 5,20,16,39,22,197,3,82,4,126,16,6,5,143,0,0,255,255,0,107,254,12,6,192,4,1,16,38,22,208,0,0,16,7,22,197,3,132,3,107, + 255,255,255,236,0,0,3,63,5,20,16,38,22,209,0,0,16,7,22,197,1,44,4,126,255,255,255,236,0,0,4,32,4,126,16,38,22,210,0,0, + 16,7,22,197,1,56,3,232,255,255,0,144,255,201,5,199,6,20,16,6,5,107,0,0,0,2,0,144,255,201,6,210,6,20,0,33,0,68,0,0, + 1,21,6,7,6,21,20,23,22,23,22,21,20,7,6,35,34,39,53,22,51,50,55,54,53,52,39,38,39,38,55,54,55,54,19,6,39,38,39,36, + 53,52,55,51,6,21,22,23,22,51,50,55,54,55,54,25,1,51,17,20,23,22,59,1,21,35,34,39,6,3,208,74,38,80,14,12,68,102,88,82, + 78,66,56,68,45,60,57,60,78,74,18,32,1,2,75,85,138,109,145,207,101,254,219,16,184,14,2,160,121,127,140,89,152,98,76,184,49,44,99,75, + 130,153,113,158,4,111,82,4,14,30,33,28,18,16,10,15,88,110,42,39,11,88,10,26,26,30,38,17,16,28,47,46,81,38,43,251,112,20,2,2, + 30,88,195,75,53,58,44,92,46,35,27,47,94,73,1,1,3,177,251,107,106,49,44,184,123,126,0,0,0,1,255,236,0,0,3,207,6,20,0,31, + 0,0,41,1,53,33,50,55,54,53,52,39,1,38,53,52,55,54,55,1,21,5,6,7,6,21,20,23,1,22,21,20,7,6,1,54,254,182,1,54, + 148,45,16,54,254,202,50,10,31,104,2,233,253,173,71,21,6,31,1,19,102,62,95,184,104,36,36,69,66,1,124,61,81,35,33,118,43,1,54,186, + 250,30,40,11,25,32,37,254,182,123,123,113,101,155,0,0,0,1,255,236,0,0,4,127,6,20,0,41,0,0,41,1,53,33,50,55,54,53,52,39, + 1,38,53,52,55,54,55,1,21,5,6,7,6,21,20,23,1,22,23,22,59,1,21,35,34,39,38,47,1,6,7,6,1,54,254,182,1,54,148,45, + 16,54,254,202,50,10,31,104,2,233,253,173,71,21,6,31,2,71,22,38,43,64,88,132,65,58,103,33,97,21,17,95,184,104,36,36,69,66,1,124, + 61,81,35,33,118,43,1,54,186,250,30,40,11,25,32,37,253,63,26,14,16,184,24,43,41,120,46,27,155,0,0,0,255,255,0,144,254,200,5,24, + 6,20,16,6,5,108,0,0,0,1,0,144,254,200,6,35,6,20,0,36,0,0,37,54,53,17,51,17,20,23,22,59,1,21,35,34,39,6,7,6, + 5,6,35,34,39,36,3,38,55,51,6,21,20,23,22,51,50,55,54,4,18,78,184,49,44,99,75,130,112,78,18,27,121,254,251,134,85,99,69,254, + 220,1,1,64,184,65,166,40,73,80,109,174,73,126,227,4,106,251,107,106,49,44,184,51,46,40,177,66,34,22,91,1,18,138,92,115,115,126,66,16, + 34,53,0,0,0,1,255,236,0,0,1,175,6,20,0,13,0,0,1,20,7,6,43,1,53,51,50,55,54,53,17,51,1,175,87,80,154,130,75,99, + 44,49,184,1,115,178,101,92,184,44,49,106,4,149,0,0,0,1,255,236,0,0,2,186,6,20,0,20,0,0,37,6,43,1,53,51,50,55,54,53, + 17,51,17,20,23,22,59,1,21,35,34,1,83,77,152,130,75,99,44,49,184,49,44,99,75,130,150,86,86,184,44,49,106,4,149,251,107,106,49,44, + 184,0,0,0,255,255,0,140,254,20,4,94,2,243,16,6,5,109,0,0,0,2,0,140,254,20,5,103,2,116,0,17,0,53,0,0,37,22,51,50, + 55,54,53,52,39,38,39,38,35,34,7,6,21,20,5,6,7,6,35,34,39,38,7,6,21,17,35,17,52,55,54,51,38,53,52,55,54,51,50,23, + 22,23,22,23,22,59,1,21,35,34,2,98,122,76,44,21,53,6,21,59,40,46,59,27,68,1,192,15,13,133,75,181,141,50,75,25,200,120,65,90, + 2,162,77,92,72,84,170,40,15,40,38,105,75,130,175,168,42,22,57,58,24,20,88,17,12,27,68,68,40,169,14,8,80,78,28,78,26,79,254,147, + 1,109,173,102,55,42,40,148,132,63,36,71,179,67,44,44,184,0,0,0,0,2,255,236,255,205,3,166,2,109,0,21,0,36,0,0,37,6,35,34, + 39,6,43,1,53,51,50,54,55,54,55,54,51,50,23,22,21,20,37,22,51,50,55,54,53,52,39,38,35,34,6,7,6,3,100,97,147,206,110,64, + 104,160,116,52,87,5,20,135,94,81,176,91,97,253,240,62,159,47,19,52,40,42,88,46,91,15,7,52,102,98,48,184,71,49,181,80,56,84,89,184, + 143,78,69,18,53,69,75,38,41,60,97,37,0,2,255,236,255,206,4,180,2,109,0,29,0,47,0,0,37,6,35,34,39,6,43,1,53,51,50,55, + 54,55,54,55,54,51,50,23,22,23,22,23,22,59,1,21,35,34,37,22,51,50,55,54,53,52,39,38,39,38,35,34,7,6,7,6,3,100,97,139, + 214,110,64,104,160,116,52,44,43,5,20,135,94,93,72,66,193,17,5,51,36,107,75,130,176,254,20,62,159,47,19,52,5,22,58,39,39,53,41,50, + 15,7,52,102,98,48,184,36,35,49,181,80,56,29,83,167,49,62,44,184,196,69,18,53,69,19,18,88,17,12,27,33,97,37,0,0,255,255,0,147, + 254,181,5,72,3,182,16,39,22,196,2,63,3,32,16,6,5,211,0,0,255,255,0,147,254,12,6,43,2,188,16,38,20,44,0,0,16,7,22,196, + 2,63,2,38,255,255,255,236,0,0,1,135,3,232,16,39,22,196,0,224,3,82,16,6,22,203,0,0,255,255,255,236,0,0,2,126,3,232,16,39, + 22,196,0,224,3,82,16,6,22,204,0,0,255,255,0,139,255,198,3,160,2,222,16,6,5,111,0,0,0,2,0,145,0,0,4,94,2,238,0,10, + 0,36,0,0,1,38,39,38,39,6,7,6,23,30,1,19,38,39,51,22,23,22,23,22,59,1,21,35,34,39,38,39,6,35,34,39,38,53,52,55, + 54,2,164,15,13,13,12,120,82,111,2,1,180,116,4,3,184,1,36,21,56,31,112,75,130,90,73,45,38,138,156,56,58,189,204,109,1,26,42,49, + 50,101,12,67,89,62,41,50,1,209,39,43,168,174,101,79,44,184,51,31,59,73,15,48,154,173,127,68,0,3,255,236,255,189,3,189,3,229,0,15, + 0,45,0,61,0,0,1,54,55,54,53,52,39,38,35,34,7,6,21,20,23,22,7,50,55,38,39,38,53,52,55,54,23,38,39,53,22,23,4,23, + 22,21,20,7,6,35,34,39,6,43,1,53,1,22,21,20,7,6,7,22,51,50,55,54,53,52,39,38,1,148,36,34,39,15,22,58,65,23,22,7, + 21,249,52,78,45,15,18,45,48,77,44,81,223,216,1,0,64,14,40,74,175,131,154,120,146,137,2,171,6,98,12,17,52,49,125,17,7,33,29,1, + 13,27,64,72,61,46,37,52,45,43,35,30,37,118,136,11,105,69,78,64,84,83,90,9,39,14,185,68,179,209,222,52,57,103,61,113,108,41,184,1, + 68,37,39,147,105,14,19,46,67,30,33,60,78,69,0,0,0,3,255,236,254,13,3,196,2,171,0,10,0,36,0,47,0,0,37,51,50,55,54,53, + 52,35,34,7,6,7,18,55,54,51,50,23,22,21,20,7,33,21,33,22,21,20,7,6,35,34,39,38,3,35,53,5,20,23,22,51,50,53,52,39, + 38,35,1,83,19,42,96,114,84,75,74,38,184,9,129,108,129,138,69,46,163,1,88,254,168,163,46,69,138,129,108,129,9,175,1,103,38,74,75,84, + 114,96,42,184,76,90,52,112,141,72,117,1,10,126,107,99,67,114,111,108,184,108,111,114,67,99,107,128,1,8,184,184,117,72,141,112,52,90,76,0, + 255,255,255,171,254,12,3,64,2,134,16,6,5,112,0,0,0,2,255,171,254,12,4,54,2,134,0,11,0,44,0,0,37,52,39,38,39,38,7,6, + 7,6,23,22,5,51,21,35,39,6,7,6,7,6,33,53,32,55,54,55,38,39,38,39,38,39,38,55,54,55,54,23,22,23,22,23,22,2,141,16, + 24,46,60,60,67,13,17,64,47,1,115,246,194,70,25,129,83,105,192,254,147,1,105,132,168,62,118,45,139,51,106,10,2,10,27,176,59,65,87,69, + 133,22,13,184,76,57,80,30,41,26,29,56,75,54,40,4,184,1,156,129,83,47,86,184,76,95,148,3,7,24,43,89,135,31,57,155,75,25,1,2, + 49,92,141,83,255,255,0,130,254,243,5,192,3,74,16,6,5,113,0,0,0,1,0,130,254,240,6,191,2,2,0,55,0,0,5,54,53,38,39,38, + 39,38,53,52,55,54,55,54,51,50,23,22,59,1,21,35,34,39,38,35,34,7,6,21,20,23,22,23,22,7,6,7,6,35,34,39,36,17,52,55, + 51,6,21,20,23,22,51,50,55,54,4,76,91,1,47,29,30,44,52,80,84,30,42,117,87,128,32,35,35,114,112,108,26,36,15,45,65,73,3,3, + 113,128,218,89,104,188,117,254,219,63,184,65,166,66,179,91,77,149,33,51,33,43,13,8,40,59,61,65,60,94,14,6,134,196,184,172,165,6,17,35, + 48,27,30,123,98,86,96,31,12,41,103,1,6,153,90,90,153,114,78,31,8,15,0,0,255,255,0,130,254,12,5,192,3,74,16,39,22,197,1,244, + 254,12,16,6,5,113,0,0,255,255,0,130,254,12,6,191,2,2,16,39,22,197,1,244,254,12,16,6,20,212,0,0,255,255,255,236,254,212,1,243, + 2,88,16,38,20,59,0,0,16,7,22,197,0,99,254,212,255,255,255,236,254,212,2,126,2,88,16,38,20,60,0,0,16,7,22,197,0,99,254,212, + 255,255,255,46,255,236,3,191,6,237,16,38,20,223,0,0,16,7,5,123,254,150,1,44,255,255,255,46,255,236,4,218,6,237,16,38,20,224,0,0, + 16,7,5,123,254,150,1,44,255,255,255,229,255,236,3,191,7,163,16,38,20,223,0,0,16,7,5,124,254,150,1,44,255,255,255,229,255,236,4,218, + 7,163,16,38,20,224,0,0,16,7,5,124,254,150,1,44,255,255,0,23,254,12,3,191,6,20,16,38,20,223,0,0,16,7,5,125,254,200,0,0, + 255,255,0,23,254,12,4,218,6,20,16,38,20,224,0,0,16,7,5,125,254,200,0,0,0,1,0,84,255,236,3,191,6,20,0,22,0,0,1,16, + 7,6,7,6,35,34,39,53,22,51,50,55,1,51,1,54,55,54,53,17,51,3,191,139,55,77,205,158,106,75,96,85,113,136,254,22,179,1,170,29, + 20,37,184,3,66,254,212,218,85,71,180,32,184,32,152,4,70,252,65,43,55,137,184,2,174,0,0,0,0,1,0,84,255,236,4,218,6,20,0,31, + 0,0,1,6,7,6,35,34,39,53,22,51,50,55,1,51,1,54,55,54,53,17,51,17,20,23,22,59,1,21,35,34,39,38,3,52,59,73,202,161, + 106,75,96,85,113,136,254,22,179,1,170,29,20,37,184,34,64,80,105,129,175,102,17,1,60,91,65,180,32,184,32,152,4,70,252,65,43,55,137,184, + 2,174,252,68,174,84,158,184,243,41,0,0,0,3,0,30,255,84,8,22,7,76,0,3,0,7,0,42,0,0,9,4,21,51,53,39,53,52,54,55, + 54,55,54,63,1,54,55,54,53,52,38,35,34,6,7,21,62,1,51,50,22,21,20,6,15,1,14,1,29,1,4,26,3,252,252,4,252,4,3,150, + 203,6,6,6,8,19,23,44,88,92,34,36,223,184,103,193,94,97,179,79,108,131,51,57,90,90,56,7,76,252,4,252,4,3,252,253,174,254,254,147, + 123,52,60,21,25,26,31,43,86,90,64,69,76,159,194,56,57,188,67,70,110,89,49,94,53,89,86,130,101,154,0,0,0,2,0,100,255,227,5,170, + 5,213,0,7,0,10,0,0,55,1,51,1,7,3,33,3,1,33,3,100,2,48,230,2,48,168,193,253,140,193,1,6,1,234,245,35,5,178,250,78, + 64,1,246,254,10,2,170,2,124,0,0,0,0,3,0,200,255,237,4,20,5,232,0,9,0,26,0,36,0,0,1,17,51,50,55,54,53,52,38,35, + 1,54,51,50,23,22,21,20,7,22,21,20,7,6,33,34,39,19,17,51,50,55,54,53,52,38,35,1,124,52,251,119,61,198,175,254,222,136,100,240, + 162,206,215,214,117,171,254,189,100,132,180,111,234,94,44,236,191,2,126,254,35,114,59,66,89,149,3,87,19,97,123,208,213,122,122,228,142,112,164,19, + 5,52,254,21,128,61,56,104,142,0,0,0,0,1,0,100,255,227,3,234,5,243,0,5,0,0,5,9,1,23,9,1,3,107,252,249,3,7,127,253, + 120,2,136,29,3,8,3,8,127,253,119,253,119,0,0,0,0,2,0,200,0,0,4,6,5,210,0,12,0,21,0,0,51,17,51,32,23,22,23,22, + 16,7,6,4,33,55,62,2,16,39,46,1,39,200,90,1,132,158,159,25,10,39,56,254,185,254,194,90,206,199,65,10,18,188,254,5,210,120,122,249, + 101,254,98,127,184,173,192,8,99,212,1,122,92,172,145,10,0,1,0,200,0,0,3,156,5,242,0,13,0,0,1,17,35,17,5,7,37,17,5,7, + 37,17,5,7,1,124,180,2,212,28,253,252,2,32,28,253,252,2,32,28,1,54,254,202,5,242,117,178,83,254,195,88,178,83,254,195,88,178,0,0, + 0,1,0,200,0,0,3,156,5,242,0,9,0,0,1,17,35,17,5,7,37,17,5,7,1,124,180,2,212,28,253,252,2,32,28,3,42,252,214,5, + 242,117,178,83,254,195,88,178,0,1,0,150,0,0,2,238,5,213,0,11,0,0,19,33,21,35,17,51,21,33,53,51,17,35,150,2,88,210,210,253, + 168,210,210,5,213,180,251,147,180,180,4,109,0,3,0,200,0,0,4,56,5,213,0,3,0,7,0,11,0,0,19,33,17,33,1,17,33,17,5,33, + 17,33,200,3,112,252,144,2,188,253,248,2,8,253,248,2,8,5,213,250,43,3,69,1,220,254,36,180,254,35,0,0,0,5,0,150,255,227,6,164, + 5,243,0,15,0,20,0,25,0,30,0,35,0,0,0,2,6,4,32,36,38,2,16,18,54,36,32,4,22,18,1,54,0,55,33,3,17,33,22,0, + 1,33,17,6,0,1,17,33,38,0,6,164,122,208,254,224,254,198,254,224,208,122,122,208,1,32,1,58,1,32,208,122,253,83,194,1,18,30,254,14, + 180,254,14,30,1,18,254,208,1,242,194,254,238,2,136,1,242,30,254,238,2,78,254,224,208,123,123,208,1,32,1,58,1,32,208,123,123,208,254,224, + 253,22,30,1,18,195,254,13,1,243,195,254,238,2,137,1,243,30,254,238,1,48,254,13,195,1,18,0,0,1,0,200,0,0,1,124,5,213,0,3, + 0,0,19,51,17,35,200,180,180,5,213,250,43,0,0,0,0,1,0,200,255,227,4,131,5,243,0,10,0,0,33,35,17,51,17,1,23,9,1,7, + 1,1,124,180,180,2,136,120,253,46,2,217,120,253,113,5,213,253,225,2,61,134,253,129,253,123,134,2,67,0,0,0,0,1,0,200,0,0,3,251, + 5,213,0,6,0,0,9,1,23,1,35,17,51,1,124,1,255,128,253,77,128,180,1,51,2,0,128,253,77,5,213,0,0,1,0,200,0,0,10,212, + 5,243,0,12,0,0,19,51,9,3,23,9,3,17,35,200,116,2,131,2,56,2,47,2,46,128,253,82,253,210,253,209,253,179,180,5,213,253,229,2, + 57,253,209,2,47,128,253,83,2,46,253,210,1,238,251,76,0,1,0,200,0,0,6,119,5,243,0,8,0,0,19,51,9,1,23,9,1,17,35,200, + 116,2,131,2,56,128,253,82,253,179,180,5,213,253,229,2,57,128,253,83,1,238,251,76,0,5,0,200,0,0,6,156,5,213,0,3,0,7,0,11, + 0,15,0,19,0,0,1,17,33,17,1,33,17,33,1,17,33,17,33,17,33,17,19,17,33,17,1,124,1,220,253,112,5,212,250,44,3,68,1,220, + 251,148,1,220,180,1,220,2,144,254,36,1,220,3,69,250,43,5,33,254,36,1,220,254,36,1,220,253,111,254,36,1,220,0,0,0,0,3,0,150, + 255,227,6,164,5,243,0,15,0,31,0,39,0,0,0,54,52,46,2,34,14,2,20,30,2,50,54,0,2,6,4,32,36,38,2,16,18,54,36,32, + 4,22,18,4,6,34,38,52,54,50,22,5,146,94,94,159,222,240,222,159,94,94,159,222,240,222,1,177,122,208,254,224,254,198,254,224,208,122,122,208, + 1,32,1,58,1,32,208,122,253,133,82,116,82,82,116,82,1,148,223,240,223,158,95,95,158,223,240,223,158,95,95,1,88,254,224,208,123,123,208,1, + 32,1,58,1,32,208,123,123,208,254,224,215,82,82,116,82,82,0,0,0,0,1,0,200,0,0,4,231,5,232,0,17,0,0,1,36,53,52,36,33, + 34,7,17,35,17,54,51,32,0,17,16,5,3,40,1,11,254,211,254,226,53,55,180,162,126,1,98,1,157,254,129,2,89,102,212,182,249,6,250,196, + 5,212,20,254,191,254,236,254,176,146,0,0,0,1,0,200,0,0,6,42,5,213,0,11,0,0,51,17,51,9,1,51,17,35,17,9,1,17,200,180, + 1,253,1,253,180,180,254,3,254,3,5,213,253,162,2,94,250,43,4,189,253,161,2,95,251,67,0,0,0,2,0,150,0,0,4,26,5,242,0,11, + 0,29,0,0,0,52,46,1,34,14,1,20,30,1,50,62,1,6,7,6,7,17,35,17,38,39,46,1,52,62,1,50,30,1,3,102,72,125,146,125, + 72,72,125,146,125,252,122,102,64,72,180,71,65,104,120,121,207,244,207,121,3,231,147,124,72,72,124,147,125,72,72,76,209,59,37,14,253,137,2,119, + 14,37,60,208,244,207,121,121,207,0,0,0,0,2,0,200,0,0,4,68,5,233,0,12,0,23,0,0,8,1,21,20,2,7,6,35,17,35,17,54, + 51,3,32,55,54,53,52,39,38,35,34,7,2,216,1,108,200,255,118,139,180,162,126,108,1,9,133,134,139,114,190,43,46,5,233,254,229,252,141,254, + 209,78,36,254,92,5,213,20,252,111,115,114,150,158,108,88,4,0,0,0,0,1,0,150,255,242,2,242,5,234,0,9,0,0,9,3,7,9,3,23, + 1,148,1,94,254,162,1,31,128,254,99,1,94,254,162,1,157,128,4,76,254,162,254,162,254,226,128,1,158,1,94,1,94,1,158,128,0,1,0,100, + 0,0,4,252,5,242,0,7,0,0,1,7,37,17,35,17,37,55,4,252,56,254,50,180,254,34,56,4,138,172,149,251,141,4,173,153,172,0,0,0, + 0,1,0,200,0,0,4,180,5,234,0,7,0,0,1,23,1,17,35,17,51,17,4,52,128,252,200,180,180,5,234,128,252,201,253,205,5,213,253,92, + 0,1,0,150,255,227,4,231,5,242,0,11,0,0,9,1,55,9,1,23,9,1,7,9,1,39,2,81,254,69,150,1,146,1,147,150,254,69,1,187, + 150,254,109,254,110,150,2,237,2,163,98,253,161,2,95,98,253,93,253,88,98,2,100,253,156,98,0,0,0,3,0,150,0,0,4,226,5,213,0,19, + 0,27,0,36,0,0,33,35,53,38,39,38,16,55,54,55,53,51,21,22,23,22,16,7,6,7,25,1,54,55,54,16,39,38,1,17,6,7,6,21, + 20,23,22,3,22,180,170,129,161,161,128,171,180,170,129,161,161,128,171,96,75,109,109,75,254,236,96,75,109,109,75,204,26,128,161,1,199,162,128,26, + 203,203,26,128,161,254,57,162,128,26,3,135,253,48,23,76,108,1,50,108,75,253,72,2,208,23,76,110,152,150,110,76,0,1,0,100,0,0,6,22, + 5,242,0,11,0,0,33,35,17,1,55,1,17,51,17,1,23,1,3,151,180,253,129,128,1,255,180,1,255,128,253,129,2,244,2,126,128,254,0,1, + 227,254,29,2,0,128,253,130,0,3,0,150,255,241,3,162,5,185,0,7,0,29,0,37,0,0,0,52,38,34,6,20,22,50,36,6,32,38,16,55, + 54,55,38,39,38,16,54,32,22,16,7,6,7,22,23,22,2,52,38,34,6,20,22,50,2,238,123,174,123,123,174,1,47,229,254,190,229,114,47,55, + 55,47,114,229,1,66,229,114,47,55,55,47,114,180,123,174,123,123,174,1,32,174,123,123,174,123,49,229,229,1,66,115,47,27,28,46,114,1,67,229, + 229,254,190,115,47,27,28,46,114,1,195,174,123,123,174,123,0,2,0,200,0,0,3,224,5,232,0,10,0,19,0,0,51,17,54,51,50,4,21,20, + 4,33,25,1,50,54,53,52,38,35,34,7,200,132,129,243,1,32,254,169,254,243,202,230,180,162,42,48,5,213,19,230,189,208,220,253,103,3,78,127, + 118,99,156,6,0,2,0,200,255,237,3,224,5,213,0,10,0,20,0,0,19,51,17,32,4,21,20,4,35,34,39,19,48,17,22,51,50,54,53,52, + 38,200,180,1,13,1,87,254,224,243,129,132,180,48,42,162,180,230,5,213,253,103,220,208,189,230,19,2,135,254,18,6,156,99,118,127,0,1,0,100, + 0,0,2,188,5,213,0,7,0,0,19,53,33,17,51,17,35,17,100,1,164,180,180,2,145,180,2,144,250,43,2,145,0,2,0,100,0,0,5,170, + 5,242,0,6,0,14,0,0,9,1,35,1,55,9,1,0,6,34,38,52,54,50,22,5,170,253,208,230,253,208,168,1,251,1,251,254,145,82,116,82, + 82,116,82,5,178,250,78,5,178,64,250,218,5,38,253,216,82,82,116,82,82,0,0,0,255,255,0,200,0,0,1,124,5,213,18,6,20,240,0,0, + 0,1,0,100,255,227,5,170,5,213,0,6,0,0,55,1,51,1,7,9,1,100,2,48,230,2,48,168,254,5,254,5,35,5,178,250,78,64,5,38, + 250,218,0,0,255,255,0,150,255,227,4,231,5,242,18,6,20,254,0,0,0,1,0,100,0,0,6,39,5,243,0,8,0,0,19,9,1,7,1,17, + 35,17,1,100,2,200,2,251,122,253,219,180,254,16,3,44,2,199,253,59,132,1,254,251,88,4,157,254,15,0,0,0,0,3,0,170,1,224,6,130, + 2,168,0,3,0,7,0,11,0,0,1,33,53,33,5,53,33,21,41,1,53,33,1,253,254,173,1,83,3,50,1,83,253,189,254,174,1,82,1,224, + 200,200,200,200,200,0,0,0,255,255,0,170,1,55,6,130,4,14,16,39,21,10,0,0,255,88,16,7,15,93,0,0,3,70,0,0,255,255,0,170, + 1,58,6,130,4,10,16,39,21,10,0,0,1,98,16,7,15,92,0,0,1,58,0,0,255,255,0,170,1,61,6,130,4,11,16,39,21,10,0,0, + 255,93,16,7,15,92,0,0,3,67,0,0,255,255,0,170,1,59,6,130,4,10,16,39,15,93,0,0,1,60,16,7,21,10,0,0,1,98,0,0, + 255,255,0,170,1,61,6,130,4,10,16,39,21,10,0,0,255,93,16,7,21,10,0,0,1,98,0,0,255,255,0,170,0,0,6,130,5,72,16,39, + 15,92,0,0,4,128,16,38,15,92,0,0,16,39,15,92,0,0,1,128,16,7,15,92,0,0,3,0,255,255,0,170,0,0,6,130,5,72,16,39, + 15,92,0,0,4,128,16,39,15,92,0,0,1,128,16,39,15,92,0,0,3,0,16,6,15,93,0,0,255,255,0,170,0,0,6,130,5,72,16,39, + 21,10,0,0,254,32,16,39,15,92,0,0,4,128,16,39,15,92,0,0,1,128,16,7,15,92,0,0,3,0,0,0,255,255,0,170,0,0,6,130, + 5,72,16,39,15,92,0,0,4,128,16,38,15,92,0,0,16,39,15,92,0,0,3,0,16,7,15,93,0,0,1,128,255,255,0,170,0,0,6,130, + 5,72,16,39,15,93,0,0,1,128,16,39,15,92,0,0,4,128,16,39,15,92,0,0,3,0,16,6,15,93,0,0,255,255,0,170,0,0,6,130, + 5,72,16,39,15,93,0,0,1,128,16,39,15,92,0,0,3,0,16,39,15,92,0,0,4,128,16,7,21,10,0,0,254,32,0,0,255,255,0,170, + 0,0,6,130,5,72,16,38,15,92,0,0,16,38,21,10,0,160,16,39,15,92,0,0,4,128,16,7,15,92,0,0,3,0,0,0,255,255,0,170, + 0,0,6,130,5,72,16,38,15,93,0,0,16,38,21,10,0,160,16,39,15,92,0,0,4,128,16,7,15,92,0,0,3,0,0,0,255,255,0,170, + 0,0,6,130,5,72,16,39,21,10,0,0,254,32,16,39,15,92,0,0,3,0,16,39,15,92,0,0,4,128,16,6,21,10,0,160,255,255,0,170, + 0,0,6,130,5,72,16,39,15,93,0,0,3,0,16,39,15,92,0,0,1,128,16,38,15,92,0,0,16,7,15,92,0,0,4,128,255,255,0,170, + 0,0,6,130,5,72,16,39,15,93,0,0,3,0,16,39,15,92,0,0,4,128,16,39,15,92,0,0,1,128,16,6,15,93,0,0,255,255,0,170, + 0,0,6,130,5,72,16,39,21,10,0,0,254,32,16,39,15,92,0,0,1,128,16,39,15,92,0,0,4,128,16,7,15,93,0,0,3,0,0,0, + 255,255,0,170,0,0,6,130,5,72,16,38,15,92,0,0,16,39,15,93,0,0,1,128,16,39,15,93,0,0,3,0,16,7,15,92,0,0,4,128, + 255,255,0,170,0,0,6,130,5,72,16,38,15,93,0,0,16,39,15,92,0,0,4,128,16,39,15,93,0,0,3,0,16,7,15,93,0,0,1,128, + 255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,254,32,16,39,15,93,0,0,1,128,16,39,15,93,0,0,3,0,16,7,15,92,0,0, + 4,128,0,0,255,255,0,170,0,0,6,130,5,72,16,38,21,10,0,160,16,39,15,92,0,0,4,128,16,39,15,93,0,0,3,0,16,6,15,92, + 0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,38,21,10,0,160,16,38,15,93,0,0,16,39,15,92,0,0,4,128,16,7,15,93,0,0, + 3,0,0,0,255,255,0,170,0,0,6,130,5,72,16,38,21,10,0,160,16,39,15,92,0,0,4,128,16,39,15,93,0,0,3,0,16,7,21,10, + 0,0,254,32,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,1,32,16,39,15,92,0,0,1,128,16,38,15,92,0,0,16,7,15,92, + 0,0,4,128,255,255,0,170,0,0,6,130,5,72,16,38,15,93,0,0,16,39,15,92,0,0,4,128,16,39,15,92,0,0,1,128,16,7,21,10, + 0,0,1,32,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,254,32,16,39,21,10,0,0,1,32,16,39,15,92,0,0,1,128,16,7, + 15,92,0,0,4,128,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,1,128,16,39,15,92,0,0,4,128,16,38,15,92,0,0, + 16,7,21,10,0,0,1,32,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,1,32,16,38,15,93,0,0,16,39,15,92,0,0,4,128, + 16,7,15,93,0,0,1,128,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,1,32,16,39,21,10,0,0,254,32,16,39,15,92,0,0, + 4,128,16,7,15,93,0,0,1,128,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,1,32,16,39,15,92,0,0,4,128,16,38, + 21,10,0,160,16,6,15,92,0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,1,32,16,39,15,92,0,0,4,128,16,38, + 21,10,0,160,16,6,15,93,0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,1,32,16,38,21,10,0,160,16,39,15,92, + 0,0,4,128,16,7,21,10,0,0,254,32,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39,15,92,0,0,3,0,16,39, + 15,92,0,0,1,128,16,6,15,92,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,38,15,93,0,0,16,39,15,92, + 0,0,3,0,16,7,15,92,0,0,1,128,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39,15,92,0,0,3,0,16,39, + 15,92,0,0,1,128,16,7,21,10,0,0,254,32,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39,15,93,0,0, + 1,128,16,39,15,92,0,0,3,0,16,6,15,92,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,38,15,93,0,0, + 16,39,15,92,0,0,3,0,16,7,15,93,0,0,1,128,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39,21,10,0,0, + 254,32,16,39,15,92,0,0,3,0,16,7,15,93,0,0,1,128,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39, + 15,92,0,0,3,0,16,38,21,10,0,160,16,6,15,92,0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39, + 15,92,0,0,3,0,16,38,21,10,0,160,16,6,15,93,0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,38, + 21,10,0,160,16,39,15,92,0,0,3,0,16,7,21,10,0,0,254,32,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,38, + 15,92,0,0,16,39,15,92,0,0,1,128,16,7,15,93,0,0,3,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,38, + 15,93,0,0,16,39,15,92,0,0,1,128,16,7,15,93,0,0,3,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39, + 15,93,0,0,3,0,16,39,15,92,0,0,1,128,16,7,21,10,0,0,254,32,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0, + 4,128,16,39,15,93,0,0,3,0,16,39,15,93,0,0,1,128,16,6,15,92,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0, + 4,128,16,39,15,93,0,0,1,128,16,39,15,93,0,0,3,0,16,6,15,93,0,0,255,255,0,170,0,0,6,130,5,72,16,39,15,93,0,0, + 4,128,16,39,15,93,0,0,3,0,16,39,15,93,0,0,1,128,16,7,21,10,0,0,254,32,0,0,255,255,0,170,0,0,6,130,5,72,16,39, + 15,93,0,0,4,128,16,38,15,92,0,0,16,39,15,93,0,0,3,0,16,6,21,10,0,160,0,0,255,255,0,170,0,0,6,130,5,72,16,39, + 15,93,0,0,4,128,16,39,15,93,0,0,3,0,16,38,15,93,0,0,16,6,21,10,0,160,0,0,255,255,0,170,0,0,6,130,5,72,16,39, + 15,93,0,0,4,128,16,39,21,10,0,0,254,32,16,39,15,93,0,0,3,0,16,6,21,10,0,160,255,255,0,170,0,0,6,130,5,72,16,39, + 15,93,0,0,4,128,16,38,15,92,0,0,16,39,15,92,0,0,1,128,16,7,21,10,0,0,1,32,255,255,0,170,0,0,6,130,5,72,16,39, + 15,93,0,0,4,128,16,39,21,10,0,0,1,32,16,39,15,92,0,0,1,128,16,6,15,93,0,0,255,255,0,170,0,0,6,130,5,72,16,39, + 15,93,0,0,4,128,16,39,15,92,0,0,1,128,16,39,21,10,0,0,1,32,16,7,21,10,0,0,254,32,0,0,255,255,0,170,0,0,6,130, + 5,72,16,39,15,93,0,0,4,128,16,39,21,10,0,0,1,32,16,38,15,92,0,0,16,7,15,93,0,0,1,128,255,255,0,170,0,0,6,130, + 5,72,16,39,15,93,0,0,4,128,16,39,15,93,0,0,1,128,16,38,15,93,0,0,16,7,21,10,0,0,1,32,255,255,0,170,0,0,6,130, + 5,72,16,39,15,93,0,0,4,128,16,39,15,93,0,0,1,128,16,39,21,10,0,0,254,32,16,7,21,10,0,0,1,32,0,0,255,255,0,170, + 0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,38,15,92,0,0,16,38,21,10,0,160,16,7,21,10,0,0,1,32,0,0,255,255,0,170, + 0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,38,15,93,0,0,16,38,21,10,0,160,16,7,21,10,0,0,1,32,0,0,255,255,0,170, + 0,0,6,130,5,72,16,39,15,93,0,0,4,128,16,39,21,10,0,0,254,32,16,38,21,10,0,160,16,7,21,10,0,0,1,32,255,255,0,170, + 0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,15,92,0,0,16,39,15,92,0,0,1,128,16,7,15,92,0,0,3,0,255,255,0,170, + 0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,15,92,0,0,1,128,16,39,15,92,0,0,3,0,16,6,15,93,0,0,255,255,0,170, + 0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0,254,32,16,39,15,92,0,0,1,128,16,7,15,92,0,0,3,0,0,0, + 255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,15,92,0,0,16,39,15,92,0,0,3,0,16,7,15,93,0,0,1,128, + 255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,15,93,0,0,1,128,16,39,15,92,0,0,3,0,16,6,15,93,0,0, + 255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,15,93,0,0,1,128,16,39,15,92,0,0,3,0,16,7,21,10,0,0, + 254,32,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,15,92,0,0,16,38,21,10,0,160,16,7,15,92,0,0, + 3,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,15,93,0,0,16,38,21,10,0,160,16,7,15,92,0,0, + 3,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0,254,32,16,39,15,92,0,0,3,0,16,6, + 21,10,0,160,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,15,93,0,0,3,0,16,39,15,92,0,0,1,128,16,6, + 15,92,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,15,93,0,0,3,0,16,39,15,92,0,0,1,128,16,6, + 15,93,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0,254,32,16,39,15,92,0,0,1,128,16,7, + 15,93,0,0,3,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,15,92,0,0,16,39,15,93,0,0,1,128, + 16,7,15,93,0,0,3,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,15,93,0,0,16,39,15,93,0,0,3,0, + 16,7,15,93,0,0,1,128,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0,254,32,16,39,15,93,0,0, + 1,128,16,7,15,93,0,0,3,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,21,10,0,160,16,39,15,93, + 0,0,3,0,16,6,15,92,0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,21,10,0,160,16,38,15,93, + 0,0,16,7,15,93,0,0,3,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,21,10,0,160,16,39,15,93, + 0,0,3,0,16,7,21,10,0,0,254,32,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0,1,32,16,39, + 15,92,0,0,1,128,16,6,15,92,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,38,15,93,0,0,16,39,15,92, + 0,0,1,128,16,7,21,10,0,0,1,32,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0,254,32,16,39, + 21,10,0,0,1,32,16,7,15,92,0,0,1,128,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,15,93,0,0, + 1,128,16,38,15,92,0,0,16,7,21,10,0,0,1,32,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0, + 1,32,16,38,15,93,0,0,16,7,15,93,0,0,1,128,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39,21,10,0,0, + 1,32,16,39,21,10,0,0,254,32,16,7,15,93,0,0,1,128,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39, + 21,10,0,0,1,32,16,38,21,10,0,160,16,6,15,92,0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39, + 21,10,0,0,1,32,16,38,21,10,0,160,16,6,15,93,0,0,0,0,255,255,0,170,0,0,6,130,5,72,16,39,21,10,0,0,2,160,16,39, + 21,10,0,0,1,32,16,38,21,10,0,160,16,7,21,10,0,0,254,32,0,3,0,16,0,0,5,220,5,213,0,3,0,11,0,14,0,0,1,35, + 1,51,9,1,33,3,33,3,35,1,23,1,33,3,93,205,1,238,205,254,87,2,58,254,92,152,253,128,153,119,2,57,24,254,227,2,56,5,113,250, + 243,5,113,250,43,1,161,254,95,5,213,199,252,247,0,0,0,6,0,201,0,0,5,78,5,213,0,12,0,20,0,28,0,32,0,37,0,42,0,0, + 19,33,50,22,21,20,7,22,17,20,4,35,33,1,17,51,50,55,17,38,35,3,17,51,54,51,17,38,35,33,17,51,17,1,54,53,52,47,1,54, + 53,52,39,201,2,102,231,250,192,254,254,240,251,253,134,1,144,234,59,51,51,59,234,214,36,32,32,36,253,254,202,2,35,208,208,62,208,208,5,213, + 192,177,229,93,97,254,225,200,218,2,233,253,123,7,2,119,7,2,136,253,220,3,2,31,2,250,243,5,13,251,17,68,220,229,68,150,54,205,196,54, + 0,4,0,232,0,0,6,51,5,213,0,8,0,16,0,20,0,25,0,0,19,33,32,0,17,16,0,41,1,1,19,51,50,55,17,38,35,33,17,51, + 3,1,54,17,16,39,232,2,3,1,178,1,150,254,104,254,80,253,253,1,146,1,99,245,160,160,246,254,112,202,1,2,198,223,223,5,213,254,151,254, + 128,254,126,254,150,5,113,250,243,65,4,139,65,250,243,5,13,251,107,149,1,123,1,113,156,0,0,0,0,2,0,201,0,0,5,83,5,213,0,3, + 0,15,0,0,1,17,51,17,37,33,21,33,17,33,21,33,17,33,21,33,1,45,202,254,210,4,120,253,26,2,199,253,57,2,248,251,118,5,113,250, + 243,5,13,100,100,253,228,100,253,115,100,0,0,2,0,201,0,0,4,236,5,213,0,9,0,13,0,0,19,33,21,33,17,33,21,33,17,33,1,35, + 17,51,201,4,35,253,111,2,81,253,175,254,110,1,46,202,202,5,213,100,253,228,100,253,15,5,113,250,243,0,0,0,0,2,0,115,255,227,5,139, + 5,240,0,29,0,38,0,0,1,38,36,35,34,7,17,22,51,50,55,54,55,17,33,53,33,17,6,4,35,32,0,17,16,0,33,50,4,23,1,17, + 6,7,6,17,16,23,22,5,100,127,254,252,133,187,135,135,187,145,127,101,86,254,82,2,18,117,254,230,160,254,162,254,117,1,139,1,94,146,1,7, + 111,252,82,28,26,169,169,26,4,228,97,71,64,251,59,64,38,31,53,1,231,100,253,127,83,85,1,153,1,109,1,110,1,153,72,70,251,99,4,73, + 22,26,175,254,186,254,187,175,26,0,0,0,0,2,0,102,0,0,2,190,5,213,0,3,0,15,0,0,1,17,51,17,37,33,21,35,17,51,21,33, + 53,51,17,35,1,46,202,254,110,2,88,100,100,253,168,100,100,5,113,250,243,5,13,100,100,250,243,100,100,5,13,0,0,2,255,150,254,102,2,89, + 5,213,0,8,0,20,0,0,1,17,20,7,54,55,54,53,17,37,33,17,16,6,35,33,53,51,50,54,53,1,45,86,144,63,79,254,212,1,144,205, + 227,254,237,63,134,110,5,113,250,177,242,100,10,74,94,234,5,9,100,250,147,254,242,244,100,150,194,0,0,2,0,201,0,0,6,48,5,213,0,10, + 0,14,0,0,19,33,17,1,51,9,1,35,1,17,33,19,17,51,17,201,1,144,3,3,159,252,163,3,146,153,252,194,254,112,100,202,5,213,253,137, + 2,119,253,64,252,235,2,207,253,49,5,113,250,243,5,13,0,2,0,201,0,0,5,50,5,213,0,5,0,9,0,0,19,33,17,33,21,33,19,17, + 51,17,201,1,146,2,215,251,151,100,202,5,213,250,143,100,5,111,250,243,5,13,0,0,0,3,0,196,0,0,7,111,5,213,0,12,0,16,0,20, + 0,0,33,17,1,35,1,3,33,17,33,9,1,33,17,1,17,51,17,33,17,51,17,5,221,254,95,71,254,98,1,254,110,1,216,1,125,1,127,1, + 215,254,210,202,250,29,202,5,113,251,174,4,82,250,143,5,213,252,8,3,248,250,43,5,113,250,243,5,13,250,243,5,13,0,0,0,0,5,0,114, + 255,227,5,218,5,240,0,15,0,23,0,31,0,39,0,40,0,0,1,32,23,22,17,16,7,6,33,32,39,38,17,16,55,54,19,22,32,55,17,38, + 32,7,3,17,6,7,6,16,23,22,1,17,54,55,54,16,39,38,1,3,38,1,58,188,190,189,189,254,198,254,197,188,189,189,188,71,108,1,16,108, + 108,254,240,108,105,36,32,155,155,32,2,222,35,31,155,155,31,251,204,5,240,210,213,254,160,254,161,212,211,211,210,1,97,1,98,211,210,250,142,50, + 50,4,215,50,50,251,106,4,84,29,37,182,253,156,181,37,4,53,251,175,29,36,182,2,99,182,36,253,244,0,0,0,0,2,0,136,255,220,4,159, + 5,246,0,17,0,45,0,0,1,6,16,22,31,1,30,1,16,7,54,16,38,47,1,46,1,52,37,21,38,32,6,20,22,31,1,30,1,16,4,32, + 37,53,22,32,54,52,38,47,1,46,1,16,36,32,1,80,100,136,172,111,169,168,38,129,156,170,110,176,158,3,15,206,254,197,162,109,148,110,202,201, + 254,224,254,19,254,251,223,1,103,169,122,138,111,202,183,1,22,1,198,5,45,91,254,202,154,41,26,39,185,254,255,78,88,1,100,187,39,27,39,157, + 227,180,112,117,137,233,105,36,27,50,235,254,88,238,102,124,149,146,253,134,32,26,47,207,1,140,244,0,0,2,255,250,0,0,5,176,5,213,0,3, + 0,11,0,0,1,17,51,17,37,33,21,33,17,33,17,33,2,114,200,252,192,5,182,253,238,254,112,253,236,5,113,250,243,5,13,100,100,250,143,5, + 113,0,0,0,0,3,0,177,255,227,5,243,5,213,0,6,0,13,0,29,0,0,1,17,16,7,36,25,1,33,17,16,5,38,19,17,37,33,17,20, + 22,32,54,53,17,33,17,16,0,32,0,17,4,198,88,1,33,251,134,1,33,89,1,254,211,1,145,128,1,32,128,1,145,254,172,253,102,254,172,5, + 113,252,153,254,230,130,98,1,97,3,64,252,192,254,158,96,124,1,31,3,103,100,252,53,240,211,211,240,3,203,252,92,254,220,254,214,1,42,1,36, + 0,2,0,16,0,0,5,183,5,213,0,3,0,10,0,0,19,1,51,1,37,33,9,1,51,1,33,154,1,238,200,254,18,254,174,1,144,1,217,1, + 218,100,253,199,254,204,5,113,250,243,5,13,100,251,23,4,233,250,43,0,0,3,0,68,0,0,8,174,5,213,0,3,0,7,0,20,0,0,9,1, + 51,1,33,1,51,1,37,33,9,1,33,9,1,51,1,33,9,1,33,4,196,1,68,200,254,188,251,53,1,68,200,254,188,254,187,1,144,1,58,1, + 57,1,144,1,58,1,57,100,254,137,254,124,254,197,254,194,254,128,5,113,250,243,5,13,250,243,5,13,100,251,18,4,238,251,18,4,238,250,43,5, + 16,250,240,0,0,2,0,108,0,0,6,6,5,213,0,3,0,15,0,0,9,1,51,1,37,33,9,1,51,9,1,33,9,1,35,1,1,40,3,92, + 198,252,164,254,126,1,184,1,118,1,132,98,254,76,2,58,254,72,254,138,254,124,100,1,182,5,113,250,243,5,13,100,253,206,2,50,253,132,252,167, + 2,50,253,206,2,123,0,0,0,2,255,252,0,0,5,172,5,213,0,8,0,14,0,0,9,1,51,1,17,33,17,1,33,9,1,35,1,17,51,3, + 110,1,218,100,253,240,254,112,253,240,1,148,1,170,254,50,200,1,204,202,3,19,2,194,252,242,253,57,2,199,3,14,252,242,2,170,253,86,253,157, + 0,4,0,123,255,227,4,147,4,123,0,7,0,34,0,44,0,51,0,0,1,52,38,39,22,21,17,51,19,17,33,53,14,1,35,34,38,53,52,54, + 59,1,53,52,38,35,34,6,7,53,62,1,51,32,4,1,53,35,34,7,17,62,1,55,54,5,17,14,1,21,20,22,4,47,150,61,75,136,100,254, + 176,63,188,86,172,203,253,251,208,117,151,96,182,84,119,223,56,1,30,1,26,254,176,208,54,47,94,98,59,58,254,103,67,136,122,2,127,211,134,24, + 93,136,253,89,2,27,253,129,170,102,97,193,162,189,192,72,127,139,46,46,116,39,39,252,254,139,85,4,253,237,4,78,72,71,220,1,253,18,103,139, + 119,116,0,0,0,4,0,148,255,227,5,19,6,20,0,15,0,26,0,30,0,45,0,0,19,33,17,62,1,51,50,0,16,2,35,34,38,39,21,33, + 1,52,39,38,39,17,54,55,54,55,54,1,17,51,17,1,38,35,34,7,6,7,6,21,20,23,22,51,50,55,148,1,78,58,177,124,203,0,255,255, + 203,124,177,58,254,178,4,18,94,44,60,60,44,57,22,15,252,82,134,1,249,25,26,165,75,77,22,14,95,93,165,26,25,6,20,253,162,100,97,254, + 188,253,240,254,188,97,100,168,2,116,159,130,61,32,252,122,32,61,79,115,75,3,218,250,172,5,84,254,100,3,105,104,116,74,158,159,130,130,3,0, + 0,2,0,113,255,227,3,231,4,123,0,26,0,35,0,0,37,21,14,1,35,34,0,17,16,0,33,50,22,23,21,38,39,38,35,34,7,17,22,51, + 50,55,54,37,17,6,7,6,21,20,23,22,3,231,77,165,93,253,254,214,1,45,1,6,85,162,76,69,109,71,74,88,72,67,81,82,72,86,254,24, + 44,36,123,122,36,143,100,36,36,1,62,1,14,1,18,1,58,35,35,100,31,24,15,20,252,87,19,16,19,27,3,83,26,37,128,234,230,131,38,0, + 0,4,0,148,255,227,5,19,6,20,0,15,0,26,0,30,0,45,0,0,1,17,33,17,33,53,14,1,35,34,2,16,0,51,50,22,1,20,23,22, + 23,22,23,17,6,7,6,1,17,51,17,1,17,22,51,50,55,54,53,52,39,38,39,38,35,34,3,197,1,78,254,178,58,177,124,203,255,0,255,203, + 124,177,253,118,15,22,57,44,60,60,44,94,3,40,134,253,129,25,26,165,93,95,14,22,77,75,165,26,3,182,2,94,249,236,168,100,97,1,68,2, + 16,1,68,97,254,90,158,75,115,79,61,32,3,134,32,61,130,2,157,250,172,5,84,254,100,252,54,3,130,130,159,158,74,116,104,105,0,3,0,111, + 255,227,4,125,4,123,0,19,0,24,0,31,0,0,1,33,19,22,51,50,55,21,14,1,35,32,0,17,16,0,51,50,0,21,1,6,17,18,23,19, + 33,46,1,35,34,7,4,125,253,139,1,75,95,217,195,109,195,107,254,244,254,199,1,41,252,229,1,4,253,35,198,1,197,105,2,1,3,204,169,74, + 64,2,4,254,98,21,93,117,45,41,1,56,1,10,1,19,1,67,254,218,247,1,113,122,254,219,254,243,142,1,211,190,231,17,0,0,0,2,0,47, + 0,0,3,227,6,20,0,10,0,32,0,0,1,6,7,6,21,17,51,17,52,55,54,37,21,35,34,7,6,29,1,33,21,33,17,33,17,35,53,51, + 53,52,55,54,51,2,17,103,46,57,135,22,18,1,241,174,148,58,57,1,132,254,124,254,177,176,176,87,88,188,5,174,10,45,56,145,251,182,4,74, + 95,68,56,139,100,57,55,146,100,100,252,26,3,230,100,100,188,84,86,0,0,4,0,113,254,86,4,240,4,123,0,7,0,35,0,46,0,61,0,0, + 1,17,20,7,22,54,25,1,1,53,30,1,51,50,54,61,1,14,1,35,34,2,16,0,51,50,22,23,53,33,17,16,0,33,34,38,3,20,23,22, + 23,17,6,7,6,7,6,1,22,51,50,55,54,55,54,53,52,39,38,35,34,7,4,6,106,5,235,252,108,81,158,82,181,180,58,177,124,203,255,0, + 255,203,124,177,58,1,78,254,214,254,205,114,202,121,94,44,60,60,44,57,22,15,1,47,25,26,165,75,77,22,14,95,93,165,26,25,3,250,252,61, + 202,140,5,157,1,18,3,111,250,151,128,44,42,189,191,113,100,97,1,68,2,16,1,68,97,100,168,252,45,254,226,254,233,29,3,119,159,130,61,32, + 3,134,32,61,79,115,75,253,194,3,105,104,116,74,158,159,130,130,3,0,0,3,0,186,0,0,5,72,6,20,0,10,0,14,0,34,0,0,1,22, + 23,22,21,17,51,17,52,39,38,1,17,51,17,39,33,17,62,1,51,50,22,21,17,33,17,52,38,35,34,6,21,17,33,4,0,9,8,71,140,83, + 53,252,194,135,235,1,79,73,198,129,212,219,254,172,107,107,128,149,254,177,4,13,11,12,104,190,253,148,2,64,193,91,58,1,182,250,180,5,76,100, + 253,158,101,100,239,232,253,92,2,208,159,158,190,164,253,85,0,3,0,230,0,0,2,53,6,20,0,3,0,7,0,11,0,0,1,17,51,17,3,51, + 21,35,7,33,17,33,1,74,135,160,185,185,75,1,79,254,177,3,252,252,104,3,152,2,24,233,203,251,160,0,0,0,0,3,255,215,254,86,2,12, + 6,20,0,8,0,22,0,26,0,0,5,17,35,17,20,7,54,55,54,7,35,53,51,50,55,54,53,17,33,17,20,7,6,3,51,21,35,1,168,135, + 37,71,40,61,244,221,49,108,36,37,1,79,81,82,97,184,184,22,4,18,251,208,181,84,15,48,72,244,100,48,49,153,4,172,251,140,214,96,96,7, + 190,233,0,0,0,2,0,186,0,0,5,50,6,20,0,10,0,14,0,0,19,33,17,1,51,9,1,35,1,17,33,19,17,51,17,186,1,79,2,132, + 140,253,72,2,209,150,253,109,254,177,100,135,6,20,252,105,1,227,253,246,253,170,2,35,253,221,5,176,250,180,5,76,0,2,0,230,0,0,2,234, + 6,20,0,8,0,20,0,0,1,20,23,22,23,38,53,17,35,19,34,39,38,53,17,33,17,20,22,51,21,1,74,61,40,71,37,135,245,182,82,81, + 1,79,76,105,1,148,160,72,48,15,84,181,4,48,250,90,96,96,214,4,126,251,74,156,94,100,0,0,0,4,0,186,0,0,8,135,4,123,0,34, + 0,38,0,49,0,60,0,0,19,33,21,62,1,51,50,22,23,62,1,51,50,22,21,17,33,17,52,38,35,34,6,21,17,33,17,52,38,35,34,6, + 21,17,33,19,17,51,17,37,22,23,22,21,17,51,17,52,39,38,37,22,23,22,21,17,51,17,52,39,38,186,1,79,73,198,129,212,157,27,84,222, + 129,212,219,254,172,107,107,128,149,254,172,107,107,128,149,254,177,100,135,2,91,9,8,71,140,83,53,2,227,9,8,71,140,83,53,4,96,174,101,100, + 172,74,128,118,239,232,253,92,2,208,159,158,190,171,253,92,2,208,159,158,190,164,253,85,3,252,252,104,3,152,17,11,12,104,190,253,148,2,64,193, + 91,58,19,11,12,104,190,253,148,2,64,193,91,58,0,0,0,3,0,186,0,0,5,72,4,123,0,10,0,14,0,34,0,0,1,22,23,22,21,17, + 51,17,52,39,38,37,17,51,17,39,33,21,62,1,51,50,22,21,17,33,17,52,38,35,34,6,21,17,33,4,0,9,8,71,140,83,53,252,194,135, + 235,1,79,73,198,129,212,219,254,172,107,107,128,149,254,177,4,13,11,12,104,190,253,148,2,64,193,91,58,2,252,104,3,152,100,174,101,100,239,232, + 253,92,2,208,159,158,190,164,253,85,0,0,0,4,0,113,255,227,4,117,4,123,0,11,0,19,0,27,0,35,0,0,1,50,0,17,16,0,35,34, + 0,17,16,0,19,22,50,55,17,38,34,7,3,17,6,7,6,16,23,22,1,17,54,55,54,16,39,38,2,115,240,1,18,254,238,240,241,254,239,1, + 17,130,51,120,51,51,120,51,100,52,39,112,112,39,1,218,51,40,112,112,40,4,123,254,200,254,236,254,237,254,199,1,57,1,19,1,20,1,56,251, + 215,11,11,3,186,11,11,252,107,3,112,29,45,128,254,36,128,45,3,82,252,146,28,45,129,1,219,128,45,0,0,0,0,4,0,113,254,86,4,240, + 4,123,0,15,0,26,0,30,0,45,0,0,37,17,33,17,33,21,62,1,51,50,0,16,2,35,34,38,1,52,39,38,39,38,39,17,54,55,54,1, + 17,35,17,1,17,38,35,34,7,6,21,20,23,22,23,22,51,50,1,191,254,178,1,78,58,177,124,203,0,255,255,203,124,177,2,138,15,22,57,44, + 60,60,44,94,252,216,134,2,127,25,26,165,93,95,14,22,77,75,165,26,168,253,174,6,8,168,100,97,254,188,253,240,254,188,97,1,166,158,75,115, + 79,61,32,252,122,32,61,130,253,111,5,72,250,184,1,144,3,202,3,130,130,159,158,74,116,104,105,0,0,4,0,113,254,86,4,240,4,123,0,15, + 0,26,0,30,0,45,0,0,37,14,1,35,34,2,16,0,51,50,22,23,53,33,17,33,1,20,23,22,23,17,6,7,6,7,6,1,51,17,35,1, + 22,51,50,55,54,55,54,53,52,39,38,35,34,7,3,162,58,177,124,203,255,0,255,203,124,177,58,1,78,254,178,253,60,94,44,60,60,44,57,22, + 15,3,40,134,134,254,7,25,26,165,75,77,22,14,95,93,165,26,25,168,100,97,1,68,2,16,1,68,97,100,168,249,248,3,148,159,130,61,32,3, + 134,32,61,79,115,75,252,50,5,72,252,72,3,105,104,116,74,158,159,130,130,3,0,0,0,2,0,186,0,0,3,223,4,123,0,3,0,21,0,0, + 1,17,51,17,39,33,21,62,1,51,50,31,1,21,46,1,35,34,6,21,17,33,1,30,134,234,1,78,58,186,133,27,15,52,31,73,44,156,167,254, + 178,3,252,252,104,3,152,100,174,102,99,3,7,133,18,17,203,190,253,122,0,2,0,111,255,227,3,199,4,123,0,29,0,69,0,0,1,6,7,6, + 21,20,23,22,31,1,22,23,22,21,20,7,54,55,54,53,52,39,38,47,1,38,39,38,53,52,3,30,1,51,50,54,53,52,38,47,1,46,1,53, + 52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,31,1,30,1,21,20,6,35,34,38,39,1,105,39,28,75,38,39,113,52,165,61,66,37,37, + 29,85,43,46,132,51,144,57,71,211,83,160,79,106,113,76,145,52,143,118,224,206,102,180,76,74,92,95,111,112,80,120,51,161,132,247,216,90,195,108, + 3,249,15,23,61,118,102,48,51,34,16,51,59,64,123,82,63,16,23,66,115,108,51,55,39,15,42,55,67,111,84,252,254,55,56,94,85,78,79,44, + 16,44,151,136,166,181,32,31,122,49,36,89,88,68,76,35,15,47,158,144,164,192,37,37,0,2,0,55,0,0,3,136,5,158,0,7,0,27,0,0, + 37,38,55,17,35,17,6,22,19,17,33,21,33,17,20,22,59,1,21,33,34,38,53,17,35,53,51,17,1,208,42,3,135,1,92,144,1,123,254,133, + 75,115,189,254,173,213,162,135,135,106,85,124,3,255,252,55,173,78,5,40,254,172,100,253,85,137,78,100,159,210,2,117,100,1,84,0,0,3,0,177, + 255,229,5,68,4,96,0,10,0,14,0,34,0,0,37,38,39,38,53,17,35,17,20,23,22,5,17,35,17,23,33,53,14,1,35,34,38,53,17,33, + 17,20,22,51,50,54,53,17,33,1,249,9,8,71,140,83,53,3,67,135,235,254,172,73,198,129,212,219,1,84,107,107,128,149,1,84,83,11,12,104, + 190,2,108,253,192,193,91,58,2,3,152,252,104,100,174,101,100,239,232,2,164,253,48,159,158,190,164,2,171,0,0,0,0,2,0,61,0,0,4,177, + 4,96,0,3,0,10,0,0,19,1,51,1,37,33,9,1,51,1,33,205,1,89,131,254,163,254,241,1,84,1,94,1,94,100,254,92,254,212,3,252, + 252,104,3,152,100,252,84,3,172,251,160,0,0,3,0,86,0,0,6,242,4,96,0,3,0,7,0,20,0,0,1,19,51,3,33,19,51,3,37,33, + 27,1,33,27,1,51,1,33,11,1,33,3,241,240,135,242,252,98,240,135,242,254,249,1,84,230,229,1,78,230,229,100,254,219,254,202,241,242,254,199, + 3,252,252,104,3,152,252,104,3,152,100,252,150,3,106,252,150,3,106,251,160,3,150,252,106,0,0,0,0,2,0,76,0,0,5,28,4,96,0,3, + 0,15,0,0,9,1,51,1,37,33,9,1,51,9,1,33,9,1,35,1,1,19,2,171,151,253,85,254,162,1,144,1,29,1,29,124,254,165,1,229, + 254,112,254,227,254,227,124,1,91,3,252,252,104,3,152,100,254,129,1,127,254,45,253,115,1,127,254,129,1,211,0,0,0,2,0,61,254,86,4,195, + 4,96,0,3,0,18,0,0,19,1,55,1,37,33,9,1,51,1,14,1,43,1,53,51,50,54,55,210,1,178,62,254,149,254,230,1,94,1,93,1, + 95,108,254,20,80,146,124,147,147,88,81,43,3,252,251,219,153,3,140,100,252,151,3,105,251,56,199,123,100,67,89,0,0,2,0,88,0,0,4,98, + 4,96,0,3,0,13,0,0,9,1,51,1,37,33,21,1,33,21,33,53,1,33,3,92,253,118,140,2,138,252,137,3,241,253,119,2,137,251,246,2, + 137,253,144,3,252,252,104,3,152,100,100,252,104,100,100,3,152,0,0,0,255,255,0,16,0,0,5,104,5,213,16,6,0,36,0,0,255,255,0,201, + 0,0,4,236,5,213,16,6,0,37,0,0,255,255,0,115,255,227,5,39,5,240,16,6,0,38,0,0,255,255,0,201,0,0,5,176,5,213,16,6, + 0,39,0,0,255,255,0,201,0,0,4,139,5,213,16,6,0,40,0,0,255,255,0,201,0,0,4,35,5,213,16,6,0,41,0,0,255,255,0,115, + 255,227,5,139,5,240,16,6,0,42,0,0,255,255,0,201,0,0,5,59,5,213,16,6,0,43,0,0,255,255,0,151,0,0,2,246,5,213,16,6, + 23,22,0,0,255,255,255,150,254,102,1,147,5,213,16,6,0,45,0,0,255,255,0,201,0,0,5,106,5,213,16,6,0,46,0,0,255,255,0,201, + 0,0,4,106,5,213,16,6,0,47,0,0,255,255,0,201,0,0,6,31,5,213,16,6,0,48,0,0,255,255,0,201,0,0,5,51,5,213,16,6, + 0,49,0,0,255,255,0,115,255,227,5,217,5,240,16,6,0,50,0,0,255,255,0,201,0,0,4,141,5,213,16,6,0,51,0,0,255,255,0,115, + 254,248,5,217,5,240,16,6,0,52,0,0,255,255,0,201,0,0,5,84,5,213,16,6,0,53,0,0,255,255,0,135,255,227,4,162,5,240,16,6, + 0,54,0,0,255,255,255,250,0,0,4,233,5,213,16,6,0,55,0,0,255,255,0,178,255,227,5,41,5,213,16,6,0,56,0,0,255,255,0,16, + 0,0,5,104,5,213,16,6,0,57,0,0,255,255,0,68,0,0,7,166,5,213,16,6,0,58,0,0,255,255,0,61,0,0,5,59,5,213,16,6, + 0,59,0,0,255,255,255,252,0,0,4,231,5,213,16,6,0,60,0,0,255,255,0,92,0,0,5,31,5,213,16,6,0,61,0,0,255,255,0,123, + 255,227,4,45,4,123,16,6,0,68,0,0,255,255,0,186,255,227,4,164,6,20,16,6,0,69,0,0,255,255,0,113,255,227,3,231,4,123,16,6, + 0,70,0,0,255,255,0,113,255,227,4,90,6,20,16,6,0,71,0,0,255,255,0,113,255,227,4,127,4,123,16,6,0,72,0,0,255,255,0,47, + 0,0,2,248,6,20,16,6,0,73,0,0,255,255,0,113,254,86,4,90,4,123,16,6,0,74,0,0,255,255,0,186,0,0,4,100,6,20,16,6, + 0,75,0,0,255,255,0,193,0,0,1,121,6,20,16,6,0,76,0,0,255,255,255,219,254,86,1,121,6,20,16,6,0,77,0,0,255,255,0,186, + 0,0,4,156,6,20,16,6,0,78,0,0,255,255,0,193,0,0,2,57,6,20,16,6,23,12,0,0,255,255,0,186,0,0,7,29,4,123,16,6, + 0,80,0,0,255,255,0,186,0,0,4,100,4,123,16,6,0,81,0,0,255,255,0,113,255,227,4,117,4,123,16,6,0,82,0,0,255,255,0,186, + 254,86,4,164,4,123,16,6,0,83,0,0,255,255,0,113,254,86,4,90,4,123,16,6,0,84,0,0,255,255,0,186,0,0,3,74,4,123,16,6, + 0,85,0,0,255,255,0,111,255,227,3,199,4,123,16,6,0,86,0,0,255,255,0,55,0,0,2,242,5,158,16,6,0,87,0,0,255,255,0,174, + 255,227,4,88,4,123,16,6,0,88,0,0,255,255,0,61,0,0,4,127,4,96,16,6,0,89,0,0,255,255,0,86,0,0,6,53,4,96,16,6, + 0,90,0,0,255,255,0,59,0,0,4,121,4,96,16,6,0,91,0,0,255,255,0,61,254,86,4,127,4,96,16,6,0,92,0,0,255,255,0,88, + 0,0,3,219,4,96,16,6,0,93,0,0,0,4,0,136,255,227,4,144,5,240,0,7,0,12,0,20,0,25,0,0,0,32,0,16,0,32,0,16, + 1,54,17,16,47,1,38,34,7,17,22,50,55,1,6,17,16,23,1,144,1,246,1,10,254,246,254,10,254,248,2,216,204,204,100,51,123,52,52,123, + 51,254,186,202,202,5,240,254,115,253,13,254,115,1,141,2,243,252,35,143,1,212,1,213,143,48,15,15,250,217,15,15,4,247,144,254,44,254,45,144, + 0,2,0,107,0,0,4,172,5,213,0,3,0,14,0,0,1,17,51,17,55,17,33,21,33,53,33,17,5,53,37,2,54,202,98,1,74,251,220,1, + 74,254,153,1,103,5,113,250,243,5,13,100,250,143,100,100,5,13,72,100,72,0,0,0,0,2,0,130,0,0,4,154,5,240,0,16,0,40,0,0, + 55,33,1,54,55,54,16,39,38,39,23,22,21,20,14,1,3,1,36,51,50,4,21,20,14,1,7,1,33,21,33,55,54,0,55,54,16,38,35,34, + 7,251,1,0,1,41,96,34,76,108,68,98,3,90,69,130,209,254,231,1,3,181,243,1,31,48,81,93,254,250,2,40,251,232,1,2,1,158,61,121, + 135,109,152,193,100,1,205,149,64,143,1,57,92,57,24,4,112,168,100,186,207,254,221,4,57,104,244,204,98,172,150,145,254,105,100,100,5,2,65,98, + 191,1,25,168,149,0,0,0,0,3,0,156,255,227,4,115,5,240,0,36,0,42,0,48,0,0,5,34,39,53,23,22,51,50,55,17,38,43,1,53, + 51,50,55,17,38,35,34,15,1,53,54,51,50,4,21,20,6,7,30,1,21,20,4,53,54,53,52,38,39,25,1,62,1,53,52,2,43,187,212,33, + 196,170,101,79,54,63,204,212,59,50,58,76,156,217,27,230,175,230,1,12,141,128,142,162,254,208,204,117,87,69,100,29,74,106,12,68,16,2,149,10, + 100,8,2,32,10,60,8,104,64,209,178,124,170,33,31,197,144,221,242,146,85,232,108,141,36,2,150,254,26,29,121,88,172,0,0,0,0,3,0,90, + 0,0,4,184,5,213,0,3,0,6,0,17,0,0,1,35,19,51,9,1,33,3,33,17,51,21,35,17,33,17,33,53,3,167,203,3,200,254,212,254, + 81,1,175,3,1,147,173,173,254,112,253,223,5,113,250,243,4,193,252,227,3,205,252,51,100,254,92,1,164,127,0,0,0,3,0,148,255,227,4,140, + 5,213,0,4,0,8,0,30,0,0,1,17,35,17,54,1,54,16,39,3,17,38,35,34,7,17,33,21,33,17,12,1,16,4,33,34,39,53,22,51, + 50,1,255,200,103,1,182,204,204,100,49,106,180,206,3,75,254,69,1,17,1,24,254,212,254,189,185,208,189,220,129,3,145,1,224,253,253,27,252,230, + 92,1,220,96,253,73,2,215,10,75,2,239,100,254,35,9,245,254,70,249,60,136,100,0,0,4,0,113,255,227,4,170,5,240,0,4,0,9,0,17, + 0,37,0,0,37,54,17,16,39,1,6,17,16,31,1,22,50,55,17,38,34,7,19,50,23,21,39,38,32,7,17,54,51,50,0,16,0,35,32,0, + 16,0,3,124,202,202,254,38,205,205,100,58,171,45,40,171,63,244,167,168,34,153,254,214,94,66,104,245,1,5,254,240,246,254,223,254,238,1,80,112, + 99,1,12,1,24,92,1,202,179,254,145,254,35,149,50,16,8,3,34,6,19,2,140,60,106,12,54,45,254,102,22,254,239,254,47,254,234,1,141,2, + 219,1,165,0,0,2,0,65,0,0,4,214,5,213,0,3,0,10,0,0,9,1,51,1,37,33,21,1,33,1,33,3,149,254,13,214,1,243,251,214, + 4,149,253,231,254,83,2,26,253,23,5,113,250,243,5,13,100,100,250,143,5,113,0,0,0,7,0,139,255,227,4,139,5,240,0,4,0,12,0,36, + 0,41,0,49,0,57,0,65,0,0,37,54,39,38,39,0,16,23,22,23,17,6,7,19,53,46,1,53,52,36,32,22,21,20,6,7,21,30,1,21, + 20,4,32,36,53,52,54,19,17,6,7,6,5,22,50,55,17,38,34,7,25,1,22,50,55,17,38,34,5,17,54,55,54,16,39,38,3,88,209,7, + 7,195,253,186,95,33,44,44,32,76,128,144,0,255,1,189,254,144,128,145,162,254,247,254,18,254,247,163,144,195,7,7,1,53,49,112,49,49,112,49, + 48,114,48,48,114,1,6,44,32,96,95,33,100,74,234,228,78,2,39,254,248,77,27,18,1,252,18,27,253,220,2,32,177,128,179,208,208,179,128,177, + 32,1,35,197,143,217,232,232,217,143,197,253,108,2,102,78,228,234,97,6,6,2,150,7,7,2,162,253,208,7,7,2,48,7,33,254,4,18,27,77, + 1,8,77,27,0,4,0,106,255,227,4,163,5,240,0,4,0,9,0,17,0,37,0,0,1,6,17,16,23,1,54,17,16,47,1,38,34,7,17,22, + 50,55,3,34,39,53,23,22,32,55,17,6,35,34,0,16,0,51,32,0,16,0,1,152,202,202,1,218,205,205,100,58,171,45,40,171,63,244,167,168, + 34,153,1,42,94,66,104,245,254,251,1,16,246,1,33,1,18,254,176,5,99,99,254,244,254,232,92,254,54,179,1,111,1,221,149,50,16,8,252,222, + 6,19,253,116,60,106,12,54,45,1,154,22,1,17,1,209,1,22,254,115,253,37,254,91,255,255,0,135,255,227,4,143,5,240,16,6,0,19,0,0, + 255,255,0,225,0,0,4,90,5,213,16,6,0,20,0,0,255,255,0,150,0,0,4,74,5,240,16,6,0,21,0,0,255,255,0,156,255,227,4,115, + 5,240,16,6,0,22,0,0,255,255,0,100,0,0,4,164,5,213,16,6,0,23,0,0,255,255,0,158,255,227,4,100,5,213,16,6,0,24,0,0, + 255,255,0,143,255,227,4,150,5,240,16,6,0,25,0,0,255,255,0,168,0,0,4,104,5,213,16,6,0,26,0,0,255,255,0,139,255,227,4,139, + 5,240,16,6,0,27,0,0,255,255,0,129,255,227,4,135,5,240,16,6,0,28,0,0,0,2,0,200,0,70,10,33,5,59,0,3,0,7,0,0, + 1,51,17,35,1,17,33,17,5,46,141,141,251,154,9,89,1,95,2,195,252,36,4,245,251,11,0,0,0,3,0,200,0,70,10,33,5,59,0,3, + 0,7,0,11,0,0,55,17,33,17,39,17,33,17,37,17,51,17,200,9,89,141,247,193,3,217,141,70,4,245,251,11,141,3,219,252,37,140,2,195, + 253,61,0,0,0,4,0,200,0,70,10,33,5,59,0,22,0,26,0,30,0,34,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,7,48,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16, + 249,152,9,89,141,247,193,3,217,141,2,195,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219, + 252,37,140,2,195,253,61,0,0,5,0,200,0,70,10,33,5,59,0,22,0,44,0,48,0,52,0,56,0,0,1,34,39,38,39,38,52,55,54,55, + 54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39, + 17,33,17,37,17,51,17,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,197,36,24,26,18,15,15,17,27,23,37, + 36,24,26,18,16,16,17,27,23,250,8,9,89,141,247,193,3,217,141,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16, + 2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,6,0,200, + 0,70,10,33,5,59,0,22,0,43,0,65,0,69,0,73,0,77,0,0,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7, + 6,7,6,1,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23, + 22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254, + 206,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,210,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23, + 250,8,9,89,141,247,193,3,217,141,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26, + 18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219, + 252,37,140,2,195,253,61,0,0,7,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,91,0,95,0,99,0,0,1,52,55,54,55,54, + 50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52, + 55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38, + 39,38,1,17,33,17,39,17,33,17,37,17,51,17,6,39,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27, + 23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27, + 23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,248,143,9,89,141,247,193,3,217,141,3,204,36,24,26,17,16,16,16,27,23,74,23,25, + 19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26, + 17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253, + 61,0,0,0,0,8,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,110,0,114,0,118,0,122,0,0,1,52,55,54,55,54,50,23, + 22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38, + 5,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,6,39,16,17,26, + 24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17, + 26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16, + 17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,3,204,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36, + 24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,9,0,200,0,70,10,33,5,59,0,20,0,42,0,64, + 0,85,0,105,0,127,0,131,0,135,0,139,0,0,1,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39, + 38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,0, + 34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,2,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22,20,7,6,7, + 0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,17,33,17,39,17,33,17,37,17,51,17,7,164,36,23,26,19, + 16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,205,74,24,25,18,16, + 16,17,26,23,38,36,23,26,17,16,1,17,17,26,2,85,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74,22,26,18,16, + 1,17,17,27,23,72,24,26,18,15,15,17,27,253,126,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,250,28,9,89,141,247, + 193,3,217,141,3,82,16,17,28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23, + 72,24,26,18,16,16,17,27,24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72, + 24,25,19,253,222,16,17,27,24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24, + 25,19,252,227,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0,4,0,200,0,70,10,33,5,59,0,21,0,25,0,29,0,33,0,0, + 1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,2,202,16,17,26,23, + 74,24,25,18,16,16,17,26,24,72,25,26,17,16,253,254,9,89,141,247,193,3,217,141,2,195,36,23,26,18,16,16,16,28,23,36,37,24,25,18, + 16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0,0,5,0,200,0,70,10,33,5,59,0,21,0,44,0,48, + 0,52,0,56,0,0,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22, + 21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,2,204,16,16,27,23,74,23,25,19,16,16,17,27,24,72,24, + 26,17,16,4,100,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,2,195,36,23,26,18, + 16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251, + 11,141,3,219,252,37,140,2,195,253,61,0,0,6,0,200,0,70,10,33,5,59,0,21,0,44,0,66,0,70,0,74,0,78,0,0,1,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7, + 6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,2,202,16,17,26, + 23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,5,231,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,197,36,24, + 26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,250,8,9,89,141,247,193,3,217,141,2,195,36,23,26,18,16,16,16,28,23,36,37, + 24,25,18,16,16,17,26,24,254,161,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16, + 16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0,0,7,0,200,0,70,10,33,5,59,0,21, + 0,44,0,65,0,87,0,91,0,95,0,99,0,0,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,34,39,38, + 39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6, + 1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,2,202,16,17,26,23, + 74,24,25,18,16,16,17,26,24,72,25,26,17,16,5,231,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,206,36,23,26, + 19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,210,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,250,8,9,89, + 141,247,193,3,217,141,2,195,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,161,16,16,27,24,72,24,25,19,16,16,17, + 27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16, + 17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,8,0,200,0,70,10,33,5,59,0,21,0,43,0,65, + 0,87,0,109,0,113,0,117,0,121,0,0,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54, + 50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52, + 55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38, + 39,38,1,17,33,17,39,17,33,17,37,17,51,17,2,202,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,3,93,16,17,26,24, + 72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26, + 24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,248,143,9,89, + 141,247,193,3,217,141,2,195,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195, + 253,61,0,0,0,9,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,109,0,132,0,136,0,140,0,144,0,0,1,52,55,54,55,54, + 50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52, + 55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39, + 38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,2,202,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,3, + 93,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18, + 253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18, + 16,254,247,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,2,195,36,23,26,18,16,16, + 16,28,23,36,37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16, + 16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16, + 16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3, + 219,252,37,140,2,195,253,61,0,10,0,200,0,70,10,33,5,59,0,21,0,42,0,64,0,86,0,107,0,127,0,149,0,153,0,157,0,161,0,0, + 1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7, + 6,7,6,3,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22, + 23,22,23,20,7,6,7,0,34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,2,34,39,38,39,46,1,55,54,55,54,50, + 23,22,23,22,20,7,6,7,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,17,33,17,39,17,33,17,37,17, + 51,17,2,202,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,4,218,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17, + 27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,205,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17, + 17,26,2,85,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17, + 27,253,126,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,250,28,9,89,141,247,193,3,217,141,2,195,36,23,26,18,16,16, + 16,28,23,36,37,24,25,18,16,16,17,26,24,180,16,17,28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36, + 23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24, + 26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26, + 17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0,5,0,200,0,70,10,33,5,59,0,21, + 0,43,0,47,0,51,0,55,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,1,34,39,38,39,38,53,52, + 55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,4,114,74,23,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,17,26,253,173,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,254,109,9,89,141,247,193,3,217,141,1,64,16,17, + 26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,252,244,4, + 245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0,0,6,0,200,0,70,10,33,5,59,0,22,0,26,0,30,0,34,0,56,0,78,0,0, + 1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,4,34,39,38,39, + 38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,7, + 48,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,254,183,74,23,25,19,16,16,17,27, + 23,37,36,24,26,17,16,16,17,26,253,173,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,2,195,36,23,26,18,16,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27, + 23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,0,0,7,0,200,0,70,10,33,5,59,0,22, + 0,44,0,48,0,52,0,56,0,78,0,100,0,0,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39, + 38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,4,34,39,38,39,38,52,55,54, + 55,54,51,50,23,22,23,22,21,20,7,6,7,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,8,177,36,23,26, + 18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,197,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,250,8,9, + 89,141,247,193,3,217,141,254,183,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,253,173,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16, + 17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37, + 24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,0,8,0,200,0,70,10,33,5,59,0,22,0,43,0,65, + 0,69,0,73,0,77,0,99,0,121,0,0,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39, + 38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17, + 33,17,39,17,33,17,37,17,51,17,4,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,1,34,39,38,39,38,53,52, + 55,54,55,54,50,23,22,23,22,20,7,6,7,6,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,206,36,23,26, + 19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,210,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,250,8,9,89, + 141,247,193,3,217,141,254,183,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,253,173,36,24,26,17,16,16,16,27,23,74,23,25, + 19,16,16,17,27,23,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17, + 27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2, + 195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24, + 26,18,16,0,0,9,0,200,0,70,10,33,5,59,0,20,0,41,0,62,0,83,0,87,0,91,0,95,0,116,0,137,0,0,1,52,55,54,55,54, + 50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,17, + 33,17,39,17,33,17,37,17,51,17,4,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,1,34,39,38,39,38,52,55,54, + 55,54,50,23,22,23,22,20,7,6,7,6,6,39,16,17,26,24,72,24,26,18,16,16,16,28,23,73,24,25,18,16,2,18,16,17,27,23,73,24, + 25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,73,24,25,18,2,2,16,17,27,23,73,24,25,18, + 16,16,17,26,24,72,24,26,18,16,248,143,9,89,141,247,193,3,217,141,254,183,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26, + 253,173,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,3,204,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23, + 253,233,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2, + 83,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24, + 72,24,26,18,16,16,17,27,23,73,24,25,18,2,2,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,0,0,0,0,10,0,200, + 0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,110,0,114,0,118,0,122,0,144,0,166,0,0,1,52,55,54,55,54,50,23,22,23,22,20, + 7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54, + 55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,4,34,39,38,39,38,52,55,54, + 55,54,51,50,23,22,23,22,21,20,7,6,7,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,6,39,16,17,26, + 24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17, + 26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16, + 17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,254,183,74,23,25,19,16,16,17,27,23,37, + 36,24,26,17,16,16,17,26,253,173,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,3,204,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36, + 24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24, + 25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,0,0,11,0,200,0,70,10,33,5,59,0,20,0,42,0,64, + 0,85,0,105,0,127,0,131,0,135,0,139,0,161,0,183,0,0,1,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3, + 34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23,20, + 7,6,7,0,34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,2,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22, + 20,7,6,7,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,17,33,17,39,17,33,17,37,17,51,17,4,34, + 39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6, + 7,6,7,164,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27, + 23,254,205,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,2,85,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15, + 17,27,23,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,253,126,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17, + 17,26,250,28,9,89,141,247,193,3,217,141,254,183,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,253,173,36,24,26,17,16,16, + 16,27,23,74,23,25,19,16,16,17,27,23,3,82,16,17,28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36, + 23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24, + 26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26, + 17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23, + 36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,0,0,0,6,0,200,0,70,10,33,5,59,0,21, + 0,43,0,65,0,69,0,73,0,77,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,37,34,39,38,39,38, + 52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,17, + 33,17,39,17,33,17,37,17,51,17,4,114,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,254,182,36,23,26,18,16,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,254,210,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,254,109,9,89,141,247,193,3,217, + 141,1,64,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16, + 1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,252,244,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0, + 0,7,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,88,0,92,0,96,0,100,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23, + 22,23,22,21,20,7,6,7,37,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,53,52,55,54, + 55,54,50,23,22,23,22,20,7,6,7,6,5,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39, + 17,33,17,37,17,51,17,4,114,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,254,182,36,23,26,18,16,16,16,28,23,36,37, + 24,25,18,16,16,17,26,24,254,210,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,4,213,16,17,26,23,38,36,24,26,17,16, + 16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,1,64,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249, + 16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,143, + 36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,8,0,200, + 0,70,10,33,5,59,0,21,0,43,0,65,0,88,0,110,0,114,0,118,0,122,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23, + 22,21,20,7,6,7,37,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,53,52,55,54,55,54, + 50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52, + 55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,4,114,74,23,25,19,16,16,17,27,23,37,36, + 24,26,17,16,16,17,26,254,182,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,210,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,6,86,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,197,36,24,26,18,15,15,17,27,23, + 37,36,24,26,18,16,16,17,27,23,250,8,9,89,141,247,193,3,217,141,1,64,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18, + 249,16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16, + 253,237,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19, + 16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0,0,9,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,88,0,109, + 0,131,0,135,0,139,0,143,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,37,34,39,38,39,38,52,55, + 54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,34,39,38, + 39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6, + 1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,4,114,74,23,25,19, + 16,16,17,27,23,37,36,24,26,17,16,16,17,26,254,182,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,210,36,24,26, + 17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,6,86,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,206,36,23, + 26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,210,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,250,8,9, + 89,141,247,193,3,217,141,1,64,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17,26,23,74,24,26,17,16,16,17,26, + 24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,237,16,16,27,24,72,24,25,19,16,16,17, + 27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16, + 17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,10,0,200,0,70,10,33,5,59,0,21,0,43,0,65, + 0,87,0,109,0,131,0,153,0,157,0,161,0,165,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,37,34, + 39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6, + 7,6,37,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22, + 20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,4,114,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16, + 17,26,254,182,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,210,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,3,204,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24, + 72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24, + 72,24,26,18,16,248,143,9,89,141,247,193,3,217,141,1,64,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17,26,23, + 74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,122,36,24,26,17, + 16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16, + 16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141, + 3,219,252,37,140,2,195,253,61,0,0,0,0,11,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,109,0,131,0,153,0,176,0,180, + 0,184,0,188,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,37,34,39,38,39,38,52,55,54,55,54,51, + 50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,37,52,55,54,55,54,50,23, + 22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38, + 5,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,4,114,74,23,25, + 19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,254,182,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,210,36,24, + 26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,3,204,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16, + 17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16, + 17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249, + 152,9,89,141,247,193,3,217,141,1,64,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17,26,23,74,24,26,17,16,16, + 17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,122,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36, + 24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,12,0,200,0,70,10,33,5,59,0,21,0,43,0,65, + 0,86,0,108,0,130,0,151,0,171,0,193,0,197,0,201,0,205,0,0,0,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7, + 6,7,37,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23, + 22,20,7,6,7,6,33,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53,52,55,54,55,54,50, + 23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,0,34,39,38,39,38,39,52,55, + 54,55,54,50,23,22,23,22,20,7,6,7,2,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22,20,7,6,7,0,34,39,38,39,38,53,52, + 55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,17,33,17,39,17,33,17,37,17,51,17,4,114,74,23,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,17,26,254,182,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,210,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,5,73,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26, + 18,16,16,17,27,23,254,205,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,2,85,74,22,26,18,16,1,17,17,27,23,72, + 24,26,18,15,15,17,27,23,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,253,126,74,24,25,18,16,16,17,26,23,38,36,23, + 26,17,16,1,17,17,26,250,28,9,89,141,247,193,3,217,141,1,64,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17, + 26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,28, + 23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24, + 71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24, + 71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141, + 3,219,252,37,140,2,195,253,61,0,0,0,0,7,0,200,0,70,10,33,5,59,0,20,0,41,0,62,0,83,0,87,0,91,0,95,0,0,1,52, + 55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39, + 36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38, + 39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,193,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,16,2,18,16,16,28,23, + 73,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,2,2,16,16,28,23,73,24, + 25,18,16,16,17,26,24,72,24,26,18,16,252,245,9,89,141,247,193,3,217,141,3,204,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17, + 27,23,253,233,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16, + 27,2,83,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,0,0,0, + 0,8,0,200,0,70,10,33,5,59,0,21,0,25,0,29,0,33,0,54,0,75,0,96,0,117,0,0,1,52,55,54,55,54,51,50,23,22,23,22, + 20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39, + 38,39,38,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7, + 6,34,39,38,39,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,7,48,16,17,26,23,38,36,24,26,17,16,16,17, + 26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,16,2,18,16, + 16,28,23,73,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,2,2,16,16,28, + 23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,2,195,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,253,168,4,245,251, + 11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,253,233,73,24,25,19,16,16,17, + 27,23,37,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27, + 23,73,24,25,19,16,16,17,27,23,0,0,0,9,0,200,0,70,10,33,5,59,0,22,0,44,0,48,0,52,0,56,0,78,0,100,0,122,0,144, + 0,0,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22, + 23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39, + 38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6, + 35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,8,177,36,23,26,18,16,16,16,28,23,36,37, + 24,25,18,16,16,17,26,24,253,197,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,250,8,9,89,141,247,193,3,217,141,252, + 6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18, + 253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18, + 16,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26, + 19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233, + 74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36, + 24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,0,0,0,10,0,200,0,70,10,33,5,59,0,22,0,43,0,65,0,69,0,73, + 0,77,0,99,0,121,0,143,0,165,0,0,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39, + 38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17, + 33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50, + 23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54, + 55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254, + 206,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,210,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23, + 250,8,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,16,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74, + 23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141, + 3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23, + 37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,0,11,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,91,0,95,0,99,0,121,0,143,0,165,0,187, + 0,0,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22, + 20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34, + 39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,6,39,16,17,26,24,72,24,26,18, + 16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26, + 18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,248,143,9,89,141,247,193,3, + 217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72, + 24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72, + 24,26,18,16,3,204,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17, + 16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253, + 233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83, + 36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,0,0,12,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,110, + 0,114,0,118,0,122,0,144,0,166,0,188,0,210,0,0,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52, + 55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39, + 38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39, + 38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6, + 35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,6,39,16,17,26,24,72,24,26,18,16,16,16, + 28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16, + 16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,38,36,24,26,17, + 16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18, + 16,2,18,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25, + 18,2,2,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,3,204,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17, + 27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16, + 27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26, + 24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74, + 23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24, + 26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,13,0,200,0,70,10,33,5,59,0,20,0,42,0,64,0,85,0,105,0,127,0,131, + 0,135,0,139,0,161,0,183,0,205,0,227,0,0,1,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39, + 38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,0, + 34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,2,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22,20,7,6,7, + 0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54, + 50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52, + 55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38, + 39,38,7,164,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27, + 23,254,205,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,2,85,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15, + 17,27,23,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,253,126,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17, + 17,26,250,28,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36, + 37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36, + 37,24,25,18,16,16,17,26,24,72,24,26,18,16,3,82,16,17,28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23, + 37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37, + 36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36, + 24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36, + 24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,0,8,0,200,0,70,10,33,5,59,0,3, + 0,7,0,11,0,33,0,55,0,77,0,99,0,121,0,0,55,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20, + 7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,200,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17, + 27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16, + 17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,74,24,25,18,16, + 16,17,26,24,72,25,26,17,16,70,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16, + 16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16, + 16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16, + 17,26,24,0,0,9,0,200,0,70,10,33,5,59,0,22,0,26,0,30,0,34,0,56,0,78,0,100,0,122,0,144,0,0,1,52,55,54,55,54, + 51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22, + 20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50, + 23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55, + 54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,7,48,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16, + 249,152,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,2,195,36,23,26,18,16,16, + 16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23, + 74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37, + 36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37, + 24,25,18,16,16,17,26,24,0,10,0,200,0,70,10,33,5,59,0,22,0,44,0,48,0,52,0,56,0,78,0,100,0,122,0,144,0,166,0,0, + 1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22, + 20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0, + 52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34, + 39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54,55,54,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,197,36,24,26,18,15,15,17,27,23,37, + 36,24,26,18,16,16,17,27,23,250,8,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16, + 2,18,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18, + 2,2,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17, + 16,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26, + 19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233, + 74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36, + 24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,0,0,0, + 0,11,0,200,0,70,10,33,5,59,0,22,0,43,0,65,0,69,0,73,0,77,0,99,0,121,0,143,0,165,0,187,0,0,1,34,39,38,39,38, + 52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,34, + 39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23, + 22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38, + 5,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16, + 17,26,24,254,206,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,210,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16, + 16,17,27,23,250,8,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,1,63,16,16, + 27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16, + 17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16, + 16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16, + 28,23,36,37,24,25,18,16,16,17,26,24,0,12,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,91,0,95,0,99,0,121,0,143, + 0,165,0,187,0,209,0,0,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22, + 23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54, + 51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20, + 7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,6,39,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2, + 18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2, + 2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,248,143,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18, + 16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26, + 18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,74,24, + 25,18,16,16,17,26,24,72,25,26,17,16,3,204,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16, + 17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16, + 27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25, + 18,16,16,17,26,24,0,0,0,13,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,110,0,114,0,118,0,122,0,144,0,166,0,188, + 0,210,0,232,0,0,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22, + 21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50, + 23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,17,33, + 17,39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23, + 22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55, + 54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,6, + 39,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18, + 253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18, + 16,254,247,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24, + 26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72, + 24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23, + 74,24,25,18,16,16,17,26,24,72,25,26,17,16,3,204,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19, + 16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16, + 16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141, + 3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23, + 37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,0,14,0,200,0,70,10,33,5,59,0,20, + 0,42,0,64,0,85,0,105,0,127,0,131,0,135,0,139,0,161,0,183,0,205,0,227,0,249,0,0,1,34,39,38,39,38,52,55,54,55,54,50, + 23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52,55,54, + 55,54,51,50,23,22,23,22,23,20,7,6,7,0,34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,2,34,39,38,39,46, + 1,55,54,55,54,50,23,22,23,22,20,7,6,7,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,17,33,17, + 39,17,33,17,37,17,51,17,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22, + 23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54, + 51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,7,164, + 36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,205,74, + 24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,2,85,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74, + 22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,253,126,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,250,28, + 9,89,141,247,193,3,217,141,252,6,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,16,28,23,36,37,24,25,18, + 16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,16,28,23,36,37,24,25,18, + 16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,3,82,16,17,28,23,72,24,26,18, + 15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16, + 16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16, + 16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140, + 2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17, + 16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,0,0,9,0,200,0,70,10,33,5,59,0,3,0,7,0,11, + 0,34,0,58,0,80,0,102,0,124,0,146,0,0,55,17,33,17,39,17,33,17,37,17,51,17,1,34,39,38,39,38,53,52,55,54,55,54,51,50, + 23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,32,34,39,38,39,38,52, + 55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,1,34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39, + 38,39,46,1,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6, + 7,200,9,89,141,247,193,3,217,141,253,132,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,254,205,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,2,48,36,23,26,18,16,1, + 17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,253,149,74,23,26,18,16, + 16,17,27,23,37,36,23,26,17,16,1,17,16,27,70,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17, + 16,16,17,26,23,74,23,25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18, + 16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26, + 18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,0,10,0,200,0,70,10,33, + 5,59,0,22,0,26,0,30,0,34,0,57,0,81,0,103,0,125,0,147,0,169,0,0,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,20,7,6, + 7,6,3,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23, + 22,23,22,23,20,7,6,7,1,34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,46,1,55,54,55, + 54,50,23,22,23,22,21,20,7,6,7,6,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,7,48,16,17,26,23, + 38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,253,132,36,23,26,18,16,16,16,28,23,36,37,24,25, + 18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,205,74,23,26,18,16,16,17,27,23,37,36,23, + 26,17,16,1,17,16,27,2,48,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72, + 24,26,18,16,16,17,27,23,253,149,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,2,195,36,23,26,18,16,16,16,28,23, + 36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17, + 26,23,74,23,25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17, + 27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16, + 17,27,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,0,0,0,0,11,0,200,0,70,10,33, + 5,59,0,22,0,44,0,48,0,52,0,56,0,79,0,103,0,125,0,147,0,169,0,191,0,0,1,34,39,38,39,38,52,55,54,55,54,51,50,23, + 22,23,22,21,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17,33,17,39,17,33,17,37, + 17,51,17,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53,52,55,54,55,54,51,50, + 23,22,23,22,21,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,1,34,39,38,39,38,39,52, + 55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,0,34,39,38, + 39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253, + 197,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,250,8,9,89,141,247,193,3,217,141,253,132,36,23,26,18,16,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,205,74,23,26,18,16,16,17, + 27,23,37,36,23,26,17,16,1,17,16,27,2,48,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1, + 17,17,27,23,72,24,26,18,16,16,17,27,23,253,149,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,1,63,16,16,27,24, + 72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251, + 11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,74,23,25,19,16,253,239,16,17,26,23,38,36, + 23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37, + 24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,17,27,23, + 36,37,24,25,18,16,16,17,26,24,72,24,26,18,0,0,0,12,0,200,0,70,10,33,5,59,0,22,0,43,0,65,0,69,0,73,0,77,0,100, + 0,124,0,146,0,168,0,190,0,212,0,0,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,1,34,39,38,39, + 38,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,1,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,1,17, + 33,17,39,17,33,17,37,17,51,17,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53, + 52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,1, + 34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,8,177,36,23,26,18,16,16,16,28,23,36,37,24,25, + 18,16,16,17,26,24,254,206,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,210,36,24,26,18,15,15,17,27,23,37,36,24, + 26,18,16,16,17,27,23,250,8,9,89,141,247,193,3,217,141,253,132,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,37,36, + 23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,205,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,2, + 48,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23, + 253,149,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,1,63,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26, + 17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26, + 19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,74,23,25,19,16,253, + 239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2, + 2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18, + 16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,0,0,0,0,13,0,200,0,70,10,33,5,59,0,21,0,43,0,65, + 0,87,0,91,0,95,0,99,0,122,0,146,0,168,0,190,0,212,0,234,0,0,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34, + 39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,17,33,17,39,17,33,17,37,17, + 51,17,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53,52,55,54,55,54,51,50,23, + 22,23,22,21,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,1,34,39,38,39,38,39,52,55, + 54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,0,34,39,38,39, + 38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,6,39,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,2,18, + 16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,2,2, + 16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,248,143,9,89,141,247,193,3,217,141,253,132,36,23,26,18,16,16,16,28,23, + 36,37,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,205,74,23,26,18,16,16,17,27, + 23,37,36,23,26,17,16,1,17,16,27,2,48,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17, + 17,27,23,72,24,26,18,16,16,17,27,23,253,149,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,3,204,36,24,26,17,16, + 16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3, + 219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,74,23,25,19,16,253,239,16,17,26,23,38,36,23,26,18, + 16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18, + 16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,0,0,14,0,200,0,70,10,33,5,59,0,21,0,43,0,65,0,87,0,110,0,114,0,118,0,122,0,145, + 0,169,0,191,0,213,0,235,1,1,0,0,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54, + 51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,36,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52, + 55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,5,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39, + 38,39,38,1,17,33,17,39,17,33,17,37,17,51,17,1,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,3,34, + 39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,22,23, + 20,7,6,7,1,34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,46,1,55,54,55,54,50,23,22, + 23,22,21,20,7,6,7,6,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,6,39,16,17,26,24,72,24,26,18, + 16,16,16,28,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,253,222,16,17,26,24,72,24,26, + 18,16,16,16,28,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,254,247,16,17,26,23,38,36, + 24,26,17,16,16,17,26,24,73,24,25,18,16,249,152,9,89,141,247,193,3,217,141,253,132,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16, + 16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,205,74,23,26,18,16,16,17,27,23,37,36,23,26,17, + 16,1,17,16,27,2,48,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72,24,26, + 18,16,16,17,27,23,253,149,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,3,204,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25, + 18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,74,23, + 25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37, + 24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,36, + 37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,0,0,0,0,15,0,200,0,70,10,33,5,59,0,20, + 0,42,0,64,0,85,0,105,0,127,0,131,0,135,0,139,0,161,0,183,0,204,0,225,0,246,1,11,0,0,1,34,39,38,39,38,52,55,54,55, + 54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52, + 55,54,55,54,51,50,23,22,23,22,23,20,7,6,7,0,34,39,38,39,38,39,52,55,54,55,54,50,23,22,23,22,20,7,6,7,2,34,39,38, + 39,46,1,55,54,55,54,50,23,22,23,22,20,7,6,7,0,34,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,17, + 33,17,39,17,33,17,37,17,51,17,1,34,39,38,39,38,53,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,38,53,52, + 55,54,55,54,50,23,22,23,22,20,7,6,7,6,32,34,39,38,39,38,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,1,34,39,38,39, + 46,1,55,54,55,54,50,23,22,23,22,20,7,6,7,6,3,34,39,38,39,46,1,55,54,55,54,50,23,22,23,22,20,7,6,7,6,0,34,39, + 38,39,38,52,55,54,55,54,51,50,23,22,23,30,1,7,6,7,7,164,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36, + 23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,254,204,73,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,2,85, + 73,23,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,73,23,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,253,125,73, + 24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,250,28,9,89,141,247,193,3,217,141,253,132,36,23,26,18,16,16,16,28,23,73, + 24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,254,204,73,23,26,18,16,16,17,27,23,37,36, + 23,26,17,16,1,17,16,27,2,48,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23, + 72,24,26,18,16,16,17,27,23,253,148,73,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,3,82,16,17,28,23,72,24,26,18, + 15,15,17,27,23,73,23,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16, + 16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16, + 16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140, + 2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,73,24,25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27, + 23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,2,2,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24, + 26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,16,2,18,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24, + 26,18,0,0,0,2,0,200,254,20,5,189,7,109,0,3,0,7,0,0,1,21,33,53,1,33,17,33,1,225,2,195,252,36,4,245,251,11,3,7, + 141,141,4,102,246,167,0,0,0,3,0,200,254,20,5,189,7,109,0,3,0,7,0,11,0,0,19,33,17,33,55,33,17,33,19,33,21,33,200,4, + 245,251,11,141,3,219,252,37,140,2,195,253,61,7,109,246,167,141,8,63,252,39,141,0,0,4,0,200,254,20,5,189,7,109,0,22,0,26,0,30, + 0,34,0,0,1,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,3, + 69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,5,16,17, + 26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,0,0,5,0,200,254,20,5,189,7,109,0,21, + 0,43,0,47,0,51,0,55,0,0,5,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,1,193,16,16,27,24,72,24,25,19,16,16,17,27, + 23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2, + 195,253,61,124,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,2,59,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16, + 17,27,23,5,248,246,167,141,8,63,252,39,141,0,0,0,0,6,0,200,254,20,5,189,7,109,0,22,0,43,0,65,0,69,0,73,0,77,0,0, + 5,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34, + 39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,1,193, + 16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1, + 8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,124,36,23,26,18, + 16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,50,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,46,36,24,26, + 18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167,141,8,63,252,39,141,0,0,0,7,0,200,254,20,5,189,7,109,0,21, + 0,43,0,65,0,87,0,91,0,95,0,99,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22, + 23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55, + 1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,4,78,36,24,26,17, + 16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16, + 16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141, + 3,219,252,37,140,2,195,253,61,2,14,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24,25, + 18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24,25, + 18,16,16,17,26,24,72,24,26,18,16,7,113,246,167,141,8,63,252,39,141,0,0,0,0,8,0,200,254,20,5,189,7,109,0,21,0,43,0,65, + 0,87,0,110,0,114,0,118,0,122,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22, + 21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50, + 23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55, + 54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,4,78,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25, + 19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17, + 16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11, + 141,3,219,252,37,140,2,195,253,61,2,14,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,16,1,9,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63, + 252,39,141,0,0,9,0,200,254,20,5,189,7,109,0,20,0,42,0,64,0,85,0,105,0,127,0,131,0,135,0,139,0,0,37,52,55,54,55,54, + 50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,16,52,55, + 54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,0,52,55,54,55,54,55,50,23,22,23,22,20,7,6,7,6,34,39,38,39, + 36,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,34,39,38,39,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39, + 38,39,1,33,17,33,55,33,17,33,19,33,21,33,3,212,16,17,28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23, + 37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37, + 36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36, + 24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140,2,195,253,61,145,36,23,26,19,16,16,17,28,23,72,24, + 26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,51,74,24,25,18,16,16,17,26,23,38,36,23, + 26,17,16,1,17,17,26,253,171,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74,22,26,18,16,1,17,17,27,23,72,24, + 26,18,15,15,17,27,2,130,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,5,228,246,167,141,8,63,252,39,141,0,0,0, + 0,4,0,200,254,20,5,189,7,109,0,21,0,25,0,29,0,33,0,0,1,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54, + 55,54,1,33,17,33,55,33,17,33,19,33,21,33,3,69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251, + 11,141,3,219,252,37,140,2,195,253,61,5,107,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,2,2,246,167,141,8,63,252,39, + 141,0,0,0,0,5,0,200,254,20,5,189,7,109,0,21,0,44,0,48,0,52,0,56,0,0,1,50,23,22,23,22,20,7,6,7,6,35,34,39, + 38,39,38,52,55,54,55,54,19,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19, + 33,21,33,3,69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16, + 16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,5,105,16,16,27,23,74,23,25,19,16,16,17,27,24,72,24,26,17,16, + 251,156,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,0,0,6,0,200,254,20,5,189, + 7,109,0,21,0,44,0,66,0,70,0,74,0,78,0,0,1,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,52, + 55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39, + 38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,3,69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,161,16,16, + 27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4, + 245,251,11,141,3,219,252,37,140,2,195,253,61,5,107,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,250,25,36,23,26,18,16, + 16,16,28,23,36,37,24,25,18,16,16,17,26,24,2,59,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167,141, + 8,63,252,39,141,0,0,0,0,7,0,200,254,20,5,189,7,109,0,21,0,44,0,65,0,87,0,91,0,95,0,99,0,0,1,50,23,22,23,22, + 20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1, + 52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38, + 39,38,1,33,17,33,55,33,17,33,19,33,21,33,3,69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,254,161,16,16,27, + 24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17, + 28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,5,107,16,17,26,23,74,24, + 25,18,16,16,17,26,24,72,25,26,17,16,250,25,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,50,36,23,26,19,16, + 16,17,28,23,72,24,26,18,16,16,17,27,23,1,46,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167,141,8, + 63,252,39,141,0,8,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,87,0,109,0,113,0,117,0,121,0,0,1,50,23,22,23,22,20,7, + 6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22, + 23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55, + 1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,3,69,36,23,26,18, + 16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25, + 19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17, + 16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,5,107,16,17,26,23,74,24,25,18, + 16,16,17,26,24,72,25,26,17,16,252,163,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24, + 25,18,16,16,17,26,24,72,24,26,18,16,7,113,246,167,141,8,63,252,39,141,0,0,0,9,0,200,254,20,5,189,7,109,0,21,0,43,0,65, + 0,87,0,109,0,132,0,136,0,140,0,144,0,0,1,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,50,23,22, + 23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55, + 18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52, + 55,54,55,54,3,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,3, + 69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23, + 253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2, + 83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253, + 168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,5,107,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,252,163,16,17,26, + 24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17, + 26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16, + 17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,0,10,0,200,254,20,5,189,7,109,0,21, + 0,42,0,64,0,86,0,107,0,127,0,149,0,153,0,157,0,161,0,0,1,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54, + 55,54,19,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6, + 34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,0,52,55,54,55,54,55,50,23,22,23,22,20, + 7,6,7,6,34,39,38,39,36,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,34,39,38,39,0,52,55,54,55,54,51,50,23,22,23,22, + 21,20,7,6,7,14,1,39,38,39,1,33,17,33,55,33,17,33,19,33,21,33,3,69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16, + 17,26,24,180,16,17,28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24, + 26,18,16,16,17,27,24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25, + 19,253,222,16,17,27,24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19, + 252,227,4,245,251,11,141,3,219,252,37,140,2,195,253,61,5,107,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,251,38,36,23, + 26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,51,74,24,25, + 18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,253,171,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74,22,26, + 18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,2,130,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,5,228,246,167, + 141,8,63,252,39,141,0,0,0,5,0,200,254,20,5,189,7,109,0,21,0,43,0,47,0,51,0,55,0,0,0,52,55,54,55,54,50,23,22,23, + 22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33, + 17,33,19,33,21,33,1,194,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17, + 26,24,72,24,26,18,16,252,244,4,245,251,11,141,3,219,252,37,140,2,195,253,61,3,195,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16, + 16,17,26,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,1,147,246,167,141,8,63,252,39,141,0,0,0,0,6,0,200, + 254,20,5,189,7,109,0,22,0,26,0,30,0,34,0,56,0,78,0,0,1,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55, + 54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,2,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55, + 54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,3,69,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24, + 253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27, + 23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,5,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246, + 167,141,8,63,252,39,141,1,73,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,2,83,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,0,0,7,0,200,254,20,5,189,7,109,0,22,0,44,0,48,0,52,0,56,0,78,0,100,0,0,5,52,55,54,55,54, + 50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1, + 33,17,33,55,33,17,33,19,33,21,33,2,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51, + 50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,193,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17, + 28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26, + 18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,124,36,23,26,18,16,16,16, + 28,23,36,37,24,25,18,16,16,17,26,24,2,59,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167,141,8,63, + 252,39,141,1,73,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,0,0,8,0,200,254,20,5,189,7,109,0,22,0,43,0,65,0,69,0,73,0,77,0,99,0,121,0,0,5,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,52,55,54, + 55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,2,52,55,54,55,54,50,23,22,23, + 22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,193,16,16,27,24, + 72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28, + 23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18, + 16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,124,36,23,26,18,16,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,1,50,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,46,36,24,26,18,15,15,17, + 27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167,141,8,63,252,39,141,1,73,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16, + 17,26,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,0,0,9,0,200,254,20,5,189,7,109,0,21,0,43,0,65, + 0,87,0,91,0,95,0,99,0,121,0,143,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22, + 23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55, + 1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,2,52,55,54,55,54, + 50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,4,78, + 36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4, + 245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37, + 24,25,18,16,16,17,26,24,72,24,26,18,16,2,14,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23, + 36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23, + 36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,7,113,246,167,141,8,63,252,39,141,1,73,74,23,25,19,16,16,17,27,23,37,36,24,26, + 17,16,16,17,26,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,0,0,0,10,0,200,254,20,5,189,7,109,0,21, + 0,43,0,65,0,87,0,110,0,114,0,118,0,122,0,144,0,166,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54, + 55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39, + 38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,21,20,7,6,7,6, + 35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,2,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6, + 35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,4,78,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25, + 18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25, + 18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,2,14,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24, + 25,18,16,253,238,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37, + 24,25,18,253,254,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16,17,26,23,38,36,24,26,17,16,16,17,26,24, + 73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,1,73,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,2,83,36,24,26, + 17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,0,11,0,200,254,20,5,189,7,109,0,20,0,42,0,64,0,85,0,105,0,127,0,131, + 0,135,0,139,0,161,0,183,0,0,37,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23, + 22,23,22,20,7,6,7,6,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,0,52,55,54,55, + 54,55,50,23,22,23,22,20,7,6,7,6,34,39,38,39,36,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,34,39,38,39,0,52,55,54, + 55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,1,33,17,33,55,33,17,33,19,33,21,33,2,52,55,54,55,54,50,23,22,23, + 22,21,20,7,6,7,6,35,34,39,38,39,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,3,212,16,17,28,23, + 72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71, + 24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71, + 24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3, + 219,252,37,140,2,195,253,61,31,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16, + 17,26,24,72,24,26,18,16,145,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26, + 18,16,16,17,27,23,1,51,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,253,171,74,22,26,18,16,1,17,17,27,23,72, + 24,26,18,15,15,17,27,23,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,2,130,74,24,25,18,16,16,17,26,23,38,36,23, + 26,17,16,1,17,17,26,5,228,246,167,141,8,63,252,39,141,1,73,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,2,83,36, + 24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,0,0,0,0,6,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,69,0,73, + 0,77,0,0,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,19,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33, + 21,33,1,194,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18, + 16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,252,244,4,245,251,11,141,3,219,252,37,140,2,195,253,61,3,195, + 74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,1,74,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1, + 46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,1,147,246,167,141,8,63,252,39,141,0,0,0,0,7,0,200,254,20,5,189, + 7,109,0,21,0,43,0,65,0,88,0,92,0,96,0,100,0,0,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39, + 19,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34, + 39,38,39,38,3,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,1, + 194,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9, + 16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,143,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253, + 168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,3,195,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,1,74,36,23,26, + 18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,251,43,16,17, + 26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,0,0,8,0,200,254,20,5,189,7,109,0,21, + 0,43,0,65,0,88,0,110,0,114,0,118,0,122,0,0,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,19,52, + 55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38, + 39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,1,194,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249, + 16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253, + 237,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16, + 252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,3,195,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,1,74,36,23, + 26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,249,170,36, + 23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,2,59,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5, + 248,246,167,141,8,63,252,39,141,0,0,0,0,9,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,88,0,109,0,131,0,135,0,139,0,143, + 0,0,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,19,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7, + 6,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21, + 20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,50,23, + 22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,1,194,16,17,26,24,72,24,26,18,16,16,17,27, + 23,36,37,24,25,18,249,16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26, + 24,72,24,26,18,16,253,237,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17, + 27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2, + 195,253,61,3,195,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,1,74,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16, + 16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,249,170,36,23,26,18,16,16,16,28,23,36,37,24,25,18, + 16,16,17,26,24,1,50,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,46,36,24,26,18,15,15,17,27,23,37,36,24,26, + 18,16,16,17,27,23,5,248,246,167,141,8,63,252,39,141,0,10,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,87,0,109,0,131,0,153, + 0,157,0,161,0,165,0,0,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,19,52,55,54,55,54,50,23,22,23, + 22,21,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,19,50,23,22,23,22, + 20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50, + 23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54, + 55,54,1,33,17,33,55,33,17,33,19,33,21,33,1,194,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16,17,26,23,74, + 24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,122,36,24,26,17,16, + 16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3, + 219,252,37,140,2,195,253,61,3,195,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,1,74,36,23,26,18,16,16,16,28,23,36, + 37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,52,16,17,26,24,72,24,26,18,16, + 16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18, + 16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,7,113,246,167,141,8,63,252,39, + 141,0,0,0,0,11,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,87,0,109,0,131,0,153,0,176,0,180,0,184,0,188,0,0,0,52, + 55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,19,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38, + 39,38,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,19,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38, + 53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35, + 34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,21,20, + 7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,1,194,16,17,26,24,72,24,26,18,16,16,17, + 27,23,36,37,24,25,18,249,16,17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17, + 26,24,72,24,26,18,16,122,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19, + 16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253, + 61,3,195,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,1,74,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17, + 26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,52,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24, + 25,18,16,253,238,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37, + 24,25,18,253,254,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16,17,26,23,38,36,24,26,17,16,16,17,26,24, + 73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,0,0,12,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,86,0,108,0,130,0,151, + 0,171,0,193,0,197,0,201,0,205,0,0,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,19,52,55,54,55,54, + 50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,17,52, + 55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39, + 38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,0,52,55,54,55,54,55,50,23,22,23,22,20,7,6,7,6, + 34,39,38,39,36,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,34,39,38,39,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6, + 7,14,1,39,38,39,1,33,17,33,55,33,17,33,19,33,21,33,1,194,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,249,16, + 17,26,23,74,24,26,17,16,16,17,26,24,73,24,25,18,16,1,9,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17, + 28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27, + 24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27, + 24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11, + 141,3,219,252,37,140,2,195,253,61,3,195,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,17,26,1,74,36,23,26,18,16,16,16,28, + 23,36,37,24,25,18,16,16,17,26,24,1,46,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,250,183,36,23,26,19,16,16,17, + 28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,51,74,24,25,18,16,16,17,26, + 23,38,36,23,26,17,16,1,17,17,26,253,171,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74,22,26,18,16,1,17,17, + 27,23,72,24,26,18,15,15,17,27,2,130,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,5,228,246,167,141,8,63,252,39, + 141,0,0,0,0,7,0,200,254,20,5,189,7,109,0,20,0,41,0,62,0,83,0,87,0,91,0,95,0,0,1,50,23,22,23,22,20,7,6,7, + 6,34,39,38,39,38,52,55,54,55,54,0,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7, + 6,7,6,35,34,39,38,39,38,52,55,54,55,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33, + 17,33,19,33,21,33,4,78,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,253,233,73,24,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,73,24,25,19, + 16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,6,116,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18, + 16,253,238,16,16,28,23,73,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,253, + 254,16,16,28,23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,3,11,246,167,141,8,63,252,39,141,0,0,0,0,8,0,200,254,20,5,189, + 7,109,0,21,0,25,0,29,0,33,0,54,0,75,0,96,0,117,0,0,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54, + 55,54,1,33,17,33,55,33,17,33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,0,50,23,22,23, + 22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,1,50,23, + 22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,69,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,253,168, + 4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,253,233,73,24,25,19, + 16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16, + 16,16,27,23,73,24,25,19,16,16,17,27,23,1,5,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8, + 63,252,39,141,3,250,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,16,253,238,16,16,28,23,73,24,25,18,16,16,17,26,24,72, + 24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,253,254,16,16,28,23,73,24,25,18,16,16,17,26,24,72,24,26, + 18,16,0,0,0,9,0,200,254,20,5,189,7,109,0,22,0,44,0,48,0,52,0,56,0,78,0,100,0,122,0,144,0,0,5,52,55,54,55,54, + 50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1, + 33,17,33,55,33,17,33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21, + 20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23, + 22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,193,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16, + 2,17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24, + 26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25, + 19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,124,36,23,26,18, + 16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,2,59,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167, + 141,8,63,252,39,141,3,250,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16, + 17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16, + 17,26,24,72,24,26,18,16,0,10,0,200,254,20,5,189,7,109,0,22,0,43,0,65,0,69,0,73,0,77,0,99,0,121,0,143,0,165,0,0, + 5,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34, + 39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,1,50, + 23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55, + 54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39, + 38,52,55,54,55,54,1,193,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17, + 27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2, + 195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16, + 16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17, + 27,23,124,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,50,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17, + 27,23,1,46,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167,141,8,63,252,39,141,3,250,16,17,26,24,72, + 24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24, + 72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,0,0,11,0,200, + 254,20,5,189,7,109,0,21,0,43,0,65,0,87,0,91,0,95,0,99,0,121,0,143,0,165,0,187,0,0,1,50,23,22,23,22,20,7,6,7, + 6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22, + 20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33, + 17,33,55,33,17,33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20, + 7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22, + 23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,4,78,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233, + 74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36, + 24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16, + 16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16, + 17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,2,14,16,17,26,24,72,24, + 26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72, + 24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,7,113,246,167,141,8, + 63,252,39,141,3,250,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26, + 24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26, + 24,72,24,26,18,16,0,0,0,12,0,200,254,20,5,189,7,109,0,20,0,41,0,62,0,83,0,105,0,109,0,113,0,117,0,138,0,159,0,180, + 0,201,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,0,50,23,22,23,22,20,7,6,7,6,35,34,39,38, + 39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,1,50,23,22,23,22,20,7,6,7,6,34,39, + 38,39,38,52,55,54,55,54,3,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33, + 21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,0,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38, + 52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39, + 38,52,55,54,55,54,4,78,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,253,233,73,24,25,19,16,16,17,27,23,37,36,24, + 26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,73,24,25,19, + 16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61, + 2,109,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,253,233,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27, + 23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,2, + 14,16,17,26,24,72,24,26,18,16,16,16,28,23,73,24,25,18,16,253,238,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24,26,18,2,34, + 16,17,26,24,72,24,26,18,16,16,16,28,23,73,24,25,18,253,254,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16, + 17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,3,250,16,17,26,24,72,24,26,18,16,16, + 17,27,23,73,24,25,18,16,253,238,16,16,28,23,73,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17, + 27,23,73,24,25,18,253,254,16,16,28,23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,0,0,0,13,0,200,254,20,5,189,7,109,0,20, + 0,42,0,64,0,85,0,105,0,127,0,131,0,135,0,139,0,161,0,183,0,205,0,227,0,0,37,52,55,54,55,54,50,23,22,23,22,20,7,6, + 7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22, + 21,20,7,6,7,6,7,34,39,38,39,0,52,55,54,55,54,55,50,23,22,23,22,20,7,6,7,6,34,39,38,39,36,52,55,54,55,62,1,23, + 22,23,22,20,7,6,7,6,34,39,38,39,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,1,33,17,33,55,33, + 17,33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6, + 35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20, + 7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,212,16,17,28,23,72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23, + 37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37, + 36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36, + 24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36, + 24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,145,36,23,26,19,16,16,17,28,23,72,24,26, + 18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,51,74,24,25,18,16,16,17,26,23,38,36,23,26, + 17,16,1,17,17,26,253,171,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74,22,26,18,16,1,17,17,27,23,72,24,26, + 18,15,15,17,27,2,130,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,5,228,246,167,141,8,63,252,39,141,3,250,16,17, + 26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16, + 17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,0,0, + 0,8,0,200,254,20,5,189,7,109,0,3,0,7,0,11,0,33,0,55,0,77,0,99,0,121,0,0,19,33,17,33,55,33,17,33,19,33,21,33, + 1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38, + 52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39, + 38,39,38,52,55,54,55,54,3,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,200,4,245,251,11,141,3,219,252,37, + 140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26, + 17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16, + 16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,7,109,246,167,141,8,63,252,39,141,3,250,16,17,26,24, + 72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26, + 24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16,17, + 26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,0,9,0,200,254,20,5,189,7,109,0,22,0,26,0,30,0,34,0,56,0,78,0,100, + 0,122,0,144,0,0,1,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21, + 33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39, + 38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34, + 39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,3,69,36,23,26,18,16,16,16, + 28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74, + 23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36, + 24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24, + 25,18,16,16,17,26,24,1,5,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,3,250, + 16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2, + 34,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16, + 1,9,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,0,10,0,200,254,20,5,189,7,109,0,21,0,43,0,47,0,51,0,55, + 0,76,0,97,0,118,0,139,0,160,0,0,5,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54, + 50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34, + 39,38,39,38,52,55,54,55,54,0,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7, + 6,35,34,39,38,39,38,52,55,54,55,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,20,7, + 6,7,6,34,39,38,39,38,52,55,54,55,54,1,193,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2,17,16,17,28,23, + 72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27, + 23,73,24,25,19,16,16,17,27,23,253,233,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23, + 37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,73, + 24,25,18,16,16,17,26,24,124,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,2,59,36,24,26,18,15,15,17,27,23,37,36, + 24,26,18,16,16,17,27,23,5,248,246,167,141,8,63,252,39,141,3,250,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,16,253,238, + 16,16,28,23,73,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,253,254,16,16, + 28,23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,0,11,0,200, + 254,20,5,189,7,109,0,22,0,43,0,65,0,69,0,73,0,77,0,99,0,121,0,143,0,165,0,187,0,0,5,52,55,54,55,54,50,23,22,23, + 22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54, + 50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34, + 39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7, + 6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22, + 23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,193,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,1, + 9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252, + 246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25, + 19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17, + 16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,124,36,23,26,18,16, + 16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,50,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,46,36,24,26,18, + 15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5,248,246,167,141,8,63,252,39,141,3,250,16,17,26,24,72,24,26,18,16,16,17,27,23, + 36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27, + 23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16,17,26,23,74,24,25,18,16,16,17, + 26,24,72,25,26,17,16,0,0,12,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,87,0,91,0,95,0,99,0,121,0,143,0,165,0,187, + 0,209,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34, + 39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38, + 53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35, + 34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,20,7, + 6,7,6,35,34,39,38,39,38,52,55,54,55,54,4,78,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19, + 16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16, + 16,16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23, + 74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37, + 36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37, + 24,25,18,16,16,17,26,24,2,14,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24,25,18, + 16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24,25,18, + 16,16,17,26,24,72,24,26,18,16,7,113,246,167,141,8,63,252,39,141,3,250,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18, + 16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25, + 18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26, + 17,16,0,0,0,13,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,87,0,110,0,114,0,118,0,122,0,144,0,166,0,188,0,210,0,232, + 0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38, + 39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6, + 34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17, + 33,19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35, + 34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7, + 6,7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,4,78,36,24,26, + 17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19, + 16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16, + 16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27, + 23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23, + 37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36, + 37,24,25,18,16,16,17,26,24,2,14,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24,25, + 18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24,25, + 18,16,16,17,26,24,72,24,26,18,16,1,9,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252, + 39,141,3,250,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72, + 24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72, + 24,26,18,16,1,9,16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,0,14,0,200,254,20,5,189,7,109,0,20,0,42,0,64, + 0,85,0,105,0,127,0,131,0,135,0,139,0,161,0,183,0,205,0,227,0,249,0,0,37,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6, + 34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20, + 7,6,7,6,7,34,39,38,39,0,52,55,54,55,54,55,50,23,22,23,22,20,7,6,7,6,34,39,38,39,36,52,55,54,55,62,1,23,22,23, + 22,20,7,6,7,6,34,39,38,39,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,1,33,17,33,55,33,17,33, + 19,33,21,33,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54,0,50,23,22,23,22,21,20,7,6,7,6,35,34, + 39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53,52,55,54,55,1,50,23,22,23,22,21,20,7,6, + 7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,54,3,212,16,17,28,23, + 72,24,26,18,15,15,17,27,23,74,22,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71, + 24,26,19,16,16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71, + 24,26,19,16,16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3, + 219,252,37,140,2,195,253,61,2,109,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16,16,17,27,23,37, + 36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16,16,27,23,74,23, + 25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,145,36,23,26,19,16,16,17,28,23,72,24,26, + 18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,51,74,24,25,18,16,16,17,26,23,38,36,23,26, + 17,16,1,17,17,26,253,171,74,22,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,23,74,22,26,18,16,1,17,17,27,23,72,24,26, + 18,15,15,17,27,2,130,74,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,5,228,246,167,141,8,63,252,39,141,3,250,16,17, + 26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,253,238,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16, + 17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,253,254,16,16,28,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,1,9, + 16,17,26,23,74,24,25,18,16,16,17,26,24,72,25,26,17,16,0,0,0,9,0,200,254,20,5,189,7,109,0,3,0,7,0,11,0,34,0,58, + 0,80,0,102,0,124,0,146,0,0,19,33,17,33,55,33,17,33,19,33,21,33,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6, + 34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22, + 21,20,7,6,7,6,7,34,39,38,39,1,52,55,54,55,54,55,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,62,1, + 23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,200,4,245, + 251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,74,23,25,19,16,253,239,16,17,26,23,38, + 36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36, + 37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,17,27, + 23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,7,109,246,167,141,8,63,252,39,141,2,124,36,23,26,18,16,16,16,28,23,36,37,24,25, + 18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,51,74,23,26,18,16,16,17,27,23,37,36,23, + 26,17,16,1,17,16,27,253,208,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72, + 24,26,18,16,16,17,27,23,2,107,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,0,0,0,0,10,0,200,254,20,5,189, + 7,109,0,22,0,26,0,30,0,34,0,57,0,81,0,103,0,125,0,147,0,169,0,0,1,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38, + 39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38, + 39,38,37,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,7,34,39,38,39,1,52,55,54,55,54,55,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,62,1,23,22,23, + 22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,3,69,36,23,26,18, + 16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24, + 26,17,16,16,17,26,23,74,23,25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24, + 26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72, + 24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,1,5,16,17,26,23, + 38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,2,124,36,23,26,18,16,16,16,28,23,36,37,24,25, + 18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,51,74,23,26,18,16,16,17,27,23,37,36,23, + 26,17,16,1,17,16,27,253,208,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72, + 24,26,18,16,16,17,27,23,2,107,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,0,0,0,0,11,0,200,254,20,5,189, + 7,109,0,22,0,44,0,48,0,52,0,56,0,79,0,103,0,125,0,147,0,169,0,191,0,0,5,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,6,35,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33,17,33,55,33,17,33,19, + 33,21,33,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,21,20, + 7,6,7,6,35,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,1,52,55,54,55,54,55,50, + 23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54, + 55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,1,193,16,16,27,24,72,24,25,19,16,16,17,27,23,37,36,24,26,17,16,2, + 17,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27, + 23,37,36,24,26,17,16,16,17,26,23,74,23,25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17, + 26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16, + 17,26,24,72,24,26,18,16,16,17,27,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,124,36, + 23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,2,59,36,24,26,18,15,15,17,27,23,37,36,24,26,18,16,16,17,27,23,5, + 248,246,167,141,8,63,252,39,141,2,124,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23, + 36,37,24,25,18,16,16,17,26,24,1,51,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,253,208,36,23,26,18,16,1,17, + 17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,2,107,74,23,26,18,16,16, + 17,27,23,37,36,23,26,17,16,1,17,16,27,0,0,0,0,12,0,200,254,20,5,189,7,109,0,22,0,43,0,65,0,69,0,73,0,77,0,100, + 0,124,0,146,0,168,0,190,0,212,0,0,5,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,1,52,55,54,55, + 54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,1,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,1,33, + 17,33,55,33,17,33,19,33,21,33,1,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51, + 50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,1, + 52,55,54,55,54,55,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,35,34,39, + 38,39,38,0,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,1,193,16,16,27,24,72,24,25,19,16,16,17,27,23, + 37,36,24,26,17,16,1,9,15,17,27,23,74,23,26,18,16,16,17,27,23,72,25,26,18,15,1,8,16,17,28,23,72,24,26,18,16,16,17,27, + 24,71,24,26,19,16,252,246,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,74,23, + 25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,36,37, + 24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,36, + 37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,124,36,23,26,18,16,16,16,28,23,36,37,24,25,18, + 16,16,17,26,24,1,50,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,1,46,36,24,26,18,15,15,17,27,23,37,36,24,26, + 18,16,16,17,27,23,5,248,246,167,141,8,63,252,39,141,2,124,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,37,36,23, + 26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,1,51,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,253,208, + 36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,2, + 107,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,0,13,0,200,254,20,5,189,7,109,0,21,0,43,0,65,0,87,0,91, + 0,95,0,99,0,122,0,146,0,168,0,190,0,212,0,234,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,53,52,55,54,55,54, + 0,50,23,22,23,22,21,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,53, + 52,55,54,55,1,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33,17,33,19,33,21,33,1,52, + 55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35, + 34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,1,52,55,54,55,54,55,50,23,22,23,22,20, + 7,6,7,6,34,39,38,39,38,37,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,0,52,55,54,55,54,51,50,23, + 22,23,22,21,20,7,6,7,14,1,39,38,39,4,78,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,253,233,74,23,25,19,16, + 16,17,27,23,37,36,24,26,17,16,16,16,27,23,74,23,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16,16, + 16,27,23,74,23,25,19,16,16,17,27,23,252,159,4,245,251,11,141,3,219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16, + 16,17,26,23,74,23,25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16, + 16,17,27,23,36,37,24,25,18,2,2,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18, + 16,16,17,27,23,36,37,24,25,18,16,2,18,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,14,16,17,26,24,72,24,26, + 18,16,16,16,28,23,36,37,24,25,18,16,253,238,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,2,34,16,17,26,24,72,24, + 26,18,16,16,16,28,23,36,37,24,25,18,253,254,16,17,27,23,36,37,24,25,18,16,16,17,26,24,72,24,26,18,16,7,113,246,167,141,8,63, + 252,39,141,2,124,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,36,37,24,25,18,16, + 16,17,26,24,1,51,74,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,253,208,36,23,26,18,16,1,17,17,27,23,72,24,26, + 18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,2,107,74,23,26,18,16,16,17,27,23,37,36,23, + 26,17,16,1,17,16,27,0,0,14,0,200,254,20,5,189,7,109,0,20,0,41,0,62,0,83,0,105,0,109,0,113,0,117,0,139,0,161,0,182, + 0,203,0,224,0,245,0,0,1,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,0,50,23,22,23,22,20,7,6,7,6, + 35,34,39,38,39,38,52,55,54,55,18,50,23,22,23,22,20,7,6,7,6,35,34,39,38,39,38,52,55,54,55,1,50,23,22,23,22,20,7,6, + 7,6,34,39,38,39,38,52,55,54,55,54,3,50,23,22,23,22,21,20,7,6,7,6,34,39,38,39,38,52,55,54,55,54,1,33,17,33,55,33, + 17,33,19,33,21,33,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22, + 20,7,6,7,6,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,1,52,55,54,55,62,1,23,22, + 23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,34,39,38,39,38,0,52,55,54,55,54,50, + 23,22,23,22,21,20,7,6,7,14,1,39,38,39,4,78,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,253,233,73,24,25,19, + 16,16,17,27,23,37,36,24,26,17,16,16,16,27,23,73,24,25,19,16,16,17,27,23,37,36,24,26,17,16,16,16,27,2,83,36,24,26,17,16, + 16,16,27,23,73,24,25,19,16,16,17,27,23,228,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,253,168,4,245,251,11,141,3, + 219,252,37,140,2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,73,24,25,19,16,253,239,16,17,26,23,38,36,23,26,18, + 16,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,2,2,16,17,27,23,73,24,25,18,16,16,17, + 26,24,72,24,26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,16,2,18,16,17,27,23,73,24,25,18,16,16,17, + 26,24,72,24,26,18,2,14,16,17,26,24,72,24,26,18,16,16,16,28,23,73,24,25,18,16,253,238,16,17,27,23,73,24,25,18,16,16,17,26, + 24,72,24,26,18,2,34,16,17,26,24,72,24,26,18,16,16,16,28,23,73,24,25,18,253,254,16,17,27,23,73,24,25,18,16,16,17,26,24,72, + 24,26,18,16,1,9,16,17,26,23,38,36,24,26,17,16,16,17,26,24,73,24,25,18,16,6,104,246,167,141,8,63,252,39,141,2,124,36,23,26, + 18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,1,52,73,23,26,18, + 16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,253,208,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26, + 18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,2,108,73,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,0,0,0, + 0,15,0,200,254,20,5,189,7,109,0,20,0,42,0,64,0,85,0,105,0,127,0,131,0,135,0,139,0,161,0,183,0,204,0,225,0,246,1,11, + 0,0,37,52,55,54,55,54,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6, + 34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,6,7,34,39,38,39,0,52,55,54,55,54,55,50,23,22,23,22,20, + 7,6,7,6,34,39,38,39,36,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,34,39,38,39,0,52,55,54,55,54,51,50,23,22,23,22, + 21,20,7,6,7,14,1,39,38,39,1,33,17,33,55,33,17,33,19,33,21,33,1,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34, + 39,38,39,38,37,52,55,54,55,54,51,50,23,22,23,22,20,7,6,7,6,34,39,38,39,38,16,52,55,54,55,54,50,23,22,23,22,21,20,7, + 6,7,14,1,39,38,39,1,52,55,54,55,62,1,23,22,23,22,20,7,6,7,6,34,39,38,39,38,37,52,55,54,55,62,1,23,22,23,22,20, + 7,6,7,6,34,39,38,39,38,0,52,55,54,55,54,50,23,22,23,22,21,20,7,6,7,14,1,39,38,39,3,212,16,17,28,23,72,24,26,18, + 15,15,17,27,23,73,23,26,19,16,253,239,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,24,71,24,26,19,16, + 16,17,28,23,36,36,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,253,222,16,17,27,24,71,24,26,19,16, + 16,17,28,23,72,24,26,18,2,2,16,17,27,23,37,36,24,26,17,16,16,16,27,24,72,24,25,19,252,227,4,245,251,11,141,3,219,252,37,140, + 2,195,253,61,1,242,16,17,27,23,37,36,24,26,17,16,16,17,26,23,73,24,25,19,16,253,239,16,17,26,23,38,36,23,26,18,16,16,17,27, + 23,73,24,25,18,16,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,2,2,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24, + 26,18,16,253,238,16,17,26,24,72,24,26,18,16,16,17,27,23,73,24,25,18,16,2,18,16,17,27,23,73,24,25,18,16,16,17,26,24,72,24, + 26,18,145,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23,37,36,23,26,19,16,16,17,28,23,72,24,26,18,16,16,17,27,23, + 1,52,73,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17,26,253,171,73,23,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17, + 27,23,73,23,26,18,16,1,17,17,27,23,72,24,26,18,15,15,17,27,2,131,73,24,25,18,16,16,17,26,23,38,36,23,26,17,16,1,17,17, + 26,5,228,246,167,141,8,63,252,39,141,2,124,36,23,26,18,16,16,16,28,23,73,24,25,18,16,16,17,26,24,37,36,23,26,18,16,16,16,28, + 23,73,24,25,18,16,16,17,26,24,1,52,73,23,26,18,16,16,17,27,23,37,36,23,26,17,16,1,17,16,27,253,208,36,23,26,18,16,1,17, + 17,27,23,72,24,26,18,16,16,17,27,23,37,36,23,26,18,16,1,17,17,27,23,72,24,26,18,16,16,17,27,23,2,108,73,23,26,18,16,16, + 17,27,23,37,36,23,26,17,16,1,17,16,27,0,0,0,0,3,0,200,254,20,7,103,7,109,0,11,0,23,0,27,0,0,1,34,21,17,20,51, + 33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,17,33,17,1,184,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1, + 44,4,71,6,245,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,247,211,7,1,248,255,0,5,0,200,254,20,7,103,7,109,0,24, + 0,36,0,48,0,51,0,59,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21,17,20, + 51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,3,33,3,51,1,35,39,33,7,35,4,215,65,1,59,9,27,195,108,66, + 30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,75,134,1,12,210,154,1,32,132,68, + 254,182,68,132,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240, + 240,7,121,240,254,172,254,85,2,15,252,188,218,218,0,0,0,4,0,200,254,20,7,103,7,109,0,24,0,36,0,48,0,73,0,0,1,22,0,23, + 22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35, + 33,34,53,17,52,1,33,21,33,53,54,55,0,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,1,6,4,215,65,1,59,9,27,195,108,66, + 30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,158,1,168,253,170,34,63,1,88,104, + 85,52,122,72,77,133,57,145,174,254,181,56,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120, + 7,121,120,120,240,248,135,240,240,7,121,240,252,63,114,110,31,56,1,49,94,66,81,35,35,123,28,28,132,108,139,254,228,48,0,0,0,4,0,200, + 254,20,7,103,7,109,0,24,0,36,0,48,0,89,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54, + 0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50, + 54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,4,215,65,1,59,9,27,195,108,66,30,59,152,59, + 30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,154,92,101,190,177,57,125,70,52,119,67,109,120,111, + 108,86,94,94,97,100,95,40,102,81,73,128,55,144,169,90,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120, + 248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,145,18,109,82,124,134,21,20,121,27,26,79,70,74,76,108,63,60,58,61,18,23,115, + 17,18,118,99,69,96,0,0,0,5,0,200,254,20,7,103,7,109,0,24,0,36,0,48,0,51,0,62,0,0,1,22,0,23,22,21,20,35,34,39, + 35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,9, + 1,33,3,51,17,51,21,35,21,35,53,33,53,4,215,65,1,59,9,27,195,108,66,30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4, + 191,120,120,251,65,4,191,240,240,251,65,240,2,142,254,203,1,53,22,166,135,135,144,254,98,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155, + 228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,254,151,254,93,2,28,253,228,109,186,186,121,0,0,0, + 0,4,0,200,254,20,7,103,7,109,0,24,0,36,0,48,0,81,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34, + 53,52,55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,5,33,21,33,21,54,55,54,51,50,23, + 22,21,20,7,6,35,34,38,39,53,22,23,22,51,50,54,52,38,35,34,6,7,4,215,65,1,59,9,27,195,108,66,30,59,152,59,30,66,108,195, + 27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,24,1,254,254,121,28,29,28,28,161,94,94,97,96,176,60,126,66, + 57,62,62,69,111,130,130,111,52,104,54,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7, + 121,120,120,240,248,135,240,240,7,121,240,240,95,204,9,4,4,77,76,131,135,75,74,18,18,113,27,14,13,102,174,102,20,21,0,0,0,5,0,200, + 254,20,7,103,7,109,0,24,0,36,0,48,0,64,0,96,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52, + 55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,34,7,6,21,20,23,22,51,50,55,54,53, + 52,39,38,19,21,38,39,38,35,34,7,6,7,54,55,54,51,50,23,22,21,20,7,6,35,34,38,53,52,55,54,51,50,23,22,4,215,65,1,59, + 9,27,195,108,66,30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,71,88,51,51,51, + 51,88,87,51,51,51,51,171,49,50,50,49,128,68,68,10,38,57,58,68,145,84,84,88,87,145,167,176,108,108,182,49,50,50,3,24,121,254,126,38, + 37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,158,52,53,91,90, + 52,53,53,52,90,91,53,52,1,98,103,20,10,11,75,76,153,49,26,26,76,77,132,127,79,78,222,212,198,117,118,8,9,0,0,0,0,4,0,200, + 254,20,7,103,7,109,0,24,0,36,0,48,0,55,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54, + 0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,23,33,21,1,35,1,33,4,215,65,1,59,9,27,195, + 108,66,30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,240,2,105,254,164,136,1,72,254, + 51,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121, + 240,240,48,252,237,2,228,0,0,6,0,200,254,20,7,103,7,109,0,24,0,36,0,48,0,61,0,91,0,106,0,0,1,22,0,23,22,21,20,35, + 34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17, + 52,0,34,7,6,21,20,22,51,50,55,54,52,39,37,38,39,38,53,52,54,32,23,22,21,20,7,6,7,22,23,22,21,20,7,6,35,34,39,38, + 53,52,55,54,55,20,23,22,51,50,55,54,53,52,39,38,34,7,6,4,215,65,1,59,9,27,195,108,66,30,59,152,59,30,66,108,195,27,9,1, + 59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,151,186,53,53,106,93,92,54,53,53,254,236,84,46,47,164,1,30,82,81,46, + 47,83,90,56,53,85,86,158,159,85,86,53,54,45,47,46,85,81,49,48,48,47,166,48,47,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155, + 228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,91,44,43,75,76,86,44,43,150,43,93,18,49,50, + 72,100,116,58,58,100,74,48,49,18,18,58,55,80,121,65,65,65,65,121,78,57,56,198,63,38,37,37,36,65,63,38,37,37,36,0,0,5,0,200, + 254,20,7,103,7,109,0,24,0,36,0,48,0,80,0,95,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52, + 55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,53,22,23,22,51,50,55,54,55,6,7,6, + 35,34,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34,39,38,19,50,54,53,52,39,38,35,34,7,6,21,20,23,22,4,215,65,1,59,9, + 27,195,108,66,30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,46,49,50,50,48,129, + 68,67,10,35,60,57,69,144,168,87,88,145,167,87,88,107,108,182,49,50,50,204,88,102,51,51,88,85,53,52,52,51,3,24,121,254,126,38,37,78, + 228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,251,223,103,20,11,10,75,75, + 154,47,27,26,152,132,129,77,78,111,111,212,198,117,118,8,9,1,114,104,92,90,52,53,53,52,90,92,52,52,0,0,0,6,0,200,254,20,7,103, + 7,109,0,24,0,36,0,48,0,62,0,74,0,81,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54, + 0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,0,34,7,6,21,20,23,22,50,55,54,53,52,47,1, + 50,22,21,20,6,35,34,38,53,52,54,1,17,7,53,55,51,17,4,215,65,1,59,9,27,195,108,66,30,59,152,59,30,66,108,195,27,9,1,59, + 253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,234,142,50,51,51,50,142,50,51,51,121,131,170,170,131,162,140,140,254,116,133,140, + 137,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121, + 240,254,200,86,86,172,173,86,86,86,86,173,172,86,175,222,211,212,222,222,212,211,222,252,172,2,209,41,116,39,252,189,0,4,0,200,254,20,7,103, + 7,109,0,24,0,36,0,48,0,61,0,0,1,22,0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21, + 17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,5,51,17,20,7,6,43,1,53,51,50,54,53,4,215,65,1,59,9, + 27,195,108,66,30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,178,127,65,64,143,49, + 40,84,70,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240, + 7,121,240,240,253,220,149,70,69,96,84,108,0,4,0,200,254,20,7,103,7,109,0,24,0,36,0,48,0,74,0,0,1,22,0,23,22,21,20,35, + 34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17, + 52,1,14,1,35,34,38,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,51,50,54,55,4,215,65,1,59,9,27,195,108,66,30,59,152, + 59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,60,49,101,57,181,200,201,180,57,102,48,47,106, + 54,124,124,123,125,55,106,46,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120, + 240,248,135,240,240,7,121,240,251,235,23,22,227,206,205,229,23,23,116,34,36,170,172,171,171,36,34,0,0,5,0,200,254,20,7,103,7,109,0,17, + 0,27,0,52,0,64,0,76,0,0,1,34,6,35,34,38,53,52,54,51,50,22,21,20,6,7,23,7,18,16,38,35,34,6,16,22,51,50,5,22, + 0,23,22,21,20,35,34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17, + 20,35,33,34,53,17,52,2,251,4,17,5,158,155,156,158,159,156,86,88,126,95,10,85,97,96,85,85,96,97,1,148,65,1,59,9,27,195,108,66, + 30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,44,1,215,218,219,215,215,219,165,201, + 40,106,56,1,128,1,112,158,158,254,144,158,110,121,254,126,38,37,78,228,155,204,107,107,204,155,228,78,37,38,1,130,4,86,120,248,135,120,120,7, + 121,120,120,240,248,135,240,240,7,121,240,0,0,4,0,200,254,20,7,103,7,109,0,24,0,36,0,48,0,59,0,0,1,22,0,23,22,21,20,35, + 34,39,35,20,23,35,54,53,35,6,35,34,53,52,55,54,0,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17, + 52,23,51,17,1,51,9,1,35,1,17,35,4,215,65,1,59,9,27,195,108,66,30,59,152,59,30,66,108,195,27,9,1,59,253,34,120,120,4,191, + 120,120,251,65,4,191,240,240,251,65,240,240,127,1,106,164,254,105,1,184,167,254,120,127,3,24,121,254,126,38,37,78,228,155,204,107,107,204,155,228, + 78,37,38,1,130,4,86,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,254,159,1,97,254,122,254,66,1,147,254,109,0,0,0, + 0,5,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,48,0,56,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54, + 51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,3,33,3,51,1,35,39,33,7,35,4, + 204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,75,134, + 1,12,210,154,1,32,132,68,254,182,68,132,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120,120, + 7,121,120,120,240,248,135,240,240,7,121,240,254,172,254,85,2,15,252,188,218,218,0,0,0,4,0,200,254,20,7,103,7,109,0,21,0,33,0,45, + 0,70,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33, + 50,21,17,20,35,33,34,53,17,52,1,33,21,33,53,54,55,0,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,1,6,4,204,22,55,62, + 84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,158,1,168,253,170,34, + 63,1,88,104,85,52,122,72,77,133,57,145,174,254,181,56,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120, + 248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,252,63,114,110,31,56,1,49,94,66,81,35,35,123,28,28,132,108,139,254,228,48,0,0, + 0,4,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,86,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50, + 23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,30,1,21,20,6,35,34,38,39,53,30,1,51, + 50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,6,4,204,22,55,62,84,139,62,19,125,254,196,254, + 192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,154,92,101,190,177,57,125,70,52,119,67,109,120,111, + 108,86,94,94,97,100,95,40,102,81,73,128,55,144,169,90,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120, + 248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,145,18,109,82,124,134,21,20,121,27,26,79,70,74,76,108,63,60,58,61,18,23,115, + 17,18,118,99,69,96,0,0,0,5,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,48,0,59,0,0,1,54,55,54,51,50,23,22,21,20, + 7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,9,1,33,3, + 51,17,51,21,35,21,35,53,33,53,4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251, + 65,4,191,240,240,251,65,240,2,142,254,203,1,53,22,166,135,135,144,254,98,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149, + 71,65,4,204,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,254,151,254,93,2,28,253,228,109,186,186,121,0,0,0,0,4,0,200, + 254,20,7,103,7,109,0,21,0,33,0,45,0,78,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34, + 21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,5,33,21,33,21,54,55,54,51,50,23,22,21,20,7,6,35,34, + 38,39,53,22,23,22,51,50,54,52,38,35,34,6,7,4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120, + 4,191,120,120,251,65,4,191,240,240,251,65,240,1,24,1,254,254,121,28,29,28,28,161,94,94,97,96,176,60,126,66,57,62,62,69,111,130,130,111, + 52,104,54,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120,120,7,121,120,120,240,248,135,240,240, + 7,121,240,240,95,204,9,4,4,77,76,131,135,75,74,18,18,113,27,14,13,102,174,102,20,21,0,0,0,5,0,200,254,20,7,103,7,109,0,21, + 0,33,0,45,0,61,0,93,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50, + 53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38,19,21,38,39,38,35,34,7, + 6,7,54,55,54,51,50,23,22,21,20,7,6,35,34,38,53,52,55,54,51,50,23,22,4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19, + 63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,71,88,51,51,51,51,88,87,51,51,51,51,171,49,50,50,49, + 128,68,68,10,38,57,58,68,145,84,84,88,87,145,167,176,108,108,182,49,50,50,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45, + 149,71,65,4,204,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,158,52,53,91,90,52,53,53,52,90,91,53,52,1,98,103,20, + 10,11,75,76,153,49,26,26,76,77,132,127,79,78,222,212,198,117,118,8,9,0,0,0,0,4,0,200,254,20,7,103,7,109,0,21,0,33,0,45, + 0,52,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33, + 50,21,17,20,35,33,34,53,17,52,23,33,21,1,35,1,33,4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2, + 120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,240,2,105,254,164,136,1,72,254,51,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157, + 160,59,45,149,71,65,4,204,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,48,252,237,2,228,0,0,6,0,200,254,20,7,103, + 7,109,0,21,0,33,0,45,0,58,0,88,0,103,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34, + 21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,0,34,7,6,21,20,22,51,50,55,54,52,39,37,38,39,38,53, + 52,54,32,23,22,21,20,7,6,7,22,23,22,21,20,7,6,35,34,39,38,53,52,55,54,55,20,23,22,51,50,55,54,53,52,39,38,34,7,6, + 4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,151, + 186,53,53,106,93,92,54,53,53,254,236,84,46,47,164,1,30,82,81,46,47,83,90,56,53,85,86,158,159,85,86,53,54,45,47,46,85,81,49,48, + 48,47,166,48,47,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120,120,7,121,120,120,240,248,135, + 240,240,7,121,240,253,91,44,43,75,76,86,44,43,150,43,93,18,49,50,72,100,116,58,58,100,74,48,49,18,18,58,55,80,121,65,65,65,65,121, + 78,57,56,198,63,38,37,37,36,65,63,38,37,37,36,0,0,5,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,77,0,92,0,0,1,54, + 55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33, + 34,53,17,52,1,53,22,23,22,51,50,55,54,55,6,7,6,35,34,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34,39,38,19,50,54,53, + 52,39,38,35,34,7,6,21,20,23,22,4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120, + 251,65,4,191,240,240,251,65,240,1,46,49,50,50,48,129,68,67,10,35,60,57,69,144,168,87,88,145,167,87,88,107,108,182,49,50,50,204,88,102, + 51,51,88,85,53,52,52,51,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120,120,7,121,120,120, + 240,248,135,240,240,7,121,240,251,223,103,20,11,10,75,75,154,47,27,26,152,132,129,77,78,111,111,212,198,117,118,8,9,1,114,104,92,90,52,53, + 53,52,90,92,52,52,0,0,0,6,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,59,0,71,0,78,0,0,1,54,55,54,51,50,23,22, + 21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,0,34, + 7,6,21,20,23,22,50,55,54,53,52,47,1,50,22,21,20,6,35,34,38,53,52,54,1,17,7,53,55,51,17,4,204,22,55,62,84,139,62,19, + 125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,234,142,50,51,51,50,142,50,51,51, + 121,131,170,170,131,162,140,140,254,116,133,140,137,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120, + 120,7,121,120,120,240,248,135,240,240,7,121,240,254,200,86,86,172,173,86,86,86,86,173,172,86,175,222,211,212,222,222,212,211,222,252,172,2,209,41, + 116,39,252,189,0,4,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,58,0,0,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52, + 55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,5,51,17,20,7,6,43,1,53,51, + 50,54,53,4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65, + 240,1,178,127,65,64,143,49,40,84,70,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120,120,7, + 121,120,120,240,248,135,240,240,7,121,240,240,253,220,149,70,69,96,84,108,0,4,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,71,0,0, + 1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20, + 35,33,34,53,17,52,1,14,1,35,34,38,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20,22,51,50,54,55,4,204,22,55,62,84,139,62, + 19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,60,49,101,57,181,200,201,180,57, + 102,48,47,106,54,124,124,123,125,55,106,46,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120,120, + 7,121,120,120,240,248,135,240,240,7,121,240,251,235,23,22,227,206,205,229,23,23,116,34,36,170,172,171,171,36,34,0,0,5,0,217,254,20,7,120, + 7,109,0,17,0,27,0,49,0,61,0,73,0,0,1,34,6,35,34,38,53,52,54,51,50,22,21,20,6,7,23,7,18,16,38,35,34,6,16,22, + 51,50,1,54,55,54,51,50,23,22,21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21, + 17,20,35,33,34,53,17,52,2,251,4,17,5,158,155,156,158,159,156,86,88,126,95,10,85,97,96,85,85,96,97,1,137,22,55,62,84,139,62,19, + 125,254,196,254,192,125,19,63,138,86,60,55,253,19,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,44,1,215,218,219,215,215,219,165,201, + 40,106,56,1,128,1,112,158,158,254,144,158,254,48,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71,65,4,204,120,248,135,120,120, + 7,121,120,120,240,248,135,240,240,7,121,240,0,4,0,200,254,20,7,103,7,109,0,21,0,33,0,45,0,56,0,0,1,54,55,54,51,50,23,22, + 21,20,7,9,1,38,53,52,55,54,51,50,23,22,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,23,51, + 17,1,51,9,1,35,1,17,35,4,204,22,55,62,84,139,62,19,125,254,196,254,192,125,19,63,138,86,60,55,253,2,120,120,4,191,120,120,251,65, + 4,191,240,240,251,65,240,240,127,1,106,164,254,105,1,184,167,254,120,127,1,182,118,62,71,149,45,59,158,159,254,110,1,146,157,160,59,45,149,71, + 65,4,204,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,254,159,1,97,254,122,254,66,1,147,254,109,0,0,0,0,5,0,200, + 254,20,7,103,7,109,0,6,0,18,0,30,0,33,0,41,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50, + 21,17,20,35,33,34,53,17,52,1,3,33,3,51,1,35,39,33,7,35,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191, + 240,240,251,65,240,2,75,134,1,12,210,154,1,32,132,68,254,182,68,132,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240, + 248,135,240,240,7,121,240,254,172,254,85,2,15,252,188,218,218,0,0,0,0,4,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,55,0,0, + 1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,33,21,33,53,54,55,0,53, + 52,38,35,34,6,7,53,62,1,51,50,22,21,20,1,6,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65, + 240,1,158,1,168,253,170,34,63,1,88,104,85,52,122,72,77,133,57,145,174,254,181,56,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7, + 121,120,120,240,248,135,240,240,7,121,240,252,63,114,110,31,56,1,49,94,66,81,35,35,123,28,28,132,108,139,254,228,48,0,0,0,0,4,0,200, + 254,20,7,103,7,109,0,6,0,18,0,30,0,71,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17, + 20,35,33,34,53,17,52,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7,53, + 62,1,51,50,22,21,20,6,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,154,92,101,190,177,57, + 125,70,52,119,67,109,120,111,108,86,94,94,97,100,95,40,102,81,73,128,55,144,169,90,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7, + 121,120,120,240,248,135,240,240,7,121,240,253,145,18,109,82,124,134,21,20,121,27,26,79,70,74,76,108,63,60,58,61,18,23,115,17,18,118,99,69, + 96,0,0,0,0,5,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,33,0,44,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33, + 50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,9,1,33,3,51,17,51,21,35,21,35,53,33,53,4,202,1,152,254,104,254,102,254, + 136,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,142,254,203,1,53,22,166,135,135,144,254,98,2,249,253,242,253,250,2,6,6,10,120, + 248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,254,151,254,93,2,28,253,228,109,186,186,121,0,4,0,200,254,20,7,103,7,109,0,6, + 0,18,0,30,0,63,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,5, + 33,21,33,21,54,55,54,51,50,23,22,21,20,7,6,35,34,38,39,53,22,23,22,51,50,54,52,38,35,34,6,7,4,202,1,152,254,104,254,102, + 254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,24,1,254,254,121,28,29,28,28,161,94,94,97,96,176,60,126,66,57,62,62,69, + 111,130,130,111,52,104,54,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,95,204,9,4,4, + 77,76,131,135,75,74,18,18,113,27,14,13,102,174,102,20,21,0,0,0,0,5,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,46,0,78, + 0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,34,7,6,21,20,23, + 22,51,50,55,54,53,52,39,38,19,21,38,39,38,35,34,7,6,7,54,55,54,51,50,23,22,21,20,7,6,35,34,38,53,52,55,54,51,50,23, + 22,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,71,88,51,51,51,51,88,87,51,51,51,51,171, + 49,50,50,49,128,68,68,10,38,57,58,68,145,84,84,88,87,145,167,176,108,108,182,49,50,50,2,249,253,242,253,250,2,6,6,10,120,248,135,120, + 120,7,121,120,120,240,248,135,240,240,7,121,240,253,158,52,53,91,90,52,53,53,52,90,91,53,52,1,98,103,20,10,11,75,76,153,49,26,26,76, + 77,132,127,79,78,222,212,198,117,118,8,9,0,4,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,37,0,0,1,48,9,1,48,1,48,1, + 34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,23,33,21,1,35,1,33,4,202,1,152,254,104,254,102,254,136, + 120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,240,2,105,254,164,136,1,72,254,51,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120, + 7,121,120,120,240,248,135,240,240,7,121,240,240,48,252,237,2,228,0,0,0,6,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,43,0,73, + 0,88,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,0,34,7,6,21, + 20,22,51,50,55,54,52,39,37,38,39,38,53,52,54,32,23,22,21,20,7,6,7,22,23,22,21,20,7,6,35,34,39,38,53,52,55,54,55,20, + 23,22,51,50,55,54,53,52,39,38,34,7,6,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,151, + 186,53,53,106,93,92,54,53,53,254,236,84,46,47,164,1,30,82,81,46,47,83,90,56,53,85,86,158,159,85,86,53,54,45,47,46,85,81,49,48, + 48,47,166,48,47,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,91,44,43,75,76,86,44, + 43,150,43,93,18,49,50,72,100,116,58,58,100,74,48,49,18,18,58,55,80,121,65,65,65,65,121,78,57,56,198,63,38,37,37,36,65,63,38,37, + 37,36,0,0,0,5,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,62,0,77,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33, + 50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,53,22,23,22,51,50,55,54,55,6,7,6,35,34,38,53,52,55,54,51,50,23, + 22,21,20,7,6,35,34,39,38,19,50,54,53,52,39,38,35,34,7,6,21,20,23,22,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120, + 251,65,4,191,240,240,251,65,240,1,46,49,50,50,48,129,68,67,10,35,60,57,69,144,168,87,88,145,167,87,88,107,108,182,49,50,50,204,88,102, + 51,51,88,85,53,52,52,51,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,251,223,103,20,11, + 10,75,75,154,47,27,26,152,132,129,77,78,111,111,212,198,117,118,8,9,1,114,104,92,90,52,53,53,52,90,92,52,52,0,0,0,0,6,0,200, + 254,20,7,103,7,109,0,6,0,18,0,30,0,44,0,56,0,63,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37, + 33,50,21,17,20,35,33,34,53,17,52,0,34,7,6,21,20,23,22,50,55,54,53,52,47,1,50,22,21,20,6,35,34,38,53,52,54,1,17,7, + 53,55,51,17,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,234,142,50,51,51,50,142,50,51,51, + 121,131,170,170,131,162,140,140,254,116,133,140,137,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240, + 254,200,86,86,172,173,86,86,86,86,173,172,86,175,222,211,212,222,222,212,211,222,252,172,2,209,41,116,39,252,189,0,0,4,0,200,254,20,7,103, + 7,109,0,6,0,18,0,30,0,43,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34, + 53,17,52,5,51,17,20,7,6,43,1,53,51,50,54,53,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65, + 240,1,178,127,65,64,143,49,40,84,70,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,253, + 220,149,70,69,96,84,108,0,0,4,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,56,0,0,1,48,9,1,48,1,48,1,34,21,17,20, + 51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,14,1,35,34,38,53,52,54,51,50,22,23,21,46,1,35,34,6,21,20, + 22,51,50,54,55,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,60,49,101,57,181,200,201,180,57, + 102,48,47,106,54,124,124,123,125,55,106,46,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,251, + 235,23,22,227,206,205,229,23,23,116,34,36,170,172,171,171,36,34,0,0,0,5,0,200,254,20,7,103,7,109,0,6,0,24,0,34,0,46,0,58, + 0,0,1,48,9,1,48,1,48,3,34,6,35,34,38,53,52,54,51,50,22,21,20,6,7,23,7,18,16,38,35,34,6,16,22,51,50,1,34,21, + 17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,4,202,1,152,254,104,254,102,53,4,17,5,158,155,156,158,159,156,86, + 88,126,95,10,85,97,96,85,85,96,97,254,117,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,249,253,242,253,250,2,6,2,65,1,215, + 218,219,215,215,219,165,201,40,106,56,1,128,1,112,158,158,254,144,158,3,111,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,0,0, + 0,4,0,200,254,20,7,103,7,109,0,6,0,18,0,30,0,41,0,0,1,48,9,1,48,1,48,1,34,21,17,20,51,33,50,53,17,52,35,37, + 33,50,21,17,20,35,33,34,53,17,52,23,51,17,1,51,9,1,35,1,17,35,4,202,1,152,254,104,254,102,254,136,120,120,4,191,120,120,251,65, + 4,191,240,240,251,65,240,240,127,1,106,164,254,105,1,184,167,254,120,127,2,249,253,242,253,250,2,6,6,10,120,248,135,120,120,7,121,120,120,240, + 248,135,240,240,7,121,240,240,254,159,1,97,254,122,254,66,1,147,254,109,0,3,0,200,254,20,7,103,7,109,0,9,0,21,0,33,0,0,1,19, + 33,1,19,9,1,19,1,33,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,4,24,142,1,209,254,137,143, + 254,137,254,135,144,254,137,1,208,254,48,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,5,49,254,71,254,239,254,71,1,17,254,239,1,185, + 1,17,3,125,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,0,0,0,0,5,0,200,254,20,7,103,7,109,0,35,0,47,0,59, + 0,62,0,70,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39, + 20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,3,33,3,51,1,35,39,33,7,35,4,85,57, + 72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251, + 65,240,2,75,134,1,12,210,154,1,32,132,68,254,182,68,132,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52, + 146,70,12,1,5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,254,172,254,85,2,15,252,188,218,218,0,0,0, + 0,4,0,200,254,20,7,103,7,109,0,35,0,47,0,59,0,84,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21, + 20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52, + 1,33,21,33,53,54,55,0,53,52,38,35,34,6,7,53,62,1,51,50,22,21,20,1,6,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1, + 216,124,49,75,171,63,16,146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,158,1,168,253,170,34,63,1,88, + 104,85,52,122,72,77,133,57,145,174,254,181,56,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1, + 5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,252,63,114,110,31,56,1,49,94,66,81,35,35,123,28,28,132, + 108,139,254,228,48,0,0,0,0,4,0,200,254,20,7,103,7,109,0,35,0,47,0,59,0,100,0,0,5,54,53,6,39,38,39,38,53,52,55,54, + 51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21, + 17,20,35,33,34,53,17,52,1,30,1,21,20,6,35,34,38,39,53,30,1,51,50,54,53,52,38,43,1,53,51,50,54,53,52,38,35,34,6,7, + 53,62,1,51,50,22,21,20,6,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146,25,53,169,73,57,252,201,120, + 120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,154,92,101,190,177,57,125,70,52,119,67,109,120,111,108,86,94,94,97,100,95,40,102,81,73, + 128,55,144,169,90,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1,5,197,251,76,7,241,120,248, + 135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,145,18,109,82,124,134,21,20,121,27,26,79,70,74,76,108,63,60,58,61,18,23,115,17, + 18,118,99,69,96,0,0,0,0,5,0,200,254,20,7,103,7,109,0,35,0,47,0,59,0,62,0,73,0,0,5,54,53,6,39,38,39,38,53,52, + 55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33, + 50,21,17,20,35,33,34,53,17,52,9,1,33,3,51,17,51,21,35,21,35,53,33,53,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216, + 124,49,75,171,63,16,146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,142,254,203,1,53,22,166,135,135,144, + 254,98,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1,5,197,251,76,7,241,120,248,135,120,120, + 7,121,120,120,240,248,135,240,240,7,121,240,254,151,254,93,2,28,253,228,109,186,186,121,0,4,0,200,254,20,7,103,7,109,0,35,0,47,0,59, + 0,92,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23, + 1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,5,33,21,33,21,54,55,54,51,50,23,22,21,20,7,6, + 35,34,38,39,53,22,23,22,51,50,54,52,38,35,34,6,7,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146, + 25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,24,1,254,254,121,28,29,28,28,161,94,94,97,96,176,60,126, + 66,57,62,62,69,111,130,130,111,52,104,54,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1,5, + 197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,95,204,9,4,4,77,76,131,135,75,74,18,18,113,27,14,13, + 102,174,102,20,21,0,0,0,0,5,0,200,254,20,7,103,7,109,0,35,0,47,0,59,0,75,0,107,0,0,5,54,53,6,39,38,39,38,53,52, + 55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33, + 50,21,17,20,35,33,34,53,17,52,1,34,7,6,21,20,23,22,51,50,55,54,53,52,39,38,19,21,38,39,38,35,34,7,6,7,54,55,54,51, + 50,23,22,21,20,7,6,35,34,38,53,52,55,54,51,50,23,22,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16, + 146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,71,88,51,51,51,51,88,87,51,51,51,51,171,49,50,50, + 49,128,68,68,10,38,57,58,68,145,84,84,88,87,145,167,176,108,108,182,49,50,50,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234, + 106,130,19,141,36,52,146,70,12,1,5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,158,52,53,91,90,52, + 53,53,52,90,91,53,52,1,98,103,20,10,11,75,76,153,49,26,26,76,77,132,127,79,78,222,212,198,117,118,8,9,0,4,0,200,254,20,7,103, + 7,109,0,35,0,47,0,59,0,66,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21, + 20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,23,33,21,1,35,1,33,4, + 85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240, + 240,251,65,240,240,2,105,254,164,136,1,72,254,51,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12, + 1,5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,48,252,237,2,228,0,0,0,6,0,200,254,20,7,103, + 7,109,0,35,0,47,0,59,0,72,0,102,0,117,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51, + 50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,0,34,7,6, + 21,20,22,51,50,55,54,52,39,37,38,39,38,53,52,54,32,23,22,21,20,7,6,7,22,23,22,21,20,7,6,35,34,39,38,53,52,55,54,55, + 20,23,22,51,50,55,54,53,52,39,38,34,7,6,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146,25,53,169, + 73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,151,186,53,53,106,93,92,54,53,53,254,236,84,46,47,164,1,30,82,81, + 46,47,83,90,56,53,85,86,158,159,85,86,53,54,45,47,46,85,81,49,48,48,47,166,48,47,252,76,251,195,3,1,12,67,149,52,36,141,19,130, + 106,234,234,106,130,19,141,36,52,146,70,12,1,5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,253,91,44,43, + 75,76,86,44,43,150,43,93,18,49,50,72,100,116,58,58,100,74,48,49,18,18,58,55,80,121,65,65,65,65,121,78,57,56,198,63,38,37,37,36, + 65,63,38,37,37,36,0,0,0,5,0,200,254,20,7,103,7,109,0,35,0,47,0,59,0,91,0,106,0,0,5,54,53,6,39,38,39,38,53,52, + 55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33, + 50,21,17,20,35,33,34,53,17,52,1,53,22,23,22,51,50,55,54,55,6,7,6,35,34,38,53,52,55,54,51,50,23,22,21,20,7,6,35,34, + 39,38,19,50,54,53,52,39,38,35,34,7,6,21,20,23,22,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146, + 25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,46,49,50,50,48,129,68,67,10,35,60,57,69,144,168,87,88, + 145,167,87,88,107,108,182,49,50,50,204,88,102,51,51,88,85,53,52,52,51,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130, + 19,141,36,52,146,70,12,1,5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,251,223,103,20,11,10,75,75,154, + 47,27,26,152,132,129,77,78,111,111,212,198,117,118,8,9,1,114,104,92,90,52,53,53,52,90,92,52,52,0,0,0,0,6,0,200,254,20,7,103, + 7,109,0,35,0,47,0,59,0,73,0,85,0,92,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51, + 50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,0,34,7,6, + 21,20,23,22,50,55,54,53,52,47,1,50,22,21,20,6,35,34,38,53,52,54,1,17,7,53,55,51,17,4,85,57,72,170,53,25,146,16,63,171, + 75,49,124,1,216,124,49,75,171,63,16,146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,234,142,50,51,51, + 50,142,50,51,51,121,131,170,170,131,162,140,140,254,116,133,140,137,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36, + 52,146,70,12,1,5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,254,200,86,86,172,173,86,86,86,86,173,172, + 86,175,222,211,212,222,222,212,211,222,252,172,2,209,41,116,39,252,189,0,0,4,0,200,254,20,7,103,7,109,0,35,0,47,0,59,0,72,0,0, + 5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17, + 20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,5,51,17,20,7,6,43,1,53,51,50,54,53,4,85,57,72,170,53,25, + 146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,1,178, + 127,65,64,143,49,40,84,70,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1,5,197,251,76,7, + 241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,240,253,220,149,70,69,96,84,108,0,0,4,0,200,254,20,7,103,7,109,0,35, + 0,47,0,59,0,85,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7, + 6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,14,1,35,34,38,53,52,54,51,50,22, + 23,21,46,1,35,34,6,21,20,22,51,50,54,55,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146,25,53,169, + 73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,3,60,49,101,57,181,200,201,180,57,102,48,47,106,54,124,124,123,125,55,106, + 46,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1,5,197,251,76,7,241,120,248,135,120,120,7, + 121,120,120,240,248,135,240,240,7,121,240,251,235,23,22,227,206,205,229,23,23,116,34,36,170,172,171,171,36,34,0,0,0,5,0,200,254,20,7,103, + 7,109,0,35,0,47,0,59,0,77,0,87,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38,53,52,32,21,20,7,54,51,50,23, + 22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52,1,34,6,35,34,38, + 53,52,54,51,50,22,21,20,6,7,23,7,18,16,38,35,34,6,16,22,51,50,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49, + 75,171,63,16,146,25,53,169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,2,51,4,17,5,158,155,156,158,159,156,86,88, + 126,95,10,85,97,96,85,85,96,97,252,76,251,195,3,1,12,67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1,5,197,251, + 76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,251,191,1,215,218,219,215,215,219,165,201,40,106,56,1,128,1,112,158,158, + 254,144,158,0,0,4,0,200,254,20,7,103,7,109,0,35,0,47,0,59,0,70,0,0,5,54,53,6,39,38,39,38,53,52,55,54,51,50,23,38, + 53,52,32,21,20,7,54,51,50,23,22,21,20,7,6,7,6,39,20,23,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33, + 34,53,17,52,23,51,17,1,51,9,1,35,1,17,35,4,85,57,72,170,53,25,146,16,63,171,75,49,124,1,216,124,49,75,171,63,16,146,25,53, + 169,73,57,252,201,120,120,4,191,120,120,251,65,4,191,240,240,251,65,240,240,127,1,106,164,254,105,1,184,167,254,120,127,252,76,251,195,3,1,12, + 67,149,52,36,141,19,130,106,234,234,106,130,19,141,36,52,146,70,12,1,5,197,251,76,7,241,120,248,135,120,120,7,121,120,120,240,248,135,240,240, + 7,121,240,240,254,159,1,97,254,122,254,66,1,147,254,109,0,4,0,200,254,20,7,103,7,109,0,9,0,19,0,31,0,43,0,0,1,3,33,5, + 3,37,5,3,37,33,3,19,5,1,19,37,5,19,1,37,1,34,21,17,20,51,33,50,53,17,52,35,37,33,50,21,17,20,35,33,34,53,17,52, + 4,24,100,254,188,1,6,101,1,7,1,5,99,1,5,254,187,98,173,1,178,254,184,96,254,137,254,135,98,254,183,1,179,254,77,120,120,4,191,120, + 120,251,65,4,191,240,240,251,65,240,4,110,254,206,190,254,205,190,190,1,51,190,1,245,254,111,40,254,226,254,84,223,223,1,168,1,34,40,3,85, + 120,248,135,120,120,7,121,120,120,240,248,135,240,240,7,121,240,0,0,0,0,8,0,153,255,106,7,191,7,86,0,7,0,17,0,25,0,35,0,43, + 0,51,0,127,0,183,0,0,0,52,54,50,22,20,6,34,55,34,6,21,20,51,50,54,53,52,36,20,6,34,38,52,54,50,23,34,6,21,20,51, + 50,54,53,52,0,52,54,50,22,20,6,34,54,20,6,34,38,52,54,50,6,50,62,3,55,19,23,7,62,4,53,52,38,39,38,39,62,1,53,52, + 38,35,34,14,1,21,20,23,7,38,53,52,55,38,34,7,22,21,20,7,39,54,53,52,46,1,35,34,6,21,20,22,23,6,7,14,1,21,20,30, + 3,23,39,55,19,30,3,18,50,23,62,1,51,50,22,21,20,7,22,21,20,14,2,7,5,7,37,7,6,7,5,7,37,14,1,34,38,39,5,39, + 37,38,47,1,5,39,37,46,3,53,52,55,38,53,52,54,51,50,22,23,2,230,66,92,66,66,92,116,17,45,13,17,46,1,175,66,92,66,66,92, + 23,17,44,13,17,45,254,111,22,32,22,22,32,236,22,32,22,22,32,161,108,78,46,27,9,2,16,134,12,59,113,115,86,54,67,55,48,65,73,98, + 98,79,83,130,67,18,130,23,1,42,168,42,1,23,130,18,67,130,83,79,98,98,73,65,48,55,67,54,86,115,113,59,12,134,16,2,9,27,46,56, + 152,76,43,202,143,139,173,93,156,75,131,152,89,1,159,4,253,236,1,2,4,1,251,22,254,13,32,169,250,169,32,254,13,22,1,251,4,2,1,253, + 236,4,1,159,89,152,131,75,156,93,173,139,143,202,43,3,56,144,103,103,144,103,130,61,24,18,62,24,17,117,144,103,103,144,103,220,61,24,18,62, + 24,17,253,34,54,39,39,54,39,93,54,39,39,54,39,224,36,57,93,87,62,1,58,6,251,31,76,107,116,147,76,74,152,55,51,40,35,131,88,81, + 105,107,164,92,66,63,38,83,84,27,14,3,3,14,27,84,83,38,63,66,92,164,107,105,81,88,131,35,40,51,55,152,74,76,147,116,107,76,31,251, + 6,254,198,62,87,93,57,6,2,6,134,190,183,140,138,114,172,200,108,200,161,126,51,26,68,35,1,31,31,174,64,172,109,138,138,109,172,64,174,31, + 31,1,35,68,26,51,126,161,200,108,200,172,114,138,140,183,190,134,0,0,0,11,0,75,255,106,9,45,6,138,0,9,0,20,0,24,0,34,0,40, + 0,44,0,142,0,153,0,159,0,253,1,7,0,0,1,34,38,52,54,51,50,22,20,6,39,50,54,53,52,35,34,7,6,21,20,23,51,21,35,1, + 34,38,52,54,51,50,22,20,6,1,55,23,7,39,55,1,21,35,53,37,23,6,7,6,21,20,23,30,1,51,50,55,54,55,54,53,52,39,38,39, + 55,22,23,62,4,55,22,51,50,62,4,55,62,1,53,52,39,46,4,35,34,14,2,15,1,6,7,38,36,32,4,7,38,47,1,46,3,35,34,14, + 3,7,6,21,20,22,23,30,5,51,50,55,30,4,23,54,37,50,54,53,52,35,34,7,6,21,20,1,7,23,7,39,55,1,52,55,39,38,39,35, + 34,46,6,39,46,1,53,52,62,1,55,62,1,51,50,30,2,23,22,31,1,54,55,54,32,23,22,23,55,54,55,62,3,51,50,22,23,30,2,21, + 20,6,7,14,7,43,1,6,15,1,22,21,20,7,6,7,6,7,6,7,14,1,34,38,39,38,39,38,39,38,39,38,1,6,32,39,22,23,22,51, + 50,54,3,121,50,62,61,51,50,62,61,30,18,45,14,17,23,22,53,110,110,2,73,51,61,62,50,51,61,62,251,83,51,197,57,63,42,3,148,110, + 253,210,66,63,17,5,57,52,177,139,105,69,128,66,57,5,17,63,66,24,18,5,30,13,20,10,1,82,39,32,56,37,47,22,54,12,49,46,52,2, + 38,30,43,43,18,17,32,35,16,19,19,63,89,61,254,247,254,190,254,247,61,89,63,19,19,16,35,32,17,18,43,43,30,38,2,52,46,49,12,54, + 22,47,37,56,32,39,82,1,10,20,13,30,5,18,3,6,18,45,14,17,23,22,1,237,170,42,63,57,197,250,203,13,21,57,16,10,33,59,43,53, + 27,55,19,63,10,66,58,41,44,35,51,135,65,29,51,50,25,23,37,17,65,40,55,164,1,164,164,55,40,65,17,37,23,25,50,51,29,65,135,51, + 35,44,41,58,66,10,63,19,55,27,53,43,59,33,10,16,57,21,13,13,34,96,9,22,32,66,54,136,196,136,54,66,32,22,9,95,35,13,3,52, + 97,254,186,97,17,31,55,157,107,126,2,209,110,130,110,110,130,110,27,65,21,17,31,29,25,18,212,210,1,139,110,130,110,110,130,110,2,181,45,218, + 186,24,148,253,77,210,210,147,118,36,68,17,25,75,59,55,34,8,13,68,59,75,25,17,68,36,118,13,15,19,104,53,87,77,39,20,11,12,32,17, + 49,10,42,76,55,46,52,2,40,26,35,19,14,34,17,25,25,78,131,101,109,109,101,131,78,25,25,17,34,14,19,35,26,40,2,52,46,55,76,42, + 10,49,17,32,12,11,20,39,77,87,53,104,19,15,78,65,21,17,31,29,25,18,2,154,187,148,24,186,218,251,239,42,44,80,221,73,9,8,27,13, + 44,15,57,9,58,107,82,52,95,53,34,50,83,18,39,24,25,39,21,82,29,27,78,78,27,29,82,21,39,25,24,39,18,83,50,34,53,95,52,82, + 107,58,9,57,15,44,13,27,8,9,73,221,80,44,42,48,40,115,66,68,48,72,46,38,27,27,38,46,72,48,68,66,115,40,254,224,22,22,36,21, + 39,38,0,0,0,8,0,61,255,106,8,29,7,20,0,17,0,25,0,40,0,50,0,65,0,78,0,127,0,184,0,0,1,55,22,51,50,55,22,51, + 50,55,23,6,35,34,39,6,35,34,1,23,6,34,39,55,22,50,1,6,7,6,35,34,39,38,53,52,55,54,51,50,22,7,34,6,21,20,23,62, + 1,55,38,5,62,1,51,50,23,22,21,20,7,6,35,34,39,38,23,22,51,50,55,54,53,52,39,38,35,34,6,5,54,53,52,46,2,39,38,39, + 6,7,38,35,34,7,38,39,6,7,14,3,21,20,23,37,23,5,22,23,37,23,5,22,23,22,32,55,54,55,37,55,5,54,55,37,55,5,38,53, + 52,62,3,55,54,63,1,23,30,1,23,54,50,23,62,1,63,1,23,22,23,30,4,21,20,7,23,7,39,6,7,23,7,39,2,7,6,33,32,39, + 38,3,7,39,55,38,39,7,39,2,166,92,69,91,58,84,84,58,91,69,92,108,144,74,68,69,73,144,1,184,62,122,194,122,62,90,134,254,252,43, + 81,32,40,70,54,21,53,47,65,70,101,78,36,48,5,43,69,18,22,1,184,5,100,70,66,47,53,21,54,70,40,32,81,121,12,26,48,40,16,4, + 12,13,44,64,1,147,18,10,10,22,4,27,42,243,153,116,155,157,116,153,243,42,27,5,21,11,10,18,1,66,10,254,191,14,23,1,30,26,254,225, + 103,164,181,1,234,181,164,103,254,225,26,1,30,21,15,254,192,10,250,192,17,7,19,12,31,5,23,38,15,60,143,253,93,105,226,105,93,253,143,59, + 16,38,23,5,31,12,19,7,17,108,10,109,15,32,110,26,109,117,195,217,254,224,254,223,217,193,118,109,26,109,30,16,109,10,1,140,98,64,44,44, + 64,98,100,28,28,1,168,120,61,61,120,46,1,6,76,28,11,35,36,45,71,48,44,97,38,48,36,14,15,7,52,37,17,29,67,97,44,48,71,45, + 36,35,11,28,4,3,22,24,28,14,12,3,59,167,130,116,46,102,62,118,25,161,167,58,196,21,21,196,58,167,161,27,114,65,101,46,116,130,43,66, + 44,69,64,121,62,122,231,119,132,132,119,231,122,62,121,57,76,44,66,61,124,143,57,106,119,65,147,24,117,140,58,9,22,137,97,13,13,97,137,22, + 9,58,140,117,24,147,65,119,106,57,143,124,15,66,14,81,87,46,62,46,254,247,142,158,158,140,1,11,46,62,46,81,87,14,66,0,0,11,0,170, + 255,106,8,150,7,11,0,7,0,17,0,29,0,37,0,49,0,59,0,71,0,104,0,152,0,170,0,188,0,0,0,52,54,50,22,20,6,34,55,34, + 6,21,20,51,50,54,53,52,3,34,53,52,55,54,51,50,21,20,7,6,0,20,6,34,38,52,54,50,1,52,51,50,23,22,21,20,35,34,39,38, + 1,34,6,21,20,51,50,54,53,52,1,55,22,51,50,54,55,23,6,33,34,38,18,32,55,54,53,52,39,62,2,53,52,39,38,35,34,6,7,46, + 1,35,34,7,6,21,20,30,1,23,6,21,20,23,18,32,4,23,22,23,54,51,50,22,21,20,7,6,7,14,1,43,1,6,7,14,1,7,6,32, + 39,46,1,39,38,39,35,34,38,39,38,39,38,53,52,54,51,50,23,54,55,54,3,38,35,34,7,14,1,21,20,23,22,23,22,59,1,54,55,38, + 37,6,7,22,23,51,50,55,54,55,54,53,52,38,39,38,35,34,3,25,82,116,82,82,116,145,22,55,16,22,56,16,24,44,37,30,24,44,37,2, + 13,82,116,82,82,116,254,255,24,31,37,44,24,31,37,44,1,30,22,55,16,22,56,252,227,106,130,206,96,180,59,106,168,254,238,128,234,138,1,192, + 165,124,84,30,29,31,86,90,130,71,113,31,28,112,71,130,90,86,31,29,30,84,124,208,1,106,1,55,97,105,16,25,29,106,144,8,13,28,34,134, + 89,7,15,58,56,171,109,148,254,224,148,109,171,56,58,15,7,89,134,34,28,13,8,144,106,29,25,16,105,97,214,24,32,13,21,40,43,7,23,71, + 31,38,4,8,60,53,5,116,16,53,60,8,4,38,31,71,23,7,43,40,21,13,32,4,8,116,82,82,116,82,104,49,19,14,49,19,14,254,82,21, + 32,36,31,21,32,36,31,2,12,116,82,82,116,82,254,5,21,31,36,32,21,31,36,1,107,49,19,14,49,19,14,253,168,84,164,88,76,84,214,114, + 254,222,203,154,184,134,149,44,48,94,49,138,105,111,69,53,53,69,111,105,138,49,94,48,44,149,134,184,154,6,0,164,124,136,155,6,164,135,44,54, + 91,63,75,105,123,112,110,173,55,76,76,55,173,110,112,123,105,75,63,91,54,44,135,164,6,155,136,124,253,204,21,7,15,82,58,30,51,151,47,21, + 135,123,87,96,96,87,123,135,21,47,151,51,30,58,82,15,7,0,0,0,0,9,0,170,255,106,7,173,6,110,0,11,0,22,0,34,0,46,0,52, + 0,57,0,62,0,66,0,70,0,0,1,52,54,51,50,22,21,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17, + 16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,1,33,16,0,32,0,5,54,55,17,35,3,17,35,17,22,37,54,55,35,5,53,35, + 22,2,130,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,252,109,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,135,2, + 14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,1,20,4,219,254,149,253,252,254,148,2,178,88,76,164,136,164,76,2,12,72,28,100,253,32, + 101,28,3,255,59,81,81,59,58,83,83,58,59,81,81,59,58,83,83,219,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15, + 253,241,254,139,254,140,253,244,2,12,1,106,254,254,254,150,1,106,223,11,42,1,37,254,166,1,90,254,219,42,153,82,100,184,184,102,0,9,0,170, + 255,106,7,173,6,110,0,11,0,23,0,35,0,47,0,53,0,58,0,63,0,67,0,71,0,0,1,16,0,33,32,0,17,16,0,33,32,0,3,16, + 0,33,32,0,17,16,0,33,32,0,1,52,54,50,22,21,35,52,38,34,6,21,33,52,54,50,22,21,35,52,38,34,6,21,7,33,16,0,32,0, + 5,54,55,17,35,3,17,35,17,22,37,54,55,35,5,53,35,22,1,49,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1, + 116,1,117,2,12,253,244,254,139,254,140,253,242,3,188,140,196,140,135,61,84,61,253,41,140,196,140,135,61,84,61,223,4,219,254,149,253,252,254,148, + 2,178,88,76,164,136,164,76,2,12,72,28,100,253,32,101,28,2,234,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253, + 241,254,139,254,140,253,244,2,12,2,22,139,197,197,139,83,119,119,83,139,197,197,139,83,119,119,83,172,254,254,254,150,1,106,223,11,42,1,37,254, + 166,1,90,254,219,42,153,82,100,184,184,102,0,9,0,95,255,106,8,249,6,110,0,3,0,7,0,12,0,17,0,23,0,35,0,47,0,89,0,126, + 0,0,1,53,35,22,5,54,55,35,1,17,35,17,22,23,54,55,17,35,37,33,16,0,32,0,19,52,54,50,22,21,35,52,38,34,6,21,33,52, + 54,50,22,21,35,52,38,34,6,21,5,16,0,33,32,0,17,20,7,23,22,23,22,21,20,6,34,39,38,47,1,2,7,0,33,32,1,38,3,7, + 6,7,6,34,38,53,52,55,54,63,1,38,55,16,0,33,32,0,17,52,39,6,35,34,39,38,47,1,23,22,23,38,39,38,33,32,7,6,7,54, + 63,1,7,6,7,6,34,39,6,3,60,101,28,3,41,72,28,100,254,76,164,76,224,88,76,164,253,78,4,219,254,149,253,252,254,148,88,140,196,140, + 135,61,84,61,1,201,140,196,140,135,61,84,61,251,189,2,14,1,116,1,117,2,12,2,93,59,24,30,54,76,31,25,18,11,42,209,254,250,254,139, + 254,140,254,249,209,43,10,18,25,31,76,54,30,23,60,92,2,135,1,191,1,60,1,61,1,189,1,27,37,38,31,25,18,45,136,41,24,47,154,222, + 254,194,254,196,224,154,47,24,41,136,45,18,25,31,76,27,1,1,161,184,102,80,82,100,254,166,1,90,254,219,42,11,11,42,1,37,135,254,254,254, + 150,1,106,1,174,139,197,197,139,83,119,119,83,139,197,197,139,83,119,119,83,162,1,117,2,15,253,241,254,139,29,27,31,20,24,31,37,38,54,31, + 25,57,32,254,233,209,254,250,1,6,208,1,22,30,57,25,31,54,38,37,31,25,19,30,28,29,254,196,254,67,1,189,1,60,20,19,26,31,25,57, + 136,45,14,15,199,154,224,224,155,198,16,13,45,136,57,25,31,27,20,0,0,6,0,170,255,106,7,173,6,110,0,11,0,22,0,34,0,46,0,52, + 0,60,0,0,1,52,54,51,50,22,21,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19, + 16,0,33,32,0,17,16,0,33,32,0,19,33,16,0,32,0,37,33,22,23,22,36,55,54,2,130,81,59,58,82,82,58,59,81,2,66,82,116,83, + 83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,141, + 4,219,254,149,253,252,254,148,4,66,252,87,33,92,142,1,148,142,92,3,255,59,81,81,59,58,83,83,58,59,81,81,59,58,83,83,219,1,117,2, + 15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,185,254,254,254,150,1,106,123,117,92,142,1, + 142,92,0,0,0,6,0,170,255,106,7,173,6,110,0,11,0,23,0,35,0,47,0,53,0,62,0,0,1,52,54,50,22,21,35,52,38,34,6,21, + 33,52,54,50,22,21,35,52,38,34,6,21,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,33,16,0, + 32,0,37,33,22,23,22,55,50,55,54,2,22,140,196,140,135,61,84,61,1,201,140,196,140,135,61,84,61,251,189,2,14,1,116,1,117,2,12,253, + 244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,141,4,219,254,149,253,252,254,148,4,66,252,87,33,92,142, + 202,202,142,92,3,140,139,197,197,139,83,119,119,83,139,197,197,139,83,119,119,83,162,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254, + 196,254,67,1,189,1,60,1,61,1,192,254,64,254,185,254,254,254,150,1,106,123,117,92,142,1,142,92,0,7,0,170,255,106,7,173,6,110,0,11, + 0,23,0,35,0,47,0,59,0,65,0,74,0,0,1,23,22,7,6,7,6,34,38,53,52,55,5,52,54,50,22,21,35,52,38,34,6,21,33,52, + 54,50,22,21,35,52,38,34,6,21,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,33,16,0,32,0, + 37,33,22,23,22,55,50,55,54,6,168,65,28,1,1,26,27,76,54,27,251,175,140,196,140,135,61,84,61,1,201,140,196,140,135,61,84,61,251,189, + 2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,141,4,219,254,149,253,252, + 254,148,4,66,252,87,33,92,142,202,202,142,92,4,44,128,56,34,43,26,27,54,44,35,53,32,139,197,197,139,83,119,119,83,139,197,197,139,83,119, + 119,83,162,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,185,254,254,254,150,1, + 106,123,117,92,142,1,142,92,0,6,0,170,255,106,7,173,6,110,0,6,0,13,0,25,0,37,0,43,0,51,0,0,1,37,23,7,23,7,37,39, + 21,5,39,55,39,55,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,33,16,0,32,0,37,33,22,23, + 22,36,55,54,4,124,1,39,77,198,198,77,254,217,160,254,217,77,198,198,77,253,245,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135, + 1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,141,4,219,254,149,253,252,254,148,4,66,252,87,33,92,142,1,148,142,92,4,39,206,110, + 139,138,110,206,85,85,206,110,138,139,110,253,245,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1, + 192,254,64,254,185,254,254,254,150,1,106,123,117,92,142,1,142,92,0,0,0,7,0,143,255,106,7,200,7,99,0,15,0,31,0,42,0,53,0,73, + 0,87,0,95,0,0,1,55,22,23,22,4,55,54,55,23,6,7,6,32,39,38,1,16,0,33,32,0,17,16,47,1,6,33,32,39,7,6,5,52, + 54,50,22,21,20,6,35,34,38,37,52,54,51,50,22,20,6,35,34,38,1,52,36,33,32,4,21,20,7,22,17,16,0,33,32,0,17,16,55,38, + 37,54,53,52,36,33,32,4,21,20,23,54,33,32,23,38,35,34,7,22,51,50,2,29,115,28,40,143,1,147,142,39,29,115,37,50,182,253,252,182, + 50,254,239,1,191,1,60,1,61,1,189,222,14,229,254,215,254,216,230,14,224,3,148,82,116,83,83,58,59,81,253,190,81,59,58,82,82,58,59,81, + 254,13,2,30,1,127,1,128,2,28,253,226,253,244,254,139,254,140,253,242,227,254,5,219,188,254,67,254,195,254,196,254,65,189,244,1,74,1,75,67, + 176,222,221,176,176,221,222,1,209,71,44,38,141,1,142,39,44,72,57,50,181,181,51,1,81,254,196,254,67,1,189,1,60,1,61,224,14,57,57,14, + 224,42,59,81,81,59,58,83,83,58,59,81,81,118,82,83,2,92,134,190,190,134,130,92,252,254,165,254,140,253,244,2,12,1,116,1,91,252,92,2, + 54,74,81,114,114,81,74,54,207,245,110,110,28,0,0,0,0,7,0,170,255,106,7,173,7,48,0,3,0,14,0,25,0,29,0,45,0,57,0,74, + 0,0,1,5,7,37,1,52,54,50,22,21,20,6,35,34,38,37,52,54,51,50,22,20,6,35,34,38,1,23,5,39,1,55,22,23,22,32,55,54, + 55,23,6,7,6,32,39,38,1,16,0,33,32,0,17,16,0,33,32,0,1,54,32,23,37,17,22,17,16,0,33,32,0,17,16,55,17,2,210,1, + 47,77,254,209,2,63,82,116,83,83,58,59,81,253,190,81,59,58,82,82,58,59,81,3,4,77,254,209,77,253,198,115,28,40,142,1,148,142,39,29, + 115,37,50,182,253,252,182,50,254,239,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,1,226,132,1,42,132,1,187,173,253,244,254,139,254, + 140,253,242,174,5,103,212,111,213,254,188,59,81,81,59,58,83,83,58,59,81,81,118,82,83,1,236,110,213,111,253,62,71,44,38,142,142,39,44,72, + 57,50,181,181,51,1,81,254,196,254,67,1,189,1,60,1,61,1,192,254,64,2,29,42,42,236,253,208,231,254,209,254,140,253,244,2,12,1,116,1, + 47,231,2,48,0,5,0,170,255,106,7,173,6,110,0,15,0,27,0,39,0,50,0,57,0,0,1,55,22,23,22,32,55,54,55,23,6,7,6,32, + 39,38,1,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,1,52,54,51,50,22,20,6,35,34,38,45,1,23, + 7,23,7,37,2,29,115,28,40,142,1,148,142,39,29,115,37,50,182,253,252,182,50,254,239,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254, + 65,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,1,216,81,59,58,82,82,58,59,81,1,250,1,39,77,198,198,77,254,217,1,209, + 71,44,38,142,142,39,44,72,57,50,181,181,51,1,81,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254,139,254, + 140,253,244,2,12,2,135,59,81,81,118,82,83,100,206,110,139,138,110,206,0,5,0,170,255,106,7,173,6,110,0,15,0,27,0,39,0,51,0,63, + 0,0,1,55,22,23,22,32,55,54,55,23,6,7,6,32,39,38,3,52,54,50,22,21,35,52,38,34,6,21,33,52,54,50,22,21,35,52,38,34, + 6,21,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,2,29,115,28,40,142,1,148,142,39,29,115,37,50, + 182,253,252,182,50,44,140,196,140,135,61,84,61,1,201,140,196,140,135,61,84,61,251,189,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242, + 135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,1,209,71,44,38,142,142,39,44,72,57,50,181,181,51,1,243,139,197,197,139,83,119, + 119,83,139,197,197,139,83,119,119,83,162,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254, + 64,0,0,0,0,5,0,170,255,106,7,173,6,110,0,11,0,23,0,55,0,67,0,81,0,0,1,52,54,50,22,21,35,52,38,34,6,21,33,52, + 54,50,22,21,35,52,38,34,6,21,5,16,0,33,50,55,38,39,6,35,32,0,17,51,20,0,32,0,53,51,20,7,22,29,1,54,17,16,0,33, + 32,0,3,16,0,33,32,0,17,16,0,33,32,0,5,6,7,22,23,22,51,50,55,54,55,52,39,38,4,102,140,196,140,135,61,84,61,253,41,140, + 196,140,135,61,84,61,254,148,1,191,1,60,136,118,101,65,43,45,254,254,254,148,135,1,29,1,148,1,28,135,123,55,209,254,67,254,195,254,196,254, + 65,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,5,16,79,92,31,38,36,27,16,13,33,1,1,2,3,140,139,197,197,139,83,119, + 119,83,139,197,197,139,83,119,119,83,162,254,196,254,67,41,48,108,5,1,106,1,2,202,254,229,1,28,201,213,160,100,99,4,218,1,51,1,61,1, + 192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,54,67,36,40,24,23,8,19,57,5,6,46,0,0,5,0,170,255,106,7,173, + 6,110,0,15,0,27,0,39,0,51,0,63,0,0,1,55,22,23,22,32,55,54,55,23,6,7,6,32,39,38,1,20,6,34,38,53,51,20,22,50, + 54,53,33,20,6,34,38,53,51,20,22,50,54,53,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,2,29, + 115,28,40,142,1,148,142,39,29,115,37,50,182,253,252,182,50,4,0,140,196,140,135,61,84,61,254,55,140,196,140,135,61,84,61,253,63,2,14,1, + 116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,1,209,71,44,38,142,142,39,44,72, + 57,50,181,181,51,2,239,139,197,197,139,83,119,119,83,139,197,197,139,83,119,119,83,254,98,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1, + 116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,5,0,170,255,106,7,173,6,110,0,23,0,47,0,59,0,71,0,87,0,0,1,50, + 23,22,21,6,15,1,35,39,38,53,38,55,54,51,22,23,22,23,51,52,55,54,33,50,23,22,21,51,54,55,54,55,50,23,22,7,20,15,1,35, + 39,38,39,52,55,54,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,55,22,23,22,32,55,54,55,23, + 6,7,6,32,39,38,5,166,26,25,60,1,50,168,2,159,62,1,10,38,63,41,32,28,10,1,13,35,253,73,61,35,13,1,10,28,32,41,63,38, + 10,1,62,159,2,168,50,1,60,25,254,18,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254, + 195,254,196,254,65,236,115,28,40,142,1,148,142,39,29,115,37,50,182,253,252,182,50,4,192,14,37,63,65,62,207,190,68,76,21,25,68,1,32,32, + 49,14,29,71,71,29,14,49,32,32,1,68,25,21,76,68,190,207,62,65,63,37,14,254,42,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1, + 116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,253,170,71,44,38,142,142,39,44,72,57,50,181,181,51,0,0,0,4,0,170,255,106,7,173, + 6,110,0,23,0,35,0,51,0,60,0,0,1,16,0,33,32,0,17,52,39,35,21,20,6,34,38,53,20,6,34,38,61,1,35,6,7,16,0,33, + 32,0,17,16,0,33,32,0,37,55,22,23,22,4,55,54,55,23,6,7,6,32,39,38,3,33,38,39,38,33,32,7,6,1,49,1,191,1,60,1, + 61,1,189,84,110,166,236,166,166,236,166,110,85,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,1,115,115,28,40,143,1,147,142,39, + 29,115,37,50,182,253,252,182,50,96,4,148,22,24,222,254,194,254,196,224,24,2,234,254,196,254,67,1,189,1,60,195,160,79,100,142,142,100,100,142, + 142,100,79,160,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,91,71,44,38,141,1,142,39,44,72,57,50,181,181,51,3,59,26,25,224,224, + 25,0,0,0,0,5,0,170,255,106,7,173,6,110,0,3,0,7,0,17,0,29,0,41,0,0,1,53,33,21,33,53,33,21,19,50,55,54,55,23, + 6,7,6,33,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,4,152,1,170,251,212,1,170,108,202,142,39, + 29,115,37,50,182,254,254,252,126,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196, + 254,65,3,140,135,135,135,135,253,172,142,39,44,72,57,50,181,2,57,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1, + 189,1,60,1,61,1,192,254,64,0,0,0,0,5,0,170,255,106,7,173,6,110,0,3,0,14,0,25,0,37,0,49,0,0,1,53,33,21,1,52, + 54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16, + 0,33,32,0,2,76,3,192,252,118,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254, + 139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,1,113,135,135,2,140,59,81,81,118,82,83,58,59,81,81,59,58, + 83,83,217,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,0,0,5,0,170, + 255,106,7,173,6,110,0,3,0,7,0,11,0,23,0,35,0,0,1,53,33,21,33,53,33,21,1,53,33,21,1,16,0,33,32,0,17,16,0,33, + 32,0,19,16,0,33,32,0,17,16,0,33,32,0,4,152,1,170,251,212,1,170,254,140,3,192,250,158,2,14,1,116,1,117,2,12,253,244,254,139, + 254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,3,140,135,135,135,135,253,229,135,135,1,121,1,117,2,15,253,241,254, + 139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,5,0,170,255,106,7,173,6,110,0,11,0,23,0,27, + 0,41,0,55,0,0,1,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,5,53,33,21,1,53,33,50,22,21, + 20,6,35,34,38,53,52,53,33,53,33,50,22,21,20,6,35,34,38,53,52,53,1,49,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65, + 135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,1,162,3,192,252,2,1,120,58,82,82,58,59,81,1,86,1,120,58,83,83,58,59, + 81,2,234,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,5,135,135,2,45,135,81, + 59,58,83,83,58,3,2,135,81,59,58,83,83,58,3,2,0,8,0,170,255,106,7,173,6,110,0,8,0,12,0,16,0,20,0,31,0,42,0,54, + 0,66,0,0,1,23,22,20,6,34,38,52,55,1,53,33,21,19,37,55,13,1,39,37,23,1,52,54,51,50,22,20,6,35,34,38,37,52,54,50, + 22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,6,80,65,27,54,76,54,27,252, + 61,3,192,11,254,168,77,1,88,251,221,77,1,88,77,254,233,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116, + 1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,3,172,128,53,79,54,54,79,53,254,69, + 135,135,2,165,240,111,241,110,110,241,111,254,175,59,81,81,118,82,83,58,59,81,81,59,58,83,83,145,1,117,2,15,253,241,254,139,254,140,253,244, + 2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,0,5,0,170,255,106,7,173,6,110,0,3,0,15,0,27,0,39,0,51, + 0,0,1,53,33,21,19,20,6,34,38,53,51,20,22,50,54,53,33,20,6,34,38,53,51,20,22,50,54,53,1,16,0,33,32,0,17,16,0,33, + 32,0,19,16,0,33,32,0,17,16,0,33,32,0,2,76,3,192,54,140,196,140,135,61,84,61,254,55,140,196,140,135,61,84,61,253,63,2,14,1, + 116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,1,113,135,135,3,23,139,197,197,139, + 83,119,119,83,139,197,197,139,83,119,119,83,254,98,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61, + 1,192,254,64,0,5,0,170,255,106,7,173,6,110,0,3,0,14,0,25,0,37,0,49,0,0,37,39,1,23,1,52,54,51,50,22,20,6,35,34, + 38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,2,149,57,3, + 103,57,252,134,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135, + 1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,172,123,1,150,123,1,187,59,81,81,118,82,83,58,59,81,81,59,58,83,83,217,1,117, + 2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,5,0,170,255,106,7,173,6,110,0,3, + 0,15,0,27,0,31,0,66,0,0,1,39,1,23,1,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,9,1, + 55,1,3,34,7,6,7,14,1,39,38,39,38,35,34,7,39,54,55,54,50,23,22,23,22,51,50,55,54,55,54,50,23,22,23,7,38,2,201,95, + 1,14,95,253,90,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,4,229, + 254,242,95,1,14,154,52,41,11,24,70,196,70,28,12,34,53,56,32,121,16,25,70,196,70,28,12,34,53,52,40,12,24,70,196,70,24,16,121,31, + 3,92,95,1,14,95,254,128,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,230, + 1,14,95,254,242,254,87,105,29,34,98,1,99,40,33,95,95,57,40,34,98,98,40,34,95,105,30,34,98,98,34,40,57,95,0,0,0,5,0,170, + 255,106,7,173,6,110,0,11,0,22,0,35,0,47,0,59,0,0,1,52,54,51,50,22,21,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34, + 38,3,55,39,55,5,21,7,23,21,5,39,55,39,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,2,130, + 81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,206,80,144,65,1,3,60,60,254,253,65,144,80,252,180,2,14,1,116,1,117,2,12, + 253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,3,255,59,81,81,59,58,83,83,58,59,81,81,59,58, + 83,83,254,36,62,78,118,141,88,46,46,88,141,118,78,62,1,35,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189, + 1,60,1,61,1,192,254,64,0,6,0,170,255,106,7,173,6,110,0,23,0,34,0,41,0,54,0,66,0,78,0,0,1,50,23,22,21,6,15,1, + 35,39,38,53,38,55,54,51,22,23,22,23,51,52,55,54,1,52,54,51,50,22,20,6,35,34,38,45,1,23,7,23,7,37,3,55,39,55,5,21, + 7,23,21,5,39,55,39,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,6,106,26,26,60,2,50,168,2, + 158,62,2,10,38,64,40,32,28,10,2,12,34,252,86,81,59,58,82,82,58,59,81,1,250,1,39,77,198,198,77,254,217,134,80,144,65,1,3,60, + 60,254,253,65,144,80,252,180,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254, + 65,2,175,14,37,63,65,62,207,190,68,76,21,25,68,1,32,32,49,14,29,71,1,78,59,81,81,118,82,83,100,206,110,139,138,110,206,254,23,62, + 78,118,141,88,46,46,88,141,118,78,62,1,35,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1, + 192,254,64,0,0,5,0,170,255,106,7,173,6,110,0,11,0,23,0,36,0,48,0,60,0,0,1,52,54,50,22,21,35,52,38,34,6,21,33,52, + 54,50,22,21,35,52,38,34,6,21,3,55,39,55,5,21,7,23,21,5,39,55,39,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32, + 0,17,16,0,33,32,0,2,22,140,196,140,135,61,84,61,1,201,140,196,140,135,61,84,61,247,80,144,65,1,3,60,60,254,253,65,144,80,252,180, + 2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,3,140,139,197,197,139,83, + 119,119,83,139,197,197,139,83,119,119,83,254,93,62,78,118,141,88,46,46,88,141,118,78,62,1,35,1,117,2,15,253,241,254,139,254,140,253,244,2, + 12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,0,0,5,0,170,255,106,7,173,6,110,0,12,0,24,0,36,0,48,0,60, + 0,0,1,55,39,55,5,21,7,23,21,5,39,55,39,1,20,6,34,38,53,51,20,22,50,54,53,33,20,6,34,38,53,51,20,22,50,54,53,1, + 16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,3,246,80,144,65,1,3,60,60,254,253,65,144,80,2,76,140, + 196,140,135,61,84,61,254,55,140,196,140,135,61,84,61,253,63,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61, + 1,189,254,67,254,195,254,196,254,65,1,233,62,78,118,141,88,46,46,88,141,118,78,62,2,193,139,197,197,139,83,119,119,83,139,197,197,139,83,119, + 119,83,254,98,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,0,6,0,170, + 255,106,7,173,6,110,0,11,0,22,0,34,0,46,0,56,0,62,0,0,1,52,54,51,50,22,21,20,6,35,34,38,37,52,54,50,22,21,20,6, + 35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,37,53,33,21,35,20,6,34,38,53,33,35,20, + 22,50,54,2,130,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,252,109,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65, + 135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,1,162,3,192,242,140,196,140,1,85,206,61,84,61,3,255,59,81,81,59,58,83,83, + 58,59,81,81,59,58,83,83,219,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,99, + 135,135,139,197,197,139,83,119,119,0,0,0,0,6,0,170,255,106,7,173,6,110,0,10,0,17,0,29,0,41,0,51,0,57,0,0,1,52,54,51, + 50,22,20,6,35,34,38,45,1,23,7,23,7,37,5,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,37,53, + 33,21,35,20,6,34,38,53,33,35,20,22,50,54,2,130,81,59,58,82,82,58,59,81,1,250,1,39,77,198,198,77,254,217,252,181,1,191,1,60, + 1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,1,162,3,192,242,140,196,140,1,85,206, + 61,84,61,3,253,59,81,81,118,82,83,100,206,110,139,138,110,206,232,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253, + 241,254,139,254,140,253,244,2,12,99,135,135,139,197,197,139,83,119,119,0,0,6,0,170,255,106,7,173,6,110,0,11,0,23,0,30,0,37,0,47, + 0,53,0,0,1,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,1,21,5,39,55,39,55,5,37,23,7,23, + 7,37,1,53,33,21,35,20,6,34,38,53,33,35,20,22,50,54,1,49,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1, + 116,1,117,2,12,253,244,254,139,254,140,253,242,3,50,254,217,77,198,198,77,1,199,1,39,77,198,198,77,254,217,253,208,3,192,242,140,196,140,1, + 85,206,61,84,61,2,234,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,2,177,85, + 206,110,138,139,110,206,206,110,139,138,110,206,254,7,135,135,139,197,197,139,83,119,119,0,0,7,0,170,255,106,7,173,6,110,0,3,0,7,0,18, + 0,29,0,41,0,53,0,70,0,0,1,37,55,13,1,39,37,23,1,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38, + 5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,54,55,54,32,23,22,23,7,38,39,38,35,38,7,6, + 7,6,23,254,168,77,1,88,251,221,77,1,88,77,254,233,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116,1, + 117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,236,37,50,182,2,4,182,51,36,115,28,40, + 142,202,202,142,39,29,4,22,240,111,241,110,110,241,111,254,175,59,81,81,118,82,83,58,59,81,81,59,58,83,83,145,1,117,2,15,253,241,254,139, + 254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,253,37,56,51,181,181,51,56,72,44,39,142,1,142,39,44,0,0, + 0,8,0,170,255,106,7,173,6,110,0,15,0,19,0,23,0,34,0,45,0,57,0,69,0,86,0,0,37,39,54,55,54,50,23,22,23,7,38,39, + 38,34,7,6,1,37,55,13,1,39,37,23,1,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0, + 17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,54,55,54,32,23,22,23,7,38,39,38,35,38,7,6,7,3,213,121,16,24, + 70,196,70,24,16,121,7,8,30,84,30,8,2,59,254,168,77,1,88,251,221,77,1,88,77,254,233,81,59,58,82,82,58,59,81,2,66,82,116,83, + 83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,236, + 37,50,182,2,4,182,51,36,115,28,40,142,202,202,142,39,29,159,57,40,34,98,98,34,40,57,19,16,60,60,16,3,100,240,111,241,110,110,241,111, + 254,175,59,81,81,118,82,83,58,59,81,81,59,58,83,83,145,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1, + 60,1,61,1,192,254,64,253,37,56,51,181,181,51,56,72,44,39,142,1,142,39,44,0,0,7,0,170,255,106,7,173,6,110,0,3,0,14,0,25, + 0,29,0,41,0,53,0,70,0,0,1,23,5,39,5,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,1,5,7,37, + 1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,19,54,55,54,32,23,22,23,7,38,39,38,35,38,7,6, + 7,5,134,77,254,209,77,254,43,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,254,14,1,47,77,254,209,254,37,2,14,1,116,1, + 117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,236,37,50,182,2,4,182,51,36,115,28,40, + 142,202,202,142,39,29,5,103,110,213,111,222,59,81,81,118,82,83,58,59,81,81,59,58,83,83,1,236,212,111,213,253,241,1,117,2,15,253,241,254, + 139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,253,37,56,51,181,181,51,56,72,44,39,142,1,142,39,44,0, + 0,8,0,170,255,106,7,173,6,110,0,16,0,28,0,40,0,44,0,55,0,66,0,70,0,86,0,0,1,54,55,54,32,23,22,23,7,38,39,38, + 35,38,7,6,7,1,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,1,5,7,37,1,52,54,50,22,21,20, + 6,35,34,38,37,52,54,51,50,22,20,6,35,34,38,1,23,5,39,3,39,54,55,54,50,23,22,23,7,38,39,38,34,7,6,2,29,37,50,182, + 2,4,182,51,36,115,28,40,142,202,202,142,39,29,254,161,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1,116,1,117,2, + 12,253,244,254,139,254,140,253,242,2,40,1,47,77,254,209,2,63,82,116,83,83,58,59,81,253,190,81,59,58,82,82,58,59,81,3,4,77,254,209, + 77,130,121,16,24,70,196,70,24,16,121,7,8,30,84,30,8,1,76,56,51,181,181,51,56,72,44,39,142,1,142,39,44,1,229,254,196,254,67,1, + 189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,3,241,212,111,213,254,188,59,81,81,59,58,83,83,58, + 59,81,81,118,82,83,1,236,110,213,111,252,12,57,40,34,98,98,34,40,57,19,16,60,60,16,0,0,0,5,0,170,255,106,7,173,6,110,0,11, + 0,23,0,35,0,52,0,79,0,0,1,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,1,20,6,34,38,53, + 51,20,22,50,54,53,1,54,55,54,32,23,22,23,7,38,39,38,35,38,7,6,7,1,20,7,6,7,23,22,7,6,7,6,34,38,53,52,63,1, + 38,39,38,53,51,20,22,50,54,53,1,49,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1,116,1,117,2,12,253,244,254, + 139,254,140,253,242,3,72,140,196,140,135,61,84,61,254,178,37,50,182,2,4,182,51,36,115,28,40,142,202,202,142,39,29,3,178,70,58,77,32,28, + 1,1,26,27,76,54,27,32,77,58,70,135,61,84,61,2,234,254,196,254,67,1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254, + 139,254,140,253,244,2,12,3,18,139,197,197,139,83,119,119,83,252,196,56,51,181,181,51,56,72,44,39,142,1,142,39,44,3,131,140,98,81,14,63, + 55,35,43,26,27,54,44,35,53,63,13,82,98,140,83,119,119,83,0,0,0,5,0,170,255,106,7,173,6,110,0,16,0,23,0,30,0,42,0,54, + 0,0,1,54,55,54,32,23,22,23,7,38,39,38,35,38,7,6,7,1,37,23,7,23,7,37,39,21,5,39,55,39,55,1,16,0,33,32,0,17, + 16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,2,29,37,50,182,2,4,182,51,36,115,28,40,142,202,202,142,39,29,1,236,1,39, + 77,198,198,77,254,217,160,254,217,77,198,198,77,253,245,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189, + 254,67,254,195,254,196,254,65,1,76,56,51,181,181,51,56,72,44,39,142,1,142,39,44,3,34,206,110,139,138,110,206,85,85,206,110,138,139,110,253, + 245,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,6,0,170,255,106,7,173, + 6,110,0,3,0,7,0,24,0,33,0,45,0,57,0,0,1,39,1,23,9,1,55,9,1,54,55,54,32,23,22,23,7,38,39,38,35,38,7,6, + 7,1,23,22,14,1,34,38,52,55,5,16,0,33,32,0,17,16,0,33,32,0,3,16,0,33,32,0,17,16,0,33,32,0,2,201,95,1,14,95, + 1,184,254,242,95,1,14,252,47,37,50,182,2,4,182,51,36,115,28,40,142,202,202,142,39,29,3,218,66,27,1,54,76,54,28,251,7,1,191,1, + 60,1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,3,92,95,1,14,95,254,242,1,14, + 95,254,242,253,145,56,51,181,181,51,56,72,44,39,142,1,142,39,44,3,35,128,53,79,54,54,79,53,190,254,196,254,67,1,189,1,60,1,61,1, + 192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,0,0,6,0,170,255,106,7,173,6,110,0,11,0,22,0,34,0,46,0,52, + 0,60,0,0,1,52,54,51,50,22,21,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19, + 16,0,33,32,0,17,16,0,33,32,0,1,33,52,0,32,0,5,33,38,39,38,32,7,6,2,130,81,59,58,82,82,58,59,81,2,66,82,116,83, + 83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,4, + 243,252,15,1,39,1,163,1,39,252,169,2,189,24,69,107,254,210,106,69,3,255,59,81,81,59,58,83,83,58,59,81,81,59,58,83,83,219,1,117, + 2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,252,164,232,1,70,254,186,97,96,76,116,117, + 76,0,0,0,0,8,0,170,255,106,7,173,6,110,0,3,0,7,0,18,0,29,0,41,0,53,0,59,0,67,0,0,1,37,55,13,1,39,37,23, + 1,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0, + 17,16,0,33,32,0,1,33,52,0,32,0,5,33,38,39,38,32,7,6,6,23,254,168,77,1,88,251,221,77,1,88,77,254,233,81,59,58,82,82, + 58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254, + 67,254,195,254,196,254,65,4,243,252,15,1,39,1,163,1,39,252,169,2,189,24,69,107,254,210,106,69,4,22,240,111,241,110,110,241,111,254,175,59, + 81,81,118,82,83,58,59,81,81,59,58,83,83,145,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61, + 1,192,254,64,252,164,232,1,70,254,186,97,96,76,116,117,76,0,0,0,0,14,0,170,255,106,7,173,6,110,0,11,0,19,0,25,0,78,0,90, + 0,102,0,108,0,120,0,132,0,138,0,144,0,150,0,156,0,162,0,0,1,20,22,51,50,54,53,52,38,35,34,6,1,33,38,39,38,32,7,6, + 5,33,52,0,32,0,1,16,0,33,32,0,17,52,39,21,35,17,38,39,17,35,53,14,1,34,39,35,53,38,52,55,17,38,39,17,35,17,6,7, + 17,22,20,7,21,35,6,34,38,39,21,35,17,6,7,17,35,53,6,7,16,0,33,32,0,17,16,0,33,32,0,1,52,54,51,50,22,21,20,6, + 35,34,38,37,54,55,53,6,7,1,52,38,35,34,6,21,20,22,51,50,54,39,20,6,35,34,38,53,52,54,51,50,22,1,21,22,23,53,38,39, + 38,39,21,54,55,37,38,39,21,22,23,37,6,7,21,54,55,37,6,7,21,22,23,4,150,116,74,85,105,111,79,76,114,254,55,2,189,24,69,107, + 254,210,106,69,3,63,252,15,1,39,1,163,1,39,251,13,1,191,1,60,1,61,1,189,53,68,30,37,68,30,109,142,56,68,43,43,33,34,68,34, + 33,43,43,68,56,142,110,29,68,37,30,68,54,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,4,113,34,23,24,33,31,26,22,35, + 253,158,32,35,35,32,1,9,114,76,79,111,105,85,74,116,133,35,22,26,31,33,24,23,34,2,31,36,31,32,103,33,34,31,36,1,14,33,34,43, + 24,252,79,35,32,25,42,1,14,34,33,36,31,4,26,82,108,117,73,79,111,111,252,233,96,76,116,117,76,230,232,1,70,254,186,1,55,254,196,254, + 67,1,189,1,60,155,133,186,1,59,46,41,254,110,89,54,71,36,64,60,156,60,1,61,4,1,253,106,2,150,1,4,254,195,60,156,60,64,36,70, + 55,89,1,147,42,46,254,197,188,134,156,1,117,2,15,253,241,254,139,254,140,253,244,2,12,2,164,24,33,33,24,22,35,32,252,10,1,162,15,18, + 254,145,79,111,111,79,73,117,108,82,25,32,35,22,24,33,33,1,121,163,1,10,140,19,40,10,8,242,20,9,38,30,24,132,33,45,210,25,29,156, + 45,33,253,7,11,195,9,20,0,8,0,170,255,106,7,173,6,110,0,3,0,7,0,11,0,15,0,27,0,39,0,45,0,53,0,0,1,39,1,23, + 9,1,55,9,1,39,1,23,9,1,55,1,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,1,33,52,0, + 32,0,5,33,38,39,38,32,7,6,2,201,95,1,14,95,1,184,254,242,95,1,14,252,219,95,1,14,95,1,184,254,242,95,1,14,250,188,2,14, + 1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,4,243,252,15,1,39,1,163,1, + 39,252,169,2,189,24,69,107,254,210,106,69,4,19,95,1,14,95,254,242,1,14,95,254,242,254,88,95,1,14,95,254,242,1,14,95,254,242,63,1, + 117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,252,164,232,1,70,254,186,97,96,76,116, + 117,76,0,0,0,7,0,170,255,106,7,173,6,110,0,17,0,29,0,41,0,53,0,65,0,71,0,79,0,0,1,55,54,55,54,51,50,23,22,23, + 22,21,20,7,6,7,6,35,3,20,6,34,38,53,51,20,22,50,54,53,33,20,6,34,38,53,51,20,22,50,54,53,1,16,0,33,32,0,17,16, + 0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,1,33,52,0,32,0,5,33,38,39,38,32,7,6,5,196,85,37,31,25,22,13,13,36, + 18,10,5,12,39,31,59,18,140,196,140,135,61,84,61,254,55,140,196,140,135,61,84,61,253,63,2,14,1,116,1,117,2,12,253,244,254,139,254,140, + 253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,4,243,252,15,1,39,1,163,1,39,252,169,2,189,24,69,107,254,210,106,69, + 2,200,116,50,15,11,4,12,34,20,21,14,15,36,20,16,1,192,139,197,197,139,83,119,119,83,139,197,197,139,83,119,119,83,254,98,1,117,2,15, + 253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,252,164,232,1,70,254,186,97,96,76,116,117,76,0, + 0,6,0,170,255,106,7,173,6,110,0,6,0,13,0,25,0,37,0,43,0,51,0,0,1,37,23,7,23,7,37,39,21,5,39,55,39,55,1,16, + 0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,1,33,52,0,32,0,5,33,38,39,38,32,7,6,4,124,1,39, + 77,198,198,77,254,217,160,254,217,77,198,198,77,253,245,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189, + 254,67,254,195,254,196,254,65,4,243,252,15,1,39,1,163,1,39,252,169,2,189,24,69,107,254,210,106,69,4,39,206,110,139,138,110,206,85,85,206, + 110,138,139,110,253,245,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,252,164,232,1, + 70,254,186,97,96,76,116,117,76,0,0,0,0,5,0,95,255,106,8,249,6,110,0,5,0,12,0,19,0,61,0,98,0,0,37,33,52,0,32,0, + 1,21,5,39,55,39,55,5,37,23,7,23,7,37,5,16,0,33,32,0,17,20,7,23,22,23,22,21,20,6,34,39,38,47,1,2,7,0,33,32, + 1,38,3,7,6,7,6,34,38,53,52,55,54,63,1,38,55,16,0,33,32,0,17,52,39,6,35,34,39,38,47,1,23,22,23,38,39,38,33,32, + 7,6,7,54,63,1,7,6,7,6,34,39,6,6,164,252,15,1,39,1,163,1,39,253,184,254,217,77,198,198,77,1,199,1,39,77,198,198,77,254, + 217,252,46,2,14,1,116,1,117,2,12,2,93,59,24,30,54,76,31,25,18,11,42,209,254,250,254,139,254,140,254,249,209,43,10,18,25,31,76,54, + 30,23,60,92,2,135,1,191,1,60,1,61,1,189,1,27,37,38,31,25,18,45,136,41,24,47,154,222,254,194,254,196,224,154,47,24,41,136,45,18, + 25,31,76,27,1,203,232,1,70,254,186,2,116,85,206,110,138,139,110,206,206,110,139,138,110,206,232,1,117,2,15,253,241,254,139,29,27,31,20,24, + 31,37,38,54,31,25,57,32,254,233,209,254,250,1,6,208,1,22,30,57,25,31,54,38,37,31,25,19,30,28,29,254,196,254,67,1,189,1,60,20, + 19,26,31,25,57,136,45,14,15,199,154,224,224,155,198,16,13,45,136,57,25,31,27,20,0,5,0,170,255,106,7,173,6,110,0,7,0,19,0,30, + 0,42,0,54,0,0,0,52,54,50,22,20,6,34,1,52,54,51,50,22,21,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,5,16,0, + 33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,3,44,150,212,150,150,212,254,192,81,59,58,82,82,58,59,81,2,66, + 82,116,83,83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196, + 254,65,1,90,212,150,150,212,150,3,59,59,81,81,59,58,83,83,58,59,81,81,59,58,83,83,219,1,117,2,15,253,241,254,139,254,140,253,244,2, + 12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,0,0,7,0,170,255,106,7,173,6,110,0,3,0,7,0,18,0,29,0,37, + 0,49,0,61,0,0,1,37,55,13,1,39,37,23,1,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6,35,34,38,0,52,54,50, + 22,20,6,34,1,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,6,23,254,168,77,1,88,251,221,77,1,88, + 77,254,233,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,254,232,75,106,75,75,106,252,179,2,14,1,116,1,117,2,12,253,244,254, + 139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,4,22,240,111,241,110,110,241,111,254,175,59,81,81,118,82,83,58, + 59,81,81,59,58,83,83,254,20,106,75,75,106,75,1,166,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60, + 1,61,1,192,254,64,0,0,0,8,0,170,255,106,7,173,6,110,0,8,0,16,0,20,0,24,0,35,0,46,0,58,0,70,0,0,1,23,22,20, + 6,34,38,52,55,0,52,54,50,22,20,6,34,1,37,55,13,1,39,37,23,1,52,54,51,50,22,20,6,35,34,38,37,52,54,50,22,21,20,6, + 35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,6,80,65,27,54,76,54,27,253,29,150,212,150, + 150,212,2,85,254,168,77,1,88,251,221,77,1,88,77,254,233,81,59,58,82,82,58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116, + 1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,3,172,128,53,79,54,54,79,53,254,46, + 212,150,150,212,150,3,82,240,111,241,110,110,241,111,254,175,59,81,81,118,82,83,58,59,81,81,59,58,83,83,145,1,117,2,15,253,241,254,139,254, + 140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,0,0,7,0,35,255,60,8,53,6,110,0,7,0,15,0,19, + 0,23,0,31,0,107,0,148,0,0,0,38,52,54,50,22,20,6,32,38,52,54,50,22,20,6,37,39,37,23,5,37,55,5,0,52,54,50,22,20, + 6,34,1,53,46,1,39,2,17,52,54,55,54,55,0,32,1,22,23,30,1,21,16,3,14,1,7,21,35,53,52,55,54,55,54,19,52,38,34,6, + 7,6,7,6,15,1,14,1,29,1,35,53,6,32,39,21,35,53,52,38,47,1,38,39,38,39,46,1,34,6,21,18,23,22,23,22,29,1,37,22, + 32,55,53,52,55,54,55,54,55,54,55,62,1,55,54,55,54,55,38,39,38,32,7,6,7,22,23,30,2,23,22,23,22,23,22,23,22,21,5,21, + 81,82,116,83,83,253,73,81,81,117,82,82,254,249,77,1,88,77,2,126,254,168,77,1,88,252,200,150,212,150,150,212,253,161,72,86,24,138,104,61, + 59,174,1,7,2,233,1,6,174,59,61,104,138,24,86,72,135,38,129,29,122,2,39,58,37,6,14,105,41,56,94,39,27,136,110,254,251,121,136,27, + 39,94,56,41,105,14,6,37,58,39,2,122,29,129,38,1,76,119,1,9,108,27,48,145,56,17,60,17,2,8,12,12,51,15,17,50,143,222,253,134, + 224,143,51,18,15,51,24,8,2,17,60,17,56,145,48,27,3,40,83,117,81,81,117,83,83,117,81,81,118,82,238,110,241,111,240,240,111,241,252,214, + 212,150,150,212,150,254,120,203,62,91,49,1,23,1,39,83,107,10,223,176,1,8,254,248,175,224,10,107,83,254,217,254,233,49,91,62,203,231,36,31, + 110,57,240,1,18,28,40,35,109,243,113,44,37,64,28,60,63,251,76,30,32,78,251,63,60,28,64,37,44,113,243,109,35,40,28,254,238,240,57,110, + 31,36,231,219,38,37,33,89,59,101,86,34,19,68,120,15,134,56,54,48,14,10,181,144,224,224,143,181,11,14,48,110,134,15,120,68,19,34,86,101, + 59,89,0,0,0,9,0,170,255,106,7,173,6,110,0,11,0,23,0,35,0,47,0,59,0,71,0,79,0,91,0,103,0,0,1,20,6,35,34,38, + 53,52,54,51,50,22,23,52,54,51,50,22,21,20,6,35,34,38,55,20,22,51,50,54,53,52,38,35,34,6,23,52,54,51,50,22,21,20,6,35, + 34,38,37,52,38,35,34,6,21,20,22,51,50,54,39,20,6,35,34,38,53,52,54,51,50,22,2,52,54,50,22,20,6,34,1,16,0,33,32,0, + 17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,3,242,146,92,106,132,139,99,95,143,116,143,95,99,139,132,106,92,146,48,116,74, + 85,105,111,79,76,114,133,34,23,24,33,31,26,22,35,254,167,114,76,79,111,105,85,74,116,133,35,22,26,31,33,24,23,34,17,150,212,150,150,212, + 252,232,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,4,26,102,136,147, + 91,99,139,139,99,99,139,139,99,91,147,136,102,82,108,117,73,79,111,111,79,24,33,33,24,22,35,32,25,79,111,111,79,73,117,108,82,25,32,35, + 22,24,33,33,253,40,212,150,150,212,150,2,38,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1, + 192,254,64,0,0,10,0,170,255,106,7,173,6,110,0,74,0,86,0,94,0,98,0,102,0,107,0,112,0,116,0,121,0,126,0,0,1,16,0,33, + 32,0,17,52,39,17,35,17,38,39,21,23,7,17,35,53,35,21,35,53,35,21,35,53,35,21,35,17,51,17,51,17,39,55,23,53,38,32,7,21, + 55,23,7,17,51,17,51,17,35,53,35,21,35,53,35,21,35,53,35,21,35,17,39,55,53,6,7,17,35,17,6,7,16,0,33,32,0,17,16,0, + 33,32,0,36,52,54,50,22,20,6,34,19,17,51,17,1,51,53,39,23,51,53,7,39,17,21,23,53,38,1,53,7,21,3,6,7,21,55,17,53, + 7,39,21,1,49,1,191,1,60,1,61,1,189,64,68,30,38,6,6,68,52,68,68,68,68,68,68,68,91,77,150,167,254,98,167,150,77,91,68,68, + 68,68,68,68,68,52,68,6,6,37,31,68,65,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,3,2,75,106,75,75,106,19,68,1, + 16,68,68,136,52,3,49,52,25,252,249,68,68,27,25,52,49,3,2,234,254,196,254,67,1,189,1,60,170,143,254,133,1,243,44,40,103,4,9,254, + 45,136,136,136,136,136,136,2,56,254,215,1,16,63,111,105,123,96,96,123,105,111,63,254,240,1,41,253,200,136,136,136,136,136,136,1,211,9,4,104, + 40,44,254,12,1,125,144,171,1,117,2,15,253,241,254,139,254,140,253,244,2,12,25,106,75,75,106,75,1,100,2,56,253,200,1,15,177,47,224,99, + 4,34,1,35,127,36,122,22,254,111,224,47,177,1,164,19,23,121,36,254,219,129,34,4,99,0,0,0,0,8,0,170,255,106,12,113,7,108,0,9, + 0,19,0,29,0,37,0,49,0,61,0,73,0,85,0,0,1,33,21,3,51,21,33,53,19,35,37,33,21,3,51,21,33,53,19,35,37,33,21,3, + 51,21,33,53,19,35,0,52,54,50,22,20,6,34,1,20,6,34,38,53,51,20,22,50,54,53,33,20,6,34,38,53,51,20,22,50,54,53,1,16, + 0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,10,246,1,123,248,248,254,123,248,238,254,23,1,123,248,248,254,123, + 248,238,254,23,1,123,248,248,254,123,248,238,252,136,75,106,75,75,106,2,75,140,196,140,135,61,84,61,254,55,140,196,140,135,61,84,61,253,63,2, + 14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,7,108,104,254,244,92,104,1, + 12,92,104,254,244,92,104,1,12,92,104,254,244,92,104,1,12,250,127,106,75,75,106,75,3,68,139,197,197,139,83,119,119,83,139,197,197,139,83,119, + 119,83,254,98,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,0,5,0,170, + 255,106,7,173,6,110,0,11,0,23,0,35,0,43,0,55,0,0,1,39,55,39,55,23,55,23,7,23,7,39,5,16,0,33,32,0,17,16,0,33, + 32,0,3,16,0,33,32,0,17,16,0,33,32,0,4,52,54,50,22,20,6,34,1,39,55,39,55,23,55,23,7,23,7,39,2,149,95,113,113,95, + 113,114,95,113,113,95,114,254,43,1,191,1,60,1,61,1,189,254,67,254,195,254,196,254,65,135,2,14,1,116,1,117,2,12,253,244,254,139,254,140, + 253,242,2,130,150,212,150,150,212,1,30,95,113,113,95,113,114,95,113,113,95,114,3,40,95,113,114,95,113,113,95,114,113,95,113,175,254,196,254,67, + 1,189,1,60,1,61,1,192,254,64,254,195,1,117,2,15,253,241,254,139,254,140,253,244,2,12,28,212,150,150,212,150,2,100,95,113,114,95,113,113, + 95,114,113,95,113,0,0,0,0,4,0,170,255,106,7,173,6,110,0,10,0,21,0,33,0,45,0,0,1,52,54,51,50,22,20,6,35,34,38,37, + 52,54,50,22,21,20,6,35,34,38,5,16,0,33,32,0,17,16,0,33,32,0,19,16,0,33,32,0,17,16,0,33,32,0,2,130,81,59,58,82, + 82,58,59,81,2,66,82,116,83,83,58,59,81,251,230,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253,242,135,1,191,1,60,1,61,1,189, + 254,67,254,195,254,196,254,65,3,253,59,81,81,118,82,83,58,59,81,81,59,58,83,83,217,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1, + 116,254,196,254,67,1,189,1,60,1,61,1,192,254,64,0,0,10,0,170,255,106,7,173,6,110,0,11,0,15,0,19,0,23,0,27,0,31,0,36, + 0,40,0,44,0,55,0,0,19,16,0,33,32,0,17,16,0,33,32,0,1,53,33,21,51,53,33,21,37,39,37,23,5,37,55,5,1,33,17,33, + 1,33,22,33,32,37,54,19,7,1,17,39,18,1,2,39,38,33,32,7,6,3,23,33,170,2,14,1,116,1,117,2,12,253,244,254,139,254,140,253, + 242,1,108,1,170,216,1,170,251,255,77,1,88,77,2,126,254,168,77,1,88,252,57,3,30,252,226,3,84,252,118,196,1,1,1,2,1,20,203,22, + 225,251,212,226,22,5,215,27,190,222,254,194,254,196,224,190,28,224,4,44,2,234,1,117,2,15,253,241,254,139,254,140,253,244,2,12,1,186,135,135, + 135,135,230,110,241,111,240,240,111,241,252,135,1,24,254,97,147,217,201,1,17,158,254,196,1,60,158,254,239,1,179,1,2,191,224,224,191,254,255,157, + 0,9,0,58,255,106,8,38,7,20,0,8,0,29,0,82,0,143,0,157,0,171,0,181,0,187,0,193,0,0,0,50,55,23,6,35,34,39,55,23, + 22,51,50,55,22,21,20,7,6,4,32,36,39,38,53,52,55,22,51,50,1,20,23,37,23,5,22,23,37,23,5,22,23,22,23,22,32,55,54,55, + 54,55,37,55,5,54,55,37,55,5,54,53,52,46,2,39,38,39,6,7,38,35,34,7,38,39,6,7,14,3,7,38,53,52,62,3,55,54,63,1, + 23,30,1,23,54,50,23,62,1,63,1,23,22,23,30,4,21,20,7,23,7,39,6,7,23,7,39,6,7,2,7,6,33,32,39,38,3,38,39,7, + 39,55,38,39,7,39,37,52,46,1,34,14,1,21,35,52,54,50,22,21,33,52,46,1,34,14,1,21,35,52,54,50,22,21,1,38,39,6,7,21, + 22,51,50,63,1,21,54,55,6,35,5,53,35,34,39,22,3,236,130,92,62,120,99,101,118,62,160,114,116,158,146,5,29,54,254,237,254,156,254,236, + 59,35,3,149,160,121,253,93,7,1,77,5,254,180,8,14,1,52,22,254,200,18,22,102,163,181,1,234,181,161,103,26,16,254,205,22,1,46,14,8, + 254,186,5,1,71,6,10,10,22,4,27,42,243,153,116,155,157,116,153,243,42,27,5,21,11,10,128,5,7,19,12,31,5,23,38,15,60,143,253,93, + 105,226,105,93,253,143,59,16,38,23,5,31,12,19,7,5,105,4,107,8,21,104,22,100,19,27,116,192,217,254,224,254,223,217,192,116,29,16,94,22, + 98,20,9,101,4,3,49,21,49,66,49,21,135,140,196,140,1,201,21,49,66,49,21,135,140,196,140,254,58,36,40,26,50,43,36,41,32,136,96,51, + 72,58,254,71,21,63,63,52,2,252,46,120,61,61,120,252,37,66,32,25,68,71,129,147,143,125,75,83,23,23,66,1,199,36,98,21,67,22,74,65, + 105,63,108,58,49,226,119,132,132,118,227,56,53,106,63,103,62,76,21,67,21,82,52,46,102,62,118,25,161,167,58,196,21,21,196,58,167,161,27,114, + 65,101,189,77,69,57,106,119,65,147,24,117,140,58,9,22,137,97,13,13,97,137,22,9,58,140,117,24,147,65,119,106,57,68,77,7,68,7,86,87, + 36,64,34,60,60,254,253,140,158,158,140,1,3,64,54,32,64,34,79,96,7,68,81,43,90,69,69,89,44,140,196,196,140,43,90,69,69,89,44,140, + 196,196,140,254,3,7,11,7,10,145,5,4,132,99,39,70,10,97,97,9,67,0,0,0,0,9,0,96,255,106,8,248,7,20,0,63,0,72,0,93, + 0,168,0,182,0,196,0,206,0,212,0,218,0,0,1,54,53,52,46,2,39,38,39,6,7,38,32,7,38,39,6,7,14,3,21,20,23,54,63,1, + 7,14,1,35,34,39,22,23,37,23,5,22,23,22,23,22,32,55,54,55,54,55,37,55,5,54,55,6,35,34,38,47,1,23,22,4,50,55,23,6, + 35,34,39,55,23,22,51,50,55,22,21,20,7,6,4,32,36,39,38,53,52,55,22,51,50,5,34,38,53,52,54,63,1,52,39,7,39,55,38,53, + 52,62,3,55,54,63,1,23,30,1,23,54,50,23,62,1,63,1,23,22,23,30,4,21,20,7,23,7,39,6,7,23,30,1,21,20,6,35,34,38, + 47,1,6,7,2,7,6,32,39,38,3,38,39,7,6,1,52,46,1,34,14,1,21,35,52,54,50,22,21,33,52,46,1,34,14,1,21,35,52,54, + 50,22,21,1,38,39,6,7,21,22,51,50,63,1,21,54,55,6,35,5,53,35,34,39,22,7,186,2,10,10,22,4,26,42,242,154,116,254,200,116, + 152,244,42,28,5,21,10,10,2,24,80,136,44,17,51,44,48,28,8,16,1,52,22,254,200,18,22,102,164,181,1,233,182,162,102,26,16,254,204,22, + 1,46,16,8,28,48,44,52,16,46,138,82,252,200,130,92,62,120,98,102,118,62,160,114,116,158,146,6,30,54,254,238,254,156,254,236,60,34,2,150, + 160,120,252,124,37,55,62,52,90,8,102,4,100,6,8,18,12,32,4,24,38,14,60,143,253,94,105,225,106,93,253,142,60,16,38,22,5,31,12,20, + 6,4,104,4,106,6,4,90,52,60,54,36,44,52,18,14,24,44,116,192,216,253,192,218,192,116,42,26,16,36,2,228,22,48,66,50,20,136,140,196, + 140,1,202,22,48,66,50,20,136,140,196,140,254,58,36,40,26,50,44,36,40,32,136,96,52,72,58,254,70,20,62,64,52,3,124,40,44,46,102,62, + 118,25,161,167,58,196,21,21,196,58,167,161,27,114,65,101,46,42,39,44,25,44,136,51,60,37,87,76,105,63,108,58,49,226,119,132,132,118,227,56, + 53,106,63,103,68,96,40,60,51,136,44,25,175,46,120,61,61,120,252,37,66,32,25,68,71,129,147,143,125,75,83,23,23,66,65,54,37,44,52,17, + 29,3,74,7,68,6,77,69,57,106,119,65,147,24,117,140,58,9,22,137,97,13,13,97,137,22,9,58,140,117,24,147,65,119,106,57,68,77,7,68, + 7,52,25,29,17,52,44,37,54,60,51,42,104,98,254,253,140,158,158,140,1,3,93,112,45,111,1,196,43,90,69,69,89,44,140,196,196,140,43,90, + 69,69,89,44,140,196,196,140,254,3,7,11,7,10,145,5,4,132,99,39,70,10,97,97,9,67,0,0,0,9,0,58,255,106,8,38,7,20,0,8, + 0,29,0,42,0,95,0,156,0,170,0,180,0,195,0,208,0,0,0,50,55,23,6,35,34,39,55,23,22,51,50,55,22,21,20,7,6,4,32,36, + 39,38,53,52,55,22,51,50,23,6,35,34,39,30,1,50,54,55,6,35,34,1,20,23,37,23,5,22,23,37,23,5,22,23,22,23,22,32,55,54, + 55,54,55,37,55,5,54,55,37,55,5,54,53,52,46,2,39,38,39,6,7,38,35,34,7,38,39,6,7,14,3,7,38,53,52,62,3,55,54,63, + 1,23,30,1,23,54,50,23,62,1,63,1,23,22,23,30,4,21,20,7,23,7,39,6,7,23,7,39,6,7,2,7,6,33,32,39,38,3,38,39, + 7,39,55,38,39,7,39,37,52,54,51,50,22,23,6,7,6,35,34,39,38,55,34,6,21,20,23,62,1,55,38,5,20,7,6,35,34,39,38,39, + 54,55,54,51,50,22,7,22,51,50,55,54,53,52,39,38,35,34,6,3,236,130,92,62,120,99,101,118,62,160,114,116,158,146,5,29,54,254,237,254, + 156,254,236,59,35,3,149,160,121,112,114,119,63,63,53,192,234,189,50,72,58,117,252,125,7,1,77,5,254,180,8,14,1,52,22,254,200,18,22,102, + 163,181,1,234,181,161,103,26,16,254,205,22,1,46,14,8,254,186,5,1,71,6,10,10,22,4,27,42,243,153,116,155,157,116,153,243,42,27,5,21, + 11,10,128,5,7,19,12,31,5,23,38,15,60,143,253,93,105,226,105,93,253,143,59,16,38,23,5,31,12,19,7,5,105,4,107,8,21,104,22,100, + 19,27,116,192,217,254,224,254,223,217,192,116,29,16,94,22,98,20,9,101,4,1,226,99,67,62,93,7,48,76,33,40,67,56,8,253,36,48,5,43, + 69,18,21,2,255,8,56,67,37,36,77,47,8,50,45,59,67,99,164,12,26,46,42,16,4,12,13,44,64,2,252,46,120,61,61,120,252,37,66,32, + 25,68,71,129,147,143,125,75,83,23,23,66,104,31,9,69,76,77,69,10,2,78,36,98,21,67,22,74,65,105,63,108,58,49,226,119,132,132,118,227, + 56,53,106,63,103,62,76,21,67,21,82,52,46,102,62,118,25,161,167,58,196,21,21,196,58,167,161,27,114,65,101,189,77,69,57,106,119,65,147,24, + 117,140,58,9,22,137,97,13,13,97,137,22,9,58,140,117,24,147,65,119,106,57,68,77,7,68,7,86,87,36,64,34,60,60,254,253,140,158,158,140, + 1,3,64,54,32,64,34,79,96,7,68,159,70,95,87,59,69,24,11,33,23,73,43,32,13,13,6,47,33,15,45,29,23,33,12,25,67,66,42,38, + 95,122,3,20,21,25,12,11,3,53,0,0,0,6,0,61,255,106,8,29,7,20,0,17,0,25,0,74,0,131,0,152,0,173,0,0,1,55,22,51, + 50,55,22,51,50,55,23,6,35,34,39,6,35,34,1,23,6,34,39,55,22,50,37,54,53,52,46,2,39,38,39,6,7,38,35,34,7,38,39,6, + 7,14,3,21,20,23,37,23,5,22,23,37,23,5,22,23,22,32,55,54,55,37,55,5,54,55,37,55,5,38,53,52,62,3,55,54,63,1,23,30, + 1,23,54,50,23,62,1,63,1,23,22,23,30,4,21,20,7,23,7,39,6,7,23,7,39,2,7,6,33,32,39,38,3,7,39,55,38,39,7,39, + 1,62,1,51,50,22,21,20,15,1,35,39,38,39,52,54,51,50,23,22,21,37,50,22,23,51,52,55,54,51,50,22,21,6,15,1,35,39,38,53, + 52,54,2,166,92,69,91,58,84,84,58,91,69,92,108,144,74,68,69,73,144,1,184,62,122,194,122,62,90,134,2,186,18,10,10,22,4,27,42,243, + 153,116,155,157,116,153,243,42,27,5,21,11,10,18,1,66,10,254,191,14,23,1,30,26,254,225,103,164,181,1,234,181,164,103,254,225,26,1,30,21, + 15,254,192,10,250,192,17,7,19,12,31,5,23,38,15,60,143,253,93,105,226,105,93,253,143,59,16,38,23,5,31,12,19,7,17,108,10,109,15,32, + 110,26,109,117,195,217,254,224,254,223,217,193,118,109,26,109,30,16,109,10,2,227,10,58,45,46,62,62,159,2,168,49,2,64,47,61,35,13,1,168, + 45,58,10,1,13,35,61,47,64,2,49,168,2,159,62,62,1,140,98,64,44,44,64,98,100,28,28,1,168,120,61,61,120,46,56,130,116,46,102,62, + 118,25,161,167,58,196,21,21,196,58,167,161,27,114,65,101,46,116,130,43,66,44,69,64,121,62,122,231,119,132,132,119,231,122,62,121,57,76,44,66, + 61,124,143,57,106,119,65,147,24,117,140,58,9,22,137,97,13,13,97,137,22,9,58,140,117,24,147,65,119,106,57,143,124,15,66,14,81,87,46,62, + 46,254,247,142,158,158,140,1,11,46,62,46,81,87,14,66,1,149,48,66,61,49,74,74,190,207,61,66,42,72,71,27,16,114,66,48,16,27,71,72, + 42,66,61,207,190,74,74,49,61,0,0,0,0,10,0,61,255,106,8,29,7,20,0,3,0,7,0,15,0,30,0,40,0,55,0,68,0,117,0,174, + 0,184,0,0,1,5,7,45,1,23,5,39,19,23,6,34,39,55,22,50,1,6,7,6,35,34,39,38,53,52,55,54,51,50,22,7,34,6,21,20, + 23,62,1,55,38,5,62,1,51,50,23,22,21,20,7,6,35,34,39,38,23,22,51,50,55,54,53,52,39,38,35,34,6,5,54,53,52,46,2,39, + 38,39,6,7,38,35,34,7,38,39,6,7,14,3,21,20,23,37,23,5,22,23,37,23,5,22,23,22,32,55,54,55,37,55,5,54,55,37,55,5, + 38,53,52,62,3,55,54,63,1,23,30,1,23,54,50,23,62,1,63,1,23,22,23,30,4,21,20,7,23,7,39,6,7,23,7,39,2,7,6,33, + 32,39,38,3,7,39,55,38,39,7,39,1,50,55,54,55,23,6,7,6,33,2,210,1,47,77,254,209,3,1,77,254,209,77,115,62,122,194,122,62, + 90,134,254,252,43,81,32,40,70,54,21,53,47,65,70,101,78,36,48,5,43,69,18,22,1,184,5,100,70,66,47,53,21,54,70,40,32,81,121,12, + 26,48,40,16,4,12,13,44,64,1,147,18,10,10,22,4,27,42,243,153,116,155,157,116,153,243,42,27,5,21,11,10,18,1,66,10,254,191,14,23, + 1,30,26,254,225,103,164,181,1,234,181,164,103,254,225,26,1,30,21,15,254,192,10,250,192,17,7,19,12,31,5,23,38,15,60,143,253,93,105,226, + 105,93,253,143,59,16,38,23,5,31,12,19,7,17,108,10,109,15,32,110,26,109,117,195,217,254,224,254,223,217,193,118,109,26,109,30,16,109,10,3, + 239,202,142,40,28,115,34,53,181,254,253,5,103,212,111,213,110,110,213,111,254,61,120,61,61,120,46,1,6,76,28,11,35,36,45,71,48,44,97,38, + 48,36,14,15,7,52,37,17,29,67,97,44,48,71,45,36,35,11,28,4,3,22,24,28,14,12,3,59,167,130,116,46,102,62,118,25,161,167,58,196, + 21,21,196,58,167,161,27,114,65,101,46,116,130,43,66,44,69,64,121,62,122,231,119,132,132,119,231,122,62,121,57,76,44,66,61,124,143,57,106,119, + 65,147,24,117,140,58,9,22,137,97,13,13,97,137,22,9,58,140,117,24,147,65,119,106,57,143,124,15,66,14,81,87,46,62,46,254,247,142,158,158, + 140,1,11,46,62,46,81,87,14,66,254,127,142,40,43,72,54,53,181,0,0,8,0,61,255,106,8,29,7,20,0,14,0,24,0,39,0,52,0,105, + 0,168,0,181,0,190,0,0,1,6,7,6,35,34,39,38,53,52,55,54,51,50,22,7,34,6,21,20,23,62,1,55,38,5,62,1,51,50,23,22, + 21,20,7,6,35,34,39,38,23,22,51,50,55,54,53,52,39,38,35,34,6,5,54,53,52,46,2,39,38,39,6,7,38,35,34,7,38,39,6,7, + 14,3,21,20,23,22,23,37,23,5,22,23,37,23,5,23,22,23,22,32,55,54,63,1,37,55,5,54,55,37,55,0,50,23,62,1,63,1,23,22, + 23,30,4,21,20,6,21,6,7,23,7,39,6,7,23,7,39,7,2,7,6,33,32,39,38,3,39,7,39,55,38,39,7,39,55,38,39,53,52,62, + 3,55,54,63,1,23,30,1,23,19,55,39,55,5,21,7,23,21,5,39,55,39,2,50,55,23,6,35,34,39,55,3,108,43,81,32,40,70,54,21, + 53,47,65,70,101,78,36,48,5,43,69,18,22,1,184,5,100,70,66,47,53,21,54,70,40,32,81,121,12,26,48,40,16,4,12,13,44,64,1,147, + 18,10,10,22,4,27,42,243,153,116,155,157,116,153,243,42,27,5,21,11,10,2,7,9,1,66,10,254,191,14,23,1,30,26,254,225,2,102,163,181, + 1,234,181,161,103,3,254,225,26,1,30,21,15,254,192,10,253,211,226,105,93,253,143,59,16,38,23,5,31,12,19,7,1,3,13,108,10,109,15,32, + 110,26,109,4,116,192,217,254,224,254,223,217,192,116,3,109,26,109,30,16,109,10,108,14,3,7,19,12,31,5,23,38,15,60,143,253,93,163,80,144, + 65,1,3,60,60,254,253,65,144,80,11,132,91,62,119,100,101,118,62,3,168,76,28,11,35,36,45,71,48,44,97,38,48,36,14,15,7,52,37,17, + 29,67,97,44,48,71,45,36,35,11,28,4,3,22,24,28,14,12,3,59,167,131,115,46,102,62,118,25,161,167,58,196,21,21,196,58,167,161,27,114, + 65,101,46,15,36,130,65,43,66,44,69,64,121,62,122,5,226,119,132,132,118,227,5,122,62,121,57,76,44,66,3,19,13,97,137,22,9,58,140,117, + 24,147,65,119,106,57,7,28,7,138,87,15,66,14,81,87,46,62,46,8,254,253,140,158,158,140,1,3,8,46,62,46,81,87,14,66,15,96,129,42, + 57,106,119,65,147,24,117,140,58,9,22,137,97,251,58,61,78,119,141,89,46,45,89,141,119,78,61,1,218,46,120,61,61,120,0,0,0,11,0,61, + 255,106,8,29,7,20,0,14,0,24,0,39,0,52,0,101,0,158,0,166,0,175,0,184,0,188,0,192,0,0,1,6,7,6,35,34,39,38,53,52, + 55,54,51,50,22,7,34,6,21,20,23,62,1,55,38,5,62,1,51,50,23,22,21,20,7,6,35,34,39,38,23,22,51,50,55,54,53,52,39,38, + 35,34,6,5,54,53,52,46,2,39,38,39,6,7,38,35,34,7,38,39,6,7,14,3,21,20,23,37,23,5,22,23,37,23,5,22,23,22,32,55, + 54,55,37,55,5,54,55,37,55,5,38,53,52,62,3,55,54,63,1,23,30,1,23,54,50,23,62,1,63,1,23,22,23,30,4,21,20,7,23,7, + 39,6,7,23,7,39,2,7,6,33,32,39,38,3,7,39,55,38,39,7,39,1,54,50,23,7,38,34,7,37,54,32,23,7,38,35,34,7,0,50, + 55,23,6,35,34,39,55,1,23,5,39,37,5,7,37,3,108,43,81,32,40,70,54,21,53,47,65,70,101,78,36,48,5,43,69,18,22,1,184,5, + 100,70,66,47,53,21,54,70,40,32,81,121,12,26,48,40,16,4,12,13,44,64,1,147,18,10,10,22,4,27,42,243,153,116,155,157,116,153,243,42, + 27,5,21,11,10,18,1,66,10,254,191,14,23,1,30,26,254,225,103,164,181,1,234,181,164,103,254,225,26,1,30,21,15,254,192,10,250,192,17,7, + 19,12,31,5,23,38,15,60,143,253,93,105,226,105,93,253,143,59,16,38,23,5,31,12,19,7,17,108,10,109,15,32,110,26,109,117,195,217,254,224, + 254,223,217,193,118,109,26,109,30,16,109,10,3,71,70,196,70,96,30,84,30,254,144,181,2,6,181,96,142,202,200,144,1,23,132,91,62,119,100,101, + 118,62,1,246,77,254,209,77,254,123,1,47,77,254,209,3,168,76,28,11,35,36,45,71,48,44,97,38,48,36,14,15,7,52,37,17,29,67,97,44, + 48,71,45,36,35,11,28,4,3,22,24,28,14,12,3,59,167,130,116,46,102,62,118,25,161,167,58,196,21,21,196,58,167,161,27,114,65,101,46,116, + 130,43,66,44,69,64,121,62,122,231,119,132,132,119,231,122,62,121,57,76,44,66,61,124,143,57,106,119,65,147,24,117,140,58,9,22,137,97,13,13, + 97,137,22,9,58,140,117,24,147,65,119,106,57,143,124,15,66,14,81,87,46,62,46,254,247,142,158,158,140,1,11,46,62,46,81,87,14,66,254,19, + 99,99,95,60,60,245,181,181,96,142,142,1,250,46,120,61,61,120,2,61,110,213,111,212,212,111,213,0,0,5,0,61,255,106,8,29,7,20,0,32, + 0,44,0,52,0,100,0,142,0,0,1,20,6,7,23,22,20,6,34,38,53,52,53,6,34,39,55,22,50,55,23,54,63,1,46,1,53,51,20,22, + 50,54,53,33,20,6,34,38,53,51,20,22,50,54,53,3,54,32,23,7,38,32,7,1,38,16,54,63,1,54,63,1,23,30,1,23,54,50,23,62, + 1,63,1,23,22,31,1,30,1,20,7,23,7,39,6,7,23,7,39,2,0,32,0,3,7,39,55,38,39,7,39,5,18,33,50,36,55,37,55,5, + 54,55,37,55,5,54,53,52,47,1,38,39,6,7,38,32,7,38,39,6,15,1,6,21,20,23,37,23,5,22,23,37,23,6,66,128,77,32,27,54, + 76,54,110,194,118,62,91,132,91,51,7,15,32,77,128,135,61,84,61,254,55,140,196,140,135,61,84,61,247,181,2,6,181,96,142,254,110,144,253,213, + 17,32,22,20,23,38,15,60,143,253,93,105,226,105,93,253,143,59,16,38,23,20,43,11,17,108,10,109,15,32,110,26,109,117,254,100,253,191,254,102, + 118,109,26,109,30,16,109,10,1,59,215,1,222,245,1,89,103,254,225,26,1,30,21,15,254,192,10,1,65,18,26,30,16,43,243,153,116,254,200,116, + 153,243,42,27,16,32,19,1,66,10,254,191,14,23,1,30,26,4,136,139,180,14,63,53,79,54,54,44,3,3,53,61,120,46,46,99,24,29,63,14, + 180,139,83,119,119,83,139,197,197,139,83,119,119,83,252,218,181,181,96,142,142,1,198,124,1,6,196,106,97,117,140,58,9,22,137,97,13,13,97,137, + 22,9,58,140,117,97,204,160,200,124,15,66,14,81,87,46,62,46,254,247,254,212,1,42,1,11,46,62,46,81,87,14,66,230,254,30,251,231,122,62, + 121,57,76,44,66,43,130,81,136,141,174,98,167,58,196,21,21,196,58,167,161,84,168,110,107,130,43,66,44,69,64,121,62,0,0,0,0,6,0,61, + 255,106,8,29,7,20,0,52,0,115,0,123,0,131,0,135,0,139,0,0,1,54,53,52,46,2,39,38,39,6,7,38,35,34,7,38,39,6,7,14, + 3,21,20,23,22,23,37,23,5,22,23,37,23,5,23,22,23,22,32,55,54,63,1,37,55,5,54,55,37,55,0,50,23,62,1,63,1,23,22,23, + 30,4,21,20,6,21,6,7,23,7,39,6,7,23,7,39,7,2,7,6,33,32,39,38,3,39,7,39,55,38,39,7,39,55,38,39,53,52,62,3, + 55,54,63,1,23,30,1,23,3,33,38,39,38,32,7,6,5,33,52,55,54,51,50,0,3,1,55,1,5,39,1,23,7,42,18,10,10,22,4,27, + 42,243,153,116,155,157,116,153,243,42,27,5,21,11,10,2,7,9,1,66,10,254,191,14,23,1,30,26,254,225,2,102,163,181,1,234,181,161,103,3, + 254,225,26,1,30,21,15,254,192,10,253,211,226,105,93,253,143,59,16,38,23,5,31,12,19,7,1,3,13,108,10,109,15,32,110,26,109,4,116,192, + 217,254,224,254,223,217,192,116,3,109,26,109,30,16,109,10,108,14,3,7,19,12,31,5,23,38,15,60,143,253,93,134,2,189,24,69,107,254,210,106, + 69,3,63,252,15,147,147,210,209,1,40,149,254,242,95,1,14,252,219,95,1,14,95,2,218,131,115,46,102,62,118,25,161,167,58,196,21,21,196,58, + 167,161,27,114,65,101,46,15,36,130,65,43,66,44,69,64,121,62,122,5,226,119,132,132,118,227,5,122,62,121,57,76,44,66,3,19,13,97,137,22, + 9,58,140,117,24,147,65,119,106,57,7,28,7,138,87,15,66,14,81,87,46,62,46,8,254,253,140,158,158,140,1,3,8,46,62,46,81,87,14,66, + 15,96,129,42,57,106,119,65,147,24,117,140,58,9,22,137,97,251,71,97,75,116,117,75,231,231,164,163,254,186,1,126,1,14,95,254,242,95,95,1, + 14,95,0,0,0,1,255,185,4,154,0,199,6,18,0,3,0,10,64,3,0,3,4,0,16,212,204,48,17,51,3,35,199,117,153,6,18,254,136,0, + 0,2,252,215,5,14,255,41,5,217,0,3,0,7,0,165,64,13,4,0,206,6,2,8,1,100,0,5,100,4,8,16,212,252,220,236,49,0,16,212, + 60,236,50,48,0,75,176,14,84,75,176,17,84,91,88,189,0,8,0,64,0,1,0,8,0,8,255,192,56,17,55,56,89,1,75,176,14,84,75,176, + 13,84,91,75,176,23,84,91,88,189,0,8,255,192,0,1,0,8,0,8,0,64,56,17,55,56,89,1,75,176,17,84,75,176,25,84,91,88,189,0, + 8,0,64,0,1,0,8,0,8,255,192,56,17,55,56,89,0,75,176,24,84,88,189,0,8,255,192,0,1,0,8,0,8,0,64,56,17,55,56,89, + 64,17,96,1,96,2,96,5,96,6,112,1,112,2,112,5,112,6,8,1,93,1,51,21,35,37,51,21,35,254,94,203,203,254,121,203,203,5,217,203, + 203,203,0,0,0,1,253,115,4,238,254,240,5,246,0,3,0,127,64,17,2,3,0,3,1,0,0,3,66,0,2,250,4,1,3,3,4,16,196,16, + 192,49,0,16,244,204,48,75,83,88,7,16,5,201,7,16,5,201,89,34,0,75,176,12,84,88,189,0,4,255,192,0,1,0,4,0,4,0,64,56, + 17,55,56,89,0,75,176,14,84,88,189,0,4,0,64,0,1,0,4,0,4,255,192,56,17,55,56,89,64,32,6,2,21,2,37,1,37,2,54,2, + 70,2,86,2,106,1,103,2,9,15,0,15,1,31,0,31,1,47,0,47,1,6,93,1,93,1,51,3,35,254,55,185,228,153,5,246,254,248,0,0, + 0,1,252,182,5,14,255,74,5,233,0,29,0,117,64,33,22,16,15,3,19,12,7,1,0,3,8,23,12,195,4,19,195,27,8,250,30,16,1,15, + 0,7,22,86,24,7,86,9,30,16,212,236,212,236,17,57,57,57,57,49,0,16,244,60,236,212,236,50,18,23,57,17,18,23,57,48,0,75,176,12, + 84,88,189,0,30,255,192,0,1,0,30,0,30,0,64,56,17,55,56,89,0,75,176,14,84,88,189,0,30,0,64,0,1,0,30,0,30,255,192,56, + 17,55,56,89,180,16,11,31,26,2,93,1,39,46,1,35,34,6,29,1,35,52,54,51,50,22,31,1,30,1,51,50,54,61,1,51,14,1,35,34, + 38,253,252,57,25,31,12,36,40,125,103,86,36,61,48,57,23,34,15,32,40,125,2,103,84,34,59,5,57,33,14,11,50,45,6,101,118,16,27,30, + 13,12,51,41,6,100,119,16,0,1,253,12,4,238,254,139,5,246,0,3,0,137,64,17,1,2,3,2,0,3,3,2,66,0,1,250,4,1,3,3, + 4,16,196,16,192,49,0,16,244,204,48,75,83,88,7,16,5,201,7,16,5,201,89,34,0,75,176,12,84,88,189,0,4,255,192,0,1,0,4,0, + 4,0,64,56,17,55,56,89,0,75,176,14,84,88,189,0,4,0,64,0,1,0,4,0,4,255,192,56,17,55,56,89,64,42,6,0,6,1,22,0, + 18,1,36,0,36,1,53,1,67,1,85,0,85,1,159,0,159,1,175,0,175,1,14,15,0,15,3,31,0,31,3,47,0,47,3,6,93,1,93,1, + 19,35,3,253,199,196,153,230,5,246,254,248,1,8,0,0,0,1,252,207,4,238,255,49,5,248,0,6,0,119,64,10,4,0,5,2,250,7,4,2, + 6,7,16,212,196,57,49,0,16,244,60,196,57,48,0,75,176,12,84,88,189,0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,0,75, + 176,14,84,88,189,0,7,0,64,0,1,0,7,0,7,255,192,56,17,55,56,89,1,75,176,14,84,88,189,0,7,255,192,0,1,0,7,0,7,0, + 64,56,17,55,56,89,64,19,15,0,15,1,12,4,31,0,31,1,29,4,47,0,47,1,45,4,9,0,93,1,51,19,35,39,7,35,253,162,188,211, + 139,166,166,139,5,248,254,246,178,178,0,0,0,1,252,207,4,238,255,49,5,248,0,6,0,134,64,10,3,4,1,0,250,7,3,5,1,7,16,212, + 196,57,49,0,16,244,196,50,57,48,0,75,176,12,84,75,176,9,84,91,75,176,10,84,91,75,176,11,84,91,88,189,0,7,255,192,0,1,0,7, + 0,7,0,64,56,17,55,56,89,0,75,176,14,84,88,189,0,7,0,64,0,1,0,7,0,7,255,192,56,17,55,56,89,1,75,176,14,84,88,189, + 0,7,255,192,0,1,0,7,0,7,0,64,56,17,55,56,89,64,19,0,0,3,3,0,6,16,0,18,3,16,6,32,0,34,3,32,6,9,0,93, + 1,3,51,23,55,51,3,253,162,211,139,166,166,139,211,4,238,1,10,178,178,254,246,0,0,1,252,199,5,6,255,57,5,248,0,13,0,0,3,35, + 46,1,35,34,6,7,35,62,1,51,50,22,199,118,13,99,83,82,97,16,118,10,160,143,144,159,5,6,54,57,55,56,119,123,122,0,0,1,252,199, + 5,6,255,57,5,248,0,13,0,106,64,14,7,0,4,195,11,250,14,7,86,8,1,86,0,14,16,212,236,212,236,49,0,16,244,252,204,50,48,0, + 75,176,12,84,88,189,0,14,255,192,0,1,0,14,0,14,0,64,56,17,55,56,89,0,75,176,14,84,88,189,0,14,0,64,0,1,0,14,0,14, + 255,192,56,17,55,56,89,1,75,176,14,84,75,176,15,84,91,88,189,0,14,255,192,0,1,0,14,0,14,0,64,56,17,55,56,89,1,51,30,1, + 51,50,54,55,51,14,1,35,34,38,252,199,118,13,99,83,82,97,16,118,10,160,143,144,159,5,248,54,57,55,56,119,123,122,0,0,0,1,253,154, + 5,14,254,102,5,219,0,3,0,71,183,0,206,2,4,1,100,0,4,16,212,236,49,0,16,212,236,48,0,75,176,14,84,75,176,17,84,91,88,189, + 0,4,0,64,0,1,0,4,0,4,255,192,56,17,55,56,89,0,75,176,24,84,88,189,0,4,255,192,0,1,0,4,0,4,0,64,56,17,55,56, + 89,1,51,21,35,253,154,204,204,5,219,205,0,2,252,230,4,238,255,178,5,246,0,3,0,7,0,19,64,7,0,4,3,7,8,0,4,16,204,49, + 0,16,212,60,204,50,48,1,51,3,35,3,51,3,35,254,249,185,228,153,139,185,228,153,5,246,254,248,1,8,254,248,0,2,252,78,4,238,255,26, + 5,246,0,3,0,7,0,0,1,19,35,3,33,19,35,3,253,7,196,153,228,2,8,196,153,228,5,246,254,248,1,8,254,248,1,8,0,1,0,0, + 0,0,0,150,0,150,0,3,0,0,53,51,21,35,150,150,150,150,0,0,0,2,0,0,0,0,1,144,0,150,0,3,0,7,0,0,55,51,21,35, + 39,51,21,35,250,150,150,250,150,150,150,150,150,150,0,0,0,3,0,0,0,0,1,144,1,144,0,3,0,7,0,11,0,0,19,51,21,35,23,51, + 21,35,39,51,21,35,125,150,150,125,150,150,250,150,150,1,144,150,100,150,150,150,0,0,0,3,0,0,255,6,1,144,0,150,0,3,0,7,0,11, + 0,0,23,51,21,35,19,51,21,35,39,51,21,35,125,150,150,125,150,150,250,150,150,100,150,1,144,150,150,150,0,0,0,2,0,0,255,6,0,150, + 0,150,0,3,0,7,0,0,21,51,21,35,17,51,21,35,150,150,150,150,100,150,1,144,150,0,0,0,0,4,0,0,255,6,1,144,0,150,0,3, + 0,7,0,11,0,15,0,0,23,51,21,35,17,51,21,35,7,51,21,35,17,51,21,35,250,150,150,150,150,250,150,150,150,150,100,150,1,144,150,100, + 150,1,144,150,0,1,0,130,255,236,7,239,2,157,0,38,0,0,1,20,23,22,59,1,21,35,34,39,38,39,6,7,4,35,34,39,36,3,38,55, + 51,6,21,20,23,22,51,36,55,54,55,54,53,52,39,51,22,6,239,70,63,63,60,102,116,71,80,24,155,233,254,253,211,196,124,254,183,1,1,64, + 184,65,203,104,151,1,4,190,199,123,59,29,184,19,1,248,208,59,53,184,73,83,66,131,53,58,38,101,1,8,138,92,94,136,125,67,34,2,55,58, + 109,52,119,62,55,75,0,0,255,255,255,236,0,0,1,135,2,88,16,6,20,59,0,0,255,255,255,236,0,0,2,126,2,88,16,6,20,60,0,0, + 0,2,0,130,255,165,8,92,3,17,0,44,0,62,0,0,37,6,7,4,33,36,39,36,3,38,55,51,6,21,20,23,22,33,50,37,55,38,39,38, + 53,52,55,54,55,54,51,50,23,22,23,22,21,20,7,22,51,33,21,33,34,39,54,53,52,39,38,39,38,35,34,7,6,7,6,21,20,23,22,6, + 120,104,110,254,232,254,240,254,207,125,254,183,1,1,64,184,65,203,81,1,43,232,1,29,28,34,29,82,4,22,188,58,52,82,81,137,18,4,80,9, + 7,1,7,254,244,105,111,104,5,14,52,34,40,24,22,61,19,6,41,49,36,43,24,60,1,39,103,1,6,138,92,94,136,115,77,31,54,4,27,44, + 124,121,31,36,155,75,23,50,83,150,37,30,144,106,1,184,223,65,122,20,27,71,39,25,10,25,60,19,18,56,66,78,0,2,255,236,0,0,3,63, + 3,217,0,15,0,48,0,0,1,54,53,52,39,38,7,6,7,6,7,20,23,22,51,50,1,51,50,55,54,55,54,55,6,7,6,39,38,53,52,55, + 54,55,54,51,50,23,22,23,22,21,20,7,6,7,6,35,33,2,86,41,66,31,44,52,40,40,1,55,40,42,72,253,174,241,84,151,79,60,31,15, + 63,97,130,78,98,8,23,150,78,76,90,66,96,46,23,78,74,124,109,145,254,191,2,25,43,77,59,51,25,1,1,42,41,51,80,38,25,254,183,23, + 12,93,48,50,55,2,2,69,87,129,52,44,148,69,36,50,72,102,51,140,208,143,136,44,39,0,0,0,0,2,255,236,0,0,4,32,3,8,0,33, + 0,53,0,0,1,22,23,22,21,20,7,6,7,22,59,1,21,35,34,39,6,43,1,53,51,50,55,38,39,38,53,52,55,54,55,54,51,50,7,34, + 7,6,7,6,21,20,23,22,23,54,55,54,53,52,39,38,39,38,2,102,183,24,8,21,29,36,39,147,127,217,136,185,185,136,217,127,147,39,29,36, + 21,8,23,185,30,65,63,63,15,18,56,24,10,24,31,68,63,36,25,11,23,57,19,2,250,80,150,50,42,73,49,67,50,17,184,57,57,184,17,40, + 77,46,76,44,48,143,87,14,184,10,32,53,21,29,43,53,68,22,21,69,50,46,24,26,52,33,10,0,0,2,0,107,254,12,6,192,2,228,0,46, + 0,64,0,0,37,38,39,38,39,38,53,52,55,54,55,54,51,50,23,22,23,22,23,22,51,33,21,33,35,6,7,6,7,6,39,36,39,38,53,52, + 55,51,6,21,20,23,22,33,50,55,54,19,54,39,38,39,38,35,34,7,6,7,6,21,20,23,22,23,22,4,184,66,46,121,57,147,6,40,147,41, + 87,112,56,99,50,20,6,26,4,1,7,254,244,48,45,61,128,158,175,205,254,142,94,69,62,184,62,27,60,1,6,140,150,213,108,4,22,19,47,34, + 39,34,21,51,21,10,57,76,100,47,10,5,13,35,43,109,185,61,26,165,69,19,50,88,145,58,214,1,184,122,70,145,78,86,1,2,190,138,125,166, + 96,107,155,76,58,130,68,98,1,90,122,87,75,35,25,10,27,58,30,25,60,44,59,20,9,0,0,0,255,255,255,236,0,0,3,63,3,217,16,6, + 22,206,0,0,255,255,255,236,0,0,4,32,3,8,16,6,22,207,0,0,255,255,255,236,0,0,1,135,3,232,16,38,22,203,0,0,16,7,22,196, + 0,224,3,82,255,255,255,236,0,0,2,126,3,232,16,38,22,204,0,0,16,7,22,196,0,224,3,82,0,2,0,0,0,0,1,182,1,183,0,11, + 0,23,0,0,37,52,39,38,34,6,21,20,23,22,50,62,1,20,7,6,34,39,38,52,55,54,50,23,1,60,28,28,82,56,28,28,82,56,122,63, + 64,184,63,64,64,63,184,64,220,40,28,29,56,41,42,28,27,56,133,184,64,64,64,64,184,64,63,63,255,255,0,130,254,144,7,239,3,32,16,39, + 22,197,2,188,2,138,16,39,22,213,2,169,254,144,16,6,22,202,0,0,255,255,255,236,254,244,2,6,3,232,16,38,22,203,0,0,16,39,22,197, + 0,99,3,82,16,7,22,213,0,80,254,244,255,255,255,236,254,244,2,126,3,232,16,38,22,204,0,0,16,39,22,197,0,99,3,82,16,7,22,213, + 0,80,254,244,255,255,0,130,255,236,7,239,3,182,16,39,22,199,2,188,3,32,16,6,22,202,0,0,255,255,255,236,0,0,1,243,4,226,16,38, + 22,203,0,0,16,7,22,199,0,99,4,76,255,255,255,236,0,0,2,126,4,226,16,38,22,204,0,0,16,7,22,199,0,99,4,76,255,255,0,157, + 254,12,5,62,5,175,16,38,20,134,0,0,16,7,5,124,0,138,255,56,255,255,255,236,0,0,4,92,5,75,16,38,20,135,0,0,16,7,5,124, + 0,88,254,212,255,255,255,236,0,0,5,62,5,75,16,38,20,136,0,0,16,7,5,124,0,88,254,212,255,255,0,157,254,12,5,62,5,170,16,38, + 20,134,0,0,16,7,22,200,2,63,5,20,255,255,255,236,0,0,4,92,5,70,16,38,20,135,0,0,16,7,22,200,2,13,4,176,255,255,255,236, + 0,0,5,62,5,70,16,38,20,136,0,0,16,7,22,200,2,13,4,176,255,255,0,157,254,12,5,62,5,170,16,38,20,134,0,0,16,7,22,198, + 1,194,4,26,255,255,255,236,0,0,4,92,5,70,16,38,20,135,0,0,16,7,22,198,1,144,3,182,255,255,255,236,0,0,5,62,5,70,16,38, + 20,136,0,0,16,7,22,198,1,144,3,182,255,255,0,157,254,12,5,62,4,176,16,38,20,134,0,0,16,39,22,196,2,63,4,26,16,7,22,199, + 1,231,0,25,255,255,255,236,254,62,4,92,4,76,16,38,20,135,0,0,16,39,22,199,1,144,255,56,16,7,22,196,2,13,3,182,255,255,255,236, + 254,62,5,62,4,76,16,38,20,136,0,0,16,39,22,199,1,156,255,56,16,7,22,196,2,13,3,182,0,1,0,0,5,51,3,95,7,43,0,3, + 0,0,9,1,53,1,3,95,252,161,3,95,6,149,254,158,150,1,98,0,0,1,0,213,254,86,5,39,5,213,0,19,0,74,64,33,17,17,1,2, + 1,2,17,16,17,16,66,11,149,10,17,2,3,0,175,16,19,11,16,1,17,2,28,4,54,17,28,0,20,16,220,236,252,236,17,57,57,204,49,0, + 47,60,236,50,57,57,220,236,48,75,83,88,7,16,4,237,7,16,4,237,89,34,178,31,21,1,1,93,19,51,1,17,51,17,20,7,6,43,1,53, + 51,50,55,54,53,1,17,35,213,184,2,226,184,82,81,181,254,233,105,38,38,253,30,184,5,213,251,131,4,125,250,23,214,96,96,156,48,49,173,4, + 125,251,131,0,0,1,0,15,0,0,2,31,4,96,0,11,0,50,64,17,2,11,169,5,8,0,188,6,5,2,1,8,8,11,0,70,12,16,252,60, + 60,236,50,50,49,0,47,228,220,60,236,50,48,64,11,16,13,64,13,80,13,96,13,112,13,5,1,93,19,51,17,51,21,35,17,35,17,35,53,51, + 195,184,164,164,184,180,180,4,96,254,8,164,254,60,1,196,164,0,0,0,0,2,254,242,254,86,2,46,4,96,0,14,0,23,0,0,19,32,53,52, + 33,51,17,51,17,51,21,35,6,7,6,3,35,34,23,22,51,50,55,54,33,254,209,1,14,193,184,181,191,18,53,82,32,181,119,3,4,123,105,38, + 18,254,86,221,205,4,96,251,160,155,112,63,96,1,16,51,65,48,23,0,255,255,1,146,6,99,3,232,8,51,16,39,0,113,0,189,2,61,16,7, + 22,185,4,188,1,85,0,0,255,255,1,146,6,97,3,232,8,52,16,39,0,113,0,189,0,255,16,7,22,185,4,188,2,91,0,0,255,255,1,146, + 6,94,3,232,8,51,16,39,22,193,4,188,1,80,16,7,0,113,0,189,2,61,0,0,255,255,1,147,6,99,3,229,8,90,16,39,22,186,4,240, + 2,100,16,7,22,185,4,188,1,85,0,0,255,255,1,147,6,99,3,229,8,90,16,39,22,188,4,140,2,100,16,7,22,185,4,188,1,85,0,0, + 255,255,1,146,6,97,3,232,8,90,16,39,22,186,4,240,2,100,16,7,0,113,0,189,0,255,0,0,255,255,1,146,6,97,3,232,8,90,16,39, + 22,188,4,140,2,100,16,7,0,113,0,189,0,255,0,0,255,255,1,118,6,106,4,10,8,51,16,39,22,187,4,192,1,92,16,7,0,113,0,189, + 2,61,0,0,255,255,1,139,6,99,3,237,8,90,16,39,22,190,4,188,2,98,16,7,22,185,4,188,1,85,0,0,255,255,1,118,6,106,4,10, + 8,86,16,39,22,185,4,188,2,125,16,7,22,187,4,192,1,92,0,0,255,255,1,139,6,99,3,237,8,87,16,39,22,190,4,188,1,117,16,7, + 22,193,4,188,2,124,0,0,255,255,1,118,6,106,4,48,8,90,16,39,22,186,5,64,2,100,16,7,22,187,4,192,1,92,0,0,255,255,1,139, + 6,99,5,24,8,58,16,39,22,189,4,188,1,117,16,7,22,186,6,40,2,68,0,0,255,255,1,139,6,99,4,109,8,58,16,39,22,188,5,226, + 2,68,16,7,22,189,4,188,1,117,0,0,255,255,1,118,6,99,4,10,8,117,16,39,22,189,4,188,1,117,16,7,22,187,4,192,2,140,0,0, + 255,255,1,118,6,86,4,10,8,89,16,39,22,192,4,188,1,80,16,7,22,187,4,192,2,112,0,0,255,255,1,131,6,86,3,245,8,90,16,39, + 22,192,4,188,1,80,16,7,22,186,4,240,2,100,0,0,255,255,1,131,6,86,3,245,8,90,16,39,22,192,4,188,1,80,16,7,22,188,4,140, + 2,100,0,0,255,255,1,131,6,86,3,245,8,139,16,39,2,186,4,171,2,16,16,7,22,192,4,188,1,80,0,0,255,255,1,139,6,99,5,7, + 8,91,16,39,2,186,6,16,1,224,16,7,22,189,4,188,1,117,0,0,255,255,252,154,4,123,255,80,6,110,16,38,2,178,0,0,16,7,2,184, + 254,248,0,90,0,1,0,0,0,0,1,44,1,44,0,3,0,0,17,33,17,33,1,44,254,212,1,44,254,212,0,0,0,1,0,0,255,227,3,79, + 5,213,0,15,0,0,61,1,30,1,51,50,54,53,17,51,17,16,6,35,34,38,91,194,104,143,113,202,211,247,96,190,61,236,81,81,149,203,3,238, + 252,18,254,230,234,44,0,0,255,255,255,171,254,12,5,19,2,38,16,38,23,4,0,0,16,7,5,127,2,6,249,30,0,1,255,171,254,12,4,246, + 2,38,0,24,0,0,1,51,22,23,22,23,22,59,1,21,35,34,39,2,7,4,33,53,32,55,54,55,54,53,52,2,120,184,30,3,10,73,42,101, + 195,250,130,50,68,251,254,228,254,190,1,48,203,218,35,10,2,38,112,30,103,77,44,184,62,254,234,133,151,184,128,138,208,58,72,126,255,255,0,144, + 254,200,6,35,7,196,16,39,5,127,2,188,1,144,16,6,20,194,0,0,255,255,255,236,0,0,2,96,7,196,16,39,5,127,255,83,1,144,16,6, + 20,195,0,0,255,255,255,236,0,0,2,186,7,196,16,39,5,127,255,83,1,144,16,6,20,196,0,0,255,255,0,130,254,240,6,191,3,70,16,39, + 5,127,0,188,253,18,16,6,20,212,0,0,255,255,255,236,254,212,2,56,4,64,16,39,5,127,255,43,254,12,16,39,22,197,0,99,254,212,16,6, + 20,59,0,0,255,255,255,236,254,212,2,126,4,64,16,39,5,127,255,43,254,12,16,39,22,197,0,99,254,212,16,6,20,60,0,0,255,255,255,171, + 254,12,4,126,4,114,16,39,5,127,0,188,254,62,16,6,20,146,0,0,0,1,0,193,0,0,2,57,6,20,0,11,0,57,181,6,2,8,0,70, + 12,16,252,236,196,75,176,14,83,75,176,16,81,90,88,185,0,6,255,192,56,89,49,0,180,0,151,6,135,7,47,236,228,48,64,13,16,13,64,13, + 80,13,96,13,112,13,240,13,6,1,93,19,51,17,20,22,59,1,21,35,34,38,53,193,184,76,105,11,32,181,163,6,20,251,130,153,97,156,192,214, + 255,255,0,145,0,0,4,94,2,238,16,6,20,206,0,0,255,255,0,113,255,227,5,37,5,240,16,6,1,228,0,0,255,255,0,113,255,227,4,113, + 5,15,16,6,1,229,0,0,255,255,0,150,254,117,2,11,4,123,16,38,0,243,0,0,16,7,2,157,255,74,0,0,0,2,0,79,0,0,2,119, + 4,96,0,3,0,7,0,0,55,51,19,35,19,33,19,33,199,134,178,134,36,254,178,218,1,78,100,3,152,252,4,4,96,0,0,0,0,2,255,22, + 254,86,2,119,4,96,0,8,0,22,0,0,5,19,35,3,6,7,54,55,54,5,35,55,51,50,55,54,55,19,33,3,6,7,6,1,53,202,134,208, + 35,53,72,50,75,254,220,220,20,49,105,48,47,29,233,1,78,222,41,100,101,22,4,18,251,208,181,84,15,48,72,244,100,48,49,153,4,172,251,140, + 214,96,96,0,255,255,255,211,254,118,2,103,4,123,16,39,2,176,255,29,0,0,16,6,0,243,0,0,255,255,0,191,254,137,1,121,4,123,16,38, + 0,243,0,0,16,7,2,212,3,29,0,0,0,2,0,240,0,216,1,195,4,251,0,3,0,7,0,0,19,51,21,35,17,51,21,35,240,211,211,211, + 211,1,214,254,4,35,254,0,0,1,0,151,0,0,2,246,5,213,0,11,0,43,64,22,10,2,149,1,129,9,4,149,6,5,2,28,4,3,28,10, + 8,11,28,9,10,12,16,212,50,236,50,16,252,50,236,50,49,0,47,236,50,244,236,50,48,19,33,21,35,17,51,21,33,53,51,17,35,151,2,94, + 202,203,253,162,201,202,5,213,170,251,127,170,170,4,129,0,0,1,1,173,2,149,5,9,3,63,0,3,0,0,1,21,33,53,5,9,252,164,3,63, + 170,170,0,0,255,255,0,200,4,203,3,56,8,242,16,39,5,115,0,0,2,88,16,6,5,121,0,0,255,255,0,200,4,203,3,56,9,85,16,39, + 5,116,0,0,2,88,16,6,5,121,0,0,255,255,0,200,4,186,3,56,8,232,16,39,5,121,0,0,1,244,16,6,5,115,0,0,255,255,0,200, + 4,203,3,56,8,2,16,39,5,118,0,0,2,88,16,6,5,121,0,0,255,255,0,200,4,203,3,56,9,85,16,39,5,119,0,0,2,88,16,6, + 5,121,0,0,255,255,0,200,4,186,3,56,8,32,16,39,5,121,0,0,1,44,16,6,5,118,0,0,255,255,0,220,4,191,3,36,7,158,16,39, + 5,118,0,0,1,244,16,6,5,124,0,0,255,255,0,220,4,191,3,36,8,241,16,39,5,119,0,0,1,244,16,6,5,124,0,0,0,1,0,193, + 0,0,2,78,5,213,0,5,0,26,64,13,4,84,2,175,0,4,7,4,3,8,1,4,6,16,252,252,252,196,49,0,47,236,236,48,51,17,51,17, + 51,21,193,184,213,5,213,250,190,147,0,0,0,1,255,236,0,0,2,78,5,213,0,7,0,30,64,15,1,4,84,7,175,2,1,9,4,0,8,6, + 4,4,8,16,196,252,252,252,196,49,0,47,236,236,50,48,37,51,21,33,53,51,17,51,1,121,213,253,158,213,184,147,147,147,5,66,0,1,255,236, + 0,0,1,121,5,213,0,5,0,26,64,13,2,84,4,175,0,7,4,0,8,4,4,2,6,16,196,252,252,236,49,0,47,236,236,48,41,1,53,51, + 17,51,1,121,254,115,213,184,147,5,66,0,0,2,0,113,255,227,4,166,3,147,0,7,0,21,0,56,64,13,21,23,69,5,28,8,19,17,1,28, + 13,69,22,16,244,236,212,182,16,17,48,17,160,17,3,93,57,57,236,252,196,49,0,64,11,7,160,15,8,3,160,10,140,19,160,8,47,236,244,236, + 16,212,236,48,0,16,22,32,54,16,38,32,1,6,35,34,0,16,0,32,0,21,20,7,51,21,1,13,185,1,6,185,185,254,250,1,42,78,89,195, + 254,235,1,21,1,134,1,21,104,237,2,62,254,250,185,185,1,6,185,253,9,29,1,21,1,134,1,21,254,235,195,169,127,147,0,0,0,2,255,236, + 255,227,4,166,3,147,0,7,0,25,0,65,64,17,24,27,69,5,28,14,11,8,23,4,21,1,28,16,69,13,26,16,196,244,236,212,182,16,21,48, + 21,160,21,3,93,23,57,236,252,196,49,0,64,13,7,160,19,12,3,160,10,140,14,23,160,25,12,47,60,236,50,244,236,16,212,236,48,0,16,22, + 32,54,16,38,32,1,6,34,39,33,53,51,38,53,52,0,32,0,21,20,7,51,21,1,13,185,1,6,185,185,254,250,1,42,78,178,78,254,74,237, + 104,1,21,1,134,1,21,104,237,2,62,254,250,185,185,1,6,185,253,9,29,29,147,127,169,195,1,21,254,235,195,169,127,147,0,0,0,2,255,236, + 255,227,4,33,3,147,0,7,0,21,0,56,64,13,23,69,5,28,19,8,15,1,28,10,69,21,22,16,196,244,236,212,182,16,15,48,15,160,15,3, + 93,57,57,236,236,49,0,64,11,7,160,13,19,3,160,17,140,8,160,19,47,236,244,236,16,212,236,48,0,16,22,32,54,16,38,32,3,38,53,52, + 0,32,0,16,0,35,34,39,33,53,1,13,185,1,6,185,185,254,250,237,104,1,21,1,134,1,21,254,235,195,89,78,254,74,2,62,254,250,185,185, + 1,6,185,253,156,127,169,195,1,21,254,235,254,122,254,235,29,147,0,0,0,1,0,61,0,0,3,120,5,217,0,10,0,52,64,13,5,8,2,10, + 12,7,6,8,28,3,4,2,11,16,220,196,50,252,196,50,220,196,17,18,57,49,0,64,12,5,2,8,3,3,1,6,3,129,10,135,1,47,236,236, + 50,17,18,23,57,48,41,1,17,1,51,27,1,51,1,17,33,3,120,253,222,254,231,194,179,179,194,254,231,1,106,3,42,2,175,254,93,1,163,253, + 81,253,105,0,0,1,255,236,0,0,3,120,5,217,0,12,0,54,64,14,8,11,5,0,14,10,9,11,28,6,7,5,3,13,16,196,220,196,50,252, + 196,50,220,196,17,18,57,49,0,64,12,8,5,11,3,1,9,6,129,12,3,135,1,47,236,50,236,50,17,23,57,48,37,21,33,53,33,17,1,51, + 27,1,51,1,17,3,120,252,116,1,106,254,231,194,179,179,194,254,231,147,147,147,2,151,2,175,254,93,1,163,253,81,253,105,0,0,0,1,255,236, + 0,0,3,39,5,217,0,10,0,52,64,13,6,9,3,12,8,7,9,28,4,5,3,1,11,16,196,220,196,50,252,196,50,204,17,18,57,49,0,64, + 12,6,3,9,3,4,10,7,4,129,1,135,10,47,236,236,50,17,18,23,57,48,35,53,33,17,1,51,27,1,51,1,17,20,1,106,254,231,194,179, + 179,194,254,231,147,2,151,2,175,254,93,1,163,253,81,252,214,0,0,0,0,1,0,61,0,0,4,208,3,113,0,8,0,0,41,1,9,1,35,1, + 51,1,51,4,208,254,236,254,162,254,162,195,1,164,250,1,109,136,2,189,253,67,3,113,253,34,0,0,0,1,255,236,0,0,4,208,3,113,0,10, + 0,0,41,1,53,51,1,51,1,51,21,33,1,1,0,254,236,136,1,109,250,1,109,136,254,236,254,162,147,2,222,253,34,147,2,189,0,1,255,236, + 0,0,4,127,3,113,0,8,0,0,41,1,53,51,1,51,1,35,1,1,0,254,236,136,1,109,250,1,164,195,254,162,147,2,222,252,143,2,189,0, + 0,1,0,186,0,0,5,79,3,113,0,9,0,36,64,11,9,11,4,7,28,5,4,28,2,4,10,16,252,236,212,252,252,196,49,0,182,6,3,163, + 8,5,135,1,47,236,50,244,60,48,41,1,17,51,17,33,17,51,17,51,5,79,251,107,185,2,85,185,206,3,113,253,34,2,222,253,34,0,0,0, + 0,1,255,236,0,0,5,79,3,113,0,11,0,40,64,12,11,13,4,10,28,8,6,28,4,4,2,12,16,196,252,236,212,252,252,196,49,0,183,8, + 5,163,3,6,10,135,1,47,236,50,50,244,60,48,41,1,53,51,17,51,17,33,17,51,17,51,5,79,250,157,206,185,2,85,185,206,147,2,222,253, + 34,2,222,253,34,0,0,0,0,1,255,236,0,0,4,129,3,113,0,9,0,36,64,11,11,4,0,28,8,6,28,4,4,2,10,16,196,252,236,212, + 252,236,49,0,182,8,5,163,3,6,135,0,47,236,50,244,60,48,41,1,53,51,17,51,17,33,17,51,4,129,251,107,206,185,2,85,185,147,2,222, + 253,34,2,222,0,1,0,186,0,0,5,79,3,113,0,9,0,36,64,10,8,11,4,6,28,2,1,4,4,10,16,252,60,212,252,252,196,49,0,183, + 4,160,6,163,7,2,160,0,47,236,50,244,236,48,51,53,33,17,33,53,33,17,51,21,186,3,14,252,242,3,199,206,147,2,75,147,253,34,147,0, + 0,1,255,236,0,0,5,79,3,113,0,9,0,36,64,10,8,11,4,6,28,2,4,4,1,10,16,196,252,212,252,252,196,49,0,183,4,160,6,163, + 7,2,160,0,47,236,50,244,236,48,35,53,33,17,33,53,33,17,51,21,20,3,220,252,242,3,199,206,147,2,75,147,253,34,147,0,0,1,255,236, + 0,0,4,129,3,113,0,7,0,32,64,9,9,4,0,28,4,6,4,3,8,16,196,252,212,252,236,49,0,182,6,160,0,163,4,160,2,47,236,244, + 236,48,1,17,33,53,33,17,33,53,4,129,251,107,3,220,252,242,3,113,252,143,147,2,75,147,0,0,0,2,0,113,0,0,4,212,5,226,0,19, + 0,31,0,58,64,14,18,33,69,27,28,12,16,28,1,21,28,6,69,32,16,252,236,220,178,64,1,1,93,252,220,178,64,12,1,93,236,252,196,49, + 0,64,11,24,149,1,16,30,149,9,145,17,160,0,47,236,244,236,212,60,236,48,33,17,38,39,46,1,52,62,1,32,30,1,20,6,7,6,7,17, + 33,21,0,20,30,1,50,62,1,52,46,1,34,6,2,4,82,74,114,133,133,228,1,12,230,131,131,115,75,82,2,24,252,57,91,156,184,157,90,90, + 157,184,156,3,14,11,32,49,168,197,169,98,98,169,197,168,49,32,11,253,133,147,4,173,112,96,56,56,96,112,96,56,56,0,0,0,0,2,255,236, + 0,0,4,212,5,226,0,21,0,33,0,62,64,15,1,35,69,29,28,17,21,28,6,23,28,11,69,4,34,16,196,252,236,220,178,64,6,1,93,252, + 220,178,64,17,1,93,236,252,196,49,0,64,12,26,149,6,21,32,149,14,145,0,5,160,2,47,236,50,244,236,212,60,236,48,37,33,21,33,53,33, + 17,38,39,46,1,52,62,1,32,30,1,20,6,7,6,7,0,20,30,1,50,62,1,52,46,1,34,6,2,188,2,24,251,24,2,24,82,74,114,133, + 133,228,1,12,230,131,131,115,75,82,254,81,91,156,184,157,90,90,157,184,156,147,147,147,2,123,11,32,49,168,197,169,98,98,169,197,168,49,32,11, + 1,159,112,96,56,56,96,112,96,56,56,0,0,2,255,236,0,0,4,79,5,226,0,19,0,31,0,58,64,14,33,69,27,28,14,18,28,3,21,28, + 8,69,1,32,16,196,252,236,220,178,64,6,1,93,252,220,178,64,17,1,93,236,236,49,0,64,11,24,149,3,18,30,149,11,145,2,160,19,47,236, + 244,236,212,60,236,48,35,53,33,17,38,39,46,1,52,62,1,32,30,1,20,6,7,6,7,17,0,20,30,1,50,62,1,52,46,1,34,6,20,2, + 24,82,74,114,133,133,228,1,12,230,131,131,115,75,82,254,81,91,156,184,157,90,90,157,184,156,147,2,123,11,32,49,168,197,169,98,98,169,197,168, + 49,32,11,252,242,4,173,112,96,56,56,96,112,96,56,56,0,2,0,186,0,0,5,79,4,166,0,8,0,12,0,38,64,10,2,6,0,5,11,4, + 13,12,14,13,16,212,196,16,252,220,204,204,50,49,0,182,2,3,5,7,11,160,9,47,236,220,220,220,204,48,1,16,51,21,34,7,51,21,35,1, + 33,53,33,2,17,242,132,2,133,241,3,62,251,107,4,149,3,156,1,10,102,154,158,252,248,147,0,0,0,2,255,236,0,0,5,79,4,166,0,8, + 0,12,0,34,183,3,6,0,5,12,14,11,13,16,196,212,196,220,204,204,50,49,0,182,2,3,5,7,11,160,9,47,236,220,220,220,204,48,1,16, + 51,21,34,7,51,21,35,1,33,53,33,2,17,242,132,2,133,241,3,62,250,157,5,99,3,156,1,10,102,154,158,252,248,147,0,0,0,2,255,236, + 0,0,4,129,4,166,0,8,0,12,0,36,64,9,2,6,0,5,12,4,14,11,13,16,196,220,252,220,204,204,50,49,0,182,2,3,5,7,11,160, + 9,47,236,220,220,220,204,48,1,16,51,21,34,7,51,21,35,1,33,53,33,2,17,242,132,2,133,241,2,112,251,107,4,149,3,156,1,10,102,154, + 158,252,248,147,0,2,0,113,0,0,6,181,5,238,0,19,0,29,0,55,64,15,18,31,17,8,1,4,20,8,2,14,27,8,9,69,30,16,252,236, + 212,60,236,50,212,252,220,196,49,0,64,13,3,5,1,160,29,15,24,160,10,145,17,160,0,47,236,244,236,212,60,236,50,204,48,33,17,33,17,35, + 17,35,34,38,16,54,32,23,22,29,1,33,17,51,21,1,53,52,39,38,34,6,20,22,51,5,46,254,67,156,248,188,176,177,1,102,94,139,2,118, + 206,252,32,93,56,198,109,114,94,2,222,254,196,1,60,214,1,85,229,102,152,182,201,253,34,147,3,113,201,131,93,56,152,198,131,0,0,2,255,236, + 0,0,6,181,5,238,0,21,0,31,0,59,64,16,18,33,17,8,1,4,22,8,2,14,29,8,9,69,21,32,16,196,252,236,212,60,236,50,212,252, + 220,196,49,0,64,14,3,5,1,160,31,15,26,160,10,145,0,17,160,19,47,236,50,244,236,212,60,236,50,204,48,37,17,33,17,35,17,35,34,38, + 16,54,32,23,22,29,1,33,17,51,21,33,53,1,53,52,39,38,34,6,20,22,51,5,46,254,67,156,248,188,176,177,1,102,94,139,2,118,206,249, + 55,2,233,93,56,198,109,114,94,147,2,75,254,196,1,60,214,1,85,229,102,152,182,201,253,34,147,147,2,222,201,131,93,56,152,198,131,0,0,0, + 0,2,255,236,0,0,5,231,5,238,0,19,0,29,0,55,64,15,31,17,8,1,4,20,8,2,14,27,8,9,69,19,30,16,196,252,236,212,60,236, + 50,212,252,204,49,0,64,13,3,5,1,160,29,15,24,160,10,145,0,160,17,47,236,244,236,212,60,236,50,204,48,37,17,33,17,35,17,35,34,38, + 16,54,32,23,22,29,1,33,17,33,53,1,53,52,39,38,34,6,20,22,51,5,46,254,67,156,248,188,176,177,1,102,94,139,2,118,250,5,2,233, + 93,56,198,109,114,94,147,2,75,254,196,1,60,214,1,85,229,102,152,182,201,252,143,147,2,222,201,131,93,56,152,198,131,0,0,0,0,1,0,193, + 0,0,3,149,5,213,0,11,0,44,64,11,10,13,7,3,19,5,9,28,1,4,12,16,252,252,60,252,60,220,196,49,0,64,11,5,160,7,0,4, + 160,2,175,10,160,0,47,236,244,236,16,220,236,48,51,17,33,21,33,17,33,21,33,17,33,21,193,2,131,254,53,1,203,254,53,2,28,5,213,147, + 254,47,146,253,180,147,0,0,0,1,255,236,0,0,3,149,5,213,0,13,0,48,64,12,12,15,9,5,19,7,11,28,3,4,1,14,16,196,252,252, + 60,252,60,220,196,49,0,64,12,7,160,9,0,6,160,4,175,2,12,160,0,47,236,50,244,236,16,220,236,48,35,53,51,17,33,21,33,17,33,21, + 33,17,33,21,20,213,2,131,254,53,1,203,254,53,2,28,147,5,66,147,254,47,146,253,180,147,0,0,0,1,255,236,0,0,3,68,5,213,0,11, + 0,44,64,11,13,6,9,19,7,11,28,4,4,2,12,16,196,252,252,60,252,60,204,49,0,64,11,8,160,10,0,7,160,5,175,2,160,0,47,236, + 244,236,16,220,236,48,41,1,53,51,17,33,21,33,17,33,21,33,1,121,254,115,213,2,131,254,53,1,203,254,53,147,5,66,147,254,47,146,0,0, + 0,1,0,61,0,0,3,149,5,213,0,11,0,44,64,11,10,13,4,8,18,0,4,19,2,6,12,16,220,60,252,60,252,252,196,49,0,64,11,4, + 160,2,0,5,160,7,175,10,160,0,47,236,244,236,16,220,236,48,33,17,33,53,33,17,33,53,33,17,51,21,2,8,254,53,1,203,254,53,2,131, + 213,2,223,146,1,209,147,250,190,147,0,0,0,1,255,236,0,0,3,149,5,213,0,13,0,48,64,12,12,15,4,10,18,6,2,19,4,8,1,14, + 16,196,220,60,252,60,252,252,196,49,0,64,12,5,160,3,0,8,160,10,175,12,2,160,0,47,236,50,244,236,16,220,236,48,35,53,33,17,33,53, + 33,17,33,53,33,17,51,21,20,2,28,254,53,1,203,254,53,2,131,213,147,2,76,146,1,209,147,250,190,147,0,0,0,1,255,236,0,0,2,192, + 5,213,0,11,0,44,64,11,13,4,11,18,3,7,19,5,9,2,12,16,196,220,60,252,60,252,236,49,0,64,11,7,160,5,0,8,160,10,175,2, + 160,0,47,236,244,236,16,220,236,48,41,1,53,33,17,33,53,33,17,33,53,33,2,192,253,44,2,28,254,53,1,203,254,53,2,131,147,2,76,146, + 1,209,147,0,0,2,0,186,0,0,4,140,5,213,0,10,0,23,0,42,64,12,22,25,27,7,28,19,14,2,28,12,4,24,16,252,252,60,212,236, + 252,196,49,0,64,9,1,160,15,13,129,3,22,160,11,16,236,50,236,212,236,48,1,33,17,33,50,55,54,53,52,39,38,1,17,51,17,33,50,23, + 22,21,20,7,51,21,2,156,254,208,1,44,82,52,44,44,61,253,217,185,1,85,105,127,88,79,211,2,222,253,181,93,79,122,125,73,95,253,34,5, + 213,253,156,135,95,210,164,130,147,0,0,0,0,2,255,236,0,0,4,140,5,213,0,14,0,25,0,46,64,13,13,27,27,22,28,10,5,17,28,3, + 4,1,26,16,196,252,252,60,212,236,252,196,49,0,64,10,16,160,6,4,129,2,18,13,160,0,47,236,50,50,236,212,236,48,35,53,51,17,51,17, + 33,50,23,22,21,20,7,51,21,1,33,17,33,50,55,54,53,52,39,38,20,206,185,1,85,105,127,88,79,211,254,16,254,208,1,44,82,52,44,44, + 61,147,5,66,253,156,135,95,210,164,130,147,2,222,253,181,93,79,122,125,73,95,0,0,0,2,255,236,0,0,4,8,5,213,0,10,0,25,0,42, + 64,12,27,27,7,28,21,16,2,28,14,4,12,26,16,196,252,252,60,212,236,236,49,0,64,9,1,160,17,15,129,13,3,160,11,47,236,50,236,212, + 236,48,1,33,17,33,50,55,54,53,52,39,38,1,53,51,17,51,17,33,50,23,22,21,20,7,6,35,2,156,254,208,1,44,82,52,44,44,61,253, + 11,206,185,1,85,105,127,88,88,88,108,2,222,253,181,93,79,122,125,73,95,253,34,147,5,66,253,156,135,95,210,173,135,133,0,0,0,1,0,193, + 0,0,4,249,5,213,0,19,0,64,64,11,18,21,4,9,17,28,5,0,6,4,20,16,244,220,178,95,0,1,93,57,252,212,252,196,0,64,11,11, + 5,0,6,10,160,7,129,17,160,0,47,236,244,236,57,17,57,57,64,7,11,18,10,18,5,6,5,7,16,5,236,236,49,48,33,52,2,39,38,39, + 3,53,33,21,5,19,22,23,22,23,22,23,33,21,2,170,27,53,77,137,195,3,99,253,153,157,136,52,66,6,2,1,1,152,153,1,95,150,220,220, + 1,57,86,147,1,254,239,234,184,230,156,64,57,147,0,0,0,1,255,236,0,0,4,249,5,213,0,22,0,68,64,12,21,24,4,12,20,28,8,2, + 9,4,1,23,16,196,244,220,178,95,2,1,93,57,252,212,252,196,0,64,12,14,8,0,9,13,160,10,129,20,2,160,0,47,236,50,244,236,57,17, + 57,57,64,7,14,18,13,18,8,9,8,7,16,5,236,236,49,48,35,53,33,38,39,38,39,38,39,3,53,33,21,5,19,22,23,22,23,22,23,33, + 21,20,2,187,3,8,13,53,77,137,195,3,99,253,153,157,136,52,66,6,2,1,1,152,147,88,93,176,150,220,220,1,57,86,147,1,254,239,234,184, + 230,156,64,57,147,0,0,0,0,1,255,236,0,0,4,36,5,213,0,19,0,64,64,11,21,4,12,19,28,8,2,9,4,1,20,16,196,244,220,178, + 95,2,1,93,57,252,212,236,0,64,11,14,8,0,9,13,160,10,129,2,160,0,47,236,244,236,57,17,57,57,64,7,14,18,13,18,8,9,8,7, + 16,5,236,236,49,48,35,53,33,38,39,38,39,38,39,3,53,33,21,5,19,22,23,22,18,7,20,2,187,3,8,13,53,77,137,195,3,99,253,153, + 157,136,52,66,11,1,147,88,93,176,150,220,220,1,57,86,147,1,254,239,234,184,230,254,201,113,0,0,0,1,0,61,0,0,2,225,5,213,0,8, + 0,58,64,9,7,10,4,3,5,28,1,3,9,16,212,220,252,17,57,220,196,49,0,64,13,2,18,1,18,3,4,3,3,4,129,6,160,8,47,236, + 244,204,178,31,3,1,93,7,16,4,236,236,180,141,2,141,1,2,93,48,33,17,1,53,1,51,17,51,21,1,84,254,233,1,21,186,213,4,223,254, + 199,246,1,57,250,190,147,0,0,1,255,236,0,0,2,225,5,213,0,10,0,62,64,10,9,12,6,5,7,28,3,5,1,11,16,196,212,220,252,17, + 57,220,196,49,0,64,14,4,18,3,18,5,6,5,5,6,129,8,2,160,10,47,236,50,244,204,178,31,5,1,93,7,16,4,236,236,180,141,4,141, + 3,2,93,48,35,53,33,17,1,53,1,51,17,51,21,20,1,104,254,233,1,21,186,213,147,4,76,254,199,246,1,57,250,190,147,0,0,1,255,236, + 0,0,2,12,5,213,0,8,0,58,64,9,10,6,5,7,28,3,5,1,9,16,196,212,220,252,17,57,204,49,0,64,13,4,18,3,18,5,6,5, + 5,6,129,2,160,8,47,236,244,204,178,31,5,1,93,7,16,4,236,236,180,141,4,141,3,2,93,48,35,53,33,17,1,53,1,51,17,20,1,104, + 254,233,1,21,186,147,4,76,254,199,246,1,57,250,43,0,0,3,0,193,0,0,7,192,4,26,0,17,0,26,0,35,0,49,64,14,16,37,28,14, + 28,18,24,28,27,33,28,1,4,36,16,252,236,212,236,212,252,252,196,49,0,64,11,21,160,10,30,160,4,16,26,35,160,0,47,236,50,50,212,236, + 212,236,48,51,17,52,18,51,50,22,23,62,1,51,50,23,22,21,17,51,21,1,52,38,35,34,6,21,17,33,1,52,38,35,34,6,29,1,33,193, + 244,198,125,120,53,37,150,211,210,94,136,213,254,113,164,90,129,127,1,254,253,72,164,90,108,148,1,254,1,238,166,0,255,75,45,45,210,88,128,104, + 253,185,147,2,124,130,128,197,149,254,110,1,99,131,127,167,210,242,0,0,0,3,255,236,0,0,7,192,4,26,0,19,0,28,0,37,0,53,64,15, + 18,39,4,16,28,20,26,28,29,35,28,3,4,1,38,16,196,252,236,212,236,212,252,252,196,49,0,64,12,23,160,12,32,160,6,17,27,36,2,160, + 19,47,236,50,50,50,212,236,212,236,48,35,53,51,17,52,18,51,50,22,23,62,1,51,50,23,22,21,17,51,21,1,52,38,35,34,6,21,17,33, + 1,52,38,35,34,6,29,1,33,20,213,244,198,125,120,53,37,150,211,210,94,136,213,254,113,164,90,129,127,1,254,253,72,164,90,108,148,1,254,147, + 1,91,166,0,255,75,45,45,210,88,128,104,253,185,147,2,124,130,128,197,149,254,110,1,99,131,127,167,210,242,0,0,0,3,255,236,0,0,6,235, + 4,26,0,17,0,26,0,35,0,49,64,14,37,4,16,28,18,24,28,27,33,28,3,4,1,36,16,196,252,236,212,236,212,252,236,49,0,64,11,21, + 160,12,30,160,6,2,34,25,160,17,47,236,50,50,212,236,212,236,48,35,53,51,17,52,18,51,50,22,23,62,1,51,50,23,22,21,17,3,52,38, + 35,34,6,21,17,33,1,52,38,35,34,6,29,1,33,20,213,244,198,125,120,53,37,150,211,210,94,136,186,164,90,129,127,1,254,253,72,164,90,108, + 148,1,254,147,1,91,166,0,255,75,45,45,210,88,128,104,253,38,2,124,130,128,197,149,254,110,1,99,131,127,167,210,242,0,0,0,0,1,0,61, + 0,0,3,220,5,213,0,13,0,45,64,12,12,15,9,31,11,7,28,5,1,31,3,14,16,220,252,60,252,60,252,220,196,49,0,64,10,9,1,160, + 3,7,6,129,12,160,0,47,236,252,220,60,252,60,48,33,17,33,53,33,17,51,17,33,21,33,17,33,21,1,136,254,181,1,75,184,1,75,254,181, + 1,156,3,129,147,1,193,254,63,147,253,18,147,0,0,0,0,1,255,236,0,0,3,220,5,213,0,15,0,49,64,13,14,17,11,31,13,9,28,7, + 3,31,5,1,16,16,196,220,252,60,252,60,252,204,196,49,0,64,11,11,3,160,5,9,8,129,2,14,160,0,47,236,50,244,220,60,252,60,48,35, + 53,33,17,33,53,33,17,51,17,33,21,33,17,33,21,20,1,156,254,181,1,75,184,1,75,254,181,1,156,147,2,238,147,1,193,254,63,147,253,18, + 147,0,0,0,0,1,255,236,0,0,3,139,5,213,0,13,0,45,64,12,15,12,31,0,10,28,8,4,31,6,2,14,16,196,220,252,60,252,60,252, + 204,49,0,64,10,12,4,160,6,10,8,129,2,160,0,47,236,244,220,60,252,60,48,41,1,53,33,17,33,53,33,17,51,17,33,21,33,2,64,253, + 172,1,156,254,181,1,75,184,1,75,254,181,147,2,238,147,1,193,254,63,147,0,0,0,0,2,0,61,0,0,6,88,5,213,0,3,0,21,0,62, + 64,17,20,23,16,31,14,18,28,0,12,10,2,28,4,8,31,6,22,16,220,252,60,252,60,220,60,252,60,252,220,196,49,0,64,14,5,1,17,160, + 7,11,15,9,13,129,3,19,160,4,47,236,50,244,60,220,60,60,236,50,50,48,37,17,33,17,7,17,33,53,33,17,51,17,33,17,51,17,33,21, + 33,17,33,21,4,4,254,61,185,254,181,1,75,185,1,195,184,1,76,254,180,1,156,147,2,238,253,18,147,3,129,147,1,193,254,63,1,193,254,63, + 147,253,18,147,0,2,255,236,0,0,6,88,5,213,0,19,0,23,0,66,64,18,18,25,14,31,12,16,28,20,10,8,22,28,2,6,31,4,0,24, + 16,196,220,252,60,252,60,220,60,252,60,252,220,196,49,0,64,15,15,21,3,160,5,9,13,7,11,129,17,23,1,160,19,47,236,50,50,244,60,220, + 60,60,236,50,50,48,35,53,33,17,33,53,33,17,51,17,33,17,51,17,33,21,33,17,33,21,37,17,33,17,20,1,156,254,181,1,75,185,1,195, + 184,1,76,254,180,1,156,253,172,254,61,147,2,238,147,1,193,254,63,1,193,254,63,147,253,18,147,147,2,238,253,18,0,2,255,236,0,0,6,8, + 5,213,0,17,0,21,0,62,64,17,23,15,31,13,17,18,18,11,9,20,28,3,7,31,5,1,22,16,196,220,252,60,252,60,220,60,252,60,252,204, + 49,0,64,14,16,19,4,160,6,10,14,12,8,129,21,2,160,0,47,236,50,244,60,220,60,60,252,60,60,48,41,1,53,33,17,33,53,33,17,51, + 17,33,17,51,17,33,21,33,3,17,33,17,4,188,251,48,1,156,254,181,1,75,185,1,195,184,1,76,254,180,184,254,61,147,2,238,147,1,193,254, + 63,1,193,254,63,147,253,18,2,238,253,18,0,2,0,186,0,0,5,79,3,113,0,5,0,9,0,37,64,11,4,11,4,2,28,8,7,28,1,4, + 10,16,252,236,212,252,252,196,49,0,183,6,160,2,163,3,8,160,0,47,236,50,244,236,48,51,17,33,17,51,21,1,17,33,17,186,3,199,206,252, + 36,2,85,3,113,253,34,147,2,222,253,181,2,75,0,0,0,2,255,236,0,0,5,79,3,113,0,7,0,11,0,42,64,12,6,13,4,4,28,10, + 9,28,3,4,1,12,16,196,252,236,212,252,252,196,49,0,64,9,8,160,4,163,2,9,5,160,0,47,236,50,50,244,236,48,35,53,51,17,33,17, + 51,21,1,17,33,17,20,206,3,199,206,252,36,2,85,147,2,222,253,34,147,2,222,253,181,2,75,0,0,2,255,236,0,0,4,129,3,113,0,5, + 0,9,0,37,64,11,11,4,5,28,8,7,28,4,4,2,10,16,196,252,236,212,252,236,49,0,183,9,160,4,163,3,7,160,0,47,236,50,244,236, + 48,41,1,53,51,17,33,5,17,33,17,4,129,251,107,206,3,199,252,242,2,85,147,2,222,147,253,181,2,75,0,0,0,2,0,61,0,0,5,20, + 5,213,0,2,0,8,0,67,180,7,10,5,4,9,16,212,196,196,196,49,0,64,10,66,1,149,4,129,2,149,7,160,3,47,236,236,244,236,48,75, + 83,88,64,18,2,17,6,1,2,0,17,5,5,6,2,17,3,1,17,4,4,3,5,7,16,236,16,236,7,16,236,8,16,236,89,1,33,1,7,1, + 33,1,33,21,3,198,253,116,1,70,115,254,48,4,134,254,104,1,233,5,66,251,126,192,5,213,250,190,147,0,0,0,0,2,255,236,0,0,5,20, + 5,213,0,2,0,10,0,70,181,9,12,7,6,4,11,16,196,212,196,196,49,0,64,11,66,1,149,6,129,2,149,4,9,160,3,47,236,50,236,244, + 236,48,75,83,88,64,18,2,17,8,1,2,0,17,7,7,8,2,17,5,1,17,6,6,5,5,7,16,236,16,236,7,16,236,8,16,236,89,1,33, + 1,5,53,33,1,33,1,33,21,3,198,253,116,1,70,253,108,1,233,254,104,4,134,254,104,1,233,5,66,251,126,192,147,5,66,250,190,147,0,0, + 0,2,255,236,0,0,4,195,5,213,0,2,0,8,0,67,180,10,7,6,4,9,16,196,212,196,196,49,0,64,10,66,1,149,6,129,2,149,4,160, + 3,47,236,236,244,236,48,75,83,88,64,18,2,17,8,1,2,0,17,7,7,8,2,17,5,1,17,6,6,5,5,7,16,236,16,236,7,16,236,8, + 16,236,89,1,33,1,5,53,33,1,33,1,3,198,253,116,1,70,253,108,1,233,254,104,4,134,254,48,5,66,251,126,192,147,5,66,250,43,0,0, + 0,3,0,193,0,0,5,243,5,213,0,10,0,14,0,31,0,56,64,16,30,33,4,5,28,23,29,0,28,18,14,12,28,16,4,32,16,252,236,212, + 60,252,60,212,236,252,196,49,0,64,13,28,11,160,1,17,10,160,19,129,13,30,160,15,47,236,50,244,236,220,60,236,50,48,1,51,50,55,54,53, + 52,39,38,43,1,1,17,33,17,1,17,33,17,33,50,23,22,21,6,7,6,47,1,17,33,21,3,109,168,93,37,31,31,29,105,164,254,13,1,59, + 254,12,1,244,1,176,132,64,69,1,68,92,140,212,2,134,3,113,81,69,61,60,100,94,253,156,253,181,2,75,253,34,3,113,2,100,133,144,124,145, + 91,124,1,1,253,181,147,0,0,3,255,236,0,0,5,243,5,213,0,10,0,14,0,33,0,60,64,17,32,35,4,5,28,25,31,0,28,20,14,12, + 28,18,4,16,34,16,196,252,236,212,60,252,60,212,236,252,196,49,0,64,14,30,11,160,1,19,10,160,21,129,17,13,32,160,15,47,236,50,50,244, + 236,220,60,236,50,48,1,51,50,55,54,53,52,39,38,43,1,1,17,33,17,1,53,51,17,33,17,33,50,23,22,21,6,7,6,47,1,17,33,21, + 3,109,168,93,37,31,31,29,105,164,254,13,1,59,253,55,213,1,244,1,176,132,64,69,1,68,92,140,212,2,134,3,113,81,69,61,60,100,94,253, + 156,253,181,2,75,253,34,147,2,222,2,100,133,144,124,145,91,124,1,1,253,181,147,0,0,3,255,236,0,0,5,110,5,213,0,10,0,14,0,31, + 0,56,64,16,33,4,5,28,26,15,0,28,21,14,12,28,19,4,17,32,16,196,252,236,212,60,252,60,212,236,236,49,0,64,13,31,11,160,1,20, + 10,160,22,129,18,13,160,16,47,236,50,244,236,220,60,236,50,48,1,51,50,55,54,53,52,39,38,43,1,1,17,33,17,19,33,53,51,17,33,17, + 33,50,23,22,21,6,7,6,47,1,3,109,168,93,37,31,31,29,105,164,254,13,1,59,184,252,127,213,1,244,1,176,132,64,69,1,68,92,140,212, + 3,113,81,69,61,60,100,94,253,156,253,181,2,75,253,34,147,2,222,2,100,133,144,124,145,91,124,1,1,0,0,0,0,1,0,193,0,0,4,81, + 5,213,0,13,0,46,64,13,12,15,4,11,28,9,1,7,3,28,5,4,14,16,252,252,60,220,60,252,252,196,49,0,64,10,4,2,160,6,8,10, + 129,12,160,0,47,236,244,220,204,252,204,48,33,17,33,17,35,17,51,17,33,17,51,17,51,21,2,197,254,181,185,185,1,75,184,212,3,129,254,252, + 2,155,254,252,1,193,250,190,147,0,0,0,0,1,255,236,0,0,4,81,5,213,0,15,0,50,64,14,14,17,4,13,28,11,3,9,5,28,7,4, + 1,16,16,196,252,252,60,220,60,252,252,196,49,0,64,11,6,4,160,8,10,12,129,2,14,160,0,47,236,50,244,220,204,252,204,48,35,53,33,17, + 33,17,35,17,51,17,33,17,51,17,51,21,20,2,217,254,181,185,185,1,75,184,212,147,2,238,254,252,2,155,254,252,1,193,250,190,147,0,0,0, + 0,1,255,236,0,0,3,125,5,213,0,13,0,46,64,13,15,4,12,28,11,3,9,5,28,7,4,1,14,16,196,252,252,60,220,60,252,236,49,0, + 64,10,6,4,160,8,10,12,129,2,160,0,47,236,244,220,204,252,204,48,35,53,33,17,33,17,35,17,51,17,33,17,51,17,20,2,217,254,181,185, + 185,1,75,184,147,2,238,254,252,2,155,254,252,1,193,250,43,0,0,0,0,2,0,112,0,0,5,223,5,213,0,10,0,29,0,51,64,14,28,31, + 4,24,31,22,26,28,11,1,7,17,27,30,16,252,204,212,60,252,60,252,252,196,49,0,64,12,25,12,160,0,23,2,160,21,129,27,160,29,47,236, + 244,236,212,60,236,50,48,1,33,17,33,34,7,6,21,20,23,22,1,17,33,34,39,38,53,52,55,54,51,33,17,33,21,33,17,33,21,1,220,1, + 48,254,212,82,52,44,44,61,1,110,254,171,107,125,88,88,88,108,2,50,1,76,254,180,2,33,2,247,2,75,93,79,122,125,73,95,253,9,2,100, + 135,95,210,173,135,133,253,34,147,254,47,147,0,2,255,236,0,0,5,223,5,213,0,10,0,31,0,55,64,15,30,33,4,26,31,24,28,28,13,1, + 7,19,27,12,32,16,196,252,204,212,60,252,60,252,252,196,49,0,64,13,27,14,160,0,25,2,160,23,129,29,13,160,31,47,236,50,244,236,212,60, + 236,50,48,1,33,17,33,34,7,6,21,20,23,22,1,53,33,17,33,34,39,38,53,52,55,54,51,33,17,33,21,33,17,33,21,1,220,1,48,254, + 212,82,52,44,44,61,254,85,3,25,254,171,107,125,88,88,88,108,2,50,1,76,254,180,2,33,2,247,2,75,93,79,122,125,73,95,253,9,147,1, + 209,135,95,210,173,135,133,253,34,147,254,47,147,0,0,0,0,2,255,236,0,0,5,10,5,213,0,10,0,29,0,51,64,14,31,4,26,31,24,28, + 28,13,1,7,19,27,12,30,16,196,252,204,212,60,252,60,252,236,49,0,64,12,27,14,160,0,25,2,160,23,129,13,160,29,47,236,244,236,212,60, + 236,50,48,1,33,17,33,34,7,6,21,20,23,22,1,53,33,17,33,34,39,38,53,52,55,54,51,33,17,33,21,33,17,1,220,1,48,254,212,82, + 52,44,44,61,254,85,3,25,254,171,107,125,88,88,88,108,2,50,1,76,254,180,2,247,2,75,93,79,122,125,73,95,253,9,147,1,209,135,95,210, + 173,135,133,253,34,147,253,156,0,1,0,61,0,0,3,220,5,213,0,9,0,36,64,10,8,11,4,31,6,28,0,31,2,10,16,220,252,252,252,220, + 196,49,0,183,1,6,160,3,129,7,160,9,47,236,244,236,50,48,33,17,33,53,33,21,33,17,33,21,1,136,254,181,3,78,254,181,1,156,5,66, + 147,147,251,81,147,0,0,0,0,1,255,236,0,0,3,220,5,213,0,11,0,41,64,11,10,13,6,31,8,28,2,31,4,1,12,16,196,220,252,252, + 252,220,196,49,0,64,9,8,3,160,6,129,2,9,160,0,47,236,50,244,236,50,48,35,53,33,17,33,53,33,21,33,17,33,21,20,1,156,254,181, + 3,78,254,181,1,156,147,4,175,147,147,251,81,147,0,0,0,1,255,236,0,0,3,139,5,213,0,9,0,36,64,10,11,7,31,9,28,3,31,5, + 2,10,16,196,220,252,252,252,204,49,0,183,9,4,160,6,129,3,160,0,47,236,244,236,50,48,41,1,53,33,17,33,53,33,21,33,2,64,253,172, + 1,156,254,181,3,78,254,181,147,4,175,147,147,0,0,0,0,2,0,61,0,0,5,20,5,213,0,2,0,8,0,64,179,8,10,3,9,16,212,196, + 196,49,0,64,9,66,1,149,5,129,6,2,160,3,47,236,50,244,236,48,75,83,88,64,18,1,17,5,2,1,0,17,6,6,5,1,17,4,2,17, + 3,3,4,5,7,16,236,16,236,7,16,236,8,16,236,89,37,9,1,7,1,51,1,51,21,3,198,254,186,254,186,253,1,208,230,1,152,137,147,4, + 130,251,126,147,5,213,250,190,147,0,0,0,0,2,255,236,0,0,5,20,5,213,0,2,0,10,0,66,179,9,12,4,11,16,196,196,196,49,0,64, + 10,66,1,149,6,129,8,4,2,160,3,47,236,50,50,244,236,48,75,83,88,64,18,1,17,7,2,1,0,17,8,8,7,1,17,6,2,17,5,5, + 6,5,7,16,236,16,236,7,16,236,8,16,236,89,37,9,1,5,53,51,1,51,1,51,21,3,198,254,186,254,186,254,178,137,1,152,230,1,152,137, + 147,4,130,251,126,147,147,5,66,250,190,147,0,2,255,236,0,0,4,195,5,213,0,2,0,8,0,64,179,10,8,4,9,16,196,196,196,49,0,64, + 9,66,1,149,6,129,4,2,160,3,47,236,50,244,236,48,75,83,88,64,18,1,17,7,2,1,0,17,8,8,7,1,17,6,2,17,5,5,6,5, + 7,16,236,16,236,7,16,236,8,16,236,89,37,9,1,5,53,51,1,51,1,3,198,254,186,254,186,254,178,137,1,152,230,1,208,147,4,130,251,126, + 147,147,5,66,250,43,0,0,0,2,0,113,0,0,4,212,5,213,0,28,0,40,0,0,33,17,38,39,46,1,52,55,54,55,54,55,53,33,53,33, + 17,22,23,30,1,20,6,7,6,7,21,33,21,0,20,30,1,50,62,1,52,46,1,34,6,2,4,82,74,114,133,67,69,111,74,82,254,181,2,3, + 88,69,114,132,132,114,74,83,2,24,252,57,91,156,184,157,90,90,157,184,156,1,134,11,31,49,166,198,83,86,47,31,11,243,147,254,123,13,30,50, + 166,198,166,49,32,11,242,147,3,34,112,95,56,56,95,112,96,56,56,0,0,2,255,236,0,0,4,212,5,213,0,30,0,42,0,0,35,53,33,53, + 38,39,46,1,52,55,54,55,54,55,53,33,53,33,17,22,23,30,1,20,6,7,6,7,21,33,21,0,20,30,1,50,62,1,52,46,1,34,6,20, + 2,24,82,74,114,133,67,69,111,74,82,254,181,2,3,88,69,114,132,132,114,74,83,2,24,252,57,91,156,184,157,90,90,157,184,156,147,243,11,31, + 49,166,198,83,86,47,31,11,243,147,254,123,13,30,50,166,198,166,49,32,11,242,147,3,34,112,95,56,56,95,112,96,56,56,0,0,0,2,255,236, + 0,0,4,79,5,213,0,28,0,40,0,0,35,53,33,53,38,39,46,1,52,55,54,55,54,55,53,33,53,33,17,22,23,30,1,20,6,7,6,7, + 17,0,20,30,1,50,62,1,52,46,1,34,6,20,2,24,82,74,114,133,67,69,111,74,82,254,181,2,3,88,69,114,132,132,114,74,83,254,81,91, + 156,184,157,90,90,157,184,156,147,243,11,31,49,166,198,83,86,47,31,11,243,147,254,123,13,30,50,166,198,166,49,32,11,254,123,3,34,112,95,56, + 56,95,112,96,56,56,0,0,0,1,0,193,0,0,4,81,5,213,0,9,0,37,64,11,8,11,4,1,28,7,3,28,5,4,10,16,252,236,212,236, + 252,196,49,0,183,4,2,160,5,129,7,160,0,47,236,244,252,204,48,33,17,33,17,35,17,33,17,51,21,2,197,254,181,185,2,188,212,5,66,254, + 197,1,206,250,190,147,0,0,0,1,255,236,0,0,4,81,5,213,0,11,0,42,64,12,10,13,4,2,28,8,4,28,6,4,1,12,16,196,252,236, + 212,236,252,196,49,0,64,9,5,4,160,8,129,2,9,160,0,47,236,50,244,252,204,48,35,53,33,17,33,17,35,17,33,17,51,21,20,2,217,254, + 181,185,2,188,212,147,4,175,254,197,1,206,250,190,147,0,0,1,255,236,0,0,3,125,5,213,0,9,0,37,64,11,11,4,3,28,9,5,28,7, + 4,1,10,16,196,252,236,212,236,236,49,0,183,6,4,160,8,129,2,160,0,47,236,244,252,204,48,35,53,33,17,33,17,35,17,33,17,20,2,217, + 254,181,185,2,188,147,4,175,254,197,1,206,250,43,0,0,0,1,0,193,0,0,4,81,4,230,0,11,0,40,64,12,11,13,4,9,28,1,7,3, + 28,5,4,12,16,252,252,60,220,252,252,196,49,0,183,6,8,160,4,2,10,160,0,47,236,212,204,252,204,48,33,17,33,17,35,17,51,17,33,17, + 51,21,2,197,254,181,185,185,2,3,212,3,79,254,252,2,155,254,252,252,177,147,0,0,0,1,255,236,0,0,4,81,4,230,0,13,0,45,64,13, + 13,15,4,11,28,3,9,5,28,7,4,1,14,16,196,252,252,60,220,252,252,196,49,0,64,9,8,10,160,6,4,2,12,160,0,47,236,50,212,204, + 252,204,48,35,53,33,17,33,17,35,17,51,17,33,17,51,21,20,2,217,254,181,185,185,2,3,212,147,2,188,254,252,2,155,254,252,252,177,147,0, + 0,1,255,236,0,0,3,125,4,230,0,11,0,40,64,12,13,4,11,28,3,9,5,28,7,4,1,12,16,196,252,252,60,220,252,236,49,0,183,8, + 10,160,6,4,2,160,0,47,236,212,204,252,204,48,35,53,33,17,33,17,35,17,51,17,33,17,20,2,217,254,181,185,185,2,3,147,2,188,254,252, + 2,155,254,252,252,30,0,0,0,2,0,193,0,0,4,66,5,213,0,3,0,13,0,47,64,13,13,15,4,11,28,7,3,1,28,5,9,4,14,16, + 252,60,236,220,60,252,252,196,49,0,64,11,0,160,6,8,160,10,129,2,12,160,4,47,236,50,244,236,212,236,48,1,17,33,17,1,17,33,17,33, + 53,33,17,51,21,1,122,1,59,254,12,1,244,254,12,2,172,213,2,222,253,181,2,75,253,34,3,113,1,209,147,250,190,147,0,0,0,2,255,236, + 0,0,4,66,5,213,0,3,0,15,0,51,64,14,15,17,4,13,28,9,3,1,28,7,11,4,5,16,16,196,252,60,236,220,60,252,252,196,49,0, + 64,12,0,160,8,10,160,12,129,6,2,14,160,4,47,236,50,50,244,236,212,236,48,1,17,33,17,1,53,51,17,33,17,33,53,33,17,51,21,1, + 122,1,59,253,55,213,1,244,254,12,2,172,213,2,222,253,181,2,75,253,34,147,2,222,1,209,147,250,190,147,0,0,0,2,255,236,0,0,3,109, + 5,213,0,3,0,13,0,47,64,13,15,4,13,28,9,3,1,28,7,11,4,5,14,16,196,252,60,236,220,60,252,236,49,0,64,11,0,160,8,10, + 160,12,129,6,2,160,4,47,236,50,244,236,212,236,48,1,17,33,17,1,53,51,17,33,17,33,53,33,17,1,122,1,59,253,55,213,1,244,254,12, + 2,172,2,222,253,181,2,75,253,34,147,2,222,1,209,147,250,43,0,0,0,2,0,113,0,0,4,212,5,213,0,11,0,38,0,66,64,16,37,40, + 69,7,28,31,26,35,28,23,13,1,28,18,69,39,16,252,236,220,178,64,13,1,93,60,252,60,220,178,64,31,1,93,236,252,196,49,0,64,13,4, + 149,35,13,10,149,26,23,25,129,36,160,12,47,236,236,212,60,236,212,60,236,48,0,20,30,1,50,62,1,52,46,1,34,6,19,17,38,39,46,1, + 52,55,54,55,54,55,17,51,17,22,23,30,1,20,6,7,6,7,21,33,21,1,13,91,156,184,157,90,90,157,184,156,156,82,74,114,133,67,69,111, + 74,82,184,88,69,114,132,132,114,74,83,2,24,3,34,112,95,56,56,95,112,96,56,56,252,126,1,134,11,31,49,166,198,83,86,47,31,11,1,134, + 254,123,13,30,50,166,198,166,49,32,11,242,147,0,0,0,0,2,255,236,0,0,4,212,5,213,0,11,0,40,0,70,64,17,12,42,69,7,28,35, + 30,39,28,27,17,1,28,22,69,15,41,16,196,252,236,220,178,64,17,1,93,60,252,60,220,178,64,35,1,93,236,252,196,49,0,64,14,4,149,39, + 17,10,149,30,27,29,129,40,16,160,14,47,236,50,236,212,60,236,212,60,236,48,0,20,30,1,50,62,1,52,46,1,34,6,1,21,33,53,33,53, + 38,39,46,1,52,55,54,55,54,55,17,51,17,22,23,30,1,20,6,7,6,7,21,1,13,91,156,184,157,90,90,157,184,156,3,108,251,24,2,24, + 82,74,114,133,67,69,111,74,82,184,88,69,114,132,132,114,74,83,3,34,112,95,56,56,95,112,96,56,56,253,17,147,147,243,11,31,49,166,198,83, + 86,47,31,11,1,134,254,123,13,30,50,166,198,166,49,32,11,242,0,0,0,2,255,236,0,0,4,79,5,213,0,11,0,38,0,66,64,16,40,69, + 7,28,31,26,35,28,23,13,1,28,18,69,38,39,16,196,252,236,220,178,64,13,1,93,60,252,60,220,178,64,31,1,93,236,236,49,0,64,13,4, + 149,35,13,10,149,26,23,25,129,12,160,37,47,236,236,212,60,236,212,60,236,48,0,20,30,1,50,62,1,52,46,1,34,6,19,53,38,39,46,1, + 52,55,54,55,54,55,17,51,17,22,23,30,1,20,6,7,6,7,17,33,53,1,13,91,156,184,157,90,90,157,184,156,156,82,74,114,133,67,69,111, + 74,82,184,88,69,114,132,132,114,74,83,253,48,3,34,112,95,56,56,95,112,96,56,56,253,17,243,11,31,49,166,198,83,86,47,31,11,1,134,254, + 123,13,30,50,166,198,166,49,32,11,254,123,147,0,0,0,0,2,0,113,0,0,4,212,5,213,0,30,0,42,0,0,33,17,38,39,46,1,52,55, + 54,55,54,55,53,33,53,33,21,33,21,22,23,30,1,20,6,7,6,7,21,33,21,0,20,30,1,50,62,1,52,46,1,34,6,2,4,82,74,114, + 133,67,69,111,74,82,254,181,3,78,254,181,88,69,114,132,132,114,74,83,2,24,252,57,91,156,184,157,90,90,157,184,156,1,134,11,31,49,166,198, + 83,86,47,31,11,243,147,147,242,13,30,50,166,198,166,49,32,11,242,147,3,34,112,95,56,56,95,112,96,56,56,0,0,2,255,236,0,0,4,212, + 5,213,0,32,0,44,0,0,37,21,33,53,33,53,38,39,46,1,52,55,54,55,54,55,53,33,53,33,21,33,21,22,23,30,1,20,6,7,6,7, + 21,0,20,30,1,50,62,1,52,46,1,34,6,4,212,251,24,2,24,82,74,114,133,67,69,111,74,82,254,181,3,78,254,181,88,69,114,132,132,114, + 74,83,254,81,91,156,184,157,90,90,157,184,156,147,147,147,243,11,31,49,166,198,83,86,47,31,11,243,147,147,242,13,30,50,166,198,166,49,32,11, + 242,2,143,112,95,56,56,95,112,96,56,56,0,2,255,236,0,0,4,79,5,213,0,30,0,42,0,0,41,1,53,33,53,38,39,46,1,52,55,54, + 55,54,55,53,33,53,33,21,33,21,22,23,30,1,20,6,7,6,7,0,20,30,1,50,62,1,52,46,1,34,6,2,188,253,48,2,24,82,74,114, + 133,67,69,111,74,82,254,181,3,78,254,181,88,69,114,132,132,114,74,83,254,81,91,156,184,157,90,90,157,184,156,147,243,11,31,49,166,198,83,86, + 47,31,11,243,147,147,242,13,30,50,166,198,166,49,32,11,1,157,112,95,56,56,95,112,96,56,56,0,255,255,252,236,3,251,255,16,6,32,16,7, + 2,156,251,254,255,26,0,0,255,255,0,170,2,134,6,130,5,213,18,39,15,92,0,0,2,134,16,39,15,92,0,0,3,202,16,7,15,92,0,0, + 5,13,0,0,255,255,0,170,2,134,6,131,5,213,18,39,15,92,0,0,2,134,16,39,15,92,0,1,3,201,16,7,15,93,0,0,5,13,0,0, + 255,255,0,170,2,134,6,130,5,213,18,39,15,92,0,0,2,134,16,39,15,93,0,0,3,201,16,7,15,92,0,0,5,13,0,0,255,255,0,170, + 2,134,6,130,5,213,18,39,15,92,0,0,2,134,16,39,15,93,0,0,3,201,16,7,15,93,0,0,5,13,0,0,255,255,0,170,2,134,6,130, + 5,213,18,39,15,93,0,0,2,134,16,39,15,92,0,0,3,201,16,7,15,92,0,0,5,13,0,0,255,255,0,170,2,134,6,130,5,213,18,39, + 15,93,0,0,2,134,16,39,15,92,0,0,3,201,16,7,15,93,0,0,5,13,0,0,255,255,0,170,2,134,6,130,5,213,18,39,15,93,0,0, + 2,134,16,39,15,93,0,0,3,201,16,7,15,92,0,0,5,13,0,0,255,255,0,170,2,134,6,130,5,213,18,39,15,93,0,0,2,134,16,39, + 15,93,0,0,3,201,16,7,15,93,0,0,5,13,0,0,0,1,1,151,5,24,5,27,5,224,0,11,0,58,64,13,2,1,0,3,6,5,4,7, + 10,9,8,11,12,16,212,64,9,63,11,111,11,143,11,144,11,4,93,220,57,57,212,220,57,57,212,204,57,57,49,0,182,5,4,7,1,10,11,12, + 16,212,204,50,220,60,204,48,1,7,35,39,35,7,35,39,35,7,35,39,5,27,100,50,50,175,50,50,50,175,50,50,100,5,224,200,100,100,100,100, + 200,0,0,0,0,1,0,201,254,86,5,252,5,213,0,14,0,0,33,35,17,1,33,17,51,17,1,33,17,51,21,1,35,5,51,196,253,106,254,240, + 196,2,150,1,16,201,254,146,134,4,225,251,31,5,213,251,31,4,225,250,213,170,254,86,0,1,0,193,254,86,5,56,4,96,0,14,0,0,33,35, + 17,1,35,17,51,17,1,51,17,51,21,1,35,4,128,183,253,228,236,183,2,27,237,184,254,222,123,3,131,252,125,4,96,252,127,3,129,252,57,153, + 254,86,0,0,0,2,0,174,254,86,4,88,4,123,0,31,0,32,0,0,37,53,14,1,35,34,38,53,17,51,17,20,22,51,50,54,53,17,51,17, + 16,2,33,34,38,39,53,30,1,51,50,54,1,3,160,67,177,117,193,200,184,124,124,149,173,184,254,254,250,97,172,81,81,158,82,181,180,254,221,106, + 66,102,99,240,231,2,166,253,97,159,159,190,164,2,123,252,43,254,226,254,233,29,30,179,44,42,189,4,208,0,0,0,255,255,0,125,254,144,4,71, + 3,82,16,39,22,213,1,25,254,144,16,6,20,142,0,0,255,255,0,125,254,162,4,71,3,82,16,39,22,196,1,169,254,162,16,6,20,142,0,0, + 255,255,0,125,254,162,4,71,5,247,16,39,5,75,255,194,255,6,16,39,22,196,1,169,254,162,16,6,20,142,0,0,255,255,0,125,255,218,4,71, + 5,120,16,39,22,199,0,250,4,226,16,6,20,142,0,0,255,255,0,125,255,218,4,71,5,170,16,39,22,201,0,250,5,20,16,6,20,142,0,0, + 255,255,255,171,254,12,4,126,2,38,16,39,22,213,2,88,254,12,16,6,20,146,0,0,255,255,255,171,254,12,4,126,2,38,16,39,22,196,3,52, + 254,72,16,6,20,146,0,0,255,255,255,171,254,12,4,126,2,38,16,39,22,196,0,180,0,40,16,39,22,196,3,52,254,72,16,6,20,146,0,0, + 255,255,255,171,254,12,4,126,3,182,16,39,22,197,1,244,3,32,16,6,20,146,0,0,255,255,255,171,254,12,4,126,4,176,16,39,22,201,1,244, + 4,26,16,6,20,146,0,0,255,255,0,130,254,12,10,71,3,182,16,38,20,150,0,0,16,39,22,196,5,95,3,32,16,7,22,196,5,245,254,162, + 255,255,255,236,254,162,6,10,3,232,16,38,20,151,0,0,16,39,22,196,3,7,3,82,16,7,22,196,3,157,254,162,255,255,255,236,254,162,7,55, + 3,232,16,38,20,152,0,0,16,39,22,196,3,7,3,82,16,7,22,196,3,157,254,162,255,255,0,130,254,12,10,71,2,238,16,38,20,150,0,0, + 16,7,22,199,5,120,255,6,255,255,255,236,254,12,6,10,2,238,16,38,20,151,0,0,16,7,22,199,3,32,255,6,255,255,255,236,254,12,7,55, + 2,238,16,38,20,152,0,0,16,7,22,199,3,32,255,6,255,255,0,130,254,12,10,71,4,176,16,38,20,150,0,0,16,39,22,198,4,226,3,32, + 16,7,22,199,5,120,255,6,255,255,255,236,254,12,6,10,4,176,16,38,20,151,0,0,16,39,22,198,2,138,3,32,16,7,22,199,3,32,255,6, + 255,255,255,236,254,12,7,55,4,176,16,38,20,152,0,0,16,39,22,198,2,138,3,32,16,7,22,199,3,32,255,6,255,255,0,130,254,12,9,225, + 2,229,16,38,20,158,0,0,16,7,22,197,5,120,254,162,255,255,255,236,254,162,6,50,2,229,16,38,20,159,0,0,16,7,22,197,2,88,254,162, + 255,255,255,236,254,162,7,4,2,229,16,38,20,160,0,0,16,7,22,197,2,88,254,162,255,255,0,130,254,12,9,225,4,176,16,38,20,158,0,0, + 16,7,22,198,4,126,3,32,255,255,255,236,0,0,6,50,4,176,16,38,20,159,0,0,16,7,22,198,1,144,3,32,255,255,255,236,0,0,7,4, + 4,176,16,38,20,160,0,0,16,7,22,198,1,144,3,32,255,255,0,144,0,0,7,172,6,20,16,38,20,166,0,0,16,7,22,198,3,132,3,82, + 255,255,255,236,0,0,5,212,6,20,16,38,20,167,0,0,16,7,22,198,2,124,3,82,255,255,255,236,0,0,6,164,6,20,16,38,20,168,0,0, + 16,7,22,198,2,124,3,82,255,255,0,117,254,12,4,178,5,70,16,38,20,174,0,0,16,7,22,198,1,44,3,182,255,255,255,236,0,0,3,248, + 6,64,16,38,20,175,0,0,16,7,22,198,1,44,4,176,255,255,255,236,0,0,3,240,5,70,16,38,20,176,0,0,16,7,22,198,1,44,3,182, + 255,255,0,130,254,162,8,92,3,17,16,38,22,205,0,0,16,7,22,196,3,107,254,162,255,255,255,236,254,212,3,63,3,217,16,38,22,206,0,0, + 16,7,22,196,1,168,254,212,255,255,255,236,254,212,4,32,3,8,16,38,22,207,0,0,16,7,22,196,1,168,254,212,255,255,0,130,254,162,8,92, + 4,76,16,38,22,205,0,0,16,39,22,196,5,245,3,182,16,7,22,196,3,107,254,162,255,255,255,236,254,212,3,63,5,20,16,38,22,206,0,0, + 16,39,22,196,1,169,4,126,16,7,22,196,1,168,254,212,255,255,255,236,254,212,4,32,4,126,16,38,22,207,0,0,16,39,22,196,1,187,3,232, + 16,7,22,196,1,168,254,212,255,255,0,130,253,168,8,92,3,17,16,38,22,205,0,0,16,7,22,199,2,238,254,162,255,255,255,236,253,218,3,63, + 3,217,16,38,22,206,0,0,16,7,22,199,1,44,254,212,255,255,255,236,253,218,4,32,3,8,16,38,22,207,0,0,16,7,22,199,1,44,254,212, + 255,255,0,107,254,12,6,192,4,1,16,38,22,208,0,0,16,7,22,196,4,1,3,107,255,255,255,236,0,0,3,63,5,20,16,38,22,209,0,0, + 16,7,22,196,1,169,4,126,255,255,255,236,0,0,4,32,4,126,16,38,22,210,0,0,16,7,22,196,1,187,3,232,255,255,0,107,254,12,6,192, + 4,251,16,38,22,208,0,0,16,7,22,198,3,132,3,107,255,255,255,236,0,0,3,63,6,14,16,38,22,209,0,0,16,7,22,198,1,44,4,126, + 255,255,255,236,0,0,4,32,5,120,16,38,22,210,0,0,16,7,22,198,1,62,3,232,0,1,0,130,255,167,8,130,6,20,0,55,0,0,37,50, + 36,54,61,1,52,39,37,36,61,1,52,55,54,55,1,33,1,6,7,6,23,22,23,5,22,29,1,20,23,22,59,1,21,35,34,38,39,6,4,35, + 33,34,39,36,17,52,55,51,6,21,20,23,22,51,4,246,184,1,107,49,121,252,89,254,157,11,19,160,2,176,1,96,252,104,95,15,9,4,6,174, + 3,202,248,47,15,22,46,90,92,57,11,83,254,108,161,254,12,192,128,254,182,63,184,65,203,104,151,88,150,108,5,9,107,18,145,55,190,7,6,62, + 99,96,1,155,253,232,55,35,10,35,53,27,150,38,248,69,94,17,5,184,50,48,57,130,38,98,1,11,138,92,94,136,126,66,34,0,0,1,255,236, + 0,0,6,132,6,20,0,32,0,0,35,53,33,50,55,54,39,38,39,37,36,61,1,52,55,54,55,1,33,1,6,7,6,23,22,23,5,22,21,20, + 7,6,35,20,5,8,147,46,19,3,13,99,252,89,254,157,11,17,162,2,176,1,96,252,104,95,15,9,4,6,174,3,202,248,62,95,223,184,104,44, + 28,110,15,145,55,190,8,5,62,98,97,1,155,253,232,55,35,10,35,53,27,150,38,248,113,101,155,0,0,1,255,236,0,0,7,6,6,20,0,41, + 0,0,35,53,33,50,55,54,53,52,39,37,36,61,1,52,55,54,55,1,33,1,6,7,6,23,22,23,5,22,29,1,20,23,22,59,1,21,35,34, + 38,39,6,35,20,5,8,136,57,16,112,252,89,254,157,11,17,162,2,176,1,96,252,104,95,15,9,4,6,174,3,202,248,47,15,22,46,90,90,56, + 11,96,167,184,104,29,24,127,17,145,55,190,8,4,63,98,97,1,155,253,232,55,35,10,35,53,27,150,38,248,69,95,16,5,184,47,40,87,0,0, + 255,255,0,130,255,167,7,217,6,20,16,38,20,28,0,0,16,7,22,213,5,70,3,132,255,255,255,236,0,0,3,207,6,20,16,38,20,191,0,0, + 16,7,22,213,1,244,3,132,255,255,255,236,0,0,4,127,6,20,16,38,20,192,0,0,16,7,22,213,1,244,3,132,255,255,0,144,255,201,6,210, + 6,20,16,38,20,190,0,0,16,7,22,196,2,238,5,70,255,255,255,236,0,0,3,207,6,114,16,38,20,191,0,0,16,7,22,196,0,200,5,220, + 255,255,255,236,0,0,4,127,6,114,16,38,20,192,0,0,16,7,22,196,0,200,5,220,255,255,0,144,253,168,6,210,6,20,16,38,20,190,0,0, + 16,7,22,199,2,88,254,162,255,255,255,236,253,218,3,207,6,20,16,38,20,191,0,0,16,7,22,199,0,200,254,212,255,255,255,236,253,218,4,127, + 6,20,16,38,20,192,0,0,16,7,22,199,0,200,254,212,255,255,0,130,255,167,7,217,7,43,16,38,20,32,0,0,16,7,22,213,5,70,3,132, + 255,255,255,236,0,0,3,207,7,43,16,38,20,33,0,0,16,7,22,213,1,244,3,132,255,255,255,236,0,0,4,127,7,43,16,38,20,34,0,0, + 16,7,22,213,1,244,3,132,255,255,0,130,254,162,7,217,7,43,16,38,20,32,0,0,16,7,22,197,2,88,254,162,255,255,255,236,254,212,3,207, + 7,43,16,38,20,33,0,0,16,7,22,197,0,200,254,212,255,255,255,236,254,212,4,127,7,43,16,38,20,34,0,0,16,7,22,197,0,200,254,212, + 255,255,0,130,255,167,7,217,8,52,16,38,20,32,0,0,16,7,22,198,3,132,6,164,255,255,255,236,0,0,3,207,8,52,16,38,20,33,0,0, + 16,7,22,198,0,75,6,164,255,255,255,236,0,0,4,127,8,52,16,38,20,34,0,0,16,7,22,198,0,75,6,164,255,255,0,144,254,200,6,35, + 7,158,16,38,20,194,0,0,16,7,22,196,4,106,7,8,255,255,255,236,0,0,1,175,7,158,16,38,20,195,0,0,16,7,22,196,1,1,7,8, + 255,255,255,236,0,0,2,186,7,158,16,38,20,196,0,0,16,7,22,196,1,1,7,8,255,255,0,144,254,200,6,35,8,52,16,38,20,194,0,0, + 16,7,22,198,3,232,6,164,255,255,255,236,0,0,2,15,8,52,16,38,20,195,0,0,16,7,22,198,0,127,6,164,255,255,255,236,0,0,2,186, + 8,52,16,38,20,196,0,0,16,7,22,198,0,127,6,164,255,255,0,144,252,224,6,35,6,20,16,38,20,194,0,0,16,7,22,199,2,38,253,218, + 255,255,255,236,254,12,1,243,6,20,16,38,20,195,0,0,16,7,22,199,0,99,255,6,255,255,255,236,254,12,2,186,6,20,16,38,20,196,0,0, + 16,7,22,199,0,129,255,6,255,255,0,147,252,199,6,43,2,188,16,38,20,44,0,0,16,39,22,196,2,63,2,38,16,7,22,196,2,188,252,199, + 255,255,255,236,254,212,1,135,3,232,16,39,22,196,0,224,3,82,16,38,22,203,0,0,16,7,22,196,0,224,254,212,255,255,255,236,254,212,2,126, + 3,232,16,39,22,196,0,224,3,82,16,38,22,204,0,0,16,7,22,196,0,224,254,212,255,255,0,147,252,174,6,43,2,188,16,38,20,44,0,0, + 16,39,22,196,2,63,2,38,16,7,22,213,2,38,252,174,255,255,255,236,254,244,2,6,3,232,16,39,22,196,0,224,3,82,16,38,22,203,0,0, + 16,7,22,213,0,80,254,244,255,255,255,236,254,244,2,126,3,232,16,39,22,196,0,224,3,82,16,38,22,204,0,0,16,7,22,213,0,80,254,244, + 255,255,0,147,254,12,6,43,3,182,16,38,20,44,0,0,16,7,22,198,1,244,2,38,255,255,255,236,0,0,1,243,4,226,16,38,22,203,0,0, + 16,7,22,198,0,99,3,82,255,255,255,236,0,0,2,126,4,226,16,38,22,204,0,0,16,7,22,198,0,99,3,82,0,1,0,0,0,2,87,10, + 221,218,237,250,95,15,60,245,0,31,8,0,0,0,0,0,206,63,215,178,0,0,0,0,206,63,215,178,247,214,252,174,13,114,9,85,0,0,0,8, + 0,0,0,1,0,0,0,0,0,1,0,0,7,109,254,29,0,0,13,226,247,214,250,81,13,114,0,1,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,23,220,4,205,0,102,0,0,0,0,2,170,0,0,2,139,0,0,3,53,1,53,3,174,0,197,6,180,0,158,5,23,0,170,7,154,0,113, + 6,61,0,129,2,51,0,197,3,31,0,176,3,31,0,164,4,0,0,61,6,180,0,217,2,139,0,158,2,227,0,100,2,139,0,219,2,178,0,0, + 5,23,0,135,5,23,0,225,5,23,0,150,5,23,0,156,5,23,0,100,5,23,0,158,5,23,0,143,5,23,0,168,5,23,0,139,5,23,0,129, + 2,178,0,240,2,178,0,158,6,180,0,217,6,180,0,217,6,180,0,217,4,63,0,147,8,0,0,135,5,121,0,16,5,125,0,201,5,150,0,115, + 6,41,0,201,5,14,0,201,4,154,0,201,6,51,0,115,6,4,0,201,2,92,0,201,2,92,255,150,5,63,0,201,4,117,0,201,6,231,0,201, + 5,252,0,201,6,76,0,115,4,211,0,201,6,76,0,115,5,143,0,201,5,20,0,135,4,227,255,250,5,219,0,178,5,121,0,16,7,233,0,68, + 5,123,0,61,4,227,255,252,5,123,0,92,3,31,0,176,2,178,0,0,3,31,0,199,6,180,0,217,4,0,255,236,4,0,0,170,4,231,0,123, + 5,20,0,186,4,102,0,113,5,20,0,113,4,236,0,113,2,209,0,47,5,20,0,113,5,18,0,186,2,57,0,193,2,57,255,219,4,162,0,186, + 2,57,0,193,7,203,0,186,5,18,0,186,4,229,0,113,5,20,0,186,5,20,0,113,3,74,0,186,4,43,0,111,3,35,0,55,5,18,0,174, + 4,188,0,61,6,139,0,86,4,188,0,59,4,188,0,61,4,51,0,88,5,23,1,0,2,178,1,4,5,23,1,0,6,180,0,217,2,139,0,0, + 3,53,1,53,5,23,0,172,5,23,0,129,5,23,0,94,5,23,0,82,2,178,1,4,4,0,0,92,4,0,0,215,8,0,1,27,3,197,0,115, + 4,229,0,158,6,180,0,217,2,227,0,100,8,0,1,27,4,0,0,213,4,0,0,195,6,180,0,217,3,53,0,94,3,53,0,98,4,0,1,115, + 5,23,0,174,5,23,0,158,2,139,0,219,4,0,1,35,3,53,0,137,3,197,0,96,4,229,0,193,7,193,0,137,7,193,0,137,7,193,0,98, + 4,63,0,143,5,121,0,16,5,121,0,16,5,121,0,16,5,121,0,16,5,121,0,16,5,121,0,16,7,203,0,8,5,150,0,115,5,14,0,201, + 5,14,0,201,5,14,0,201,5,14,0,201,2,92,0,59,2,92,0,162,2,92,255,254,2,92,0,6,6,51,0,10,5,252,0,201,6,76,0,115, + 6,76,0,115,6,76,0,115,6,76,0,115,6,76,0,115,6,180,1,25,6,76,0,102,5,219,0,178,5,219,0,178,5,219,0,178,5,219,0,178, + 4,227,255,252,4,215,0,201,5,10,0,186,4,231,0,123,4,231,0,123,4,231,0,123,4,231,0,123,4,231,0,123,4,231,0,123,7,219,0,123, + 4,102,0,113,4,236,0,113,4,236,0,113,4,236,0,113,4,236,0,113,2,57,255,199,2,57,0,144,2,57,255,222,2,57,255,244,4,229,0,113, + 5,18,0,186,4,229,0,113,4,229,0,113,4,229,0,113,4,229,0,113,4,229,0,113,6,180,0,217,4,229,0,72,5,18,0,174,5,18,0,174, + 5,18,0,174,5,18,0,174,4,188,0,61,5,20,0,186,4,188,0,61,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,121,0,16, + 4,231,0,123,5,150,0,115,4,102,0,113,5,150,0,115,4,102,0,113,5,150,0,115,4,102,0,113,5,150,0,115,4,102,0,113,6,41,0,201, + 5,20,0,113,6,51,0,10,5,20,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201, + 4,236,0,113,5,14,0,201,4,236,0,113,6,51,0,115,5,20,0,113,6,51,0,115,5,20,0,113,6,51,0,115,5,20,0,113,6,51,0,115, + 5,20,0,113,6,4,0,201,5,18,255,229,7,84,0,201,5,143,0,120,2,92,255,228,2,57,255,211,2,92,0,3,2,57,255,242,2,92,255,245, + 2,57,255,228,2,92,0,176,2,57,0,150,2,92,0,201,2,57,0,193,4,184,0,201,4,114,0,193,2,92,255,150,2,57,255,219,5,63,0,201, + 4,162,0,186,4,162,0,186,4,117,0,201,2,57,0,193,4,117,0,201,2,57,0,136,4,117,0,201,3,0,0,193,4,117,0,201,2,188,0,193, + 4,127,255,242,2,70,0,2,5,252,0,201,5,18,0,186,5,252,0,201,5,18,0,186,5,252,0,201,5,18,0,186,6,130,0,205,5,252,0,201, + 5,18,0,186,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,8,143,0,115,8,47,0,113,5,143,0,201, + 3,74,0,186,5,143,0,201,3,74,0,130,5,143,0,201,3,74,0,186,5,20,0,135,4,43,0,111,5,20,0,135,4,43,0,111,5,20,0,135, + 4,43,0,111,5,20,0,135,4,43,0,111,4,227,255,250,3,35,0,55,4,227,255,250,3,35,0,55,4,227,255,250,3,35,0,55,5,219,0,178, + 5,18,0,174,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,5,219,0,178, + 5,18,0,174,7,233,0,68,6,139,0,86,4,227,255,252,4,188,0,61,4,227,255,252,5,123,0,92,4,51,0,88,5,123,0,92,4,51,0,88, + 5,123,0,92,4,51,0,88,2,209,0,47,5,20,0,32,5,225,255,151,5,125,0,201,5,20,0,186,5,125,0,0,5,20,0,0,5,160,0,115, + 5,150,0,115,4,102,0,113,6,51,0,10,6,141,255,151,5,125,0,201,5,20,0,113,4,229,0,113,5,14,0,131,6,76,0,117,4,234,0,164, + 4,154,255,150,2,209,255,127,6,51,0,115,5,126,0,8,7,223,0,186,2,212,0,201,2,92,0,10,5,247,0,201,4,162,0,185,2,57,0,10, + 4,188,0,61,7,203,0,178,5,252,255,150,5,18,0,186,6,76,0,115,7,78,0,103,4,229,0,118,7,151,0,115,6,19,0,113,5,55,255,151, + 5,20,0,185,5,143,0,201,5,20,0,114,4,43,0,100,5,14,0,201,2,176,254,242,3,35,0,55,4,227,0,24,3,35,0,55,4,227,255,250, + 6,221,0,173,5,18,0,176,6,29,0,78,5,196,0,201,5,243,255,252,5,216,0,61,5,123,0,92,4,51,0,88,5,84,0,160,5,84,0,92, + 4,159,0,104,4,51,0,113,5,23,0,150,5,84,0,93,4,159,0,104,4,21,0,88,5,20,0,186,2,92,0,201,3,240,0,201,3,172,0,20, + 2,93,0,201,11,96,0,201,10,100,0,201,9,60,0,113,6,175,0,201,6,75,0,201,3,167,0,193,7,115,0,201,7,100,0,201,6,97,0,186, + 5,121,0,16,4,231,0,123,2,92,255,254,2,57,255,224,6,76,0,115,4,229,0,113,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174, + 5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,4,236,0,113,5,121,0,16,4,231,0,123,5,121,0,16, + 4,231,0,123,7,203,0,8,7,219,0,123,6,51,0,115,5,20,0,113,6,51,0,115,5,20,0,113,5,63,0,201,4,162,255,233,6,76,0,115, + 4,229,0,113,6,76,0,115,4,229,0,113,5,84,0,160,4,159,0,88,2,57,255,219,11,96,0,201,10,100,0,201,9,60,0,113,6,51,0,115, + 5,20,0,113,8,231,0,201,5,117,0,201,5,252,0,201,5,18,0,186,5,121,0,16,4,231,0,123,7,203,0,8,7,219,0,123,6,76,0,102, + 4,229,0,72,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,2,92,255,167, + 2,57,255,195,2,92,0,5,2,57,255,227,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,5,143,0,199,3,74,0,130,5,143,0,201, + 3,74,0,186,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,5,20,0,135,4,43,0,111,4,227,255,250,3,35,0,55,5,4,0,156, + 4,44,0,71,6,4,0,201,5,18,255,240,5,226,0,201,6,180,0,113,5,150,0,113,4,226,0,113,5,123,0,92,4,51,0,88,5,121,0,16, + 4,231,0,123,5,14,0,201,4,236,0,113,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,6,76,0,115, + 4,229,0,113,4,227,255,252,4,188,0,61,3,204,0,138,6,190,0,186,3,209,0,55,2,57,255,219,7,252,0,113,7,252,0,113,5,121,255,253, + 5,150,0,12,4,102,0,9,4,117,0,10,4,227,255,178,4,43,0,111,4,51,0,88,4,211,0,80,3,213,0,80,5,125,0,10,5,219,0,12, + 5,121,0,16,5,14,0,201,4,236,0,113,2,92,255,150,2,57,255,219,6,64,0,115,5,20,0,113,5,143,0,10,3,74,0,14,4,227,255,246, + 4,188,0,11,4,205,0,174,5,20,0,113,5,20,0,186,5,20,0,186,4,101,0,127,4,102,0,113,5,20,0,113,5,146,0,113,4,236,0,113, + 4,236,0,113,6,142,0,124,4,83,0,133,4,65,0,133,6,52,0,133,5,80,0,113,2,57,255,219,5,145,0,113,5,20,0,113,5,9,0,113, + 4,196,0,96,4,196,0,96,5,18,0,174,5,18,0,186,5,18,0,186,2,57,0,14,2,181,0,166,2,249,0,116,3,42,0,75,3,230,0,77, + 2,58,0,193,5,166,0,193,7,203,0,186,7,203,0,186,7,203,0,186,5,43,255,219,5,35,0,186,5,18,0,179,4,229,0,113,6,221,0,113, + 5,211,0,148,5,71,0,112,3,80,0,0,3,80,0,0,3,79,0,0,3,74,0,186,3,73,0,186,4,62,0,132,4,62,0,116,4,212,0,186, + 4,212,0,186,4,43,0,111,2,176,255,217,2,176,255,217,3,177,0,55,2,176,254,242,3,35,0,55,3,35,0,55,5,18,0,0,4,241,0,113, + 4,201,0,193,4,188,0,61,6,139,0,86,4,188,0,61,4,227,0,102,4,51,0,88,4,51,0,88,4,159,0,88,4,159,0,109,4,21,0,88, + 4,21,0,88,4,21,0,88,4,21,0,88,6,76,0,115,4,163,0,186,5,80,0,113,5,170,0,113,5,59,0,186,2,86,254,242,5,86,0,186, + 4,14,0,186,5,209,0,113,4,21,0,88,4,21,0,88,8,29,0,113,8,118,0,113,8,26,0,113,6,164,0,55,4,225,0,55,6,58,0,55, + 6,201,0,47,5,165,0,193,5,60,0,193,4,31,0,54,4,31,0,54,5,74,0,0,5,79,0,0,3,60,0,117,3,49,0,117,1,102,255,233, + 2,18,0,117,2,93,0,72,2,94,0,72,3,8,0,32,4,31,0,54,2,251,0,38,2,58,0,160,3,174,0,160,2,139,0,174,2,139,0,178, + 2,139,0,196,2,117,0,117,2,117,0,117,2,245,0,117,2,245,0,117,4,0,1,11,4,0,1,11,4,0,0,193,4,0,0,193,4,0,0,193, + 4,0,0,193,2,51,0,214,4,0,0,213,4,0,1,115,4,0,0,170,2,51,0,214,4,0,0,213,4,0,0,170,4,0,1,115,2,178,0,111, + 2,178,0,111,2,117,0,117,2,117,0,117,4,0,1,31,4,0,1,31,3,30,0,100,2,138,0,100,4,0,0,199,4,0,1,154,4,0,0,238, + 4,0,1,76,4,0,0,182,4,0,0,240,2,134,255,255,4,0,0,239,3,104,0,117,1,84,0,122,2,252,0,117,3,141,0,117,2,245,0,117, + 3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,4,0,0,193,4,0,0,213,4,37,0,174,4,0,0,238,4,0,0,182, + 0,0,252,168,0,0,253,113,0,0,252,193,0,0,252,180,0,0,252,217,0,0,251,236,0,0,252,191,0,0,253,162,0,0,252,215,0,0,253,55, + 0,0,252,236,0,0,252,244,0,0,252,197,0,0,253,188,0,0,252,240,0,0,252,93,0,0,252,191,0,0,252,191,0,0,254,31,0,0,253,144, + 0,0,253,144,0,0,255,121,0,0,252,168,0,0,253,113,0,0,253,36,0,0,253,196,0,0,254,85,0,0,254,240,0,0,253,128,0,0,253,11, + 0,0,253,11,0,0,253,36,0,0,253,11,0,0,253,122,0,0,253,119,0,0,253,162,0,0,252,213,0,0,253,40,0,0,253,106,0,0,253,35, + 0,0,253,76,0,0,253,188,0,0,252,240,0,0,252,99,0,0,252,197,0,0,252,191,0,0,252,191,0,0,252,191,0,0,252,180,0,0,252,217, + 0,0,251,236,0,0,251,236,0,0,251,140,0,0,253,120,0,0,250,237,0,0,251,104,0,0,250,18,0,0,253,172,0,0,252,241,0,0,253,33, + 0,0,252,99,0,0,253,43,0,0,254,6,0,0,251,236,0,0,252,168,0,0,253,113,0,0,252,180,0,0,253,144,0,0,252,231,0,0,253,198, + 0,0,252,213,0,0,253,31,0,0,253,21,0,0,253,31,0,0,252,182,0,0,252,182,0,0,252,182,0,0,252,99,0,0,253,51,0,0,0,0, + 0,0,253,120,0,0,252,191,0,0,253,43,0,0,253,120,0,0,255,46,0,0,252,144,0,0,252,112,0,0,252,112,0,0,252,112,0,0,252,112, + 0,0,253,42,0,0,252,112,0,0,252,119,5,60,0,201,4,139,0,193,6,229,0,201,5,46,0,201,2,58,0,160,2,58,0,160,5,252,0,201, + 5,51,0,186,4,0,1,182,4,101,0,127,4,102,0,113,4,101,0,127,2,178,0,158,4,0,1,115,4,0,0,215,5,138,0,16,2,139,0,219, + 5,248,255,231,6,248,255,243,3,68,255,237,6,128,255,242,6,153,255,225,6,155,255,219,2,181,0,5,5,121,0,16,5,125,0,201,4,117,0,201, + 5,121,0,16,5,14,0,201,5,123,0,92,6,4,0,201,6,76,0,115,2,92,0,201,5,63,0,201,5,121,0,16,6,231,0,201,5,252,0,201, + 5,14,0,201,6,76,0,115,6,4,0,201,4,211,0,201,5,14,0,201,4,227,255,250,4,227,255,252,6,76,0,115,5,123,0,61,6,76,0,115, + 6,29,0,78,2,92,0,6,4,227,255,252,5,70,0,113,4,83,0,133,5,18,0,186,2,181,0,166,4,161,0,149,5,70,0,113,5,27,0,192, + 4,188,0,32,4,229,0,113,4,83,0,133,4,90,0,107,5,18,0,186,4,229,0,113,2,181,0,166,4,183,0,191,4,188,0,61,5,23,0,174, + 4,120,0,74,4,118,0,107,4,229,0,113,4,209,0,74,5,20,0,186,4,178,0,113,5,18,0,113,4,209,0,100,4,161,0,149,5,71,0,112, + 4,159,0,59,5,71,0,112,6,179,0,135,2,181,0,5,4,161,0,149,4,229,0,113,4,161,0,149,6,179,0,135,5,63,0,201,4,234,0,167, + 4,244,0,113,5,151,0,87,6,189,255,225,5,151,0,87,5,71,0,112,6,179,0,65,5,79,0,112,6,76,0,115,4,229,0,113,5,48,0,139, + 4,178,0,113,4,154,0,201,3,171,255,64,5,71,0,179,5,71,0,191,6,236,0,114,5,5,0,119,7,120,0,115,6,179,0,135,6,17,0,115, + 5,70,0,113,6,85,0,201,4,235,0,45,5,126,0,79,4,219,0,100,6,36,0,115,5,0,0,54,5,152,0,115,4,229,0,113,4,227,0,44, + 4,74,0,55,5,79,0,112,5,20,0,186,4,102,0,113,2,57,255,219,6,76,0,115,4,236,0,113,4,236,0,196,4,215,0,201,5,20,0,186, + 5,150,0,115,6,231,0,201,5,53,0,127,5,20,0,85,5,160,0,115,5,150,0,115,5,160,0,115,5,14,0,201,5,14,0,201,6,74,255,250, + 4,225,0,201,5,150,0,115,5,20,0,135,2,92,0,201,2,92,0,6,2,92,255,150,8,192,0,84,8,92,0,201,6,74,255,250,5,174,0,201, + 5,252,0,201,4,224,0,35,6,4,0,201,5,121,0,16,5,125,0,201,5,125,0,201,4,225,0,201,6,64,0,101,5,14,0,201,8,158,0,40, + 5,33,0,135,5,252,0,201,5,252,0,201,5,174,0,201,6,4,0,84,6,231,0,201,6,4,0,201,6,76,0,115,6,4,0,201,4,211,0,201, + 5,150,0,115,4,227,255,250,4,224,0,35,6,227,0,121,5,123,0,61,6,54,0,201,5,124,0,175,8,142,0,201,8,192,0,201,6,169,0,60, + 7,15,0,201,5,125,0,201,5,150,0,111,8,163,0,211,5,143,0,136,4,231,0,123,4,239,0,112,4,183,0,186,4,52,0,186,5,136,0,107, + 4,236,0,113,7,53,0,70,4,65,0,133,5,51,0,186,5,51,0,186,4,213,0,186,5,29,0,76,6,9,0,186,5,59,0,186,4,229,0,113, + 5,59,0,186,5,20,0,186,4,102,0,113,4,169,0,60,4,188,0,61,6,215,0,112,4,188,0,59,5,114,0,186,4,186,0,150,7,82,0,186, + 7,137,0,186,5,167,0,62,6,81,0,186,4,183,0,186,4,100,0,113,6,188,0,193,4,208,0,116,4,236,0,113,4,236,0,113,5,0,0,47, + 4,52,0,186,4,100,0,113,4,43,0,111,2,57,0,193,2,57,255,244,2,57,255,219,7,56,0,76,7,48,0,186,5,55,0,47,4,213,0,186, + 5,51,0,186,4,188,0,61,5,59,0,186,7,120,0,115,6,179,0,135,6,42,0,30,5,96,0,30,7,138,0,211,5,254,0,193,7,9,0,16, + 6,68,0,51,9,71,0,201,8,3,0,193,6,76,0,115,4,229,0,107,8,55,0,201,6,152,0,193,5,23,0,115,4,83,0,91,6,218,0,16, + 7,3,0,50,6,76,0,115,4,229,0,113,6,64,0,16,5,82,0,50,6,64,0,16,5,82,0,50,7,240,0,115,7,60,0,113,7,160,0,115, + 6,17,0,113,9,112,0,118,8,57,0,152,7,120,0,115,6,179,0,135,5,150,0,115,4,102,0,113,4,5,0,59,0,0,251,218,0,0,253,7, + 0,0,253,179,0,0,253,179,0,0,249,202,3,88,247,214,3,88,248,88,6,46,0,201,5,106,0,193,5,125,0,33,4,183,0,38,4,211,0,201, + 5,20,0,186,4,225,0,201,4,52,0,186,5,102,0,71,4,185,0,56,4,254,0,201,4,61,0,186,8,158,0,40,7,53,0,70,5,33,0,135, + 4,65,0,133,5,174,0,201,4,213,0,186,5,174,0,201,4,213,0,186,5,174,0,33,4,213,0,61,6,218,0,50,6,167,0,42,6,4,0,201, + 5,73,0,193,8,29,0,201,7,4,0,193,8,166,0,201,7,83,0,193,7,6,0,115,5,139,0,113,5,150,0,115,4,102,0,113,4,227,255,250, + 4,169,0,60,4,227,255,252,4,188,0,61,4,227,255,252,4,188,0,61,5,123,0,61,4,188,0,59,7,121,255,250,6,116,0,5,5,124,0,175, + 4,186,0,150,5,124,0,175,4,186,0,150,5,124,0,175,5,18,0,186,7,135,0,20,5,211,0,15,7,135,0,20,5,211,0,15,2,92,0,201, + 8,158,0,40,7,53,0,70,5,63,0,201,4,213,0,191,6,53,0,54,5,93,0,46,6,4,0,201,5,73,0,193,6,54,0,201,5,114,0,193, + 5,124,0,175,4,186,0,150,7,26,0,201,6,50,0,193,2,57,0,193,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,7,203,0,8, + 7,219,0,123,5,14,0,201,4,236,0,113,6,76,0,117,4,236,0,113,6,76,0,117,4,236,0,113,8,158,0,40,7,53,0,70,5,33,0,135, + 4,65,0,133,5,84,0,160,4,159,0,88,5,252,0,201,5,51,0,186,5,252,0,201,5,51,0,186,6,76,0,115,4,229,0,113,6,76,0,115, + 4,229,0,113,6,76,0,115,4,229,0,113,5,150,0,111,4,100,0,113,4,224,0,35,4,188,0,61,4,224,0,35,4,188,0,61,4,224,0,35, + 4,188,0,61,5,124,0,175,4,186,0,150,4,225,0,201,4,52,0,186,7,15,0,201,6,81,0,186,5,102,0,71,4,185,0,56,5,123,0,61, + 4,188,0,59,5,123,0,61,4,188,0,59,5,125,0,145,4,183,0,113,8,12,0,145,7,45,0,113,7,204,0,201,6,244,0,171,5,110,0,201, + 4,181,0,171,8,147,0,54,7,168,0,46,8,231,0,201,7,189,0,193,6,51,0,115,5,71,0,113,6,47,255,250,5,176,0,5,4,234,0,164, + 4,83,0,133,6,4,0,84,5,29,0,76,9,90,0,84,7,243,0,76,7,39,0,201,6,234,0,186,8,65,0,136,7,227,0,116,6,76,0,115, + 5,20,0,113,7,233,0,68,6,139,0,86,5,174,0,201,4,213,0,186,8,165,0,84,7,62,0,76,8,166,0,201,7,76,0,186,6,88,0,201, + 5,118,0,186,6,33,0,178,5,219,0,178,6,7,0,93,6,7,0,90,5,219,0,178,6,45,0,178,5,31,0,188,5,219,0,178,6,224,0,178, + 6,7,0,93,5,135,0,188,4,68,0,188,7,96,0,188,6,232,1,8,5,219,0,178,5,186,0,70,6,32,0,168,6,7,0,100,6,35,0,105, + 6,85,0,178,5,210,0,146,5,213,0,0,6,15,0,160,5,219,0,178,5,180,0,120,6,103,0,90,6,37,0,168,6,85,0,178,5,219,0,178, + 6,7,0,100,5,164,0,150,5,141,0,178,5,243,0,160,4,77,0,188,6,124,0,120,6,14,0,50,6,76,0,115,6,82,0,110,2,117,0,117, + 2,139,0,178,1,224,0,0,2,228,0,5,1,231,255,255,3,62,0,8,4,0,0,90,7,203,0,174,5,18,0,186,5,67,0,113,5,78,0,186, + 5,18,0,174,5,20,0,113,4,30,0,186,5,18,0,186,5,232,0,186,5,67,0,113,5,18,0,186,2,44,0,186,7,215,0,186,4,251,0,113, + 5,18,0,174,5,18,0,186,4,221,0,106,5,19,0,186,5,8,0,140,5,18,0,174,2,44,255,212,5,18,255,217,3,253,0,0,5,18,0,186, + 3,60,0,10,7,203,0,174,4,123,0,110,5,48,0,186,5,18,0,174,5,18,0,174,7,202,0,174,5,18,0,186,5,17,0,111,3,122,0,186, + 7,202,0,174,5,23,0,41,4,224,0,111,6,113,0,70,6,126,0,174,2,178,0,240,2,227,0,100,0,0,2,68,0,0,0,171,0,0,0,255, + 0,0,0,255,0,0,2,68,0,0,1,199,0,0,1,199,0,0,1,99,0,0,1,99,0,0,0,0,0,0,0,0,0,0,1,47,0,0,2,78, + 0,0,2,68,2,227,0,100,0,0,1,99,2,92,0,209,0,0,5,25,0,0,0,197,2,92,0,209,3,136,0,102,0,0,1,99,5,89,0,186, + 4,160,0,88,3,76,0,88,4,94,0,88,5,58,0,186,2,46,0,186,2,197,0,88,5,58,0,186,5,48,0,185,1,202,0,136,4,76,0,88, + 4,59,0,88,4,140,0,88,5,79,0,186,5,111,0,88,2,46,0,186,3,52,0,88,5,49,0,185,5,2,0,88,5,30,0,186,4,255,0,186, + 4,81,0,88,4,191,0,88,5,173,0,186,4,132,0,88,5,171,0,88,5,66,0,20,3,196,0,186,3,98,0,136,2,165,0,136,3,83,0,186, + 5,40,0,186,5,25,0,0,5,25,0,0,6,14,0,133,7,208,0,133,2,149,0,219,0,0,0,252,2,139,0,219,4,63,0,147,3,195,0,163, + 2,57,255,181,2,57,0,108,3,221,255,171,2,57,0,108,6,67,0,130,2,57,0,193,7,136,0,130,4,49,0,139,7,136,0,130,7,136,0,130, + 5,42,0,157,5,42,0,157,5,42,0,157,3,144,0,125,3,144,0,125,3,221,255,171,3,221,255,171,9,196,0,130,9,196,0,130,9,172,0,130, + 9,172,0,130,7,102,0,144,7,102,0,144,4,198,0,117,4,198,0,117,2,88,255,236,8,75,0,130,6,53,0,107,6,152,0,144,5,208,0,144, + 4,244,0,140,5,224,0,147,4,49,0,139,3,221,255,171,6,67,0,130,6,67,0,130,0,0,0,220,0,0,0,220,0,0,0,220,0,0,0,220, + 0,0,0,220,0,0,0,220,0,0,0,200,0,0,0,236,0,0,0,152,0,0,1,79,0,0,1,79,0,0,0,220,4,0,0,243,4,76,1,184, + 4,76,1,22,4,76,0,82,4,76,0,76,4,76,0,175,4,76,0,135,4,76,0,85,4,76,0,60,4,76,0,60,4,76,0,100,4,76,0,133, + 2,153,0,0,2,139,0,178,4,92,0,87,7,136,0,130,6,53,0,107,0,0,1,201,2,86,0,122,7,136,0,130,7,136,0,130,7,136,0,130, + 7,136,0,130,7,136,0,130,7,136,0,130,7,136,0,130,7,136,0,130,5,42,0,157,5,42,0,157,5,42,0,157,5,42,0,157,5,42,0,157, + 5,42,0,157,5,42,0,157,3,144,0,125,3,144,0,125,3,144,0,125,3,144,0,125,3,144,0,125,3,144,0,125,3,144,0,125,3,144,0,125, + 3,144,0,125,3,221,255,171,3,221,255,171,3,252,255,171,4,61,255,171,4,226,255,171,4,61,255,171,3,221,255,171,3,221,255,171,3,221,255,171, + 9,196,0,130,9,196,0,130,9,196,0,130,9,172,0,130,9,172,0,130,7,102,0,144,4,198,0,117,8,75,0,130,8,75,0,130,8,75,0,130, + 8,75,0,130,8,75,0,130,8,75,0,130,6,53,0,107,6,53,0,107,7,41,0,130,8,110,0,130,7,41,0,130,6,152,0,144,6,152,0,144, + 6,152,0,144,7,41,0,130,7,41,0,130,7,41,0,130,7,41,0,130,7,41,0,130,7,41,0,130,5,208,0,144,5,208,0,144,5,208,0,144, + 5,208,0,144,5,224,0,147,5,224,0,147,5,224,0,147,5,224,0,147,5,224,0,147,5,150,0,144,5,42,0,157,3,221,255,171,6,67,0,130, + 6,67,0,130,4,49,0,139,4,76,1,184,4,76,1,22,4,76,0,82,4,76,0,76,4,76,0,82,4,76,0,106,4,76,0,208,4,76,0,60, + 4,76,0,60,4,76,0,100,5,23,0,135,5,23,0,225,5,23,0,225,5,23,0,225,5,23,0,225,5,23,0,225,5,23,0,225,5,23,0,214, + 5,23,0,214,5,23,0,157,2,57,0,193,4,146,0,113,3,100,0,61,4,188,0,61,5,59,0,186,5,59,0,186,4,192,0,113,5,59,0,186, + 6,161,0,113,3,129,0,193,3,129,0,61,4,120,0,186,4,229,0,193,2,205,0,61,7,172,0,193,3,200,0,61,6,68,0,61,5,59,0,186, + 5,0,0,61,5,223,0,193,4,61,0,193,5,203,0,112,3,200,0,61,5,0,0,61,4,192,0,113,4,61,0,193,4,61,0,193,4,46,0,193, + 4,192,0,113,4,192,0,113,0,0,0,217,0,0,0,66,0,0,1,164,0,0,0,191,0,0,0,91,0,0,0,66,0,0,0,91,0,0,1,154, + 0,0,0,213,2,130,0,200,2,130,0,200,4,123,0,100,4,123,0,100,2,227,255,236,5,23,0,176,5,93,0,130,5,120,0,139,5,129,0,137, + 3,220,0,109,5,6,0,127,5,120,0,139,5,128,0,115,5,91,0,186,5,34,0,129,5,41,0,0,5,62,0,87,5,69,0,95,5,0,0,73, + 5,0,0,73,5,246,0,89,6,34,0,186,5,126,0,104,5,126,0,104,5,157,0,64,5,128,0,115,5,120,0,139,5,50,0,79,5,15,0,115, + 5,160,0,79,6,141,0,127,5,16,0,115,5,120,0,139,6,77,0,203,5,15,0,111,0,0,251,96,4,80,0,123,4,80,252,154,0,0,251,64, + 0,0,251,64,0,0,251,64,0,0,251,64,0,0,252,254,0,0,252,167,0,0,251,96,0,0,251,28,5,78,0,129,3,0,0,122,5,66,0,122, + 3,174,255,211,4,97,0,92,3,238,0,188,5,100,0,147,0,0,253,18,0,0,251,127,0,0,251,62,0,0,252,78,0,0,251,28,0,0,252,154, + 5,23,0,135,5,32,0,99,5,32,0,99,5,93,0,22,5,0,0,99,5,0,0,99,5,160,0,89,5,93,0,130,5,100,0,150,5,106,0,105, + 8,58,0,127,8,58,0,127,6,254,0,120,5,222,0,110,5,110,0,111,6,173,0,110,4,236,0,100,6,36,0,80,6,7,0,60,7,80,0,121, + 3,160,0,60,4,245,0,120,6,190,0,60,7,15,0,120,4,255,0,130,6,214,0,100,6,64,0,50,5,9,0,80,7,75,0,110,4,247,0,130, + 4,246,0,130,6,214,0,100,6,237,0,100,5,202,0,90,5,10,0,131,4,247,0,110,5,0,0,120,4,245,0,130,6,139,0,121,6,253,0,120, + 4,236,0,130,4,252,0,100,5,0,0,130,5,204,0,60,6,193,0,60,4,196,0,130,5,130,0,111,4,196,0,60,4,192,0,110,5,232,0,80, + 4,16,0,100,4,36,0,100,4,166,0,90,6,139,0,100,4,16,0,100,4,26,0,100,4,1,0,41,6,104,0,100,4,36,0,100,4,21,0,90, + 8,132,0,100,4,46,0,100,4,46,0,130,6,74,0,100,4,16,0,100,4,36,0,100,6,94,0,100,4,46,0,130,5,60,0,90,4,46,0,10, + 6,154,0,100,4,26,0,100,6,74,0,100,4,36,0,100,4,36,0,60,4,46,0,130,4,146,0,90,4,46,0,100,4,36,0,131,4,41,0,100, + 4,46,0,130,3,162,0,20,4,16,0,100,4,36,0,120,4,16,0,100,4,16,0,100,4,36,0,100,4,111,0,100,6,159,0,100,4,106,0,90, + 4,16,0,100,4,146,0,80,4,16,0,100,3,149,0,110,2,151,0,100,5,121,0,16,5,121,0,16,5,121,0,16,5,121,0,16,6,39,0,201, + 6,39,0,201,6,39,0,201,6,39,0,201,6,39,0,119,6,39,0,119,6,174,0,201,6,173,0,16,6,174,0,201,6,173,0,16,6,174,0,201, + 6,173,0,16,7,188,0,201,8,14,0,201,7,188,0,201,8,14,0,201,6,39,0,201,7,188,0,201,8,14,0,119,7,188,0,201,8,14,0,119, + 6,39,0,119,2,12,0,201,4,88,0,137,3,99,0,94,3,99,0,94,3,29,0,137,3,29,0,137,3,37,0,137,3,29,0,137,3,186,0,72, + 3,21,0,137,2,12,0,201,3,29,0,137,3,29,0,137,3,29,0,137,8,184,0,16,7,69,0,16,7,160,0,201,8,239,0,119,5,121,0,16, + 5,121,0,16,5,121,0,16,5,121,0,16,5,213,0,119,5,213,0,119,5,213,0,119,5,213,0,119,5,213,0,119,5,213,0,119,6,174,0,201, + 5,121,0,16,6,174,0,201,6,173,0,16,6,174,0,201,6,173,0,16,7,188,0,201,8,14,0,119,7,188,0,201,8,14,0,119,7,188,0,201, + 8,14,0,119,7,188,0,201,8,14,0,119,5,213,0,119,4,17,0,137,1,137,0,137,5,219,0,178,5,219,0,178,5,219,0,178,5,219,0,178, + 5,215,0,119,5,215,0,119,5,215,0,119,5,215,0,119,5,215,0,121,5,215,0,121,7,94,0,201,7,28,0,178,7,94,0,201,7,28,0,178, + 7,94,0,201,7,28,0,178,7,108,0,201,7,52,0,119,7,108,0,201,7,52,0,119,7,148,0,201,7,52,0,121,7,148,0,201,7,52,0,121, + 7,148,0,240,3,121,0,137,7,5,0,178,7,5,0,178,6,237,0,119,7,31,0,121,5,7,0,70,5,7,0,201,5,7,0,201,5,7,0,201, + 5,7,0,70,5,7,0,70,5,7,0,70,5,7,0,201,5,7,0,201,6,225,0,201,6,42,0,70,6,133,0,201,6,135,0,201,6,133,0,201, + 6,135,0,201,6,225,0,201,6,42,0,70,6,225,0,201,6,42,0,70,6,133,0,201,6,135,0,201,6,133,0,201,6,135,0,201,6,133,0,240, + 3,65,0,137,3,65,0,56,6,1,0,70,6,51,0,201,6,1,0,70,6,51,0,201,5,7,0,70,5,7,0,201,5,7,0,201,5,7,0,201, + 5,7,0,70,5,7,0,70,5,7,0,70,5,7,0,201,5,7,0,201,6,225,0,201,6,42,0,70,6,133,0,201,6,135,0,201,6,133,0,201, + 6,135,0,201,6,225,0,201,6,42,0,70,6,225,0,201,6,42,0,70,6,133,0,201,6,135,0,201,6,133,0,201,6,135,0,201,6,133,0,240, + 3,122,0,137,3,122,0,137,4,225,0,119,4,117,0,201,4,117,0,201,4,117,0,201,4,225,0,119,4,225,0,119,4,225,0,119,4,117,0,201, + 4,117,0,201,5,254,0,201,6,38,0,119,5,248,0,201,6,28,0,201,5,248,0,201,6,28,0,201,5,254,0,201,6,38,0,119,5,254,0,201, + 6,38,0,119,5,248,0,201,6,28,0,201,5,248,0,201,6,28,0,201,5,248,0,240,3,22,0,137,4,17,0,137,3,22,0,137,6,208,0,119, + 6,208,0,70,6,208,0,70,6,208,0,11,6,208,0,119,6,208,0,119,6,208,0,119,6,208,0,70,6,208,0,70,8,142,0,201,8,71,0,119, + 8,121,0,201,6,208,0,70,8,121,0,201,6,208,0,70,6,208,0,70,4,205,0,137,3,159,0,137,4,205,0,137,6,208,0,119,6,208,0,70, + 6,208,0,70,6,208,0,70,6,208,0,119,6,208,0,119,6,208,0,119,6,208,0,70,6,208,0,70,8,142,0,201,8,71,0,119,8,121,0,201, + 8,61,0,70,8,121,0,201,8,61,0,70,8,142,0,201,8,71,0,119,8,142,0,201,8,71,0,119,8,170,0,201,8,61,0,70,8,170,0,201, + 8,61,0,70,4,205,0,137,5,213,0,119,4,211,0,70,4,211,0,201,4,211,0,201,4,211,0,201,4,211,0,70,4,211,0,70,4,211,0,70, + 4,211,0,201,4,211,0,201,6,173,0,201,6,8,0,70,6,86,0,201,6,43,0,201,6,86,0,201,6,43,0,201,6,173,0,201,6,8,0,70, + 6,173,0,201,6,8,0,70,6,86,0,201,6,43,0,201,6,86,0,201,6,43,0,201,6,86,0,240,3,89,0,137,3,93,0,137,3,89,0,137, + 5,178,0,70,5,178,0,70,5,178,0,70,7,34,0,70,7,34,0,70,7,34,0,70,7,34,0,70,7,71,0,201,6,250,0,70,7,71,0,201, + 6,250,0,70,7,71,0,201,6,250,0,70,9,31,0,201,8,204,0,70,9,31,0,201,8,204,0,70,9,31,0,201,8,204,0,70,9,31,0,201, + 8,204,0,70,5,32,0,137,5,4,0,119,5,4,0,201,5,4,0,201,5,4,0,201,5,4,0,119,5,4,0,119,5,4,0,119,5,4,0,201, + 5,4,0,201,6,193,0,201,6,63,0,119,6,135,0,201,6,140,0,201,6,135,0,201,6,140,0,201,6,193,0,201,6,63,0,119,6,193,0,201, + 6,63,0,119,6,135,0,201,6,140,0,201,6,135,0,201,6,140,0,201,6,135,0,240,3,89,0,137,3,29,0,137,3,224,0,137,7,83,0,201, + 7,83,0,119,7,83,0,119,7,83,0,201,7,83,0,201,7,83,0,201,4,211,0,201,4,211,0,201,4,211,0,201,4,211,0,70,4,211,0,70, + 4,211,0,70,6,173,0,201,6,8,0,70,3,89,0,137,5,213,0,119,5,121,0,150,5,121,0,150,5,121,0,150,5,121,0,150,5,207,0,77, + 5,207,0,77,5,207,0,119,5,207,0,119,7,100,0,201,8,14,0,119,4,17,0,137,5,219,0,178,5,219,0,178,5,219,0,178,5,219,0,178, + 5,219,0,178,5,219,0,178,5,215,0,83,5,215,0,83,5,215,0,121,5,215,0,121,7,148,0,201,7,52,0,121,4,17,0,137,6,165,0,70, + 6,165,0,119,6,165,0,119,6,165,0,70,6,165,0,70,6,165,0,119,6,165,0,119,4,130,0,137,6,4,0,201,3,224,0,137,8,96,0,137, + 8,96,0,137,8,96,0,137,8,96,0,137,8,96,0,137,8,96,0,137,8,96,0,137,6,154,0,137,6,165,0,70,6,165,0,119,6,165,0,70, + 6,165,0,119,10,19,0,137,10,19,0,137,10,19,0,137,8,4,0,137,8,4,0,137,10,19,0,137,10,19,0,137,5,153,0,137,8,149,0,137, + 6,208,0,70,6,208,0,70,6,208,0,119,6,208,0,119,6,208,0,70,6,208,0,70,4,205,0,137,5,37,0,119,5,37,0,33,5,37,0,33, + 5,37,0,119,5,37,0,119,5,37,0,33,5,37,0,33,3,89,0,10,5,7,0,201,6,41,0,201,6,35,0,115,3,191,0,137,3,191,0,137, + 3,141,0,117,8,96,0,137,10,122,0,137,13,15,0,137,13,15,0,137,11,0,0,137,11,0,0,137,13,15,0,137,13,15,0,137,3,209,255,236, + 3,241,255,236,5,178,255,236,7,115,255,236,9,52,255,236,10,245,255,236,3,241,255,236,5,178,255,236,7,115,255,236,9,51,255,236,10,245,255,236, + 3,252,255,236,5,191,255,236,7,130,255,236,9,69,255,236,11,8,255,236,3,241,255,236,5,178,255,236,7,112,255,236,9,50,255,236,10,245,255,236, + 3,252,255,236,6,5,255,236,6,79,255,236,9,163,255,236,9,51,255,236,5,119,255,236,4,15,0,113,4,14,255,236,4,188,0,61,5,189,0,11, + 7,219,0,123,4,176,0,62,4,102,0,113,4,215,0,186,4,215,0,36,3,237,0,186,4,83,0,130,2,57,0,193,3,40,0,0,4,162,0,186, + 4,170,0,2,6,9,0,186,5,51,0,186,4,229,0,113,4,102,0,127,5,121,0,113,5,121,0,113,5,121,0,51,8,47,0,113,4,229,0,113, + 4,229,0,113,4,50,0,151,4,208,0,50,4,208,0,50,4,169,0,60,4,152,0,186,5,229,0,174,7,149,0,174,5,26,0,47,4,188,0,61, + 6,139,0,86,4,51,0,88,4,53,0,120,4,170,0,179,4,188,0,61,4,131,0,151,4,50,0,151,4,185,0,90,5,29,0,76,3,114,0,10, + 4,232,0,5,3,117,0,127,3,225,0,127,3,47,0,127,3,47,0,83,3,231,0,72,3,202,0,127,1,124,0,127,1,124,255,189,3,78,0,127, + 2,206,0,127,4,89,0,127,3,197,0,127,3,197,0,127,3,247,0,72,3,132,0,71,3,10,0,127,3,128,0,127,3,20,255,252,3,176,0,112, + 4,251,0,43,3,34,0,77,3,34,0,77,3,62,0,71,5,47,0,77,3,109,0,117,3,62,0,71,3,86,0,71,3,86,0,71,2,226,0,84, + 2,224,0,82,3,62,0,71,1,110,0,122,3,104,0,117,4,252,0,117,3,69,0,117,3,79,0,71,2,246,0,71,3,79,0,71,3,79,0,71, + 3,109,0,117,2,92,0,35,3,61,0,110,3,194,0,110,4,252,0,117,3,86,0,38,3,55,0,121,2,251,0,20,3,21,0,71,3,83,0,71, + 2,233,0,37,1,110,0,122,2,18,0,117,3,61,0,110,3,86,0,38,3,55,0,121,2,251,0,20,3,75,0,121,3,83,0,71,2,233,0,37, + 5,20,0,186,3,202,0,127,2,249,0,116,5,86,0,50,2,57,0,145,3,62,0,71,2,246,0,71,2,246,0,71,3,79,0,71,2,226,0,84, + 2,95,0,30,1,221,255,233,3,62,0,71,3,61,0,110,2,23,0,73,1,255,0,122,2,22,0,73,2,23,0,73,1,224,255,86,1,255,0,122, + 1,225,0,91,3,3,0,113,4,252,0,117,4,252,0,117,3,73,255,233,3,214,0,117,3,69,0,113,3,79,0,71,3,79,0,71,2,226,0,70, + 2,75,255,233,2,92,0,35,4,16,0,94,3,89,0,71,2,228,0,117,3,64,0,122,3,86,0,38,2,238,0,55,3,126,0,55,2,238,0,55, + 3,35,0,55,3,79,0,71,0,0,252,91,0,0,252,91,0,0,252,91,0,0,252,91,0,0,252,66,0,0,252,66,5,121,0,16,4,231,0,123, + 5,125,0,201,5,20,0,184,5,125,0,201,5,20,0,186,5,125,0,201,5,20,0,186,5,150,0,115,4,102,0,113,6,41,0,201,5,20,0,113, + 6,41,0,201,5,20,0,113,6,41,0,201,5,20,0,113,6,41,0,201,5,20,0,113,6,41,0,201,5,20,0,113,5,14,0,201,4,236,0,113, + 5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,4,154,0,201,2,209,0,47, + 6,51,0,115,5,20,0,113,6,4,0,201,5,18,0,184,6,4,0,201,5,18,0,186,6,4,0,201,5,18,255,237,6,4,0,17,5,18,0,2, + 6,4,0,201,5,18,0,186,2,92,0,0,2,57,255,211,2,92,0,7,2,57,255,244,5,63,0,201,4,162,0,186,5,63,0,201,4,162,0,186, + 5,63,0,201,4,162,0,186,4,117,0,201,2,77,0,201,4,117,0,3,2,77,255,253,4,117,0,201,2,57,255,244,4,117,0,201,2,57,255,222, + 6,231,0,201,7,203,0,186,6,231,0,201,7,203,0,186,6,231,0,201,7,203,0,186,5,252,0,201,5,18,0,186,5,252,0,201,5,18,0,186, + 5,252,0,201,5,18,0,186,5,252,0,201,5,18,0,186,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113, + 6,76,0,115,4,229,0,113,4,211,0,201,5,20,0,186,4,211,0,201,5,20,0,186,5,143,0,201,3,74,0,186,5,143,0,201,3,74,0,186, + 5,143,0,201,3,74,0,186,5,143,0,201,3,74,0,84,5,20,0,135,4,43,0,111,5,20,0,135,4,43,0,111,5,20,0,135,4,43,0,111, + 5,20,0,135,4,43,0,111,5,20,0,135,4,43,0,111,4,227,255,250,3,35,0,55,4,227,255,250,3,35,0,55,4,227,255,250,3,35,0,55, + 4,227,255,250,3,35,0,55,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174, + 5,219,0,178,5,18,0,174,5,121,0,16,4,188,0,61,5,121,0,16,4,188,0,61,7,233,0,68,6,139,0,86,7,233,0,68,6,139,0,86, + 7,233,0,68,6,139,0,86,7,233,0,68,6,139,0,86,7,233,0,68,6,139,0,86,5,123,0,61,4,188,0,59,5,123,0,61,4,188,0,59, + 4,227,255,252,4,188,0,61,5,123,0,92,4,51,0,88,5,123,0,92,4,51,0,88,5,123,0,92,4,51,0,88,5,18,0,186,3,35,0,4, + 6,139,0,86,4,188,0,61,4,231,0,123,2,209,0,47,2,209,0,2,2,209,0,47,6,38,0,178,4,229,0,113,5,121,0,16,4,231,0,123, + 5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123, + 5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123,5,121,0,16,4,231,0,123, + 5,121,0,16,4,231,0,123,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113, + 5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,5,14,0,201,4,236,0,113,2,92,0,90,2,57,0,68, + 2,92,0,201,2,57,0,191,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113, + 6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,6,76,0,115,4,229,0,113,7,78,0,103,4,229,0,118,7,78,0,103,4,229,0,118, + 7,78,0,103,4,229,0,118,7,78,0,103,4,229,0,118,7,78,0,103,4,229,0,118,5,219,0,178,5,18,0,174,5,219,0,178,5,18,0,174, + 6,221,0,173,5,18,0,176,6,221,0,173,5,18,0,176,6,221,0,173,5,18,0,176,6,221,0,173,5,18,0,176,6,221,0,173,5,18,0,176, + 4,227,255,252,4,188,0,61,4,227,255,252,4,188,0,61,4,227,255,252,4,188,0,61,4,227,255,252,4,188,0,61,6,39,0,201,3,209,0,32, + 5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,121,0,16,5,121,0,16, + 7,5,0,5,7,5,0,6,6,39,0,7,6,105,0,4,5,170,0,7,5,241,0,4,4,83,0,133,4,83,0,133,4,83,0,133,4,83,0,133, + 4,83,0,133,4,83,0,133,5,176,0,7,5,176,0,7,7,186,0,5,7,204,0,6,7,48,0,7,7,108,0,4,5,18,0,186,5,18,0,186, + 5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,6,178,0,7,6,175,0,7,8,176,0,5,8,182,0,6, + 8,55,0,7,8,104,0,4,7,120,0,7,7,147,0,4,2,181,0,155,2,181,0,145,2,181,255,177,2,181,255,187,2,181,0,5,2,181,255,211, + 2,181,255,203,2,181,255,198,3,10,0,7,2,254,0,7,5,20,0,5,5,20,0,6,4,144,0,7,4,204,0,4,3,234,0,7,3,241,0,4, + 4,229,0,113,4,229,0,113,4,229,0,113,4,229,0,113,4,229,0,113,4,229,0,113,6,111,0,7,6,201,0,7,8,194,0,5,8,204,0,6, + 7,130,0,7,7,195,0,4,4,161,0,149,4,161,0,149,4,161,0,149,4,161,0,149,4,161,0,149,4,161,0,149,4,161,0,149,4,161,0,149, + 6,69,0,7,7,251,0,6,8,25,0,4,7,46,0,4,6,179,0,135,6,179,0,135,6,179,0,135,6,179,0,135,6,179,0,135,6,179,0,135, + 6,179,0,135,6,179,0,135,6,107,0,7,6,191,0,7,8,183,0,5,8,195,0,6,7,145,0,7,7,199,0,4,7,95,0,7,7,158,0,4, + 5,70,0,113,5,70,0,113,4,83,0,133,4,99,0,133,5,18,0,186,5,60,0,186,2,181,255,141,2,181,0,166,4,229,0,113,4,229,0,113, + 4,161,0,149,4,161,0,149,6,179,0,135,6,179,0,135,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113, + 5,70,0,113,5,70,0,113,5,121,0,16,5,121,0,16,7,5,0,5,7,5,0,6,6,39,0,7,6,105,0,4,5,170,0,7,5,241,0,4, + 5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,5,18,0,186,6,178,0,7,6,175,0,7, + 8,176,0,5,8,182,0,6,8,55,0,7,8,104,0,4,7,120,0,7,7,147,0,4,6,179,0,135,6,179,0,135,6,179,0,135,6,179,0,135, + 6,179,0,135,6,179,0,135,6,179,0,135,6,179,0,135,6,107,0,7,6,191,0,7,8,183,0,5,8,195,0,6,7,145,0,7,7,199,0,4, + 7,95,0,7,7,158,0,4,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,70,0,113,5,121,0,16, + 5,121,0,16,5,187,255,252,5,138,0,16,5,121,0,16,4,0,1,134,4,0,1,182,4,0,1,134,4,0,0,182,4,0,0,182,5,18,0,186, + 5,18,0,186,5,60,0,186,5,18,0,186,5,18,0,186,6,112,255,252,5,248,255,231,7,114,255,252,6,248,255,243,6,4,0,201,4,0,0,137, + 4,0,0,180,4,0,0,182,2,181,255,235,2,181,255,227,2,181,255,216,2,181,0,5,2,181,255,228,2,181,255,230,2,92,255,245,2,92,0,3, + 3,205,255,252,3,68,255,237,4,0,0,126,4,0,0,149,4,0,0,182,4,161,0,149,4,161,0,149,4,161,0,149,4,161,0,149,5,20,0,186, + 5,20,0,186,4,161,0,149,4,161,0,149,4,227,255,252,4,227,255,252,6,195,255,252,6,153,255,225,5,123,0,7,4,0,0,170,4,0,0,215, + 4,0,0,170,6,179,0,135,6,179,0,135,6,179,0,135,6,179,0,135,6,179,0,135,7,135,255,252,6,128,255,242,7,97,255,252,6,155,255,219, + 6,29,0,78,4,0,1,115,4,0,1,134,4,0,0,0,8,0,0,0,4,0,0,0,8,0,0,0,2,163,0,0,2,0,0,0,1,86,0,0, + 5,23,0,0,2,139,0,0,1,153,0,0,0,204,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,227,0,100, + 2,227,0,100,5,23,0,100,4,0,0,100,8,0,0,100,8,0,0,0,4,0,1,4,4,0,255,236,2,139,0,174,2,139,0,178,2,139,0,174, + 2,139,0,178,4,37,0,174,4,37,0,174,4,37,0,174,4,37,0,174,4,0,0,57,4,0,0,57,4,184,1,51,4,184,1,51,2,173,0,236, + 5,87,0,236,8,0,0,236,2,139,0,220,0,0,0,0,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,153,0,0,10,188,0,113,13,226,0,113,1,209,0,40,2,253,0,40,4,41,0,40,1,209,0,40,2,253,0,40,4,41,0,40,2,182,0,11, + 3,51,0,158,3,51,0,193,6,180,0,195,3,226,0,147,4,63,0,147,4,0,255,236,6,110,255,167,6,110,255,167,2,0,255,170,8,0,0,61, + 4,0,0,221,1,86,254,137,3,31,0,176,3,31,0,176,7,96,0,74,5,221,0,147,5,221,0,147,3,250,0,100,5,23,0,236,4,0,0,216, + 4,0,0,216,4,0,0,61,2,178,1,29,6,110,255,167,4,0,0,61,3,153,0,145,8,0,0,100,6,110,255,167,6,180,1,56,4,176,0,250, + 5,78,0,40,6,180,1,102,6,180,1,102,2,139,0,219,6,97,0,100,6,180,0,112,2,139,0,219,2,139,0,219,1,199,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,53,0,87,1,110,0,122,3,53,0,63,3,53,0,102,3,53,0,92,3,53,0,108,3,53,0,89,3,53,0,83,4,57,0,137,4,57,0,137, + 4,57,0,137,1,247,0,111,1,247,0,103,3,48,0,117,3,53,0,87,3,53,0,137,3,53,0,94,3,53,0,98,3,53,0,63,3,53,0,102, + 3,53,0,92,3,53,0,108,3,53,0,89,3,53,0,83,4,57,0,137,4,57,0,137,4,57,0,137,1,247,0,111,1,247,0,103,3,34,0,77, + 3,86,0,71,3,79,0,71,3,141,0,117,3,86,0,71,3,60,0,117,3,104,0,117,1,84,0,122,4,252,0,117,3,48,0,117,3,109,0,117, + 2,252,0,117,2,92,0,35,7,4,0,86,5,23,0,115,5,23,0,96,5,23,0,133,5,23,0,129,7,203,0,186,5,252,0,117,10,46,0,201, + 8,151,0,201,7,233,0,59,6,70,0,95,5,23,0,113,5,23,0,0,5,23,0,40,5,23,0,20,10,46,0,208,5,23,0,46,5,23,0,68, + 5,23,0,93,5,23,0,16,6,49,0,117,5,23,0,165,5,23,0,20,5,23,0,106,5,110,0,10,0,0,252,19,0,0,252,61,0,0,252,61, + 0,0,252,61,0,0,252,19,0,0,251,80,0,0,252,61,8,38,0,67,8,38,0,67,5,150,0,115,8,252,0,195,5,35,255,214,8,38,0,60, + 8,137,0,60,4,234,0,164,5,150,0,111,7,157,0,195,7,232,0,73,6,9,0,2,6,204,0,201,5,18,0,72,5,18,0,90,3,194,0,59, + 5,148,0,106,5,195,0,68,3,78,255,228,6,139,0,32,6,104,0,198,8,82,0,54,8,0,1,27,5,148,0,110,5,156,0,200,6,76,0,115, + 6,98,0,66,6,131,0,83,6,86,0,200,7,44,0,169,5,121,0,201,8,40,1,3,8,152,255,252,8,0,1,39,5,121,0,16,5,245,0,92, + 4,159,0,88,6,29,0,78,6,29,0,78,4,238,0,24,2,181,0,68,5,63,0,201,5,121,0,16,6,74,0,92,5,160,0,130,6,214,0,125, + 4,188,0,87,4,216,0,162,6,74,0,84,4,154,0,201,8,142,0,57,3,178,0,104,5,246,0,103,5,100,255,251,3,186,0,27,5,40,0,86, + 3,10,0,70,7,104,0,90,9,141,0,151,5,158,0,36,5,210,0,0,5,60,0,200,6,202,0,201,6,124,0,25,6,51,0,163,4,117,0,8, + 4,117,0,7,4,227,255,252,6,141,0,87,5,170,0,90,4,236,0,91,2,207,0,79,2,207,255,22,6,61,0,59,4,54,0,81,7,193,0,137, + 7,193,0,137,10,246,0,137,7,193,0,137,7,193,0,94,7,193,0,137,7,193,0,94,7,193,0,98,7,193,0,63,7,193,0,137,7,193,0,102, + 7,193,0,137,7,193,0,98,7,193,0,102,7,193,0,108,4,139,0,137,2,92,0,201,3,240,0,201,5,132,0,201,7,98,0,201,5,121,0,16, + 7,97,0,16,8,245,0,16,10,137,0,16,7,87,0,201,5,123,0,61,7,119,0,61,9,13,0,61,4,117,0,201,5,150,0,115,6,41,0,201, + 6,231,0,201,2,57,0,193,3,169,0,193,5,25,0,193,6,126,0,193,4,188,0,61,6,125,0,61,7,237,0,61,9,93,0,61,6,141,0,193, + 4,188,0,59,6,148,0,59,8,4,0,59,2,57,0,193,4,102,0,113,5,20,0,113,7,203,0,186,9,246,0,121,6,41,0,201,9,246,0,121, + 5,160,0,115,4,101,0,127,5,150,0,115,7,193,0,87,6,180,0,100,6,180,1,163,6,180,0,117,6,180,1,163,6,180,0,100,6,180,1,163, + 6,180,1,32,6,180,1,32,6,180,1,32,6,180,1,32,6,180,0,100,6,180,0,117,6,180,0,44,6,180,0,22,6,180,0,100,6,180,1,165, + 6,180,0,117,6,180,1,165,6,180,0,100,6,180,0,117,6,180,0,100,6,180,1,165,6,180,0,117,6,180,1,165,6,180,1,165,6,180,0,100, + 6,180,0,118,6,180,0,100,6,180,0,118,6,180,0,100,6,180,0,100,6,180,1,42,6,180,1,90,6,180,1,172,6,180,1,90,6,180,1,172, + 6,180,1,221,6,180,0,100,6,180,0,45,6,180,0,79,6,180,0,222,6,180,0,112,6,180,0,211,6,180,0,157,6,180,0,100,6,180,0,100, + 6,180,3,5,6,180,1,163,6,180,0,117,6,180,0,117,6,180,3,5,6,180,1,163,6,180,0,100,6,180,0,119,6,180,0,100,6,180,0,100, + 6,180,0,120,6,180,0,118,6,180,0,120,6,180,0,100,6,180,0,100,6,180,0,100,6,180,0,100,6,180,0,117,6,180,0,100,6,180,1,165, + 6,180,0,117,6,180,1,165,6,180,0,100,6,180,1,164,6,180,1,32,6,180,0,188,6,180,0,188,6,180,1,32,6,180,0,100,6,180,0,117, + 6,180,0,100,6,180,0,117,6,180,1,163,6,180,1,163,6,180,0,100,6,180,1,163,6,180,0,117,6,180,1,163,6,180,0,107,6,180,0,117, + 6,180,0,55,6,180,1,94,6,180,0,72,6,180,1,94,6,180,1,94,6,180,1,94,6,180,1,64,6,180,1,94,6,180,1,94,6,180,1,94, + 6,180,0,117,6,180,0,122,6,180,0,122,6,180,1,94,6,180,0,117,6,180,0,119,6,180,0,117,6,180,0,100,6,180,0,117,6,180,0,100, + 6,180,0,100,6,180,0,117,6,180,0,100,6,180,0,55,6,180,0,117,6,180,0,55,5,121,0,16,5,23,0,135,4,35,0,95,5,14,0,201, + 5,14,0,201,6,248,0,155,5,90,255,250,5,90,255,250,6,248,0,175,6,248,0,175,5,190,0,217,6,248,0,175,6,248,0,175,5,190,0,217, + 5,23,1,44,6,14,0,156,6,14,0,156,5,100,0,25,6,180,0,217,6,180,0,217,6,180,0,217,2,178,0,0,5,24,1,138,6,180,1,5, + 5,2,1,68,5,2,1,88,5,25,0,61,5,25,0,61,5,25,0,61,5,183,0,220,6,170,0,220,6,180,1,27,7,44,0,175,7,44,0,175, + 6,180,0,237,4,0,1,176,4,0,0,102,4,0,1,16,4,0,0,102,5,219,1,8,5,219,1,8,5,219,1,8,5,219,1,8,4,43,0,117, + 6,80,0,117,8,117,0,117,4,43,0,117,6,80,0,117,8,117,0,117,4,43,0,117,4,43,0,117,4,43,0,117,5,23,0,121,5,23,0,121, + 2,21,0,161,5,23,0,121,6,180,0,217,6,180,0,217,6,180,0,216,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,162,6,180,0,217, + 3,0,0,208,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,216,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,182,0,217,6,182,0,217, + 8,0,0,207,8,0,0,205,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,218,6,180,0,218, + 6,180,0,218,6,180,0,218,8,96,0,148,8,96,0,148,3,182,0,176,6,180,0,216,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,218,6,180,0,217,6,180,0,217,6,180,0,208,6,180,0,208,6,180,0,208,6,180,0,208,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,204,6,180,0,204,6,180,0,204,6,180,0,204, + 6,180,0,190,6,180,0,217,6,180,0,190,6,180,0,217,6,180,0,190,6,180,0,190,5,219,1,8,5,219,1,8,5,219,1,8,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,62,0,217,6,62,0,217,6,180,0,187,6,180,0,187,6,180,0,187,6,180,0,187,6,180,0,187, + 6,180,0,187,6,180,0,187,6,180,0,187,6,180,0,187,6,180,0,187,6,180,0,187,6,180,0,187,6,180,0,187,6,248,0,175,6,248,0,175, + 6,248,0,175,6,248,0,175,4,42,0,175,4,42,0,175,6,248,0,175,6,248,0,175,6,248,0,175,6,248,0,175,6,248,0,175,6,248,0,175, + 6,248,0,175,6,248,0,175,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,8,0,0,121,8,0,0,121, + 6,180,0,98,6,180,0,121,4,42,0,238,5,219,0,200,5,219,0,200,5,219,0,200,6,180,1,27,6,180,1,27,6,144,255,250,6,144,255,250, + 6,144,0,140,6,144,0,140,3,244,0,6,2,139,0,219,5,2,0,249,6,180,0,217,8,0,0,217,8,0,0,217,8,0,0,217,8,0,0,217, + 8,0,0,217,6,180,0,217,5,220,0,99,5,220,0,99,6,180,0,190,6,180,0,217,6,180,0,210,6,180,0,210,6,180,1,124,6,180,0,217, + 6,180,0,217,6,180,0,217,11,97,0,148,11,97,0,148,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,225, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,213,8,0,3,150,8,0,0,236,8,0,0,236,8,0,0,236,8,0,0,88,6,248,0,175, + 5,190,0,217,6,248,0,175,6,248,0,175,5,190,0,217,6,248,0,175,6,248,0,175,8,0,0,88,6,248,0,175,5,190,0,217,6,248,0,175, + 5,190,0,217,6,248,0,217,4,209,0,74,4,209,0,114,5,20,0,146,6,180,1,163,6,180,1,163,6,180,1,163,6,180,1,163,3,232,1,59, + 3,31,0,176,3,31,0,199,3,31,0,176,3,31,0,199,6,120,2,244,6,120,0,100,6,120,2,244,6,120,0,100,6,180,0,217,4,27,0,6, + 8,0,0,247,6,180,0,217,3,192,0,176,3,192,0,134,3,192,0,176,3,192,0,134,4,43,1,175,4,43,0,42,9,56,0,156,9,56,0,156, + 11,80,0,156,9,56,0,156,11,140,0,120,11,80,0,1,6,252,0,150,2,181,0,166,5,20,0,186,6,179,0,135,5,70,0,113,6,15,0,26, + 9,56,0,156,6,252,0,35,4,0,0,176,4,0,0,176,4,0,0,176,4,0,0,176,4,0,2,141,4,0,0,176,4,0,0,176,4,0,0,176, + 4,0,0,176,4,0,0,176,4,0,2,141,4,0,0,176,6,0,2,163,6,0,0,168,6,0,2,163,6,0,2,163,6,0,0,168,6,0,2,163, + 6,0,0,168,4,43,1,175,6,180,0,55,7,143,0,186,6,252,0,150,6,39,0,6,5,23,0,89,5,20,255,131,5,20,0,146,7,44,0,152, + 7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,4,209,255,236, + 4,209,255,236,4,209,2,24,4,209,1,200,4,209,255,236,4,209,255,236,4,209,2,24,4,209,1,200,4,209,255,235,4,209,255,236,4,209,2,24, + 4,209,1,200,4,209,2,24,4,209,2,24,4,209,1,200,4,209,1,200,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,2,24, + 4,209,2,24,4,209,1,200,4,209,1,200,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,2,24,4,209,2,24,4,209,1,200, + 4,209,1,200,4,209,1,200,4,209,1,200,4,209,1,200,4,209,1,200,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236, + 4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236, + 4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236, + 4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236, + 4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,2,24,4,209,1,200,4,209,255,236, + 4,209,1,120,4,209,2,24,4,209,1,120,4,209,1,120,4,209,255,236,4,209,255,236,4,209,255,236,4,209,2,24,4,209,1,120,4,209,1,120, + 4,209,255,236,4,209,255,236,4,209,255,236,4,209,2,24,4,209,1,120,4,209,1,120,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236, + 4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,255,236,4,209,2,24,4,209,255,236, + 4,209,255,236,4,209,2,24,4,209,255,147,4,209,255,147,4,209,255,147,4,209,255,236,4,209,2,24,4,209,2,124,4,209,2,24,4,209,255,236, + 4,209,1,200,4,209,2,124,4,209,1,200,4,209,255,236,4,209,1,200,4,209,255,236,4,209,1,200,6,39,255,236,6,39,255,236,6,39,255,236, + 6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236, + 6,39,255,236,6,39,255,236,6,39,255,236,6,39,3,19,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,5,113,6,39,255,236, + 6,39,3,19,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,255,236,6,39,3,19,6,39,255,236,6,39,255,236,7,143,0,186, + 7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,5,108,0,186, + 5,108,0,186,7,143,0,186,7,143,0,186,4,103,0,186,4,103,0,186,6,39,0,6,6,39,0,6,6,39,0,6,6,39,0,6,4,4,0,6, + 4,4,0,6,6,39,0,6,6,39,0,6,4,4,0,6,4,4,0,6,6,39,0,6,6,39,0,6,6,39,0,6,6,39,0,6,4,4,0,6, + 4,4,0,6,6,39,0,6,6,39,0,6,4,4,0,6,4,4,0,6,6,39,0,6,6,39,0,6,6,39,0,6,6,39,0,6,6,39,0,6, + 6,251,0,112,3,244,0,6,6,251,0,112,6,251,0,114,6,251,0,112,6,251,0,112,6,251,0,112,6,251,0,112,6,251,0,112,6,251,0,112, + 6,251,0,112,6,251,0,112,6,251,0,112,4,55,0,112,4,55,0,186,6,84,0,186,7,195,0,186,7,195,0,186,7,195,0,186,3,25,0,6, + 3,25,0,6,3,25,0,6,3,25,0,6,6,251,0,112,6,251,0,112,6,39,0,6,6,39,0,6,6,39,0,6,6,39,0,6,4,184,1,51, + 7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,7,143,0,186,6,39,0,6,6,39,0,6,6,39,0,6,8,244,0,112,7,143,0,186, + 7,143,0,186,7,143,0,186,7,143,0,186,6,251,0,112,6,251,0,112,6,251,0,112,6,251,0,112,6,39,0,6,6,39,0,6,6,39,0,6, + 6,164,0,186,6,164,0,186,5,220,0,186,5,220,0,186,6,39,0,6,7,44,0,171,8,0,0,104,7,44,0,100,7,44,0,170,7,44,0,131, + 7,44,0,133,7,44,0,133,4,149,0,170,7,43,0,170,7,44,0,170,7,27,0,125,7,27,0,125,5,95,0,125,8,26,0,125,9,247,0,140, + 10,1,0,145,7,44,0,184,7,44,0,183,7,44,0,183,4,66,0,154,7,44,0,100,7,44,0,152,7,44,0,172,7,44,0,172,7,44,0,159, + 7,44,0,171,7,44,0,172,7,44,0,172,7,44,0,178,4,223,0,147,7,44,0,177,4,223,0,147,7,44,0,125,7,44,0,172,7,44,0,170, + 7,44,0,100,5,90,0,100,5,248,0,170,5,50,0,170,6,69,0,170,4,92,0,170,7,44,0,170,7,44,0,178,7,44,0,170,5,175,0,170, + 7,44,0,171,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,135,8,87,0,170,8,87,0,170,8,87,0,170,7,44,0,170,7,44,2,221,7,44,0,170,4,233,0,175,5,220,0,175, + 5,220,0,175,7,44,0,162,7,44,1,83,7,44,1,192,7,44,0,248,7,44,1,4,7,44,1,236,7,44,0,93,7,44,0,183,7,44,0,192, + 7,44,0,231,7,44,1,30,7,44,0,109,7,44,0,171,7,44,0,69,7,44,0,169,7,44,0,192,7,44,0,176,7,44,1,65,7,44,0,201, + 7,44,0,226,7,44,1,85,7,44,1,182,7,44,1,81,7,44,1,48,7,44,0,201,7,44,0,226,7,44,1,85,7,44,1,182,7,44,1,76, + 7,44,1,48,7,44,1,67,7,44,0,185,7,44,1,88,7,44,0,228,7,44,1,66,7,44,0,182,7,44,1,88,7,44,0,228,7,44,0,216, + 3,198,0,172,5,27,0,172,7,44,1,120,7,44,0,188,3,198,0,181,2,220,0,172,3,223,0,173,5,252,0,172,6,32,0,132,7,44,0,172, + 7,44,0,156,7,44,0,156,7,44,0,156,7,44,0,156,7,44,0,156,7,44,0,156,7,44,0,156,7,44,0,156,7,44,0,172,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,1,49,6,244,0,150,6,244,0,150,6,244,0,150,6,244,0,150,6,244,0,150,6,244,0,150,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,1,88, + 7,44,1,88,7,44,0,106,7,44,0,198,7,44,1,13,4,84,0,125,7,44,0,121,7,44,0,125,7,44,1,41,7,44,0,194,7,44,1,6, + 7,44,1,5,7,44,1,5,7,44,0,100,5,158,0,170,8,9,0,175,8,183,0,162,9,102,0,175,7,57,0,175,6,180,1,13,6,180,0,207, + 6,180,1,128,6,180,0,9,6,180,1,127,6,180,1,127,6,180,1,250,6,180,1,100,6,180,0,84,6,180,0,10,6,192,0,210,6,180,1,177, + 5,220,0,175,5,220,1,89,5,220,0,176,5,220,0,176,6,204,0,120,5,220,1,142,5,220,1,68,6,180,0,86,6,180,0,86,6,180,0,86, + 6,180,0,86,5,220,0,175,6,180,0,22,6,180,0,86,6,180,0,22,6,180,0,73,6,180,0,86,6,180,0,86,6,180,0,120,6,180,0,132, + 6,180,1,179,6,180,0,43,6,180,0,182,6,180,0,53,6,180,0,182,6,180,0,88,6,180,0,138,6,180,1,51,6,180,0,237,6,180,1,3, + 6,180,0,175,6,180,0,241,6,180,0,252,6,180,0,112,6,180,0,112,6,180,0,112,6,180,0,112,6,180,1,82,6,180,1,12,6,180,1,62, + 6,180,0,112,6,180,0,187,6,180,0,84,6,180,0,86,6,180,0,83,6,180,0,84,6,180,0,87,6,180,0,87,6,180,0,47,6,180,0,86, + 6,180,0,48,6,180,0,47,6,180,0,48,6,180,0,48,6,180,0,48,6,180,0,50,6,180,0,132,6,180,0,152,6,180,0,112,6,180,0,64, + 6,180,0,84,6,180,0,187,6,180,0,84,6,180,0,84,6,180,0,84,6,180,0,112,6,180,0,167,6,180,0,167,6,180,0,161,6,180,0,161, + 6,180,0,110,6,180,0,110,6,180,0,84,6,180,0,86,6,180,0,161,6,180,0,182,6,180,0,156,6,180,0,130,6,180,0,161,6,180,0,97, + 6,180,0,97,6,180,0,84,6,180,0,84,7,44,0,102,7,44,0,122,7,44,0,122,7,44,0,122,7,44,0,122,7,44,0,170,6,180,3,5, + 6,180,2,176,6,180,2,6,2,148,0,174,2,148,0,120,4,78,0,174,4,78,0,120,6,180,1,62,6,180,1,158,6,180,1,78,6,180,0,110, + 6,180,1,88,6,180,0,126,6,180,0,160,6,180,1,145,6,180,1,145,6,180,2,29,6,180,2,29,6,180,1,185,6,180,1,219,6,180,1,35, + 6,180,1,57,6,180,1,85,6,180,1,119,6,180,2,196,6,180,2,108,6,180,1,102,6,180,1,161,7,44,0,152,7,44,0,152,7,44,0,152, + 7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,7,44,0,152,6,180,0,9,6,180,0,9,6,180,0,9, + 6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9, + 6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,9,6,180,0,117,6,180,0,252,6,180,0,117, + 6,180,0,252,6,180,0,117,6,180,0,117,6,180,0,117,6,180,0,117,6,180,0,117,6,180,0,117,6,180,0,117,6,180,0,228,6,180,0,228, + 6,180,0,228,6,180,0,117,6,180,0,117,6,180,1,236,6,180,0,117,6,180,0,117,6,180,0,117,6,180,0,43,6,180,0,43,6,180,1,21, + 6,180,1,21,6,180,0,127,6,180,0,127,6,180,1,60,6,180,0,130,6,180,0,165,6,180,0,117,6,180,0,167,6,180,0,167,6,180,0,117, + 6,180,0,167,6,180,0,115,6,180,0,150,6,180,0,162,6,180,0,162,6,180,0,117,3,31,0,110,3,31,0,79,3,244,0,6,3,246,0,176, + 3,246,0,175,3,31,0,183,3,31,0,164,4,115,0,183,4,115,0,164,6,180,0,91,6,180,0,89,6,180,0,79,6,180,0,79,9,66,0,117, + 11,120,0,100,11,120,0,117,11,120,0,100,11,120,0,100,11,120,0,117,11,120,0,100,11,120,0,100,11,120,0,117,11,120,0,100,11,120,0,117, + 11,120,0,117,5,220,0,0,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,3,132,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44, + 5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,5,220,1,44,6,180,0,100,6,180,0,117,6,180,1,0, + 6,180,1,0,5,119,0,79,5,119,0,79,5,223,1,0,5,223,1,0,6,180,0,217,8,0,0,217,8,0,0,217,8,0,0,217,8,0,0,217, + 8,0,0,217,8,0,0,217,8,0,0,217,3,244,0,6,6,180,0,217,6,180,0,217,8,0,0,58,8,0,0,58,8,0,0,58,10,154,0,117, + 4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117, + 4,43,255,190,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,117,4,43,0,107,6,180,1,25,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,218,6,180,0,218,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217,6,180,0,217, + 6,180,0,181,6,180,1,32,6,180,0,181,6,180,1,32,6,180,0,55,6,180,0,55,6,180,1,94,6,180,1,94,6,180,0,181,6,180,1,32, + 6,180,0,181,6,180,1,32,6,180,0,55,6,180,1,94,6,176,0,117,6,176,0,117,6,176,0,72,6,176,0,72,7,143,0,186,7,143,0,186, + 7,143,0,186,7,143,0,186,6,39,0,6,6,39,0,6,6,39,0,6,6,39,0,6,7,143,0,186,6,244,0,36,6,244,0,36,6,252,0,150, + 6,252,0,150,6,252,0,34,8,244,0,112,6,244,0,77,6,244,0,77,4,117,0,10,2,57,0,10,4,117,255,215,4,211,0,10,5,143,0,201, + 4,231,0,72,3,35,255,232,6,4,0,201,5,18,0,186,5,63,0,201,4,162,0,186,5,123,0,92,4,51,0,88,6,64,0,115,6,231,0,201, + 5,121,0,16,6,64,0,115,5,224,0,61,9,6,0,68,7,177,0,86,4,188,0,104,5,60,0,201,4,139,0,193,5,71,0,112,3,80,0,0, + 4,229,0,113,3,237,0,98,1,102,255,233,3,114,0,10,5,20,0,135,5,123,0,92,4,186,0,123,4,194,0,50,4,132,0,80,4,208,0,127, + 4,179,0,105,7,73,0,80,5,3,0,0,7,157,0,108,4,195,0,142,4,219,0,104,7,161,0,80,4,245,0,109,4,195,0,80,7,105,0,104, + 4,194,0,104,6,115,0,142,7,115,0,104,4,173,0,104,4,189,0,102,7,99,0,104,7,159,0,123,6,159,0,100,4,196,0,80,4,194,0,104, + 4,184,0,104,4,188,0,80,4,188,0,86,4,247,0,122,7,93,0,80,4,183,0,60,4,177,0,96,4,166,0,70,7,80,0,80,4,196,0,100, + 4,194,0,122,4,189,0,124,5,34,0,104,7,53,0,122,5,44,0,113,7,26,0,115,7,26,0,115,5,117,0,64,5,120,0,67,5,21,0,64, + 4,126,0,150,5,121,0,16,5,121,0,16,5,14,0,201,5,14,0,131,5,118,0,150,6,255,0,219,5,123,0,92,3,237,0,150,5,123,0,92, + 7,26,0,115,7,26,0,115,2,103,0,150,5,4,0,41,6,4,0,201,5,63,0,62,4,56,0,150,5,123,0,92,5,40,0,150,5,14,0,201, + 4,5,0,111,7,159,0,111,6,58,0,111,5,252,0,201,4,247,0,204,2,92,0,201,6,58,0,111,2,92,0,201,6,4,0,159,5,16,0,99, + 7,26,0,115,7,26,0,115,6,4,0,201,2,144,0,201,5,254,0,150,7,26,0,115,7,26,0,115,5,150,0,115,6,36,0,100,5,123,0,61, + 5,150,0,115,4,250,0,201,5,121,0,16,6,4,0,201,5,14,0,201,6,78,0,115,4,137,0,201,6,78,0,115,4,31,0,54,4,63,0,143, + 6,180,0,217,3,31,0,176,3,31,0,199,3,31,0,176,3,31,0,199,4,63,0,147,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 5,125,0,201,4,211,0,201,4,211,0,70,6,41,0,201,4,227,255,250,4,227,255,250,6,51,0,115,5,63,0,201,5,63,255,213,4,24,0,0, + 5,150,0,115,5,160,0,115,5,123,0,92,4,154,0,201,4,154,0,201,6,231,0,201,5,252,0,201,4,117,0,201,5,20,0,135,5,143,0,201, + 5,143,0,59,5,121,0,16,5,121,0,16,6,4,0,201,6,51,0,163,4,24,0,201,7,233,0,68,5,123,0,61,4,227,255,252,5,125,0,145, + 5,121,0,16,5,121,0,16,5,14,0,201,5,14,0,131,2,92,0,201,6,76,0,115,5,219,0,178,5,219,0,178,4,117,0,8,6,35,0,115, + 2,102,0,175,2,102,0,146,4,197,0,175,4,197,0,175,2,102,0,146,2,102,0,175,4,180,0,175,4,180,0,175,5,20,0,114,4,43,0,100, + 2,212,0,201,2,181,0,166,9,112,0,118,8,57,0,152,8,59,0,60,7,64,0,62,8,163,0,115,6,188,0,112,7,208,0,211,6,190,0,193, + 8,127,0,101,7,75,0,107,8,136,0,84,7,53,0,76,9,109,0,201,8,16,0,186,6,76,0,115,4,229,0,113,6,216,0,115,5,179,0,113, + 10,221,0,115,8,38,0,113,7,8,0,58,6,66,255,250,5,122,0,60,4,227,255,250,4,169,0,60,5,124,0,175,5,18,0,186,3,242,0,214, + 3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214, + 3,242,0,214,3,242,0,214,3,242,0,214,3,242,0,214,2,244,0,102,2,244,0,102,2,5,0,195,2,5,0,195,2,5,0,195,3,21,0,137, + 2,217,0,137,3,198,0,115,3,198,0,115,6,4,0,201,5,18,0,186,7,6,255,250,5,173,0,55,4,234,0,164,4,83,0,133,3,237,0,186, + 4,43,0,111,9,255,0,16,7,225,0,123,9,160,0,16,7,235,0,123,9,35,0,16,7,217,0,123,7,197,0,16,6,139,0,123,7,197,0,16, + 6,139,0,123,7,172,0,16,6,139,0,123,5,160,0,115,4,101,0,127,5,63,0,10,4,170,0,14,5,113,0,201,3,35,0,193,4,167,0,83, + 3,106,0,120,6,116,0,10,5,162,0,10,10,221,0,115,8,38,0,113,4,211,0,10,5,20,255,251,5,223,0,50,6,50,0,50,6,76,0,115, + 5,20,0,113,4,215,0,10,5,20,255,251,4,215,0,10,5,20,255,251,4,117,0,11,2,57,0,193,5,226,0,201,5,18,0,186,2,178,0,240, + 3,2,0,160,3,53,1,53,2,51,0,197,5,124,0,175,3,230,0,77,6,46,0,201,5,85,0,186,6,51,0,4,5,20,0,4,5,63,0,4, + 4,162,0,4,5,252,0,4,5,18,0,4,5,143,0,4,3,74,0,4,5,20,0,4,4,43,0,4,6,104,255,151,7,82,0,186,4,154,0,119, + 4,211,0,70,6,231,0,201,2,92,0,201,9,152,0,68,1,181,0,194,1,231,0,141,2,14,0,110,2,28,0,96,2,35,0,90,1,231,0,141, + 1,181,0,194,1,231,0,141,2,14,0,110,2,28,0,96,2,14,0,110,1,231,0,141,1,181,0,194,1,231,0,141,2,14,0,110,2,28,0,96, + 2,14,0,110,1,231,0,141,1,181,0,194,1,231,0,141,2,35,0,90,2,28,0,96,2,14,0,110,1,231,0,141,1,181,0,194,2,51,0,214, + 7,208,0,150,7,208,0,150,7,208,0,150,7,208,0,150,4,164,0,110,4,164,0,110,4,253,0,110,7,29,0,110,4,174,0,111,4,164,0,110, + 5,57,0,110,7,14,0,110,4,113,0,110,4,164,0,110,9,89,0,110,4,182,0,110,4,184,0,130,6,244,0,110,4,164,0,110,4,183,0,110, + 7,79,0,110,4,184,0,130,5,217,0,110,4,170,0,50,6,250,0,110,4,183,0,110,7,41,0,110,4,182,0,110,4,182,0,110,4,185,0,131, + 5,49,0,112,4,182,0,110,4,183,0,131,4,202,0,110,4,184,0,130,4,33,0,50,4,163,0,110,4,172,0,120,4,164,0,110,4,164,0,110, + 4,165,0,110,5,27,0,110,7,164,0,110,7,115,0,122,6,119,0,100,4,16,0,100,4,16,0,100,4,16,0,100,4,16,0,100,4,16,0,100, + 4,16,0,100,4,16,0,100,4,16,0,100,4,16,0,100,4,16,0,100,4,36,0,100,4,36,0,100,4,36,0,100,6,75,0,100,6,75,0,100, + 6,75,0,100,6,75,0,100,6,75,0,100,4,95,0,60,4,95,0,60,4,95,0,60,4,95,0,60,4,95,0,60,4,95,0,60,4,229,0,113, + 5,131,0,47,5,10,0,47,5,10,0,47,7,188,0,47,7,188,0,47,5,125,0,47,6,227,0,111,9,157,0,171,9,157,0,174,9,145,0,174, + 9,125,0,174,12,60,0,174,1,202,0,136,0,0,1,86,2,165,0,74,5,22,0,78,6,217,0,174,6,49,0,88,7,63,0,186,6,44,0,88, + 6,191,0,88,6,215,0,186,6,117,0,88,7,1,0,96,6,180,0,217,5,171,0,88,5,171,0,78,5,171,0,88,5,171,0,88,5,89,0,186, + 5,89,0,186,5,89,0,186,4,160,0,88,3,76,0,88,4,94,0,88,5,58,0,186,2,216,0,89,3,63,0,89,5,48,0,185,2,164,0,89, + 4,76,0,88,4,59,0,88,4,140,0,88,5,111,0,88,3,50,0,88,5,49,0,185,5,30,0,186,4,255,0,186,4,191,0,88,5,173,0,186, + 4,132,0,88,5,171,0,88,5,66,0,20,2,46,0,186,4,160,0,88,4,59,0,88,4,255,0,186,5,8,0,88,7,136,0,130,7,219,0,130, + 2,58,255,236,2,106,255,236,7,136,0,130,7,219,0,130,2,58,255,236,2,106,255,236,7,136,0,130,7,219,0,130,2,58,255,236,2,106,255,236, + 7,136,0,130,7,219,0,130,2,58,255,236,2,106,255,236,7,136,0,130,7,219,0,130,2,58,255,236,2,106,255,236,7,136,0,130,7,219,0,130, + 2,58,255,236,2,106,255,236,8,75,0,130,8,72,0,130,3,211,255,236,4,12,255,236,8,75,0,130,8,72,0,130,3,211,255,236,4,12,255,236, + 5,42,0,157,5,42,0,157,4,242,255,236,5,42,255,236,5,42,0,157,5,42,0,157,4,242,255,236,5,42,255,236,5,42,0,157,5,42,0,157, + 4,242,255,236,5,42,255,236,5,42,0,157,5,42,0,157,4,242,255,236,5,42,255,236,3,144,0,125,4,51,0,125,3,144,0,125,4,51,0,125, + 3,144,0,125,4,51,0,125,3,144,0,125,4,51,0,125,3,221,255,171,4,106,255,171,3,221,255,171,4,106,255,171,7,41,0,130,7,41,0,130, + 3,207,255,236,4,107,255,236,7,41,0,130,7,41,0,130,3,207,255,236,4,107,255,236,7,41,0,130,7,41,0,130,3,207,255,236,4,107,255,236, + 7,41,0,130,7,41,0,130,3,207,255,236,4,107,255,236,5,224,0,147,6,23,0,147,5,224,0,147,6,23,0,147,2,58,255,236,2,106,255,236, + 5,150,0,144,5,14,0,144,4,56,255,236,3,176,255,236,6,152,0,144,6,190,0,144,3,207,255,236,4,107,255,236,3,221,255,171,4,34,255,171, + 2,58,255,236,2,106,255,236,6,67,0,130,6,171,0,130,2,58,255,236,2,106,255,236,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,252,112,0,0,0,0,0,0,253,42,0,0,0,0,2,88,0,8,2,88,255,236,2,88,0,8,2,24,0,105, + 2,88,0,8,2,88,0,8,2,88,255,236,2,88,0,8,2,88,255,236,2,88,0,8,2,88,255,236,2,88,255,244,2,88,255,236,2,88,0,24, + 2,88,255,236,3,195,0,163,2,57,255,181,2,112,255,181,2,57,0,108,2,112,0,108,3,221,255,171,4,34,255,171,2,57,0,108,2,112,0,108, + 6,67,0,130,6,171,0,130,2,58,255,236,2,106,255,236,2,57,0,193,2,112,0,193,7,136,0,130,7,219,0,130,2,58,255,236,2,106,255,236, + 4,49,0,139,4,74,0,145,7,136,0,130,7,219,0,130,2,58,255,236,2,106,255,236,7,136,0,130,7,219,0,130,2,58,255,236,2,106,255,236, + 5,42,0,157,5,42,0,157,4,242,255,236,5,42,255,236,5,42,0,157,5,42,0,157,4,242,255,236,5,42,255,236,5,42,0,157,5,42,0,157, + 4,242,255,236,5,42,255,236,3,144,0,125,4,51,0,125,3,144,0,125,4,51,0,125,3,221,255,171,4,106,255,171,3,221,255,171,4,106,255,171, + 9,196,0,130,10,51,0,130,6,180,255,236,7,35,255,236,9,196,0,130,10,51,0,130,6,180,255,236,7,35,255,236,9,172,0,130,9,205,0,130, + 6,203,255,236,6,240,255,236,9,172,0,130,9,205,0,130,6,203,255,236,6,240,255,236,7,102,0,144,7,152,0,144,6,94,255,236,6,144,255,236, + 7,102,0,144,7,152,0,144,6,94,255,236,6,144,255,236,4,198,0,117,4,66,0,117,4,198,255,236,3,220,255,236,4,198,0,117,4,66,0,117, + 4,47,255,236,3,220,255,236,8,75,0,130,8,72,0,130,3,211,255,236,4,12,255,236,6,53,0,107,6,172,0,107,3,211,255,236,4,12,255,236, + 6,152,0,144,6,190,0,144,3,207,255,236,4,107,255,236,5,208,0,144,6,15,0,144,2,112,255,236,2,166,255,236,4,244,0,140,5,83,0,140, + 4,73,255,236,4,160,255,236,5,224,0,147,6,23,0,147,2,58,255,236,2,106,255,236,4,49,0,139,4,74,0,145,4,56,255,236,3,176,255,236, + 3,221,255,171,4,34,255,171,6,67,0,130,6,171,0,130,6,67,0,130,6,171,0,130,2,58,255,236,2,106,255,236,4,144,255,46,4,198,255,46, + 4,144,255,229,4,198,255,229,4,144,0,23,4,198,0,23,4,144,0,84,4,198,0,84,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,8,52,0,30,6,14,0,100,4,220,0,200,4,128,0,100,4,206,0,200,4,100,0,200,4,100,0,200,3,132,0,150,5,0,0,200, + 7,58,0,150,2,68,0,200,5,25,0,200,4,95,0,200,11,106,0,200,7,13,0,200,7,100,0,200,7,58,0,150,5,125,0,200,6,242,0,200, + 4,176,0,150,4,218,0,200,3,136,0,150,5,146,0,100,5,24,0,200,5,125,0,150,5,120,0,150,6,122,0,100,4,56,0,150,4,118,0,200, + 4,118,0,200,3,132,0,100,6,14,0,100,2,68,0,200,6,14,0,100,5,125,0,150,6,139,0,100,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,5,237,0,16,5,217,0,201,6,141,0,232,5,214,0,201,5,99,0,201,6,51,0,115, + 3,36,0,102,3,34,255,150,6,5,0,201,5,61,0,201,8,51,0,196,6,76,0,114,5,20,0,136,5,170,255,250,6,164,0,177,5,200,0,16, + 8,221,0,68,6,114,0,108,5,168,255,252,5,75,0,123,5,170,0,148,4,102,0,113,5,170,0,148,4,236,0,111,3,185,0,47,5,170,0,113, + 5,229,0,186,2,207,0,230,2,207,255,215,5,53,0,186,2,207,0,230,9,34,0,186,5,229,0,186,4,229,0,113,5,170,0,113,5,170,0,113, + 3,223,0,186,4,43,0,111,3,185,0,55,5,234,0,177,4,220,0,61,7,72,0,86,5,104,0,76,4,255,0,61,4,184,0,88,5,121,0,16, + 5,125,0,201,5,150,0,115,6,41,0,201,5,14,0,201,4,154,0,201,6,51,0,115,6,4,0,201,3,140,0,151,2,92,255,150,5,63,0,201, + 4,117,0,201,6,231,0,201,5,252,0,201,6,76,0,115,4,211,0,201,6,76,0,115,5,143,0,201,5,20,0,135,4,227,255,250,5,219,0,178, + 5,121,0,16,7,233,0,68,5,123,0,61,4,227,255,252,5,123,0,92,4,231,0,123,5,20,0,186,4,102,0,113,5,20,0,113,4,236,0,113, + 2,209,0,47,5,20,0,113,5,18,0,186,2,57,0,193,2,57,255,219,4,162,0,186,2,57,0,193,7,203,0,186,5,18,0,186,4,229,0,113, + 5,20,0,186,5,20,0,113,3,74,0,186,4,43,0,111,3,35,0,55,5,18,0,174,4,188,0,61,6,139,0,86,4,188,0,59,4,188,0,61, + 4,51,0,88,5,23,0,136,5,23,0,107,5,23,0,130,5,23,0,156,5,23,0,90,5,23,0,148,5,23,0,113,5,23,0,65,5,23,0,139, + 5,20,0,106,5,23,0,135,5,23,0,225,5,23,0,150,5,23,0,156,5,23,0,100,5,23,0,158,5,23,0,143,5,23,0,168,5,23,0,139, + 5,23,0,129,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200, + 10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200, + 10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200, + 10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200, + 10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200,10,233,0,200, + 10,233,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200, + 6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200, + 6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200, + 6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200, + 6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200,6,133,0,200, + 6,133,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200, + 8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200, + 8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,64,0,217,8,47,0,200, + 8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200, + 8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200, + 8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200,8,47,0,200, + 8,88,0,153,9,120,0,75,8,87,0,61,9,64,0,170,8,87,0,170,8,87,0,170,9,89,0,95,8,87,0,170,8,87,0,170,8,87,0,170, + 8,87,0,170,8,87,0,143,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170, + 8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170, + 8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170, + 8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,170,9,89,0,95,8,87,0,170,8,87,0,170, + 8,87,0,170,8,87,0,35,8,87,0,170,8,87,0,170,12,213,0,170,8,87,0,170,8,87,0,170,8,87,0,170,8,87,0,58,9,89,0,96, + 8,87,0,58,8,87,0,61,8,87,0,61,8,87,0,61,8,87,0,61,8,87,0,61,8,87,0,61,0,0,255,185,0,0,252,215,0,0,253,115, + 0,0,252,182,0,0,253,12,0,0,252,207,0,0,252,207,0,0,252,199,0,0,252,199,0,0,253,154,0,0,252,230,0,0,252,78,0,150,0,0, + 1,144,0,0,1,144,0,0,1,144,0,0,0,150,0,0,1,144,0,0,7,219,0,130,2,58,255,236,2,106,255,236,8,72,0,130,3,211,255,236, + 4,12,255,236,6,172,0,107,3,211,255,236,4,12,255,236,2,58,255,236,2,106,255,236,1,182,0,0,7,219,0,130,2,58,255,236,2,106,255,236, + 7,219,0,130,2,58,255,236,2,106,255,236,5,42,0,157,4,242,255,236,5,42,255,236,5,42,0,157,4,242,255,236,5,42,255,236,5,42,0,157, + 4,242,255,236,5,42,255,236,5,42,0,157,4,242,255,236,5,42,255,236,3,95,0,0,5,252,0,213,2,57,0,15,2,238,254,242,5,120,1,146, + 5,120,1,146,5,120,1,146,5,120,1,147,5,120,1,147,5,120,1,146,5,120,1,146,5,120,1,118,5,120,1,139,5,120,1,118,5,120,1,139, + 5,120,1,118,5,120,1,139,5,120,1,139,5,120,1,118,5,120,1,118,5,120,1,131,5,120,1,131,5,120,1,131,5,120,1,139,0,0,252,154, + 1,44,0,0,4,24,0,0,4,226,255,171,4,226,255,171,6,15,0,144,2,112,255,236,2,166,255,236,6,171,0,130,2,58,255,236,2,106,255,236, + 4,106,255,171,2,57,0,193,4,74,0,145,5,150,0,113,4,226,0,113,2,57,0,150,2,207,0,79,2,207,255,22,2,57,255,211,2,57,0,191, + 2,178,0,240,3,140,0,151,6,180,1,173,0,0,0,200,0,0,0,200,0,0,0,200,0,0,0,200,0,0,0,200,0,0,0,200,0,0,0,220, + 0,0,0,220,2,58,0,193,2,58,255,236,2,58,255,236,4,146,0,113,4,146,255,236,4,146,255,236,3,100,0,61,3,100,255,236,3,100,255,236, + 4,188,0,61,4,188,255,236,4,188,255,236,5,59,0,186,5,59,255,236,5,59,255,236,5,59,0,186,5,59,255,236,5,59,255,236,4,192,0,113, + 4,192,255,236,4,192,255,236,5,59,0,186,5,59,255,236,5,59,255,236,6,161,0,113,6,161,255,236,6,161,255,236,3,129,0,193,3,129,255,236, + 3,129,255,236,3,129,0,61,3,129,255,236,3,129,255,236,4,120,0,186,4,120,255,236,4,120,255,236,4,229,0,193,4,229,255,236,4,229,255,236, + 2,205,0,61,2,205,255,236,2,205,255,236,7,172,0,193,7,172,255,236,7,172,255,236,3,200,0,61,3,200,255,236,3,200,255,236,6,68,0,61, + 6,68,255,236,6,68,255,236,5,59,0,186,5,59,255,236,5,59,255,236,5,0,0,61,5,0,255,236,5,0,255,236,5,223,0,193,5,223,255,236, + 5,223,255,236,4,61,0,193,4,61,255,236,4,61,255,236,5,203,0,112,5,203,255,236,5,203,255,236,3,200,0,61,3,200,255,236,3,200,255,236, + 5,0,0,61,5,0,255,236,5,0,255,236,4,192,0,113,4,192,255,236,4,192,255,236,4,61,0,193,4,61,255,236,4,61,255,236,4,61,0,193, + 4,61,255,236,4,61,255,236,4,46,0,193,4,46,255,236,4,46,255,236,4,192,0,113,4,192,255,236,4,192,255,236,4,192,0,113,4,192,255,236, + 4,192,255,236,0,0,252,236,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170,7,44,0,170, + 6,179,1,151,6,46,0,201,5,106,0,193,5,18,0,174,4,51,0,125,4,51,0,125,4,51,0,125,4,51,0,125,4,51,0,125,4,106,255,171, + 4,106,255,171,4,106,255,171,4,106,255,171,4,106,255,171,10,51,0,130,6,180,255,236,7,35,255,236,10,51,0,130,6,180,255,236,7,35,255,236, + 10,51,0,130,6,180,255,236,7,35,255,236,9,205,0,130,6,203,255,236,6,240,255,236,9,205,0,130,6,203,255,236,6,240,255,236,7,152,0,144, + 6,94,255,236,6,144,255,236,4,66,0,117,4,198,255,236,3,220,255,236,8,72,0,130,3,211,255,236,4,12,255,236,8,72,0,130,3,211,255,236, + 4,12,255,236,8,72,0,130,3,211,255,236,4,12,255,236,6,172,0,107,3,211,255,236,4,12,255,236,6,172,0,107,3,211,255,236,4,12,255,236, + 8,110,0,130,6,242,255,236,6,242,255,236,7,41,0,130,3,207,255,236,4,107,255,236,6,190,0,144,3,207,255,236,4,107,255,236,6,190,0,144, + 3,207,255,236,4,107,255,236,7,41,0,130,3,207,255,236,4,107,255,236,7,41,0,130,3,207,255,236,4,107,255,236,7,41,0,130,3,207,255,236, + 4,107,255,236,6,15,0,144,2,112,255,236,2,166,255,236,6,15,0,144,2,112,255,236,2,166,255,236,6,15,0,144,2,112,255,236,2,166,255,236, + 6,23,0,147,2,58,255,236,2,106,255,236,6,23,0,147,2,58,255,236,2,106,255,236,6,23,0,147,2,58,255,236,2,106,255,236,0,0,0,1, + 0,0,63,248,0,1,10,167,48,0,0,11,15,234,0,16,0,36,255,211,0,16,0,37,255,183,0,16,0,42,0,75,0,16,0,45,0,114,0,16, + 0,50,0,57,0,16,0,52,0,75,0,16,0,55,255,68,0,16,0,57,255,136,0,16,0,58,255,173,0,16,0,59,255,154,0,16,0,60,255,13, + 0,16,0,82,0,38,0,16,0,89,255,201,0,16,0,92,255,220,0,16,0,130,255,211,0,16,0,131,255,211,0,16,0,132,255,211,0,16,0,133, + 255,211,0,16,0,134,255,211,0,16,0,148,0,57,0,16,0,149,0,57,0,16,0,150,0,57,0,16,0,151,0,57,0,16,0,152,0,57,0,16, + 0,159,255,13,0,16,0,180,0,38,0,16,0,181,0,38,0,16,0,182,0,38,0,16,0,183,0,38,0,16,0,184,0,38,0,16,0,191,255,220, + 0,16,0,193,255,220,0,16,0,194,255,211,0,16,0,196,255,211,0,16,0,198,255,211,0,16,0,224,0,75,0,16,1,38,255,68,0,16,1,58, + 255,13,0,36,0,16,255,211,0,36,0,17,255,220,0,36,0,29,255,220,0,36,0,36,0,57,0,36,0,38,255,220,0,36,0,42,255,220,0,36, + 0,50,255,220,0,36,0,52,255,220,0,36,0,55,255,97,0,36,0,57,255,125,0,36,0,58,255,144,0,36,0,60,255,97,0,36,0,70,255,220, + 0,36,0,71,255,220,0,36,0,72,255,220,0,36,0,73,255,183,0,36,0,82,255,220,0,36,0,84,255,220,0,36,0,87,255,220,0,36,0,89, + 255,136,0,36,0,90,255,173,0,36,0,92,255,117,0,36,0,109,255,183,0,36,0,130,0,57,0,36,0,131,0,57,0,36,0,132,0,57,0,36, + 0,133,0,57,0,36,0,134,0,57,0,36,0,137,255,220,0,36,0,148,255,220,0,36,0,149,255,220,0,36,0,150,255,220,0,36,0,151,255,220, + 0,36,0,152,255,220,0,36,0,159,255,97,0,36,0,169,255,220,0,36,0,170,255,220,0,36,0,171,255,220,0,36,0,172,255,220,0,36,0,173, + 255,220,0,36,0,180,255,220,0,36,0,181,255,220,0,36,0,182,255,220,0,36,0,183,255,220,0,36,0,184,255,220,0,36,0,191,255,117,0,36, + 0,193,255,117,0,36,0,194,0,57,0,36,0,196,0,57,0,36,0,198,0,57,0,36,0,200,255,220,0,36,0,201,255,220,0,36,0,202,255,220, + 0,36,0,203,255,220,0,36,0,204,255,220,0,36,0,205,255,220,0,36,0,206,255,220,0,36,0,207,255,220,0,36,0,209,255,220,0,36,0,211, + 255,220,0,36,0,213,255,220,0,36,0,215,255,220,0,36,0,217,255,220,0,36,0,219,255,220,0,36,0,221,255,220,0,36,0,222,255,220,0,36, + 0,224,255,220,0,36,0,226,255,220,0,36,1,14,255,220,0,36,1,15,255,220,0,36,1,16,255,220,0,36,1,17,255,220,0,36,1,18,255,220, + 0,36,1,19,255,220,0,36,1,36,255,97,0,36,1,37,255,220,0,36,1,38,255,97,0,36,1,39,255,220,0,36,1,54,255,144,0,36,1,55, + 255,173,0,36,1,56,255,97,0,36,1,57,255,117,0,36,1,58,255,97,0,36,1,136,255,220,0,36,1,172,255,220,0,36,1,173,255,220,0,36, + 1,174,255,220,0,36,1,175,255,220,0,36,1,220,255,97,0,36,1,221,255,220,0,36,1,240,255,220,0,36,1,243,255,220,0,36,1,244,255,97, + 0,36,1,245,255,117,0,36,9,121,255,144,0,36,9,122,255,173,0,36,9,123,255,144,0,36,9,124,255,173,0,36,9,125,255,144,0,36,9,126, + 255,173,0,36,9,235,255,97,0,36,9,236,255,117,0,36,10,250,254,248,0,36,10,251,255,3,0,36,10,252,0,47,0,37,0,38,255,220,0,37, + 0,42,255,220,0,37,0,50,255,220,0,37,0,54,255,220,0,37,0,57,255,193,0,37,0,58,255,183,0,37,0,60,255,144,0,37,0,109,255,193, + 0,37,0,125,255,220,0,37,0,137,255,220,0,37,0,148,255,220,0,37,0,149,255,220,0,37,0,150,255,220,0,37,0,151,255,220,0,37,0,152, + 255,220,0,37,0,159,255,144,0,37,0,200,255,220,0,37,0,202,255,220,0,37,0,204,255,220,0,37,0,206,255,220,0,37,0,222,255,220,0,37, + 0,224,255,220,0,37,0,226,255,220,0,37,0,228,255,220,0,37,1,14,255,220,0,37,1,16,255,220,0,37,1,18,255,220,0,37,1,28,255,220, + 0,37,1,30,255,220,0,37,1,32,255,220,0,37,1,34,255,220,0,37,1,54,255,183,0,37,1,56,255,144,0,37,1,58,255,144,0,37,1,172, + 255,220,0,37,1,174,255,220,0,37,1,218,255,220,0,37,1,240,255,220,0,37,9,121,255,183,0,37,9,123,255,183,0,37,9,125,255,183,0,37, + 9,235,255,144,0,37,10,250,255,144,0,37,10,251,255,144,0,37,10,252,255,173,0,38,0,60,255,220,0,38,0,109,255,220,0,38,0,125,255,220, + 0,38,0,159,255,220,0,38,1,56,255,220,0,38,1,58,255,220,0,38,1,244,255,220,0,38,9,235,255,220,0,38,10,251,0,38,0,39,0,36, + 255,220,0,39,0,57,255,220,0,39,0,60,255,144,0,39,0,109,255,220,0,39,0,125,255,220,0,39,0,130,255,220,0,39,0,131,255,220,0,39, + 0,132,255,220,0,39,0,133,255,220,0,39,0,134,255,220,0,39,0,159,255,144,0,39,0,194,255,220,0,39,0,196,255,220,0,39,0,198,255,220, + 0,39,1,56,255,144,0,39,1,58,255,144,0,39,1,244,255,144,0,39,9,235,255,144,0,39,10,250,255,211,0,39,10,251,255,201,0,39,10,252, + 255,68,0,41,0,17,254,183,0,41,0,29,255,97,0,41,0,36,255,68,0,41,0,54,255,220,0,41,0,55,255,220,0,41,0,68,255,68,0,41, + 0,72,255,144,0,41,0,76,255,107,0,41,0,82,255,183,0,41,0,85,255,107,0,41,0,88,255,144,0,41,0,92,255,68,0,41,0,130,255,68, + 0,41,0,131,255,68,0,41,0,132,255,68,0,41,0,133,255,68,0,41,0,134,255,68,0,41,0,162,255,68,0,41,0,163,255,68,0,41,0,164, + 255,68,0,41,0,165,255,68,0,41,0,166,255,68,0,41,0,167,255,68,0,41,0,170,255,144,0,41,0,171,255,144,0,41,0,172,255,144,0,41, + 0,173,255,144,0,41,0,180,255,183,0,41,0,181,255,183,0,41,0,182,255,183,0,41,0,183,255,183,0,41,0,184,255,183,0,41,0,187,255,144, + 0,41,0,188,255,144,0,41,0,189,255,144,0,41,0,190,255,144,0,41,0,191,255,68,0,41,0,193,255,68,0,41,0,194,255,68,0,41,0,195, + 255,68,0,41,0,196,255,68,0,41,0,197,255,68,0,41,0,198,255,68,0,41,0,199,255,68,0,41,0,213,255,144,0,41,0,215,255,144,0,41, + 0,217,255,144,0,41,0,219,255,144,0,41,0,221,255,144,0,41,0,241,255,107,0,41,0,245,255,107,0,41,1,15,255,183,0,41,1,17,255,183, + 0,41,1,19,255,183,0,41,1,23,255,107,0,41,1,25,255,107,0,41,1,27,255,107,0,41,1,28,255,220,0,41,1,30,255,220,0,41,1,32, + 255,220,0,41,1,34,255,220,0,41,1,36,255,220,0,41,1,38,255,220,0,41,1,40,255,220,0,41,1,43,255,144,0,41,1,45,255,144,0,41, + 1,47,255,144,0,41,1,49,255,144,0,41,1,51,255,144,0,41,1,53,255,144,0,41,1,57,255,68,0,41,1,173,255,183,0,41,1,175,255,183, + 0,41,1,218,255,220,0,41,1,220,255,220,0,41,1,241,255,183,0,41,1,245,255,68,0,41,9,236,255,68,0,41,10,250,255,211,0,41,10,252, + 254,136,0,42,0,55,255,183,0,42,0,60,255,154,0,42,0,109,255,220,0,42,0,125,255,220,0,42,0,159,255,154,0,42,1,38,255,183,0,42, + 1,58,255,154,0,42,10,250,255,211,0,42,10,251,255,211,0,42,10,252,255,201,0,43,0,17,255,220,0,43,10,250,255,183,0,43,10,251,255,193, + 0,43,10,252,255,183,0,45,0,16,255,183,0,45,0,36,255,220,0,45,0,109,255,220,0,45,0,125,255,220,0,45,0,130,255,220,0,45,0,131, + 255,220,0,45,0,132,255,220,0,45,0,133,255,220,0,45,0,134,255,220,0,45,10,250,255,183,0,45,10,251,255,193,0,45,10,252,255,144,0,46, + 0,16,255,41,0,46,0,36,255,220,0,46,0,38,255,144,0,46,0,50,255,144,0,46,0,55,255,97,0,46,0,56,255,201,0,46,0,58,255,183, + 0,46,0,60,255,183,0,46,0,68,255,220,0,46,0,72,255,154,0,46,0,82,255,154,0,46,0,88,255,154,0,46,0,92,255,107,0,46,0,109, + 255,125,0,46,0,130,255,220,0,46,0,131,255,220,0,46,0,132,255,220,0,46,0,133,255,220,0,46,0,134,255,220,0,46,0,137,255,144,0,46, + 0,148,255,144,0,46,0,149,255,144,0,46,0,150,255,144,0,46,0,151,255,144,0,46,0,152,255,144,0,46,0,155,255,201,0,46,0,156,255,201, + 0,46,0,157,255,201,0,46,0,158,255,201,0,46,0,159,255,183,0,46,0,162,255,220,0,46,0,163,255,220,0,46,0,164,255,220,0,46,0,165, + 255,220,0,46,0,166,255,220,0,46,0,167,255,220,0,46,0,170,255,154,0,46,0,171,255,154,0,46,0,172,255,154,0,46,0,173,255,154,0,46, + 0,180,255,154,0,46,0,181,255,154,0,46,0,182,255,154,0,46,0,183,255,154,0,46,0,184,255,154,0,46,0,187,255,154,0,46,0,188,255,154, + 0,46,0,189,255,154,0,46,0,190,255,154,0,46,0,191,255,107,0,46,0,193,255,107,0,46,0,200,255,144,0,46,0,206,255,144,0,46,0,221, + 255,154,0,46,1,38,255,97,0,46,1,48,255,201,0,46,1,49,255,154,0,46,1,58,255,183,0,46,10,250,255,193,0,46,10,251,255,193,0,47, + 0,16,255,220,0,47,0,36,0,47,0,47,0,50,255,183,0,47,0,55,254,230,0,47,0,56,255,154,0,47,0,57,255,31,0,47,0,58,255,68, + 0,47,0,60,254,240,0,47,0,72,255,220,0,47,0,82,255,220,0,47,0,88,255,220,0,47,0,92,255,68,0,47,0,130,0,47,0,47,0,131, + 0,47,0,47,0,132,0,47,0,47,0,133,0,47,0,47,0,134,0,47,0,47,0,148,255,183,0,47,0,149,255,183,0,47,0,150,255,183,0,47, + 0,151,255,183,0,47,0,152,255,183,0,47,0,155,255,154,0,47,0,156,255,154,0,47,0,157,255,154,0,47,0,158,255,154,0,47,0,159,254,240, + 0,47,0,170,255,220,0,47,0,171,255,220,0,47,0,172,255,220,0,47,0,173,255,220,0,47,0,180,255,220,0,47,0,181,255,220,0,47,0,182, + 255,220,0,47,0,183,255,220,0,47,0,184,255,220,0,47,0,187,255,220,0,47,0,188,255,220,0,47,0,189,255,220,0,47,0,190,255,220,0,47, + 0,191,255,68,0,47,0,193,255,68,0,47,0,221,255,220,0,47,1,38,254,230,0,47,1,48,255,154,0,47,1,49,255,220,0,47,1,58,254,240, + 0,47,10,250,254,97,0,47,10,251,253,230,0,50,0,16,0,57,0,50,0,17,255,173,0,50,0,29,255,220,0,50,0,36,255,220,0,50,0,57, + 255,220,0,50,0,59,255,125,0,50,0,60,255,144,0,50,0,109,255,220,0,50,0,130,255,220,0,50,0,131,255,220,0,50,0,132,255,220,0,50, + 0,133,255,220,0,50,0,134,255,220,0,50,0,159,255,144,0,50,1,58,255,144,0,50,10,250,255,211,0,50,10,251,255,220,0,50,10,252,255,68, + 0,51,0,16,255,211,0,51,0,17,254,193,0,51,0,36,255,125,0,51,0,60,255,211,0,51,0,68,255,164,0,51,0,72,255,183,0,51,0,76, + 255,211,0,51,0,81,255,220,0,51,0,82,255,183,0,51,0,85,255,220,0,51,0,86,255,220,0,51,0,88,255,220,0,51,0,109,255,220,0,51, + 0,130,255,125,0,51,0,131,255,125,0,51,0,132,255,125,0,51,0,133,255,125,0,51,0,134,255,125,0,51,0,159,255,211,0,51,0,162,255,164, + 0,51,0,163,255,164,0,51,0,164,255,164,0,51,0,165,255,164,0,51,0,166,255,164,0,51,0,167,255,164,0,51,0,170,255,183,0,51,0,171, + 255,183,0,51,0,172,255,183,0,51,0,173,255,183,0,51,0,179,255,220,0,51,0,180,255,183,0,51,0,181,255,183,0,51,0,182,255,183,0,51, + 0,183,255,183,0,51,0,184,255,183,0,51,0,187,255,220,0,51,0,188,255,220,0,51,0,189,255,220,0,51,0,190,255,220,0,51,0,221,255,183, + 0,51,1,10,255,220,0,51,1,23,255,220,0,51,1,27,255,220,0,51,1,33,255,220,0,51,1,35,255,220,0,51,1,49,255,220,0,51,1,58, + 255,211,0,51,10,250,0,38,0,51,10,251,0,38,0,51,10,252,254,183,0,52,0,16,0,57,0,52,10,250,255,211,0,52,10,251,255,220,0,52, + 10,252,255,125,0,53,0,16,255,173,0,53,0,17,255,183,0,53,0,29,255,193,0,53,0,36,255,173,0,53,0,38,255,154,0,53,0,55,255,107, + 0,53,0,57,255,144,0,53,0,58,255,173,0,53,0,60,255,125,0,53,0,68,255,211,0,53,0,72,255,164,0,53,0,82,255,164,0,53,0,88, + 255,164,0,53,0,92,255,144,0,53,0,109,255,144,0,53,0,125,255,220,0,53,0,130,255,173,0,53,0,131,255,173,0,53,0,132,255,173,0,53, + 0,133,255,173,0,53,0,134,255,173,0,53,0,137,255,154,0,53,0,159,255,125,0,53,0,162,255,211,0,53,0,163,255,211,0,53,0,164,255,211, + 0,53,0,165,255,211,0,53,0,166,255,211,0,53,0,167,255,211,0,53,0,170,255,164,0,53,0,171,255,164,0,53,0,172,255,164,0,53,0,173, + 255,164,0,53,0,180,255,164,0,53,0,181,255,164,0,53,0,182,255,164,0,53,0,183,255,164,0,53,0,184,255,164,0,53,0,187,255,164,0,53, + 0,188,255,164,0,53,0,189,255,164,0,53,0,190,255,164,0,53,0,191,255,144,0,53,0,193,255,144,0,53,0,200,255,154,0,53,0,206,255,154, + 0,53,0,221,255,164,0,53,1,38,255,107,0,53,1,49,255,164,0,53,1,58,255,125,0,53,10,250,255,107,0,53,10,251,255,125,0,53,10,252, + 255,220,0,54,0,36,0,38,0,54,0,130,0,38,0,54,0,131,0,38,0,54,0,132,0,38,0,54,0,133,0,38,0,54,0,134,0,38,0,55, + 0,16,255,68,0,55,0,17,255,13,0,55,0,29,255,31,0,55,0,36,255,97,0,55,0,38,255,136,0,55,0,55,255,220,0,55,0,68,254,173, + 0,55,0,70,254,164,0,55,0,72,254,164,0,55,0,76,255,193,0,55,0,82,254,164,0,55,0,85,254,211,0,55,0,86,254,173,0,55,0,88, + 254,201,0,55,0,90,254,173,0,55,0,92,254,193,0,55,0,109,255,68,0,55,0,125,255,144,0,55,0,130,255,97,0,55,0,131,255,97,0,55, + 0,132,255,97,0,55,0,133,255,97,0,55,0,134,255,97,0,55,0,137,255,136,0,55,0,162,255,17,0,55,0,163,254,173,0,55,0,164,255,17, + 0,55,0,165,255,17,0,55,0,166,255,17,0,55,0,167,255,17,0,55,0,169,254,164,0,55,0,170,254,224,0,55,0,171,254,164,0,55,0,172, + 254,224,0,55,0,173,254,224,0,55,0,180,254,244,0,55,0,181,254,164,0,55,0,182,254,244,0,55,0,183,254,244,0,55,0,184,254,244,0,55, + 0,187,254,231,0,55,0,188,254,201,0,55,0,189,254,231,0,55,0,190,254,231,0,55,0,191,254,193,0,55,0,193,254,193,0,55,0,200,255,136, + 0,55,0,201,254,164,0,55,0,206,255,136,0,55,0,207,254,164,0,55,0,221,254,164,0,55,1,23,254,211,0,55,1,27,254,211,0,55,1,33, + 254,173,0,55,1,35,254,173,0,55,1,38,255,220,0,55,1,49,254,201,0,55,10,251,255,211,0,55,10,252,254,248,0,56,0,61,255,220,0,56, + 1,63,255,220,0,57,0,16,255,136,0,57,0,17,254,248,0,57,0,29,255,89,0,57,0,36,255,125,0,57,0,50,255,220,0,57,0,68,255,97, + 0,57,0,72,255,97,0,57,0,76,255,211,0,57,0,82,255,97,0,57,0,88,255,117,0,57,0,92,255,201,0,57,0,109,255,78,0,57,0,125, + 255,144,0,57,0,130,255,125,0,57,0,131,255,125,0,57,0,132,255,125,0,57,0,133,255,125,0,57,0,134,255,125,0,57,0,148,255,220,0,57, + 0,149,255,220,0,57,0,150,255,220,0,57,0,151,255,220,0,57,0,152,255,220,0,57,0,162,255,97,0,57,0,163,255,97,0,57,0,164,255,97, + 0,57,0,165,255,97,0,57,0,166,255,97,0,57,0,167,255,97,0,57,0,170,255,97,0,57,0,171,255,97,0,57,0,172,255,97,0,57,0,173, + 255,97,0,57,0,180,255,97,0,57,0,181,255,97,0,57,0,182,255,97,0,57,0,183,255,97,0,57,0,184,255,97,0,57,0,187,255,117,0,57, + 0,188,255,117,0,57,0,189,255,117,0,57,0,190,255,117,0,57,0,191,255,201,0,57,0,193,255,201,0,57,0,221,255,97,0,57,1,49,255,117, + 0,57,10,252,254,230,0,58,0,16,255,173,0,58,0,17,255,21,0,58,0,29,255,136,0,58,0,36,255,144,0,58,0,68,255,125,0,58,0,72, + 255,136,0,58,0,76,255,211,0,58,0,82,255,136,0,58,0,85,255,164,0,58,0,88,255,183,0,58,0,92,255,220,0,58,0,109,255,144,0,58, + 0,125,255,220,0,58,0,130,255,144,0,58,0,131,255,144,0,58,0,132,255,144,0,58,0,133,255,144,0,58,0,134,255,144,0,58,0,162,255,125, + 0,58,0,163,255,125,0,58,0,164,255,125,0,58,0,165,255,125,0,58,0,166,255,125,0,58,0,167,255,125,0,58,0,170,255,136,0,58,0,171, + 255,136,0,58,0,172,255,136,0,58,0,173,255,136,0,58,0,180,255,136,0,58,0,181,255,136,0,58,0,182,255,136,0,58,0,183,255,136,0,58, + 0,184,255,136,0,58,0,187,255,183,0,58,0,188,255,183,0,58,0,189,255,183,0,58,0,190,255,183,0,58,0,191,255,220,0,58,0,193,255,220, + 0,58,0,221,255,136,0,58,1,23,255,164,0,58,1,27,255,164,0,58,1,49,255,183,0,58,10,250,255,220,0,58,10,252,254,248,0,59,0,16, + 255,154,0,59,0,38,255,107,0,59,0,50,255,125,0,59,0,55,255,220,0,59,0,72,255,164,0,59,0,109,255,144,0,59,0,137,255,107,0,59, + 0,148,255,125,0,59,0,149,255,125,0,59,0,150,255,125,0,59,0,151,255,125,0,59,0,152,255,125,0,59,0,170,255,164,0,59,0,171,255,164, + 0,59,0,172,255,164,0,59,0,173,255,164,0,59,0,200,255,107,0,59,0,206,255,107,0,59,0,221,255,164,0,59,1,38,255,220,0,59,10,250, + 255,97,0,59,10,251,255,173,0,59,10,252,255,211,0,60,0,16,255,13,0,60,0,17,254,97,0,60,0,29,254,240,0,60,0,36,255,97,0,60, + 0,38,255,144,0,60,0,50,255,144,0,60,0,68,254,230,0,60,0,72,254,240,0,60,0,76,255,183,0,60,0,82,254,240,0,60,0,88,255,21, + 0,60,0,109,255,31,0,60,0,125,255,107,0,60,0,130,255,97,0,60,0,131,255,97,0,60,0,132,255,97,0,60,0,133,255,97,0,60,0,134, + 255,97,0,60,0,137,255,144,0,60,0,148,255,144,0,60,0,149,255,144,0,60,0,150,255,144,0,60,0,151,255,144,0,60,0,152,255,144,0,60, + 0,162,254,230,0,60,0,163,254,230,0,60,0,164,254,230,0,60,0,165,254,230,0,60,0,166,254,230,0,60,0,167,254,230,0,60,0,170,254,240, + 0,60,0,171,254,240,0,60,0,172,254,240,0,60,0,173,254,240,0,60,0,180,254,240,0,60,0,181,254,240,0,60,0,182,254,240,0,60,0,183, + 254,240,0,60,0,184,254,240,0,60,0,187,255,21,0,60,0,188,255,21,0,60,0,189,255,21,0,60,0,190,255,21,0,60,0,200,255,144,0,60, + 0,206,255,144,0,60,0,221,254,240,0,60,1,49,255,21,0,60,10,250,255,144,0,60,10,251,255,220,0,60,10,252,254,248,0,61,0,16,255,220, + 0,61,10,250,255,220,0,61,10,251,255,220,0,61,10,252,255,220,0,72,0,91,255,220,0,73,0,16,255,144,0,73,0,17,255,107,0,73,0,29, + 255,183,0,73,0,87,255,220,0,73,0,90,255,220,0,73,0,92,255,220,0,73,0,109,255,183,0,73,0,125,255,220,0,73,0,191,255,220,0,73, + 0,193,255,220,0,73,1,39,255,220,0,73,10,250,0,65,0,73,10,252,255,21,0,78,0,68,255,220,0,78,0,72,255,183,0,78,0,82,255,183, + 0,78,0,88,255,193,0,78,0,92,255,183,0,78,0,162,255,220,0,78,0,163,255,220,0,78,0,164,255,220,0,78,0,165,255,220,0,78,0,166, + 255,220,0,78,0,167,255,220,0,78,0,170,255,183,0,78,0,171,255,183,0,78,0,172,255,183,0,78,0,173,255,183,0,78,0,180,255,183,0,78, + 0,181,255,183,0,78,0,182,255,183,0,78,0,183,255,183,0,78,0,184,255,183,0,78,0,187,255,193,0,78,0,188,255,193,0,78,0,189,255,193, + 0,78,0,190,255,193,0,78,0,191,255,183,0,78,0,193,255,183,0,78,0,221,255,183,0,78,1,49,255,193,0,81,10,250,255,107,0,81,10,251, + 255,144,0,81,10,252,255,164,0,82,0,16,0,38,0,82,0,17,255,220,0,82,0,91,255,193,0,82,10,250,255,107,0,82,10,251,255,183,0,82, + 10,252,255,125,0,85,0,16,255,125,0,85,0,17,255,68,0,85,0,29,255,220,0,85,0,70,255,211,0,85,0,71,255,220,0,85,0,72,255,211, + 0,85,0,74,255,220,0,85,0,75,255,220,0,85,0,80,255,220,0,85,0,81,255,220,0,85,0,82,255,211,0,85,0,84,255,220,0,85,0,85, + 255,220,0,85,0,91,255,201,0,85,0,109,255,183,0,85,0,169,255,211,0,85,0,170,255,211,0,85,0,171,255,211,0,85,0,172,255,211,0,85, + 0,173,255,211,0,85,0,179,255,220,0,85,0,180,255,211,0,85,0,181,255,211,0,85,0,182,255,211,0,85,0,183,255,211,0,85,0,184,255,211, + 0,85,0,201,255,211,0,85,0,207,255,211,0,85,0,209,0,72,0,85,0,221,255,211,0,85,0,225,255,220,0,85,1,10,255,220,0,85,1,23, + 255,220,0,85,1,27,255,220,0,85,10,251,0,86,0,85,10,252,254,201,0,89,0,16,255,201,0,89,0,17,255,97,0,89,0,29,255,144,0,89, + 0,109,255,220,0,89,0,125,255,220,0,89,10,251,255,220,0,89,10,252,254,240,0,90,0,17,255,68,0,90,0,29,255,144,0,90,0,109,255,220, + 0,90,0,125,255,220,0,90,10,252,255,41,0,91,0,70,255,220,0,91,0,72,255,193,0,91,0,82,255,193,0,91,0,169,255,220,0,91,0,170, + 255,193,0,91,0,171,255,193,0,91,0,172,255,193,0,91,0,173,255,193,0,91,0,180,255,193,0,91,0,181,255,193,0,91,0,182,255,193,0,91, + 0,183,255,193,0,91,0,184,255,193,0,91,0,201,255,220,0,91,0,207,255,220,0,91,0,221,255,193,0,92,0,16,255,220,0,92,0,17,254,220, + 0,92,0,29,255,107,0,92,0,109,255,220,0,92,0,125,255,220,0,92,10,252,254,211,0,109,0,37,255,220,0,109,0,38,255,220,0,109,0,39, + 255,220,0,109,0,42,255,220,0,109,0,45,255,220,0,109,0,55,255,144,0,109,0,57,255,144,0,109,0,58,255,220,0,109,0,60,255,107,0,109, + 0,89,255,220,0,109,0,90,255,220,0,109,0,92,255,220,0,109,0,136,0,151,0,109,0,137,255,220,0,109,0,159,255,107,0,109,0,191,255,220, + 0,109,0,193,255,220,0,109,0,200,255,220,0,109,0,206,255,220,0,109,0,208,255,220,0,109,0,224,255,220,0,109,1,38,255,144,0,109,1,58, + 255,107,0,125,0,36,255,183,0,125,0,37,255,183,0,125,0,38,255,220,0,125,0,39,255,220,0,125,0,45,255,220,0,125,0,50,255,220,0,125, + 0,55,255,68,0,125,0,57,255,78,0,125,0,58,255,144,0,125,0,59,255,144,0,125,0,60,255,31,0,125,0,89,255,220,0,125,0,90,255,220, + 0,125,0,92,255,220,0,125,0,130,255,183,0,125,0,131,255,183,0,125,0,132,255,183,0,125,0,133,255,183,0,125,0,134,255,183,0,125,0,137, + 255,220,0,125,0,148,255,220,0,125,0,149,255,220,0,125,0,150,255,220,0,125,0,151,255,220,0,125,0,152,255,220,0,125,0,159,255,31,0,125, + 0,191,255,220,0,125,0,193,255,220,0,125,0,200,255,220,0,125,0,206,255,220,0,125,0,208,255,220,0,125,1,38,255,68,0,125,1,58,255,31, + 0,130,0,16,255,211,0,130,0,17,255,220,0,130,0,29,255,220,0,130,0,36,0,57,0,130,0,38,255,220,0,130,0,42,255,220,0,130,0,50, + 255,220,0,130,0,52,255,220,0,130,0,55,255,97,0,130,0,57,255,125,0,130,0,58,255,144,0,130,0,60,255,97,0,130,0,70,255,220,0,130, + 0,71,255,220,0,130,0,72,255,220,0,130,0,73,255,183,0,130,0,82,255,220,0,130,0,84,255,220,0,130,0,87,255,220,0,130,0,89,255,136, + 0,130,0,90,255,173,0,130,0,92,255,117,0,130,0,109,255,183,0,130,0,130,0,57,0,130,0,131,0,57,0,130,0,132,0,57,0,130,0,133, + 0,57,0,130,0,134,0,57,0,130,0,137,255,220,0,130,0,148,255,220,0,130,0,149,255,220,0,130,0,150,255,220,0,130,0,151,255,220,0,130, + 0,152,255,220,0,130,0,159,255,97,0,130,0,169,255,220,0,130,0,170,255,220,0,130,0,171,255,220,0,130,0,172,255,220,0,130,0,173,255,220, + 0,130,0,180,255,220,0,130,0,181,255,220,0,130,0,182,255,220,0,130,0,183,255,220,0,130,0,184,255,220,0,130,0,191,255,117,0,130,0,193, + 255,117,0,130,0,194,0,57,0,130,0,196,0,57,0,130,0,198,0,57,0,130,0,200,255,220,0,130,0,201,255,220,0,130,0,202,255,220,0,130, + 0,204,255,220,0,130,0,205,255,220,0,130,0,206,255,220,0,130,0,207,255,220,0,130,0,209,255,220,0,130,0,213,255,220,0,130,0,215,255,220, + 0,130,0,217,255,220,0,130,0,219,255,220,0,130,0,221,255,220,0,130,0,222,255,220,0,130,0,224,255,220,0,130,0,226,255,220,0,130,1,14, + 255,220,0,130,1,15,255,220,0,130,1,16,255,220,0,130,1,17,255,220,0,130,1,18,255,220,0,130,1,19,255,220,0,130,1,36,255,97,0,130, + 1,37,255,220,0,130,1,38,255,97,0,130,1,39,255,220,0,130,1,54,255,144,0,130,1,55,255,173,0,130,1,56,255,97,0,130,1,57,255,117, + 0,130,1,58,255,97,0,130,1,240,255,220,0,130,1,241,255,220,0,130,9,121,255,144,0,130,9,124,255,173,0,130,9,125,255,144,0,130,9,126, + 255,173,0,130,9,235,255,97,0,130,9,236,255,117,0,130,10,250,254,248,0,130,10,251,255,3,0,130,10,252,0,47,0,131,0,16,255,211,0,131, + 0,17,255,220,0,131,0,29,255,220,0,131,0,36,0,57,0,131,0,38,255,220,0,131,0,42,255,220,0,131,0,50,255,220,0,131,0,52,255,220, + 0,131,0,55,255,97,0,131,0,57,255,125,0,131,0,58,255,144,0,131,0,60,255,97,0,131,0,70,255,220,0,131,0,71,255,220,0,131,0,72, + 255,220,0,131,0,73,255,183,0,131,0,82,255,220,0,131,0,84,255,220,0,131,0,87,255,220,0,131,0,89,255,136,0,131,0,90,255,173,0,131, + 0,92,255,117,0,131,0,109,255,183,0,131,0,130,0,57,0,131,0,131,0,57,0,131,0,132,0,57,0,131,0,133,0,57,0,131,0,134,0,57, + 0,131,0,137,255,220,0,131,0,148,255,220,0,131,0,149,255,220,0,131,0,150,255,220,0,131,0,151,255,220,0,131,0,152,255,220,0,131,0,159, + 255,97,0,131,0,169,255,220,0,131,0,170,255,220,0,131,0,171,255,220,0,131,0,172,255,220,0,131,0,173,255,220,0,131,0,180,255,220,0,131, + 0,181,255,220,0,131,0,182,255,220,0,131,0,183,255,220,0,131,0,184,255,220,0,131,0,191,255,117,0,131,0,193,255,117,0,131,0,194,0,57, + 0,131,0,196,0,57,0,131,0,198,0,57,0,131,0,200,255,220,0,131,0,201,255,220,0,131,0,202,255,220,0,131,0,204,255,220,0,131,0,205, + 255,220,0,131,0,206,255,220,0,131,0,207,255,220,0,131,0,209,255,220,0,131,0,213,255,220,0,131,0,215,255,220,0,131,0,217,255,220,0,131, + 0,219,255,220,0,131,0,221,255,220,0,131,0,222,255,220,0,131,0,224,255,220,0,131,0,226,255,220,0,131,1,14,255,220,0,131,1,15,255,220, + 0,131,1,16,255,220,0,131,1,17,255,220,0,131,1,18,255,220,0,131,1,19,255,220,0,131,1,36,255,97,0,131,1,37,255,220,0,131,1,38, + 255,97,0,131,1,39,255,220,0,131,1,54,255,144,0,131,1,55,255,173,0,131,1,56,255,97,0,131,1,57,255,117,0,131,1,58,255,97,0,131, + 1,240,255,220,0,131,1,241,255,220,0,131,9,121,255,144,0,131,9,123,255,144,0,131,9,124,255,173,0,131,9,125,255,144,0,131,9,126,255,173, + 0,131,9,235,255,97,0,131,9,236,255,117,0,131,10,250,254,248,0,131,10,251,255,3,0,131,10,252,0,47,0,132,0,16,255,211,0,132,0,17, + 255,220,0,132,0,29,255,220,0,132,0,36,0,57,0,132,0,38,255,220,0,132,0,42,255,220,0,132,0,50,255,220,0,132,0,52,255,220,0,132, + 0,55,255,97,0,132,0,57,255,125,0,132,0,58,255,144,0,132,0,60,255,97,0,132,0,70,255,220,0,132,0,71,255,220,0,132,0,72,255,220, + 0,132,0,73,255,183,0,132,0,82,255,220,0,132,0,84,255,220,0,132,0,87,255,220,0,132,0,89,255,136,0,132,0,90,255,173,0,132,0,92, + 255,117,0,132,0,109,255,183,0,132,0,130,0,57,0,132,0,131,0,57,0,132,0,132,0,57,0,132,0,133,0,57,0,132,0,134,0,57,0,132, + 0,137,255,220,0,132,0,148,255,220,0,132,0,149,255,220,0,132,0,150,255,220,0,132,0,151,255,220,0,132,0,152,255,220,0,132,0,159,255,97, + 0,132,0,169,255,220,0,132,0,170,255,220,0,132,0,171,255,220,0,132,0,172,255,220,0,132,0,173,255,220,0,132,0,180,255,220,0,132,0,181, + 255,220,0,132,0,182,255,220,0,132,0,183,255,220,0,132,0,184,255,220,0,132,0,191,255,117,0,132,0,193,255,117,0,132,0,194,0,57,0,132, + 0,196,0,57,0,132,0,198,0,57,0,132,0,200,255,220,0,132,0,201,255,220,0,132,0,202,255,220,0,132,0,204,255,220,0,132,0,205,255,220, + 0,132,0,206,255,220,0,132,0,207,255,220,0,132,0,209,255,220,0,132,0,213,255,220,0,132,0,215,255,220,0,132,0,217,255,220,0,132,0,219, + 255,220,0,132,0,221,255,220,0,132,0,222,255,220,0,132,0,224,255,220,0,132,0,226,255,220,0,132,1,14,255,220,0,132,1,15,255,220,0,132, + 1,16,255,220,0,132,1,17,255,220,0,132,1,18,255,220,0,132,1,19,255,220,0,132,1,36,255,97,0,132,1,37,255,220,0,132,1,38,255,97, + 0,132,1,39,255,220,0,132,1,54,255,144,0,132,1,55,255,173,0,132,1,56,255,97,0,132,1,57,255,117,0,132,1,58,255,97,0,132,1,240, + 255,220,0,132,1,241,255,220,0,132,9,121,255,144,0,132,9,123,255,144,0,132,9,124,255,173,0,132,9,125,255,144,0,132,9,126,255,173,0,132, + 9,235,255,97,0,132,9,236,255,117,0,132,10,250,254,248,0,132,10,251,255,3,0,132,10,252,0,47,0,133,0,16,255,211,0,133,0,17,255,220, + 0,133,0,29,255,220,0,133,0,36,0,57,0,133,0,38,255,220,0,133,0,42,255,220,0,133,0,50,255,220,0,133,0,52,255,220,0,133,0,55, + 255,97,0,133,0,57,255,125,0,133,0,58,255,144,0,133,0,60,255,97,0,133,0,70,255,220,0,133,0,71,255,220,0,133,0,72,255,220,0,133, + 0,73,255,183,0,133,0,82,255,220,0,133,0,84,255,220,0,133,0,87,255,220,0,133,0,89,255,136,0,133,0,90,255,173,0,133,0,92,255,117, + 0,133,0,109,255,183,0,133,0,130,0,57,0,133,0,131,0,57,0,133,0,132,0,57,0,133,0,133,0,57,0,133,0,134,0,57,0,133,0,137, + 255,220,0,133,0,148,255,220,0,133,0,149,255,220,0,133,0,150,255,220,0,133,0,151,255,220,0,133,0,152,255,220,0,133,0,159,255,97,0,133, + 0,169,255,220,0,133,0,170,255,220,0,133,0,171,255,220,0,133,0,172,255,220,0,133,0,173,255,220,0,133,0,180,255,220,0,133,0,181,255,220, + 0,133,0,182,255,220,0,133,0,183,255,220,0,133,0,184,255,220,0,133,0,191,255,117,0,133,0,193,255,117,0,133,0,194,0,57,0,133,0,196, + 0,57,0,133,0,198,0,57,0,133,0,200,255,220,0,133,0,201,255,220,0,133,0,202,255,220,0,133,0,204,255,220,0,133,0,205,255,220,0,133, + 0,206,255,220,0,133,0,207,255,220,0,133,0,209,255,220,0,133,0,213,255,220,0,133,0,215,255,220,0,133,0,217,255,220,0,133,0,219,255,220, + 0,133,0,221,255,220,0,133,0,222,255,220,0,133,0,224,255,220,0,133,0,226,255,220,0,133,1,14,255,220,0,133,1,15,255,220,0,133,1,16, + 255,220,0,133,1,17,255,220,0,133,1,18,255,220,0,133,1,19,255,220,0,133,1,36,255,97,0,133,1,37,255,220,0,133,1,38,255,97,0,133, + 1,39,255,220,0,133,1,54,255,144,0,133,1,55,255,173,0,133,1,56,255,97,0,133,1,57,255,117,0,133,1,58,255,97,0,133,1,240,255,220, + 0,133,9,121,255,144,0,133,9,123,255,144,0,133,9,124,255,173,0,133,9,125,255,144,0,133,9,126,255,173,0,133,9,235,255,97,0,133,9,236, + 255,117,0,133,10,250,254,248,0,133,10,251,255,3,0,133,10,252,0,47,0,134,0,16,255,211,0,134,0,17,255,220,0,134,0,29,255,220,0,134, + 0,36,0,57,0,134,0,38,255,220,0,134,0,42,255,220,0,134,0,50,255,220,0,134,0,52,255,220,0,134,0,55,255,97,0,134,0,57,255,125, + 0,134,0,58,255,144,0,134,0,60,255,97,0,134,0,70,255,220,0,134,0,71,255,220,0,134,0,72,255,220,0,134,0,73,255,183,0,134,0,82, + 255,220,0,134,0,84,255,220,0,134,0,87,255,220,0,134,0,89,255,136,0,134,0,90,255,173,0,134,0,92,255,117,0,134,0,109,255,183,0,134, + 0,130,0,57,0,134,0,131,0,57,0,134,0,132,0,57,0,134,0,133,0,57,0,134,0,134,0,57,0,134,0,137,255,220,0,134,0,148,255,220, + 0,134,0,149,255,220,0,134,0,150,255,220,0,134,0,151,255,220,0,134,0,152,255,220,0,134,0,159,255,97,0,134,0,169,255,220,0,134,0,170, + 255,220,0,134,0,171,255,220,0,134,0,172,255,220,0,134,0,173,255,220,0,134,0,180,255,220,0,134,0,181,255,220,0,134,0,182,255,220,0,134, + 0,183,255,220,0,134,0,184,255,220,0,134,0,191,255,117,0,134,0,193,255,117,0,134,0,194,0,57,0,134,0,196,0,57,0,134,0,198,0,57, + 0,134,0,200,255,220,0,134,0,201,255,220,0,134,0,202,255,220,0,134,0,204,255,220,0,134,0,205,255,220,0,134,0,206,255,220,0,134,0,207, + 255,220,0,134,0,209,255,220,0,134,0,213,255,220,0,134,0,215,255,220,0,134,0,217,255,220,0,134,0,219,255,220,0,134,0,221,255,220,0,134, + 0,222,255,220,0,134,0,224,255,220,0,134,0,226,255,220,0,134,1,14,255,220,0,134,1,15,255,220,0,134,1,16,255,220,0,134,1,17,255,220, + 0,134,1,18,255,220,0,134,1,19,255,220,0,134,1,36,255,97,0,134,1,37,255,220,0,134,1,38,255,97,0,134,1,39,255,220,0,134,1,54, + 255,144,0,134,1,55,255,173,0,134,1,56,255,97,0,134,1,57,255,117,0,134,1,58,255,97,0,134,1,240,255,220,0,134,1,241,255,220,0,134, + 9,121,255,144,0,134,9,123,255,144,0,134,9,124,255,173,0,134,9,125,255,144,0,134,9,126,255,173,0,134,9,235,255,97,0,134,9,236,255,117, + 0,134,10,250,254,248,0,134,10,251,255,3,0,134,10,252,0,47,0,136,10,250,255,173,0,136,10,251,255,164,0,136,10,252,255,144,0,137,0,60, + 255,220,0,137,0,109,255,220,0,137,0,125,255,220,0,137,0,159,255,220,0,137,1,58,255,220,0,137,10,251,0,38,0,146,0,36,255,220,0,146, + 0,57,255,220,0,146,0,60,255,144,0,146,0,109,255,220,0,146,0,125,255,220,0,146,0,130,255,220,0,146,0,131,255,220,0,146,0,132,255,220, + 0,146,0,133,255,220,0,146,0,134,255,220,0,146,0,159,255,144,0,146,0,194,255,220,0,146,0,196,255,220,0,146,0,198,255,220,0,146,1,56, + 255,144,0,146,1,58,255,144,0,146,1,244,255,144,0,146,9,235,255,144,0,146,10,250,255,211,0,146,10,251,255,201,0,146,10,252,255,68,0,148, + 0,16,0,57,0,148,0,17,255,173,0,148,0,29,255,220,0,148,0,36,255,220,0,148,0,57,255,220,0,148,0,59,255,125,0,148,0,60,255,144, + 0,148,0,109,255,220,0,148,0,130,255,220,0,148,0,131,255,220,0,148,0,132,255,220,0,148,0,133,255,220,0,148,0,134,255,220,0,148,0,159, + 255,144,0,148,1,58,255,144,0,148,10,250,255,211,0,148,10,251,255,220,0,148,10,252,255,68,0,149,0,16,0,57,0,149,0,17,255,173,0,149, + 0,29,255,220,0,149,0,36,255,220,0,149,0,57,255,220,0,149,0,59,255,125,0,149,0,60,255,144,0,149,0,109,255,220,0,149,0,130,255,220, + 0,149,0,131,255,220,0,149,0,132,255,220,0,149,0,133,255,220,0,149,0,134,255,220,0,149,0,159,255,144,0,149,1,58,255,144,0,149,10,250, + 255,211,0,149,10,251,255,220,0,149,10,252,255,68,0,150,0,16,0,57,0,150,0,17,255,173,0,150,0,29,255,220,0,150,0,36,255,220,0,150, + 0,57,255,220,0,150,0,59,255,125,0,150,0,60,255,144,0,150,0,109,255,220,0,150,0,130,255,220,0,150,0,131,255,220,0,150,0,132,255,220, + 0,150,0,133,255,220,0,150,0,134,255,220,0,150,0,159,255,144,0,150,1,58,255,144,0,150,10,250,255,211,0,150,10,251,255,220,0,150,10,252, + 255,68,0,151,0,16,0,57,0,151,0,17,255,173,0,151,0,29,255,220,0,151,0,36,255,220,0,151,0,57,255,220,0,151,0,59,255,125,0,151, + 0,60,255,144,0,151,0,109,255,220,0,151,0,130,255,220,0,151,0,131,255,220,0,151,0,132,255,220,0,151,0,133,255,220,0,151,0,134,255,220, + 0,151,0,159,255,144,0,151,1,58,255,144,0,151,10,250,255,211,0,151,10,251,255,220,0,151,10,252,255,68,0,152,0,16,0,57,0,152,0,17, + 255,173,0,152,0,29,255,220,0,152,0,36,255,220,0,152,0,57,255,220,0,152,0,59,255,125,0,152,0,60,255,144,0,152,0,109,255,220,0,152, + 0,130,255,220,0,152,0,131,255,220,0,152,0,132,255,220,0,152,0,133,255,220,0,152,0,134,255,220,0,152,0,159,255,144,0,152,1,58,255,144, + 0,152,10,250,255,211,0,152,10,251,255,220,0,152,10,252,255,68,0,155,0,61,255,220,0,155,1,63,255,220,0,156,0,61,255,220,0,156,1,63, + 255,220,0,157,0,61,255,220,0,157,1,63,255,220,0,158,0,61,255,220,0,158,1,63,255,220,0,159,0,16,255,13,0,159,0,17,254,97,0,159, + 0,29,254,240,0,159,0,36,255,97,0,159,0,38,255,144,0,159,0,50,255,144,0,159,0,68,254,230,0,159,0,72,254,240,0,159,0,76,255,183, + 0,159,0,82,254,240,0,159,0,88,255,21,0,159,0,109,255,31,0,159,0,125,255,107,0,159,0,130,255,97,0,159,0,131,255,97,0,159,0,132, + 255,97,0,159,0,133,255,97,0,159,0,134,255,97,0,159,0,137,255,144,0,159,0,148,255,144,0,159,0,149,255,144,0,159,0,150,255,144,0,159, + 0,151,255,144,0,159,0,152,255,144,0,159,0,162,254,230,0,159,0,163,254,230,0,159,0,164,254,230,0,159,0,165,254,230,0,159,0,166,254,230, + 0,159,0,167,254,230,0,159,0,170,254,240,0,159,0,171,254,240,0,159,0,172,254,240,0,159,0,173,254,240,0,159,0,180,254,240,0,159,0,181, + 254,240,0,159,0,182,254,240,0,159,0,183,254,240,0,159,0,184,254,240,0,159,0,187,255,21,0,159,0,188,255,21,0,159,0,189,255,21,0,159, + 0,190,255,21,0,159,0,200,255,144,0,159,0,206,255,144,0,159,0,221,254,240,0,159,1,49,255,21,0,159,10,250,255,144,0,159,10,251,255,220, + 0,159,10,252,254,248,0,160,0,17,255,107,0,160,0,29,255,183,0,160,10,250,255,220,0,160,10,252,255,68,0,161,0,16,0,38,0,161,10,250, + 255,144,0,161,10,251,255,144,0,161,10,252,255,173,0,170,0,91,255,220,0,171,0,91,255,220,0,172,0,91,255,220,0,173,0,91,255,220,0,178, + 10,250,255,164,0,178,10,251,255,144,0,178,10,252,255,183,0,179,10,250,255,107,0,179,10,251,255,144,0,179,10,252,255,164,0,180,0,16,0,38, + 0,180,0,17,255,220,0,180,0,91,255,193,0,180,10,250,255,107,0,180,10,251,255,183,0,180,10,252,255,125,0,181,0,16,0,38,0,181,0,17, + 255,220,0,181,0,91,255,193,0,181,10,250,255,107,0,181,10,251,255,183,0,181,10,252,255,125,0,182,0,16,0,38,0,182,0,17,255,220,0,182, + 0,91,255,193,0,182,10,250,255,107,0,182,10,251,255,183,0,182,10,252,255,125,0,183,0,16,0,38,0,183,0,17,255,220,0,183,0,91,255,193, + 0,183,10,250,255,107,0,183,10,251,255,183,0,183,10,252,255,125,0,184,0,16,0,38,0,184,0,17,255,220,0,184,0,91,255,193,0,184,10,250, + 255,107,0,184,10,251,255,183,0,184,10,252,255,125,0,191,0,16,255,220,0,191,0,17,254,220,0,191,0,29,255,107,0,191,0,109,255,220,0,191, + 0,125,255,220,0,191,10,252,254,211,0,193,0,16,255,220,0,193,0,17,254,220,0,193,0,29,255,107,0,193,0,109,255,220,0,193,0,125,255,220, + 0,193,10,252,254,211,0,194,0,16,255,211,0,194,0,17,255,220,0,194,0,29,255,220,0,194,0,36,0,57,0,194,0,38,255,220,0,194,0,42, + 255,220,0,194,0,50,255,220,0,194,0,52,255,220,0,194,0,55,255,97,0,194,0,57,255,125,0,194,0,58,255,144,0,194,0,60,255,97,0,194, + 0,70,255,220,0,194,0,71,255,220,0,194,0,72,255,220,0,194,0,73,255,183,0,194,0,82,255,220,0,194,0,84,255,220,0,194,0,87,255,220, + 0,194,0,89,255,136,0,194,0,90,255,173,0,194,0,92,255,117,0,194,0,109,255,183,0,194,0,130,0,57,0,194,0,131,0,57,0,194,0,132, + 0,57,0,194,0,133,0,57,0,194,0,134,0,57,0,194,0,148,255,220,0,194,0,149,255,220,0,194,0,150,255,220,0,194,0,151,255,220,0,194, + 0,152,255,220,0,194,0,159,255,97,0,194,0,169,255,220,0,194,0,170,255,220,0,194,0,171,255,220,0,194,0,172,255,220,0,194,0,173,255,220, + 0,194,0,180,255,220,0,194,0,181,255,220,0,194,0,182,255,220,0,194,0,183,255,220,0,194,0,184,255,220,0,194,0,191,255,117,0,194,0,193, + 255,117,0,194,0,194,0,57,0,194,0,196,0,57,0,194,0,198,0,57,0,194,0,200,255,220,0,194,0,202,255,220,0,194,0,204,255,220,0,194, + 0,205,255,220,0,194,0,206,255,220,0,194,0,209,255,220,0,194,0,211,255,220,0,194,0,213,255,220,0,194,0,215,255,220,0,194,0,217,255,220, + 0,194,0,219,255,220,0,194,0,221,255,220,0,194,0,222,255,220,0,194,0,226,255,220,0,194,1,14,255,220,0,194,1,15,255,220,0,194,1,16, + 255,220,0,194,1,17,255,220,0,194,1,18,255,220,0,194,1,19,255,220,0,194,1,36,255,97,0,194,1,37,255,220,0,194,1,38,255,97,0,194, + 1,39,255,220,0,194,1,54,255,144,0,194,1,55,255,173,0,194,1,56,255,97,0,194,1,57,255,117,0,194,1,58,255,97,0,194,1,240,255,220, + 0,194,1,241,255,220,0,194,9,121,255,144,0,194,9,123,255,144,0,194,9,124,255,173,0,194,9,125,255,144,0,194,9,126,255,173,0,194,9,235, + 255,97,0,194,9,236,255,117,0,194,10,250,254,248,0,194,10,251,255,2,0,194,10,252,0,47,0,196,0,16,255,211,0,196,0,17,255,220,0,196, + 0,29,255,220,0,196,0,36,0,57,0,196,0,38,255,220,0,196,0,42,255,220,0,196,0,50,255,220,0,196,0,52,255,220,0,196,0,55,255,97, + 0,196,0,57,255,125,0,196,0,58,255,144,0,196,0,60,255,97,0,196,0,70,255,220,0,196,0,71,255,220,0,196,0,72,255,220,0,196,0,73, + 255,183,0,196,0,82,255,220,0,196,0,84,255,220,0,196,0,87,255,220,0,196,0,89,255,136,0,196,0,90,255,173,0,196,0,92,255,117,0,196, + 0,109,255,183,0,196,0,130,0,57,0,196,0,131,0,57,0,196,0,132,0,57,0,196,0,133,0,57,0,196,0,134,0,57,0,196,0,148,255,220, + 0,196,0,149,255,220,0,196,0,150,255,220,0,196,0,151,255,220,0,196,0,152,255,220,0,196,0,159,255,97,0,196,0,169,255,220,0,196,0,170, + 255,220,0,196,0,171,255,220,0,196,0,172,255,220,0,196,0,173,255,220,0,196,0,180,255,220,0,196,0,181,255,220,0,196,0,182,255,220,0,196, + 0,183,255,220,0,196,0,184,255,220,0,196,0,191,255,117,0,196,0,193,255,117,0,196,0,194,0,57,0,196,0,196,0,57,0,196,0,198,0,57, + 0,196,0,200,255,220,0,196,0,202,255,220,0,196,0,204,255,220,0,196,0,205,255,220,0,196,0,206,255,220,0,196,0,209,255,220,0,196,0,211, + 255,220,0,196,0,213,255,220,0,196,0,215,255,220,0,196,0,217,255,220,0,196,0,219,255,220,0,196,0,221,255,220,0,196,0,222,255,220,0,196, + 0,226,255,220,0,196,1,14,255,220,0,196,1,15,255,220,0,196,1,16,255,220,0,196,1,17,255,220,0,196,1,18,255,220,0,196,1,19,255,220, + 0,196,1,36,255,97,0,196,1,37,255,220,0,196,1,38,255,97,0,196,1,39,255,220,0,196,1,54,255,144,0,196,1,55,255,173,0,196,1,56, + 255,97,0,196,1,57,255,117,0,196,1,58,255,97,0,196,1,240,255,220,0,196,1,241,255,220,0,196,9,121,255,144,0,196,9,123,255,144,0,196, + 9,124,255,173,0,196,9,125,255,144,0,196,9,126,255,173,0,196,9,235,255,97,0,196,9,236,255,117,0,196,10,250,254,248,0,196,10,251,255,2, + 0,196,10,252,0,47,0,198,0,16,255,211,0,198,0,17,255,220,0,198,0,29,255,220,0,198,0,36,0,57,0,198,0,38,255,220,0,198,0,42, + 255,220,0,198,0,50,255,220,0,198,0,52,255,220,0,198,0,55,255,97,0,198,0,57,255,125,0,198,0,58,255,144,0,198,0,60,255,97,0,198, + 0,70,255,220,0,198,0,71,255,220,0,198,0,72,255,220,0,198,0,73,255,183,0,198,0,82,255,220,0,198,0,84,255,220,0,198,0,87,255,220, + 0,198,0,89,255,136,0,198,0,90,255,173,0,198,0,109,255,183,0,198,0,130,0,57,0,198,0,131,0,57,0,198,0,132,0,57,0,198,0,133, + 0,57,0,198,0,134,0,57,0,198,0,148,255,220,0,198,0,149,255,220,0,198,0,150,255,220,0,198,0,151,255,220,0,198,0,152,255,220,0,198, + 0,159,255,97,0,198,0,169,255,220,0,198,0,170,255,220,0,198,0,171,255,220,0,198,0,172,255,220,0,198,0,173,255,220,0,198,0,180,255,220, + 0,198,0,181,255,220,0,198,0,182,255,220,0,198,0,183,255,220,0,198,0,184,255,220,0,198,0,194,0,57,0,198,0,196,0,57,0,198,0,198, + 0,57,0,198,0,200,255,220,0,198,0,202,255,220,0,198,0,204,255,220,0,198,0,205,255,220,0,198,0,206,255,220,0,198,0,209,255,220,0,198, + 0,211,255,220,0,198,0,213,255,220,0,198,0,215,255,220,0,198,0,217,255,220,0,198,0,219,255,220,0,198,0,221,255,220,0,198,0,222,255,220, + 0,198,0,226,255,220,0,198,1,14,255,220,0,198,1,15,255,220,0,198,1,16,255,220,0,198,1,17,255,220,0,198,1,19,255,220,0,198,1,36, + 255,97,0,198,1,37,255,220,0,198,1,38,255,97,0,198,1,39,255,220,0,198,1,54,255,144,0,198,1,55,255,173,0,198,1,56,255,97,0,198, + 1,58,255,97,0,198,1,240,255,220,0,198,1,241,255,220,0,198,9,121,255,144,0,198,9,123,255,144,0,198,9,124,255,173,0,198,9,125,255,144, + 0,198,9,126,255,173,0,198,9,235,255,97,0,198,10,250,254,248,0,198,10,251,255,2,0,198,10,252,0,47,0,200,0,60,255,220,0,200,0,109, + 255,220,0,200,0,125,255,220,0,200,0,159,255,220,0,200,1,58,255,220,0,200,10,251,0,38,0,206,0,60,255,220,0,206,0,109,255,220,0,206, + 0,125,255,220,0,206,0,159,255,220,0,206,1,58,255,220,0,206,10,251,0,38,0,208,0,36,255,220,0,208,0,57,255,220,0,208,0,60,255,144, + 0,208,0,109,255,220,0,208,0,125,255,220,0,208,0,130,255,220,0,208,0,131,255,220,0,208,0,132,255,220,0,208,0,133,255,220,0,208,0,134, + 255,220,0,208,0,159,255,144,0,208,0,194,255,220,0,208,0,196,255,220,0,208,0,198,255,220,0,208,1,56,255,144,0,208,1,58,255,144,0,208, + 1,244,255,144,0,208,9,235,255,144,0,208,10,250,255,211,0,208,10,251,255,201,0,208,10,252,255,68,0,210,0,36,255,220,0,210,0,57,255,220, + 0,210,0,60,255,144,0,210,0,109,255,220,0,210,0,125,255,220,0,210,0,130,255,220,0,210,0,131,255,220,0,210,0,132,255,220,0,210,0,133, + 255,220,0,210,0,134,255,220,0,210,0,159,255,144,0,210,1,58,255,144,0,210,10,250,255,211,0,210,10,251,255,201,0,210,10,252,255,68,0,221, + 0,91,255,220,0,224,0,55,255,183,0,224,0,60,255,154,0,224,0,109,255,220,0,224,0,125,255,220,0,224,0,159,255,154,0,224,1,38,255,183, + 0,224,1,58,255,154,0,224,10,250,255,211,0,224,10,251,255,211,0,224,10,252,255,201,0,251,0,16,255,220,0,251,0,36,0,47,0,251,0,50, + 255,183,0,251,0,55,254,230,0,251,0,56,255,154,0,251,0,57,255,31,0,251,0,58,255,68,0,251,0,60,254,240,0,251,0,72,255,220,0,251, + 0,82,255,220,0,251,0,88,255,220,0,251,0,92,255,68,0,251,0,130,0,47,0,251,0,131,0,47,0,251,0,132,0,47,0,251,0,133,0,47, + 0,251,0,134,0,47,0,251,0,148,255,183,0,251,0,149,255,183,0,251,0,150,255,183,0,251,0,151,255,183,0,251,0,152,255,183,0,251,0,155, + 255,154,0,251,0,156,255,154,0,251,0,157,255,154,0,251,0,158,255,154,0,251,0,159,254,240,0,251,0,170,255,220,0,251,0,171,255,220,0,251, + 0,172,255,220,0,251,0,173,255,220,0,251,0,180,255,220,0,251,0,181,255,220,0,251,0,182,255,220,0,251,0,183,255,220,0,251,0,184,255,220, + 0,251,0,187,255,220,0,251,0,188,255,220,0,251,0,189,255,220,0,251,0,190,255,220,0,251,0,191,255,68,0,251,0,193,255,68,0,251,0,221, + 255,220,0,251,1,38,254,230,0,251,1,48,255,154,0,251,1,49,255,220,0,251,1,58,254,240,0,251,10,250,254,97,0,251,10,251,253,230,0,255, + 0,16,255,220,0,255,0,36,0,47,0,255,0,50,255,183,0,255,0,55,254,230,0,255,0,56,255,154,0,255,0,57,255,31,0,255,0,58,255,68, + 0,255,0,60,254,240,0,255,0,72,255,220,0,255,0,82,255,220,0,255,0,88,255,220,0,255,0,92,255,68,0,255,0,130,0,47,0,255,0,131, + 0,47,0,255,0,132,0,47,0,255,0,133,0,47,0,255,0,134,0,47,0,255,0,148,255,183,0,255,0,149,255,183,0,255,0,150,255,183,0,255, + 0,151,255,183,0,255,0,152,255,183,0,255,0,155,255,154,0,255,0,156,255,154,0,255,0,157,255,154,0,255,0,158,255,154,0,255,0,159,254,240, + 0,255,0,170,255,220,0,255,0,171,255,220,0,255,0,172,255,220,0,255,0,173,255,220,0,255,0,180,255,220,0,255,0,181,255,220,0,255,0,182, + 255,220,0,255,0,183,255,220,0,255,0,184,255,220,0,255,0,187,255,220,0,255,0,188,255,220,0,255,0,189,255,220,0,255,0,190,255,220,0,255, + 0,191,255,68,0,255,0,193,255,68,0,255,0,221,255,220,0,255,1,38,254,230,0,255,1,48,255,154,0,255,1,49,255,220,0,255,1,58,254,240, + 0,255,10,250,254,97,0,255,10,251,253,230,1,2,0,79,255,63,1,10,10,250,255,107,1,10,10,251,255,144,1,10,10,252,255,164,1,22,0,16, + 255,173,1,22,0,17,255,183,1,22,0,29,255,193,1,22,0,36,255,173,1,22,0,38,255,154,1,22,0,55,255,107,1,22,0,57,255,144,1,22, + 0,58,255,173,1,22,0,60,255,125,1,22,0,68,255,211,1,22,0,72,255,164,1,22,0,82,255,164,1,22,0,88,255,164,1,22,0,92,255,144, + 1,22,0,109,255,144,1,22,0,125,255,220,1,22,0,130,255,173,1,22,0,131,255,173,1,22,0,132,255,173,1,22,0,133,255,173,1,22,0,134, + 255,173,1,22,0,137,255,154,1,22,0,159,255,125,1,22,0,162,255,211,1,22,0,163,255,211,1,22,0,164,255,211,1,22,0,165,255,211,1,22, + 0,166,255,211,1,22,0,167,255,211,1,22,0,170,255,164,1,22,0,171,255,164,1,22,0,172,255,164,1,22,0,173,255,164,1,22,0,180,255,164, + 1,22,0,181,255,164,1,22,0,182,255,164,1,22,0,183,255,164,1,22,0,184,255,164,1,22,0,187,255,164,1,22,0,188,255,164,1,22,0,189, + 255,164,1,22,0,190,255,164,1,22,0,191,255,144,1,22,0,193,255,144,1,22,0,200,255,154,1,22,0,206,255,154,1,22,0,221,255,164,1,22, + 1,38,255,107,1,22,1,49,255,164,1,22,1,58,255,125,1,22,10,250,255,107,1,22,10,251,255,125,1,22,10,252,255,220,1,23,0,16,255,125, + 1,23,0,17,255,68,1,23,0,29,255,220,1,23,0,70,255,211,1,23,0,71,255,220,1,23,0,72,255,211,1,23,0,74,255,220,1,23,0,75, + 255,220,1,23,0,80,255,220,1,23,0,81,255,220,1,23,0,82,255,211,1,23,0,84,255,220,1,23,0,85,255,220,1,23,0,91,255,201,1,23, + 0,109,255,183,1,23,0,169,255,211,1,23,0,170,255,211,1,23,0,171,255,211,1,23,0,172,255,211,1,23,0,173,255,211,1,23,0,179,255,220, + 1,23,0,180,255,211,1,23,0,181,255,211,1,23,0,182,255,211,1,23,0,183,255,211,1,23,0,184,255,211,1,23,0,201,255,211,1,23,0,207, + 255,211,1,23,0,209,0,72,1,23,0,221,255,211,1,23,0,225,255,220,1,23,1,10,255,220,1,23,1,23,255,220,1,23,1,27,255,220,1,23, + 10,251,0,86,1,23,10,252,254,201,1,26,0,16,255,173,1,26,0,17,255,183,1,26,0,29,255,193,1,26,0,36,255,173,1,26,0,38,255,154, + 1,26,0,55,255,107,1,26,0,57,255,144,1,26,0,58,255,173,1,26,0,60,255,125,1,26,0,68,255,211,1,26,0,72,255,164,1,26,0,82, + 255,164,1,26,0,88,255,164,1,26,0,92,255,144,1,26,0,109,255,144,1,26,0,125,255,220,1,26,0,130,255,173,1,26,0,131,255,173,1,26, + 0,132,255,173,1,26,0,133,255,173,1,26,0,134,255,173,1,26,0,137,255,154,1,26,0,159,255,125,1,26,0,162,255,211,1,26,0,163,255,211, + 1,26,0,164,255,211,1,26,0,165,255,211,1,26,0,166,255,211,1,26,0,167,255,211,1,26,0,170,255,164,1,26,0,171,255,164,1,26,0,172, + 255,164,1,26,0,173,255,164,1,26,0,180,255,164,1,26,0,181,255,164,1,26,0,182,255,164,1,26,0,183,255,164,1,26,0,184,255,164,1,26, + 0,187,255,164,1,26,0,188,255,164,1,26,0,189,255,164,1,26,0,190,255,164,1,26,0,191,255,144,1,26,0,193,255,144,1,26,0,200,255,154, + 1,26,0,206,255,154,1,26,0,221,255,164,1,26,1,38,255,107,1,26,1,49,255,164,1,26,1,58,255,125,1,26,10,250,255,107,1,26,10,251, + 255,125,1,26,10,252,255,220,1,27,0,16,255,125,1,27,0,17,255,68,1,27,0,29,255,220,1,27,0,70,255,211,1,27,0,71,255,220,1,27, + 0,72,255,211,1,27,0,74,255,220,1,27,0,75,255,220,1,27,0,80,255,220,1,27,0,81,255,220,1,27,0,82,255,211,1,27,0,84,255,220, + 1,27,0,85,255,220,1,27,0,91,255,201,1,27,0,109,255,183,1,27,0,169,255,211,1,27,0,170,255,211,1,27,0,171,255,211,1,27,0,172, + 255,211,1,27,0,173,255,211,1,27,0,179,255,220,1,27,0,180,255,211,1,27,0,181,255,211,1,27,0,182,255,211,1,27,0,183,255,211,1,27, + 0,184,255,211,1,27,0,201,255,211,1,27,0,207,255,211,1,27,0,209,255,220,1,27,0,221,255,211,1,27,0,225,255,220,1,27,1,10,255,220, + 1,27,1,23,255,220,1,27,1,27,255,220,1,27,10,251,0,86,1,27,10,252,254,201,1,32,0,36,0,38,1,32,0,130,0,38,1,32,0,131, + 0,38,1,32,0,132,0,38,1,32,0,133,0,38,1,32,0,134,0,38,1,34,0,36,0,38,1,34,0,130,0,38,1,34,0,131,0,38,1,34, + 0,132,0,38,1,34,0,133,0,38,1,34,0,134,0,38,1,38,0,16,255,68,1,38,0,17,255,13,1,38,0,29,255,31,1,38,0,36,255,97, + 1,38,0,38,255,136,1,38,0,55,255,220,1,38,0,68,254,173,1,38,0,70,254,164,1,38,0,72,254,164,1,38,0,76,255,193,1,38,0,82, + 254,164,1,38,0,85,254,211,1,38,0,86,254,173,1,38,0,88,254,201,1,38,0,90,254,173,1,38,0,92,254,193,1,38,0,109,255,68,1,38, + 0,125,255,144,1,38,0,130,255,97,1,38,0,131,255,97,1,38,0,132,255,97,1,38,0,133,255,97,1,38,0,134,255,97,1,38,0,137,255,136, + 1,38,0,162,254,173,1,38,0,163,254,173,1,38,0,164,254,173,1,38,0,165,254,173,1,38,0,166,254,173,1,38,0,167,254,173,1,38,0,169, + 254,164,1,38,0,170,254,164,1,38,0,171,254,164,1,38,0,172,254,164,1,38,0,173,254,164,1,38,0,180,254,164,1,38,0,181,254,164,1,38, + 0,182,254,164,1,38,0,183,254,164,1,38,0,184,254,164,1,38,0,187,254,201,1,38,0,188,254,201,1,38,0,189,254,201,1,38,0,190,254,201, + 1,38,0,191,254,193,1,38,0,193,254,193,1,38,0,200,255,136,1,38,0,201,254,164,1,38,0,206,255,136,1,38,0,207,254,164,1,38,0,221, + 254,164,1,38,1,23,254,211,1,38,1,27,254,211,1,38,1,33,254,173,1,38,1,35,254,173,1,38,1,38,255,220,1,38,1,49,254,201,1,38, + 10,251,255,211,1,38,10,252,254,248,1,48,0,61,255,220,1,48,1,63,255,220,1,58,0,16,255,13,1,58,0,17,254,97,1,58,0,29,254,240, + 1,58,0,36,255,97,1,58,0,38,255,144,1,58,0,50,255,144,1,58,0,68,254,230,1,58,0,72,254,240,1,58,0,76,255,183,1,58,0,82, + 254,240,1,58,0,88,255,21,1,58,0,109,255,31,1,58,0,125,255,107,1,58,0,130,255,97,1,58,0,131,255,97,1,58,0,132,255,97,1,58, + 0,133,255,97,1,58,0,134,255,97,1,58,0,137,255,144,1,58,0,148,255,144,1,58,0,149,255,144,1,58,0,150,255,144,1,58,0,151,255,144, + 1,58,0,152,255,144,1,58,0,162,254,230,1,58,0,163,254,230,1,58,0,164,254,230,1,58,0,165,254,230,1,58,0,166,254,230,1,58,0,167, + 254,230,1,58,0,170,254,240,1,58,0,171,254,240,1,58,0,172,254,240,1,58,0,173,254,240,1,58,0,180,254,240,1,58,0,181,254,240,1,58, + 0,182,254,240,1,58,0,183,254,240,1,58,0,184,254,240,1,58,0,187,255,21,1,58,0,188,255,21,1,58,0,189,255,21,1,58,0,190,255,21, + 1,58,0,200,255,144,1,58,0,206,255,144,1,58,0,221,254,240,1,58,1,49,255,21,1,58,10,250,255,144,1,58,10,251,255,220,1,58,10,252, + 254,248,1,63,0,16,255,220,1,63,10,250,255,220,1,63,10,251,255,220,1,63,10,252,255,220,10,238,0,36,255,211,10,238,0,37,255,183,10,238, + 0,42,0,75,10,238,0,45,0,114,10,238,0,50,0,57,10,238,0,52,0,75,10,238,0,55,255,68,10,238,0,57,255,136,10,238,0,58,255,173, + 10,238,0,59,255,154,10,238,0,60,255,13,10,238,0,82,0,38,10,238,0,89,255,201,10,238,0,92,255,220,10,238,0,130,255,211,10,238,0,131, + 255,211,10,238,0,132,255,211,10,238,0,133,255,211,10,238,0,134,255,211,10,238,0,148,0,57,10,238,0,149,0,57,10,238,0,150,0,57,10,238, + 0,151,0,57,10,238,0,152,0,57,10,238,0,159,255,13,10,238,0,180,0,38,10,238,0,181,0,38,10,238,0,182,0,38,10,238,0,183,0,38, + 10,238,0,184,0,38,10,238,0,191,255,220,10,238,0,193,255,220,10,238,0,224,0,75,10,238,1,38,255,68,10,238,1,58,255,13,10,250,0,36, + 254,248,10,250,0,37,255,193,10,250,0,38,255,183,10,250,0,39,255,193,10,250,0,41,255,193,10,250,0,42,255,183,10,250,0,43,255,193,10,250, + 0,45,255,193,10,250,0,46,255,193,10,250,0,47,255,193,10,250,0,50,255,183,10,250,0,51,255,193,10,250,0,52,255,183,10,250,0,53,255,193, + 10,250,0,59,255,136,10,250,0,61,255,220,10,250,0,73,255,183,10,250,0,81,255,144,10,250,0,82,255,107,10,250,0,85,255,144,10,250,0,89, + 255,183,10,250,0,90,255,183,10,250,0,92,255,183,10,250,0,130,254,248,10,250,0,131,254,248,10,250,0,132,254,248,10,250,0,133,254,248,10,250, + 0,134,254,248,10,250,0,136,254,125,10,250,0,137,255,183,10,250,0,148,255,183,10,250,0,149,255,183,10,250,0,150,255,183,10,250,0,151,255,183, + 10,250,0,152,255,183,10,250,0,160,255,193,10,250,0,161,255,193,10,250,0,178,255,183,10,250,0,179,255,144,10,250,0,180,255,107,10,250,0,181, + 255,107,10,250,0,182,255,107,10,250,0,183,255,107,10,250,0,184,255,107,10,250,0,191,255,183,10,250,0,193,255,183,10,250,0,200,255,183,10,250, + 0,206,255,183,10,250,0,208,255,193,10,250,0,224,255,183,10,250,0,251,255,193,10,250,0,255,255,193,10,250,1,10,255,144,10,250,1,22,255,193, + 10,250,1,23,255,144,10,250,1,26,255,193,10,250,1,27,255,144,10,250,1,63,255,220,10,250,19,20,255,193,10,252,0,36,0,38,10,252,0,37, + 255,183,10,252,0,38,255,144,10,252,0,39,255,183,10,252,0,41,255,183,10,252,0,42,255,183,10,252,0,43,255,183,10,252,0,45,0,47,10,252, + 0,46,255,183,10,252,0,47,255,183,10,252,0,50,255,144,10,252,0,51,255,183,10,252,0,52,255,144,10,252,0,53,255,183,10,252,0,55,254,230, + 10,252,0,57,254,136,10,252,0,58,255,3,10,252,0,59,255,183,10,252,0,60,254,136,10,252,0,73,255,220,10,252,0,81,255,183,10,252,0,82, + 255,183,10,252,0,85,255,183,10,252,0,89,255,21,10,252,0,90,255,60,10,252,0,92,255,144,10,252,0,130,0,38,10,252,0,131,0,38,10,252, + 0,132,0,38,10,252,0,133,0,38,10,252,0,134,0,38,10,252,0,136,0,38,10,252,0,137,255,144,10,252,0,148,255,144,10,252,0,149,255,144, + 10,252,0,150,255,144,10,252,0,151,255,144,10,252,0,152,255,144,10,252,0,159,254,136,10,252,0,160,255,183,10,252,0,161,255,183,10,252,0,178, + 255,183,10,252,0,179,255,183,10,252,0,180,255,183,10,252,0,181,255,183,10,252,0,182,255,183,10,252,0,183,255,183,10,252,0,184,255,183,10,252, + 0,191,255,144,10,252,0,193,255,144,10,252,0,200,255,144,10,252,0,206,255,144,10,252,0,208,255,183,10,252,0,224,255,183,10,252,0,251,255,183, + 10,252,0,255,255,183,10,252,1,10,255,183,10,252,1,22,255,183,10,252,1,23,255,183,10,252,1,26,255,183,10,252,1,27,255,183,10,252,1,38, + 254,230,10,252,1,58,254,136,10,252,19,20,255,183,18,252,0,16,255,68,18,252,0,17,255,13,18,252,0,29,255,31,18,252,0,36,255,97,18,252, + 0,38,255,136,18,252,0,55,255,220,18,252,0,68,254,173,18,252,0,70,254,164,18,252,0,72,254,164,18,252,0,76,255,193,18,252,0,82,254,164, + 18,252,0,85,254,211,18,252,0,86,254,173,18,252,0,88,254,201,18,252,0,90,254,173,18,252,0,92,254,193,18,252,0,109,255,68,18,252,0,125, + 255,144,18,252,0,130,255,97,18,252,0,131,255,97,18,252,0,132,255,97,18,252,0,133,255,97,18,252,0,134,255,97,18,252,0,137,255,136,18,252, + 0,162,255,17,18,252,0,163,254,173,18,252,0,164,255,17,18,252,0,165,255,17,18,252,0,166,255,17,18,252,0,167,255,17,18,252,0,169,254,164, + 18,252,0,170,254,224,18,252,0,171,254,164,18,252,0,172,254,224,18,252,0,173,254,224,18,252,0,180,254,244,18,252,0,181,254,164,18,252,0,182, + 254,244,18,252,0,183,254,244,18,252,0,184,254,244,18,252,0,187,254,231,18,252,0,188,254,201,18,252,0,189,254,231,18,252,0,190,254,231,18,252, + 0,191,254,193,18,252,0,193,254,193,18,252,0,200,255,136,18,252,0,201,254,164,18,252,0,206,255,136,18,252,0,207,254,164,18,252,0,221,254,164, + 18,252,1,23,254,211,18,252,1,27,254,211,18,252,1,33,254,173,18,252,1,35,254,173,18,252,1,38,255,220,18,252,1,49,254,201,18,252,10,251, + 255,211,18,252,10,252,254,248,19,20,0,16,255,41,19,20,0,36,255,220,19,20,0,38,255,144,19,20,0,50,255,144,19,20,0,55,255,97,19,20, + 0,56,255,201,19,20,0,58,255,183,19,20,0,60,255,183,19,20,0,68,255,220,19,20,0,72,255,154,19,20,0,82,255,154,19,20,0,88,255,154, + 19,20,0,92,255,107,19,20,0,109,255,125,19,20,0,130,255,220,19,20,0,131,255,220,19,20,0,132,255,220,19,20,0,133,255,220,19,20,0,134, + 255,220,19,20,0,137,255,144,19,20,0,148,255,144,19,20,0,149,255,144,19,20,0,150,255,144,19,20,0,151,255,144,19,20,0,152,255,144,19,20, + 0,155,255,201,19,20,0,156,255,201,19,20,0,157,255,201,19,20,0,158,255,201,19,20,0,159,255,183,19,20,0,162,255,220,19,20,0,163,255,220, + 19,20,0,164,255,220,19,20,0,165,255,220,19,20,0,166,255,220,19,20,0,167,255,220,19,20,0,170,255,154,19,20,0,171,255,154,19,20,0,172, + 255,154,19,20,0,173,255,154,19,20,0,180,255,154,19,20,0,181,255,154,19,20,0,182,255,154,19,20,0,183,255,154,19,20,0,184,255,154,19,20, + 0,187,255,154,19,20,0,188,255,154,19,20,0,189,255,154,19,20,0,190,255,154,19,20,0,191,255,107,19,20,0,193,255,107,19,20,0,200,255,144, + 19,20,0,206,255,144,19,20,0,221,255,154,19,20,1,38,255,97,19,20,1,48,255,201,19,20,1,49,255,154,19,20,1,58,255,183,19,20,10,250, + 255,193,19,20,10,251,255,193,19,21,0,68,255,220,19,21,0,72,255,183,19,21,0,82,255,183,19,21,0,88,255,193,19,21,0,92,255,183,19,21, + 0,162,255,220,19,21,0,163,255,220,19,21,0,164,255,220,19,21,0,165,255,220,19,21,0,166,255,220,19,21,0,167,255,220,19,21,0,170,255,183, + 19,21,0,171,255,183,19,21,0,172,255,183,19,21,0,173,255,183,19,21,0,180,255,183,19,21,0,181,255,183,19,21,0,182,255,183,19,21,0,183, + 255,183,19,21,0,184,255,183,19,21,0,187,255,193,19,21,0,188,255,193,19,21,0,189,255,193,19,21,0,190,255,193,19,21,0,191,255,183,19,21, + 0,193,255,183,19,21,0,221,255,183,19,21,1,49,255,193,19,70,19,94,255,216,19,71,19,94,255,177,19,72,19,94,255,163,19,73,19,94,255,156, + 19,74,19,94,255,216,19,76,19,94,255,216,19,77,19,94,255,177,19,78,19,94,255,163,19,79,19,94,255,177,19,80,19,94,255,216,19,82,19,94, + 255,216,19,83,19,94,255,177,19,84,19,94,255,163,19,85,19,94,255,177,19,86,19,94,255,216,19,88,19,94,255,216,19,89,19,94,255,156,19,90, + 19,94,255,163,19,91,19,94,255,177,19,92,19,94,255,216,0,0,0,0,0,0,0,68,0,0,0,68,0,0,0,68,0,0,0,68,0,0,0,168, + 0,0,1,20,0,0,1,236,0,0,3,68,0,0,4,108,0,0,6,212,0,0,7,40,0,0,7,152,0,0,7,240,0,0,8,140,0,0,8,224, + 0,0,9,24,0,0,9,68,0,0,9,108,0,0,9,184,0,0,10,60,0,0,10,172,0,0,11,172,0,0,12,148,0,0,13,80,0,0,14,16, + 0,0,14,232,0,0,15,116,0,0,16,72,0,0,17,28,0,0,17,92,0,0,17,172,0,0,18,36,0,0,18,104,0,0,18,224,0,0,19,184, + 0,0,21,56,0,0,22,52,0,0,22,228,0,0,23,124,0,0,23,252,0,0,24,92,0,0,24,176,0,0,25,88,0,0,25,180,0,0,25,252, + 0,0,26,108,0,0,27,148,0,0,27,216,0,0,28,212,0,0,29,124,0,0,30,8,0,0,30,136,0,0,31,84,0,0,32,104,0,0,33,96, + 0,0,33,208,0,0,34,84,0,0,35,52,0,0,36,240,0,0,37,148,0,0,38,88,0,0,39,24,0,0,39,120,0,0,39,196,0,0,40,24, + 0,0,40,92,0,0,40,136,0,0,40,216,0,0,42,4,0,0,42,156,0,0,43,52,0,0,43,204,0,0,44,160,0,0,45,56,0,0,46,0, + 0,0,46,120,0,0,46,200,0,0,47,68,0,0,48,52,0,0,48,112,0,0,49,52,0,0,49,172,0,0,50,80,0,0,50,240,0,0,51,144, + 0,0,52,0,0,0,53,96,0,0,53,220,0,0,54,96,0,0,55,132,0,0,57,168,0,0,59,44,0,0,60,248,0,0,61,196,0,0,62,160, + 0,0,62,208,0,0,63,188,0,0,64,64,0,0,64,64,0,0,64,208,0,0,65,156,0,0,66,84,0,0,67,108,0,0,68,144,0,0,68,216, + 0,0,70,32,0,0,70,216,0,0,71,252,0,0,72,216,0,0,73,164,0,0,73,220,0,0,74,8,0,0,75,84,0,0,75,160,0,0,76,24, + 0,0,76,136,0,0,77,40,0,0,77,228,0,0,78,52,0,0,78,232,0,0,79,68,0,0,79,112,0,0,79,208,0,0,80,40,0,0,80,176, + 0,0,81,128,0,0,81,160,0,0,81,192,0,0,81,224,0,0,82,216,0,0,82,240,0,0,83,8,0,0,83,52,0,0,83,100,0,0,83,148, + 0,0,84,212,0,0,85,172,0,0,85,196,0,0,85,220,0,0,85,244,0,0,86,24,0,0,86,60,0,0,86,84,0,0,86,108,0,0,86,144, + 0,0,86,180,0,0,87,128,0,0,87,176,0,0,87,200,0,0,87,224,0,0,88,12,0,0,88,64,0,0,88,112,0,0,89,56,0,0,90,112, + 0,0,90,136,0,0,90,160,0,0,90,208,0,0,91,8,0,0,91,32,0,0,91,168,0,0,92,208,0,0,92,244,0,0,93,24,0,0,93,56, + 0,0,93,100,0,0,93,156,0,0,93,220,0,0,95,152,0,0,95,176,0,0,95,200,0,0,95,224,0,0,96,4,0,0,96,40,0,0,96,64, + 0,0,96,88,0,0,96,124,0,0,96,160,0,0,98,80,0,0,98,104,0,0,98,128,0,0,98,152,0,0,98,184,0,0,98,228,0,0,99,16, + 0,0,99,108,0,0,100,224,0,0,100,248,0,0,101,16,0,0,101,48,0,0,101,96,0,0,101,120,0,0,102,24,0,0,102,72,0,0,102,116, + 0,0,102,156,0,0,102,200,0,0,102,232,0,0,103,0,0,0,103,24,0,0,103,48,0,0,103,72,0,0,103,108,0,0,103,132,0,0,103,156, + 0,0,103,180,0,0,103,216,0,0,103,240,0,0,104,8,0,0,104,48,0,0,104,64,0,0,104,252,0,0,105,20,0,0,105,56,0,0,105,92, + 0,0,105,128,0,0,105,152,0,0,105,176,0,0,105,200,0,0,105,224,0,0,106,4,0,0,106,48,0,0,106,84,0,0,106,120,0,0,106,144, + 0,0,106,168,0,0,106,204,0,0,106,228,0,0,106,252,0,0,107,20,0,0,107,68,0,0,107,136,0,0,108,16,0,0,108,164,0,0,108,200, + 0,0,108,236,0,0,109,16,0,0,109,52,0,0,109,88,0,0,109,124,0,0,109,148,0,0,109,172,0,0,109,220,0,0,110,40,0,0,110,76, + 0,0,110,112,0,0,110,148,0,0,110,184,0,0,110,208,0,0,110,232,0,0,111,216,0,0,111,240,0,0,112,40,0,0,112,64,0,0,112,100, + 0,0,112,124,0,0,112,160,0,0,112,184,0,0,112,236,0,0,113,104,0,0,113,248,0,0,114,28,0,0,114,64,0,0,114,88,0,0,114,112, + 0,0,114,160,0,0,114,204,0,0,114,228,0,0,115,124,0,0,116,24,0,0,116,68,0,0,116,100,0,0,116,144,0,0,116,176,0,0,116,200, + 0,0,116,224,0,0,117,128,0,0,118,168,0,0,118,192,0,0,118,216,0,0,118,240,0,0,119,8,0,0,119,44,0,0,119,84,0,0,119,108, + 0,0,119,132,0,0,119,172,0,0,119,208,0,0,119,232,0,0,120,0,0,0,120,40,0,0,120,80,0,0,120,104,0,0,120,128,0,0,120,172, + 0,0,120,208,0,0,121,84,0,0,121,240,0,0,122,28,0,0,122,64,0,0,122,112,0,0,122,148,0,0,122,192,0,0,122,228,0,0,122,252, + 0,0,123,32,0,0,123,56,0,0,123,80,0,0,123,104,0,0,123,128,0,0,123,164,0,0,123,200,0,0,123,236,0,0,124,12,0,0,124,48, + 0,0,124,72,0,0,124,96,0,0,124,120,0,0,124,160,0,0,124,184,0,0,124,224,0,0,125,56,0,0,126,4,0,0,126,204,0,0,126,220, + 0,0,127,144,0,0,128,28,0,0,128,196,0,0,129,84,0,0,130,20,0,0,130,208,0,0,130,224,0,0,131,116,0,0,131,240,0,0,132,152, + 0,0,133,112,0,0,133,204,0,0,134,124,0,0,135,52,0,0,135,180,0,0,136,108,0,0,137,56,0,0,138,76,0,0,139,28,0,0,139,120, + 0,0,139,232,0,0,140,164,0,0,141,184,0,0,142,24,0,0,143,0,0,0,143,192,0,0,144,144,0,0,144,160,0,0,145,68,0,0,145,92, + 0,0,145,116,0,0,146,28,0,0,146,200,0,0,147,96,0,0,148,32,0,0,148,220,0,0,149,176,0,0,150,248,0,0,151,8,0,0,151,164, + 0,0,152,60,0,0,152,204,0,0,153,104,0,0,153,244,0,0,154,12,0,0,154,36,0,0,154,208,0,0,155,92,0,0,156,24,0,0,157,232, + 0,0,158,240,0,0,159,252,0,0,160,220,0,0,161,172,0,0,162,188,0,0,163,40,0,0,163,156,0,0,164,48,0,0,164,188,0,0,165,48, + 0,0,165,196,0,0,166,4,0,0,166,28,0,0,166,156,0,0,166,172,0,0,166,196,0,0,166,220,0,0,166,244,0,0,167,12,0,0,167,36, + 0,0,167,60,0,0,167,84,0,0,167,108,0,0,167,132,0,0,167,164,0,0,167,196,0,0,167,236,0,0,168,20,0,0,168,44,0,0,168,76, + 0,0,168,108,0,0,168,144,0,0,168,168,0,0,168,192,0,0,168,216,0,0,168,240,0,0,169,8,0,0,169,32,0,0,169,56,0,0,169,80, + 0,0,169,96,0,0,169,120,0,0,169,144,0,0,169,168,0,0,169,192,0,0,169,216,0,0,169,240,0,0,170,196,0,0,171,184,0,0,171,228, + 0,0,171,252,0,0,172,20,0,0,172,88,0,0,172,112,0,0,172,136,0,0,172,160,0,0,172,184,0,0,172,208,0,0,172,232,0,0,173,16, + 0,0,173,40,0,0,173,64,0,0,173,88,0,0,173,112,0,0,173,136,0,0,174,32,0,0,174,184,0,0,174,208,0,0,174,232,0,0,175,0, + 0,0,175,24,0,0,175,48,0,0,175,72,0,0,175,96,0,0,175,120,0,0,175,144,0,0,175,168,0,0,175,192,0,0,175,216,0,0,175,240, + 0,0,176,8,0,0,176,32,0,0,176,56,0,0,176,80,0,0,176,104,0,0,176,128,0,0,176,152,0,0,176,176,0,0,176,200,0,0,176,224, + 0,0,176,248,0,0,177,16,0,0,177,40,0,0,177,64,0,0,177,88,0,0,177,112,0,0,177,136,0,0,177,160,0,0,177,184,0,0,177,208, + 0,0,177,232,0,0,178,0,0,0,178,24,0,0,178,164,0,0,179,56,0,0,179,80,0,0,179,148,0,0,180,8,0,0,180,172,0,0,181,184, + 0,0,182,156,0,0,183,136,0,0,184,128,0,0,184,152,0,0,184,176,0,0,184,200,0,0,184,224,0,0,184,248,0,0,185,16,0,0,185,40, + 0,0,185,64,0,0,185,88,0,0,185,112,0,0,185,136,0,0,185,160,0,0,185,184,0,0,185,208,0,0,186,36,0,0,186,168,0,0,187,16, + 0,0,187,116,0,0,188,84,0,0,189,56,0,0,189,168,0,0,190,64,0,0,190,208,0,0,191,60,0,0,191,144,0,0,192,72,0,0,192,160, + 0,0,193,36,0,0,193,172,0,0,194,136,0,0,195,72,0,0,195,88,0,0,195,192,0,0,196,108,0,0,197,8,0,0,197,164,0,0,198,100, + 0,0,199,32,0,0,200,72,0,0,200,212,0,0,201,36,0,0,201,132,0,0,202,168,0,0,203,64,0,0,203,216,0,0,204,144,0,0,205,24, + 0,0,205,248,0,0,206,184,0,0,207,104,0,0,208,76,0,0,208,240,0,0,210,16,0,0,210,32,0,0,210,48,0,0,211,76,0,0,212,24, + 0,0,212,160,0,0,213,132,0,0,214,60,0,0,214,216,0,0,215,204,0,0,216,192,0,0,217,60,0,0,217,212,0,0,218,128,0,0,218,244, + 0,0,219,4,0,0,219,88,0,0,220,4,0,0,220,140,0,0,220,228,0,0,222,12,0,0,222,220,0,0,223,176,0,0,224,160,0,0,225,72, + 0,0,225,220,0,0,226,132,0,0,227,24,0,0,227,196,0,0,228,116,0,0,228,132,0,0,228,236,0,0,229,84,0,0,229,224,0,0,230,84, + 0,0,230,224,0,0,231,60,0,0,231,152,0,0,232,172,0,0,233,80,0,0,234,92,0,0,234,208,0,0,235,124,0,0,235,220,0,0,236,112, + 0,0,236,228,0,0,237,100,0,0,238,8,0,0,238,192,0,0,239,80,0,0,239,224,0,0,242,8,0,0,242,148,0,0,242,252,0,0,243,236, + 0,0,245,12,0,0,246,32,0,0,246,176,0,0,247,68,0,0,247,216,0,0,248,112,0,0,249,12,0,0,249,152,0,0,249,168,0,0,250,120, + 0,0,251,56,0,0,251,72,0,0,251,216,0,0,252,16,0,0,252,76,0,0,253,4,0,0,253,192,0,0,254,124,0,0,255,12,0,0,255,212, + 0,1,0,144,0,1,1,52,0,1,1,192,0,1,2,144,0,1,3,36,0,1,3,156,0,1,4,104,0,1,4,204,0,1,5,60,0,1,5,192, + 0,1,6,92,0,1,6,208,0,1,7,96,0,1,7,192,0,1,8,32,0,1,8,120,0,1,8,244,0,1,9,96,0,1,9,152,0,1,9,220, + 0,1,9,236,0,1,10,4,0,1,10,20,0,1,10,36,0,1,10,92,0,1,10,196,0,1,11,44,0,1,11,180,0,1,12,64,0,1,12,104, + 0,1,12,144,0,1,12,244,0,1,13,104,0,1,13,196,0,1,14,32,0,1,14,80,0,1,14,96,0,1,14,124,0,1,14,156,0,1,14,204, + 0,1,14,224,0,1,15,0,0,1,15,28,0,1,15,136,0,1,15,216,0,1,15,236,0,1,16,0,0,1,16,36,0,1,16,72,0,1,16,116, + 0,1,16,144,0,1,17,28,0,1,17,132,0,1,17,240,0,1,18,80,0,1,19,16,0,1,19,124,0,1,19,180,0,1,19,232,0,1,20,52, + 0,1,20,92,0,1,20,244,0,1,21,44,0,1,21,60,0,1,21,112,0,1,21,188,0,1,21,252,0,1,22,72,0,1,22,124,0,1,22,144, + 0,1,22,168,0,1,22,184,0,1,22,204,0,1,23,152,0,1,23,244,0,1,24,76,0,1,24,180,0,1,24,200,0,1,24,220,0,1,24,240, + 0,1,25,4,0,1,25,72,0,1,25,188,0,1,26,48,0,1,26,68,0,1,26,88,0,1,26,192,0,1,26,236,0,1,27,8,0,1,27,120, + 0,1,27,148,0,1,27,224,0,1,28,8,0,1,28,48,0,1,28,84,0,1,28,112,0,1,28,132,0,1,28,152,0,1,28,188,0,1,28,220, + 0,1,28,252,0,1,29,112,0,1,29,192,0,1,29,228,0,1,30,8,0,1,30,52,0,1,30,80,0,1,30,128,0,1,30,176,0,1,30,200, + 0,1,30,220,0,1,31,72,0,1,31,108,0,1,31,128,0,1,31,148,0,1,31,188,0,1,31,224,0,1,32,40,0,1,32,100,0,1,32,160, + 0,1,32,180,0,1,32,232,0,1,32,252,0,1,33,16,0,1,33,36,0,1,33,56,0,1,33,148,0,1,33,176,0,1,33,204,0,1,33,236, + 0,1,34,12,0,1,34,88,0,1,34,124,0,1,34,164,0,1,34,236,0,1,35,32,0,1,35,128,0,1,35,156,0,1,35,176,0,1,35,196, + 0,1,35,216,0,1,35,232,0,1,35,252,0,1,36,16,0,1,36,52,0,1,36,92,0,1,36,132,0,1,36,164,0,1,37,32,0,1,37,148, + 0,1,37,172,0,1,37,228,0,1,38,12,0,1,38,12,0,1,38,76,0,1,38,100,0,1,38,120,0,1,38,184,0,1,38,204,0,1,39,48, + 0,1,39,68,0,1,39,88,0,1,39,116,0,1,39,144,0,1,40,4,0,1,40,24,0,1,40,64,0,1,40,80,0,1,40,96,0,1,40,144, + 0,1,40,192,0,1,40,240,0,1,41,32,0,1,41,48,0,1,41,64,0,1,41,116,0,1,41,132,0,1,41,156,0,1,41,180,0,1,41,196, + 0,1,42,20,0,1,42,68,0,1,42,92,0,1,42,108,0,1,42,136,0,1,42,164,0,1,42,192,0,1,42,216,0,1,42,244,0,1,43,12, + 0,1,43,36,0,1,43,52,0,1,43,68,0,1,43,124,0,1,43,232,0,1,43,248,0,1,44,8,0,1,44,24,0,1,44,200,0,1,44,216, + 0,1,44,232,0,1,45,76,0,1,45,92,0,1,45,108,0,1,45,204,0,1,45,220,0,1,45,236,0,1,45,252,0,1,46,120,0,1,46,136, + 0,1,46,152,0,1,47,88,0,1,47,104,0,1,47,252,0,1,48,172,0,1,48,208,0,1,48,244,0,1,49,12,0,1,49,36,0,1,49,60, + 0,1,49,84,0,1,49,108,0,1,50,188,0,1,51,88,0,1,51,216,0,1,52,188,0,1,53,140,0,1,54,48,0,1,54,172,0,1,55,116, + 0,1,55,196,0,1,56,68,0,1,56,200,0,1,56,216,0,1,57,104,0,1,58,36,0,1,58,52,0,1,58,176,0,1,59,68,0,1,59,240, + 0,1,60,132,0,1,60,228,0,1,61,112,0,1,62,48,0,1,63,60,0,1,63,208,0,1,64,100,0,1,64,124,0,1,64,148,0,1,64,172, + 0,1,64,196,0,1,64,220,0,1,65,28,0,1,65,236,0,1,66,148,0,1,67,76,0,1,67,104,0,1,67,128,0,1,68,72,0,1,68,248, + 0,1,69,164,0,1,70,92,0,1,71,8,0,1,71,172,0,1,72,72,0,1,72,88,0,1,73,8,0,1,73,100,0,1,73,212,0,1,74,76, + 0,1,74,168,0,1,75,192,0,1,76,152,0,1,77,44,0,1,77,184,0,1,78,108,0,1,79,84,0,1,79,204,0,1,80,60,0,1,80,240, + 0,1,81,160,0,1,82,52,0,1,82,204,0,1,83,60,0,1,83,168,0,1,84,68,0,1,84,252,0,1,85,12,0,1,85,28,0,1,85,44, + 0,1,85,156,0,1,86,8,0,1,86,24,0,1,86,40,0,1,86,56,0,1,87,8,0,1,87,148,0,1,88,20,0,1,88,36,0,1,88,60, + 0,1,88,84,0,1,88,108,0,1,89,12,0,1,89,152,0,1,89,176,0,1,90,92,0,1,90,108,0,1,90,124,0,1,90,140,0,1,90,156, + 0,1,91,52,0,1,91,196,0,1,92,52,0,1,92,76,0,1,92,100,0,1,92,124,0,1,92,212,0,1,92,228,0,1,93,100,0,1,93,116, + 0,1,93,172,0,1,94,56,0,1,94,72,0,1,95,60,0,1,95,244,0,1,96,160,0,1,96,224,0,1,97,116,0,1,97,212,0,1,97,228, + 0,1,97,244,0,1,98,4,0,1,98,76,0,1,98,92,0,1,98,108,0,1,98,124,0,1,99,0,0,1,99,180,0,1,99,196,0,1,100,28, + 0,1,100,120,0,1,100,212,0,1,101,64,0,1,101,192,0,1,101,216,0,1,102,76,0,1,102,248,0,1,103,184,0,1,104,84,0,1,104,100, + 0,1,105,44,0,1,105,200,0,1,106,0,0,1,106,136,0,1,106,152,0,1,107,136,0,1,108,76,0,1,108,188,0,1,108,252,0,1,109,140, + 0,1,109,236,0,1,110,116,0,1,110,204,0,1,110,220,0,1,111,36,0,1,111,52,0,1,111,68,0,1,111,136,0,1,111,152,0,1,112,128, + 0,1,112,144,0,1,112,232,0,1,113,100,0,1,113,192,0,1,114,44,0,1,114,168,0,1,114,192,0,1,115,48,0,1,115,212,0,1,116,120, + 0,1,117,8,0,1,117,32,0,1,117,192,0,1,118,100,0,1,118,124,0,1,119,32,0,1,119,48,0,1,119,64,0,1,119,80,0,1,119,96, + 0,1,119,252,0,1,120,144,0,1,121,32,0,1,121,56,0,1,121,80,0,1,121,104,0,1,121,192,0,1,122,152,0,1,122,168,0,1,123,72, + 0,1,123,220,0,1,124,108,0,1,124,220,0,1,125,32,0,1,125,96,0,1,125,188,0,1,126,20,0,1,126,252,0,1,127,224,0,1,128,92, + 0,1,128,212,0,1,129,192,0,1,130,156,0,1,131,0,0,1,131,100,0,1,131,116,0,1,131,132,0,1,131,208,0,1,132,32,0,1,132,56, + 0,1,132,80,0,1,132,244,0,1,133,120,0,1,134,112,0,1,135,92,0,1,135,124,0,1,135,156,0,1,135,180,0,1,135,204,0,1,136,104, + 0,1,137,0,0,1,137,76,0,1,137,228,0,1,138,24,0,1,138,64,0,1,138,104,0,1,138,168,0,1,139,236,0,1,140,168,0,1,140,192, + 0,1,140,216,0,1,141,116,0,1,142,20,0,1,142,116,0,1,142,252,0,1,143,60,0,1,143,128,0,1,143,224,0,1,144,64,0,1,144,204, + 0,1,145,92,0,1,145,192,0,1,146,32,0,1,146,56,0,1,146,80,0,1,146,148,0,1,146,216,0,1,147,36,0,1,147,108,0,1,147,184, + 0,1,148,4,0,1,148,164,0,1,149,68,0,1,149,180,0,1,150,32,0,1,150,132,0,1,150,228,0,1,151,124,0,1,152,20,0,1,153,8, + 0,1,153,228,0,1,153,252,0,1,154,20,0,1,154,112,0,1,154,200,0,1,154,216,0,1,155,116,0,1,155,188,0,1,156,0,0,1,156,72, + 0,1,156,144,0,1,157,0,0,1,157,112,0,1,157,228,0,1,158,112,0,1,158,192,0,1,159,12,0,1,159,108,0,1,159,124,0,1,160,88, + 0,1,161,84,0,1,161,240,0,1,162,136,0,1,162,152,0,1,162,176,0,1,162,200,0,1,163,36,0,1,163,136,0,1,163,212,0,1,164,32, + 0,1,164,152,0,1,165,16,0,1,165,76,0,1,165,136,0,1,166,0,0,1,166,144,0,1,166,220,0,1,167,40,0,1,167,56,0,1,167,100, + 0,1,167,132,0,1,167,180,0,1,167,236,0,1,167,252,0,1,168,12,0,1,168,48,0,1,168,84,0,1,168,100,0,1,168,116,0,1,168,140, + 0,1,168,164,0,1,168,188,0,1,168,212,0,1,168,236,0,1,169,4,0,1,169,20,0,1,169,36,0,1,169,60,0,1,169,84,0,1,169,108, + 0,1,169,132,0,1,169,180,0,1,169,224,0,1,169,240,0,1,170,0,0,1,170,24,0,1,170,48,0,1,170,72,0,1,170,96,0,1,170,120, + 0,1,170,144,0,1,170,168,0,1,170,192,0,1,170,216,0,1,170,240,0,1,171,8,0,1,171,32,0,1,171,108,0,1,171,184,0,1,171,208, + 0,1,171,232,0,1,172,116,0,1,173,0,0,1,173,96,0,1,173,192,0,1,174,16,0,1,174,96,0,1,174,216,0,1,175,84,0,1,176,36, + 0,1,176,240,0,1,177,208,0,1,178,180,0,1,179,104,0,1,180,36,0,1,180,200,0,1,181,104,0,1,181,120,0,1,182,12,0,1,182,156, + 0,1,183,36,0,1,183,168,0,1,184,48,0,1,184,64,0,1,184,80,0,1,184,208,0,1,185,80,0,1,185,180,0,1,186,28,0,1,186,124, + 0,1,186,244,0,1,187,96,0,1,187,248,0,1,188,8,0,1,188,24,0,1,188,40,0,1,188,56,0,1,188,140,0,1,188,216,0,1,189,132, + 0,1,190,52,0,1,190,220,0,1,191,136,0,1,191,184,0,1,191,232,0,1,192,96,0,1,192,184,0,1,193,40,0,1,193,124,0,1,193,212, + 0,1,194,76,0,1,194,120,0,1,194,200,0,1,195,108,0,1,195,216,0,1,196,36,0,1,196,72,0,1,196,168,0,1,197,92,0,1,197,168, + 0,1,198,4,0,1,198,196,0,1,199,20,0,1,199,148,0,1,199,232,0,1,200,132,0,1,200,216,0,1,201,96,0,1,201,172,0,1,202,28, + 0,1,202,120,0,1,203,36,0,1,203,124,0,1,203,140,0,1,203,224,0,1,204,140,0,1,204,216,0,1,205,144,0,1,205,184,0,1,206,56, + 0,1,206,192,0,1,206,208,0,1,207,112,0,1,207,168,0,1,207,204,0,1,207,232,0,1,208,48,0,1,208,68,0,1,208,188,0,1,208,220, + 0,1,209,88,0,1,209,164,0,1,210,32,0,1,210,104,0,1,210,188,0,1,211,68,0,1,211,112,0,1,211,180,0,1,212,92,0,1,212,208, + 0,1,213,20,0,1,213,52,0,1,213,176,0,1,214,60,0,1,214,128,0,1,214,144,0,1,215,84,0,1,215,156,0,1,216,76,0,1,216,152, + 0,1,216,196,0,1,217,16,0,1,217,152,0,1,217,168,0,1,218,56,0,1,218,180,0,1,219,112,0,1,219,220,0,1,219,236,0,1,220,56, + 0,1,220,172,0,1,220,244,0,1,221,4,0,1,221,36,0,1,221,156,0,1,222,32,0,1,222,48,0,1,222,216,0,1,223,36,0,1,223,72, + 0,1,223,112,0,1,223,176,0,1,223,224,0,1,224,52,0,1,224,152,0,1,224,192,0,1,224,232,0,1,225,104,0,1,225,148,0,1,225,208, + 0,1,225,248,0,1,226,8,0,1,226,104,0,1,226,148,0,1,226,192,0,1,226,220,0,1,227,8,0,1,227,64,0,1,227,108,0,1,227,148, + 0,1,227,220,0,1,228,44,0,1,228,104,0,1,229,80,0,1,229,204,0,1,230,108,0,1,230,188,0,1,231,56,0,1,231,116,0,1,231,236, + 0,1,232,92,0,1,233,28,0,1,233,92,0,1,233,208,0,1,234,88,0,1,234,188,0,1,235,48,0,1,236,12,0,1,236,76,0,1,236,176, + 0,1,237,96,0,1,237,248,0,1,238,164,0,1,239,108,0,1,240,4,0,1,240,200,0,1,241,84,0,1,241,212,0,1,242,236,0,1,243,148, + 0,1,243,172,0,1,243,196,0,1,243,220,0,1,244,12,0,1,244,84,0,1,244,244,0,1,245,164,0,1,245,228,0,1,246,48,0,1,246,80, + 0,1,246,172,0,1,246,220,0,1,247,76,0,1,247,188,0,1,247,212,0,1,247,236,0,1,248,4,0,1,248,28,0,1,248,52,0,1,248,80, + 0,1,248,104,0,1,248,128,0,1,248,152,0,1,248,176,0,1,248,200,0,1,249,48,0,1,249,72,0,1,249,156,0,1,249,180,0,1,249,248, + 0,1,250,16,0,1,250,208,0,1,250,232,0,1,251,172,0,1,251,196,0,1,252,48,0,1,252,72,0,1,252,200,0,1,252,224,0,1,252,248, + 0,1,253,16,0,1,253,40,0,1,253,228,0,1,254,68,0,1,254,208,0,1,254,232,0,1,255,80,0,1,255,208,0,2,0,124,0,2,0,148, + 0,2,0,192,0,2,1,96,0,2,1,136,0,2,1,164,0,2,2,48,0,2,2,76,0,2,2,200,0,2,3,12,0,2,3,84,0,2,3,104, + 0,2,3,124,0,2,4,8,0,2,4,48,0,2,4,76,0,2,4,124,0,2,4,212,0,2,5,80,0,2,5,212,0,2,6,60,0,2,6,132, + 0,2,6,212,0,2,7,36,0,2,7,156,0,2,7,208,0,2,8,16,0,2,8,52,0,2,8,104,0,2,8,204,0,2,9,124,0,2,9,152, + 0,2,9,236,0,2,10,4,0,2,10,28,0,2,10,52,0,2,10,84,0,2,10,108,0,2,10,132,0,2,10,156,0,2,10,180,0,2,10,204, + 0,2,10,228,0,2,10,252,0,2,11,20,0,2,11,44,0,2,11,68,0,2,11,92,0,2,11,116,0,2,11,140,0,2,11,164,0,2,11,196, + 0,2,11,220,0,2,11,244,0,2,12,12,0,2,12,36,0,2,12,60,0,2,12,84,0,2,12,108,0,2,12,132,0,2,12,156,0,2,12,180, + 0,2,12,212,0,2,12,236,0,2,13,4,0,2,13,28,0,2,13,60,0,2,13,84,0,2,13,116,0,2,13,140,0,2,13,164,0,2,13,188, + 0,2,13,212,0,2,14,144,0,2,14,168,0,2,14,200,0,2,14,224,0,2,14,248,0,2,15,16,0,2,15,40,0,2,15,64,0,2,15,212, + 0,2,16,108,0,2,16,132,0,2,16,156,0,2,16,180,0,2,16,204,0,2,16,228,0,2,16,252,0,2,17,20,0,2,17,44,0,2,17,68, + 0,2,17,92,0,2,17,116,0,2,17,140,0,2,17,164,0,2,17,188,0,2,17,220,0,2,18,60,0,2,18,84,0,2,18,116,0,2,18,140, + 0,2,19,76,0,2,19,108,0,2,19,132,0,2,19,148,0,2,19,172,0,2,19,188,0,2,19,204,0,2,19,220,0,2,19,236,0,2,19,252, + 0,2,20,124,0,2,20,252,0,2,21,96,0,2,21,112,0,2,21,128,0,2,21,144,0,2,22,20,0,2,22,108,0,2,22,184,0,2,23,0, + 0,2,23,76,0,2,23,144,0,2,23,208,0,2,24,32,0,2,24,124,0,2,25,24,0,2,25,72,0,2,25,196,0,2,26,28,0,2,26,68, + 0,2,26,136,0,2,26,208,0,2,27,128,0,2,27,220,0,2,28,108,0,2,28,192,0,2,29,20,0,2,29,140,0,2,30,12,0,2,30,104, + 0,2,31,4,0,2,31,92,0,2,31,220,0,2,32,40,0,2,32,148,0,2,33,48,0,2,33,136,0,2,34,20,0,2,34,88,0,2,34,196, + 0,2,35,68,0,2,35,140,0,2,35,220,0,2,36,64,0,2,36,248,0,2,37,128,0,2,37,172,0,2,37,244,0,2,38,28,0,2,38,120, + 0,2,38,228,0,2,39,44,0,2,39,148,0,2,39,188,0,2,39,252,0,2,40,64,0,2,40,128,0,2,40,196,0,2,41,32,0,2,41,76, + 0,2,41,236,0,2,42,176,0,2,43,128,0,2,44,40,0,2,44,208,0,2,45,132,0,2,46,96,0,2,47,44,0,2,47,184,0,2,48,124, + 0,2,49,64,0,2,50,0,0,2,50,168,0,2,51,68,0,2,51,224,0,2,52,176,0,2,53,96,0,2,54,36,0,2,54,232,0,2,55,92, + 0,2,56,40,0,2,56,232,0,2,57,200,0,2,58,112,0,2,59,56,0,2,59,244,0,2,60,176,0,2,61,144,0,2,62,24,0,2,62,52, + 0,2,62,196,0,2,63,64,0,2,63,88,0,2,63,188,0,2,64,44,0,2,64,164,0,2,65,40,0,2,65,112,0,2,65,236,0,2,66,80, + 0,2,66,200,0,2,67,100,0,2,67,248,0,2,68,16,0,2,68,148,0,2,69,56,0,2,69,172,0,2,70,96,0,2,70,136,0,2,71,16, + 0,2,71,172,0,2,71,248,0,2,72,12,0,2,72,88,0,2,72,188,0,2,73,60,0,2,73,180,0,2,74,64,0,2,74,196,0,2,75,104, + 0,2,76,40,0,2,76,152,0,2,77,156,0,2,78,8,0,2,78,240,0,2,80,0,0,2,80,104,0,2,80,180,0,2,81,4,0,2,81,120, + 0,2,81,192,0,2,82,20,0,2,82,120,0,2,82,220,0,2,83,4,0,2,83,104,0,2,83,216,0,2,84,76,0,2,84,160,0,2,85,40, + 0,2,85,112,0,2,85,192,0,2,86,28,0,2,86,104,0,2,86,192,0,2,87,68,0,2,87,200,0,2,88,8,0,2,88,76,0,2,88,140, + 0,2,88,240,0,2,89,48,0,2,89,152,0,2,90,4,0,2,90,92,0,2,90,204,0,2,91,20,0,2,91,92,0,2,91,172,0,2,91,232, + 0,2,92,88,0,2,92,152,0,2,92,232,0,2,93,132,0,2,93,204,0,2,94,48,0,2,94,172,0,2,95,56,0,2,95,136,0,2,95,244, + 0,2,96,108,0,2,96,216,0,2,97,28,0,2,97,124,0,2,98,28,0,2,98,132,0,2,98,224,0,2,99,72,0,2,99,164,0,2,100,0, + 0,2,100,128,0,2,100,204,0,2,101,56,0,2,101,160,0,2,102,76,0,2,102,164,0,2,103,32,0,2,103,124,0,2,103,252,0,2,104,88, + 0,2,104,200,0,2,105,20,0,2,105,144,0,2,106,8,0,2,106,84,0,2,106,204,0,2,107,64,0,2,107,180,0,2,108,20,0,2,108,120, + 0,2,108,240,0,2,109,112,0,2,109,232,0,2,110,84,0,2,110,176,0,2,111,44,0,2,111,140,0,2,111,188,0,2,112,8,0,2,112,116, + 0,2,112,140,0,2,112,156,0,2,112,180,0,2,113,32,0,2,113,56,0,2,113,80,0,2,113,104,0,2,113,216,0,2,113,240,0,2,114,8, + 0,2,114,32,0,2,114,56,0,2,114,80,0,2,114,104,0,2,114,128,0,2,114,152,0,2,114,176,0,2,114,200,0,2,114,224,0,2,114,248, + 0,2,115,16,0,2,115,40,0,2,115,64,0,2,115,88,0,2,115,112,0,2,115,136,0,2,115,180,0,2,115,212,0,2,115,244,0,2,116,48, + 0,2,116,108,0,2,116,168,0,2,116,236,0,2,117,32,0,2,117,104,0,2,117,128,0,2,117,156,0,2,117,200,0,2,117,236,0,2,118,4, + 0,2,118,28,0,2,118,52,0,2,118,76,0,2,118,92,0,2,118,116,0,2,118,132,0,2,118,156,0,2,119,0,0,2,119,24,0,2,119,48, + 0,2,119,72,0,2,119,172,0,2,119,196,0,2,119,220,0,2,119,244,0,2,120,12,0,2,120,36,0,2,120,60,0,2,120,84,0,2,120,108, + 0,2,120,132,0,2,120,156,0,2,120,180,0,2,120,204,0,2,120,228,0,2,120,252,0,2,121,20,0,2,121,44,0,2,121,144,0,2,121,192, + 0,2,121,208,0,2,121,232,0,2,122,84,0,2,122,108,0,2,122,212,0,2,122,236,0,2,123,4,0,2,123,28,0,2,123,132,0,2,123,156, + 0,2,123,180,0,2,123,204,0,2,123,228,0,2,123,252,0,2,124,20,0,2,124,44,0,2,124,68,0,2,124,92,0,2,124,116,0,2,124,140, + 0,2,124,164,0,2,124,188,0,2,124,212,0,2,124,236,0,2,125,4,0,2,125,96,0,2,125,120,0,2,125,144,0,2,125,168,0,2,125,192, + 0,2,126,60,0,2,126,84,0,2,126,208,0,2,126,232,0,2,127,104,0,2,127,128,0,2,127,152,0,2,128,24,0,2,128,48,0,2,128,72, + 0,2,128,96,0,2,128,120,0,2,128,144,0,2,128,168,0,2,128,192,0,2,128,216,0,2,128,240,0,2,129,8,0,2,129,32,0,2,129,56, + 0,2,129,80,0,2,129,104,0,2,129,128,0,2,129,152,0,2,130,16,0,2,130,100,0,2,130,124,0,2,130,148,0,2,130,172,0,2,130,196, + 0,2,131,24,0,2,131,48,0,2,131,136,0,2,131,160,0,2,131,248,0,2,132,16,0,2,132,40,0,2,132,128,0,2,132,152,0,2,132,176, + 0,2,132,200,0,2,132,224,0,2,132,248,0,2,133,16,0,2,133,40,0,2,133,64,0,2,133,88,0,2,133,112,0,2,133,136,0,2,133,160, + 0,2,133,184,0,2,133,208,0,2,133,232,0,2,134,0,0,2,134,88,0,2,134,144,0,2,134,200,0,2,134,224,0,2,135,24,0,2,135,48, + 0,2,135,104,0,2,135,128,0,2,135,152,0,2,135,168,0,2,135,192,0,2,135,216,0,2,135,240,0,2,136,8,0,2,136,32,0,2,136,56, + 0,2,136,80,0,2,136,104,0,2,136,128,0,2,136,152,0,2,136,176,0,2,136,200,0,2,136,224,0,2,136,248,0,2,137,16,0,2,137,40, + 0,2,137,100,0,2,137,196,0,2,137,228,0,2,138,96,0,2,138,120,0,2,138,248,0,2,139,16,0,2,139,136,0,2,139,160,0,2,139,184, + 0,2,140,48,0,2,140,72,0,2,140,96,0,2,140,120,0,2,140,144,0,2,140,168,0,2,140,192,0,2,140,216,0,2,140,240,0,2,141,64, + 0,2,141,128,0,2,141,212,0,2,142,40,0,2,142,64,0,2,142,148,0,2,142,172,0,2,143,0,0,2,143,24,0,2,143,48,0,2,143,132, + 0,2,143,156,0,2,143,180,0,2,143,204,0,2,143,228,0,2,143,252,0,2,144,20,0,2,144,44,0,2,144,68,0,2,144,92,0,2,144,116, + 0,2,144,140,0,2,144,164,0,2,144,188,0,2,144,212,0,2,144,236,0,2,145,36,0,2,145,96,0,2,145,180,0,2,145,204,0,2,146,36, + 0,2,146,60,0,2,146,144,0,2,146,168,0,2,146,192,0,2,147,24,0,2,147,48,0,2,147,72,0,2,147,96,0,2,147,120,0,2,147,144, + 0,2,147,168,0,2,147,192,0,2,147,216,0,2,147,240,0,2,148,8,0,2,148,32,0,2,148,56,0,2,148,80,0,2,148,104,0,2,148,128, + 0,2,148,152,0,2,148,232,0,2,149,108,0,2,149,160,0,2,149,248,0,2,150,80,0,2,150,104,0,2,150,228,0,2,150,252,0,2,151,124, + 0,2,151,148,0,2,151,172,0,2,151,196,0,2,151,220,0,2,151,244,0,2,152,12,0,2,152,36,0,2,152,60,0,2,152,84,0,2,152,108, + 0,2,152,132,0,2,152,156,0,2,152,180,0,2,152,204,0,2,152,228,0,2,153,88,0,2,153,176,0,2,153,200,0,2,154,36,0,2,154,60, + 0,2,154,152,0,2,154,176,0,2,154,200,0,2,155,36,0,2,155,60,0,2,155,84,0,2,155,108,0,2,155,132,0,2,155,156,0,2,155,180, + 0,2,155,204,0,2,155,228,0,2,155,252,0,2,156,20,0,2,156,44,0,2,156,68,0,2,156,92,0,2,156,116,0,2,156,140,0,2,156,164, + 0,2,157,4,0,2,157,20,0,2,157,80,0,2,157,188,0,2,158,40,0,2,158,140,0,2,158,164,0,2,159,8,0,2,159,32,0,2,159,136, + 0,2,159,160,0,2,160,8,0,2,160,112,0,2,160,136,0,2,160,236,0,2,161,4,0,2,161,28,0,2,161,136,0,2,161,196,0,2,162,120, + 0,2,162,144,0,2,163,68,0,2,163,92,0,2,164,20,0,2,164,44,0,2,164,224,0,2,164,248,0,2,165,16,0,2,165,40,0,2,165,148, + 0,2,166,16,0,2,166,140,0,2,167,8,0,2,167,132,0,2,167,156,0,2,167,180,0,2,168,48,0,2,168,72,0,2,168,200,0,2,168,224, + 0,2,168,248,0,2,169,16,0,2,169,136,0,2,169,236,0,2,170,84,0,2,170,108,0,2,170,208,0,2,170,232,0,2,171,76,0,2,171,100, + 0,2,171,196,0,2,171,212,0,2,171,228,0,2,171,252,0,2,172,20,0,2,172,44,0,2,172,68,0,2,172,92,0,2,172,116,0,2,172,140, + 0,2,172,164,0,2,173,36,0,2,173,164,0,2,174,40,0,2,174,176,0,2,174,200,0,2,174,224,0,2,174,248,0,2,175,16,0,2,175,40, + 0,2,175,64,0,2,175,88,0,2,175,204,0,2,176,120,0,2,176,248,0,2,177,16,0,2,177,140,0,2,177,164,0,2,178,36,0,2,178,60, + 0,2,178,128,0,2,178,188,0,2,178,248,0,2,179,16,0,2,179,76,0,2,179,100,0,2,179,160,0,2,179,184,0,2,179,244,0,2,180,120, + 0,2,180,136,0,2,180,248,0,2,181,40,0,2,181,136,0,2,181,192,0,2,181,216,0,2,181,240,0,2,182,8,0,2,182,32,0,2,182,56, + 0,2,182,80,0,2,182,104,0,2,182,128,0,2,182,156,0,2,182,196,0,2,182,244,0,2,183,48,0,2,183,116,0,2,183,196,0,2,183,236, + 0,2,184,28,0,2,184,88,0,2,184,156,0,2,184,236,0,2,185,32,0,2,185,108,0,2,185,208,0,2,186,76,0,2,186,224,0,2,187,16, + 0,2,187,84,0,2,187,172,0,2,188,24,0,2,188,152,0,2,188,224,0,2,189,56,0,2,189,112,0,2,190,8,0,2,190,224,0,2,191,8, + 0,2,191,60,0,2,191,112,0,2,191,168,0,2,191,248,0,2,192,212,0,2,193,64,0,2,193,80,0,2,193,152,0,2,193,240,0,2,194,32, + 0,2,194,176,0,2,194,212,0,2,195,16,0,2,195,32,0,2,195,88,0,2,195,104,0,2,195,120,0,2,195,136,0,2,195,152,0,2,195,240, + 0,2,196,72,0,2,196,216,0,2,197,148,0,2,197,204,0,2,198,4,0,2,198,72,0,2,198,184,0,2,199,40,0,2,199,56,0,2,199,116, + 0,2,199,184,0,2,200,20,0,2,200,136,0,2,200,152,0,2,200,168,0,2,200,184,0,2,201,8,0,2,201,40,0,2,201,56,0,2,201,96, + 0,2,201,112,0,2,201,204,0,2,201,220,0,2,202,16,0,2,202,92,0,2,202,216,0,2,203,40,0,2,203,88,0,2,203,136,0,2,203,248, + 0,2,204,40,0,2,204,68,0,2,204,116,0,2,204,168,0,2,204,200,0,2,205,0,0,2,205,48,0,2,205,96,0,2,205,192,0,2,206,124, + 0,2,206,200,0,2,207,52,0,2,207,92,0,2,207,160,0,2,207,216,0,2,208,88,0,2,208,224,0,2,209,72,0,2,210,32,0,2,210,132, + 0,2,210,236,0,2,211,96,0,2,212,8,0,2,212,156,0,2,213,44,0,2,213,192,0,2,213,228,0,2,214,24,0,2,214,180,0,2,215,72, + 0,2,215,204,0,2,216,52,0,2,216,112,0,2,216,168,0,2,217,12,0,2,217,76,0,2,217,152,0,2,217,228,0,2,218,96,0,2,218,136, + 0,2,218,232,0,2,219,32,0,2,219,168,0,2,220,36,0,2,220,124,0,2,220,144,0,2,220,164,0,2,220,184,0,2,220,204,0,2,220,224, + 0,2,220,244,0,2,221,80,0,2,221,100,0,2,221,120,0,2,221,248,0,2,222,8,0,2,222,72,0,2,222,212,0,2,223,16,0,2,223,120, + 0,2,223,216,0,2,224,92,0,2,224,236,0,2,225,124,0,2,225,192,0,2,226,4,0,2,226,140,0,2,226,216,0,2,227,16,0,2,227,64, + 0,2,227,108,0,2,227,168,0,2,228,0,0,2,228,52,0,2,228,116,0,2,228,148,0,2,229,44,0,2,229,168,0,2,230,8,0,2,230,108, + 0,2,230,156,0,2,231,12,0,2,231,156,0,2,232,68,0,2,232,148,0,2,232,236,0,2,233,84,0,2,233,204,0,2,234,16,0,2,234,116, + 0,2,234,156,0,2,234,204,0,2,235,24,0,2,235,116,0,2,235,224,0,2,236,76,0,2,236,108,0,2,236,144,0,2,236,180,0,2,236,212, + 0,2,237,0,0,2,237,48,0,2,237,72,0,2,237,96,0,2,237,120,0,2,237,144,0,2,237,168,0,2,237,192,0,2,237,216,0,2,237,240, + 0,2,238,8,0,2,238,32,0,2,238,56,0,2,238,80,0,2,238,104,0,2,238,128,0,2,238,152,0,2,238,176,0,2,238,200,0,2,238,224, + 0,2,238,248,0,2,239,16,0,2,239,40,0,2,239,64,0,2,239,88,0,2,239,112,0,2,239,136,0,2,239,160,0,2,239,184,0,2,239,208, + 0,2,239,240,0,2,240,16,0,2,240,40,0,2,240,64,0,2,240,88,0,2,240,112,0,2,240,136,0,2,240,160,0,2,240,184,0,2,240,208, + 0,2,240,232,0,2,241,0,0,2,241,24,0,2,241,48,0,2,241,72,0,2,241,96,0,2,241,120,0,2,241,144,0,2,241,168,0,2,241,192, + 0,2,241,216,0,2,241,240,0,2,242,8,0,2,242,32,0,2,242,56,0,2,242,80,0,2,242,104,0,2,242,128,0,2,242,160,0,2,242,184, + 0,2,242,208,0,2,242,232,0,2,243,0,0,2,243,24,0,2,243,48,0,2,243,72,0,2,243,96,0,2,243,120,0,2,243,144,0,2,243,168, + 0,2,243,192,0,2,243,216,0,2,243,240,0,2,244,8,0,2,244,32,0,2,244,56,0,2,244,80,0,2,244,104,0,2,244,128,0,2,244,152, + 0,2,244,176,0,2,244,208,0,2,244,232,0,2,245,0,0,2,245,24,0,2,245,48,0,2,245,72,0,2,245,96,0,2,245,120,0,2,245,144, + 0,2,245,168,0,2,245,192,0,2,245,216,0,2,245,240,0,2,246,8,0,2,246,32,0,2,246,56,0,2,246,80,0,2,246,104,0,2,246,128, + 0,2,246,152,0,2,246,176,0,2,246,208,0,2,246,240,0,2,247,8,0,2,247,32,0,2,247,56,0,2,247,80,0,2,247,104,0,2,247,128, + 0,2,247,152,0,2,247,176,0,2,247,200,0,2,247,224,0,2,247,248,0,2,248,16,0,2,248,40,0,2,248,64,0,2,248,88,0,2,248,112, + 0,2,248,136,0,2,248,160,0,2,248,184,0,2,248,208,0,2,248,232,0,2,249,0,0,2,249,24,0,2,249,48,0,2,249,72,0,2,249,96, + 0,2,249,120,0,2,249,144,0,2,249,168,0,2,249,192,0,2,249,216,0,2,249,240,0,2,250,8,0,2,250,32,0,2,250,56,0,2,250,80, + 0,2,250,104,0,2,250,128,0,2,250,152,0,2,250,176,0,2,250,200,0,2,250,224,0,2,250,248,0,2,251,16,0,2,251,40,0,2,251,64, + 0,2,251,88,0,2,251,112,0,2,251,136,0,2,251,160,0,2,251,184,0,2,251,208,0,2,251,232,0,2,252,0,0,2,252,80,0,2,252,152, + 0,2,253,48,0,2,253,64,0,2,253,88,0,2,253,112,0,2,253,136,0,2,253,160,0,2,253,184,0,2,253,208,0,2,253,232,0,2,254,0, + 0,2,254,24,0,2,254,48,0,2,254,72,0,2,254,96,0,2,254,120,0,2,254,144,0,2,254,168,0,2,254,192,0,2,254,216,0,2,254,240, + 0,2,255,8,0,2,255,32,0,2,255,56,0,2,255,80,0,2,255,104,0,2,255,128,0,2,255,152,0,2,255,176,0,2,255,200,0,2,255,224, + 0,2,255,248,0,3,0,16,0,3,0,40,0,3,0,64,0,3,0,88,0,3,0,112,0,3,0,136,0,3,0,160,0,3,0,184,0,3,0,208, + 0,3,0,232,0,3,1,8,0,3,1,32,0,3,1,56,0,3,1,80,0,3,1,104,0,3,1,128,0,3,1,152,0,3,1,176,0,3,1,200, + 0,3,1,224,0,3,1,248,0,3,2,16,0,3,2,40,0,3,2,64,0,3,2,88,0,3,2,112,0,3,2,136,0,3,2,160,0,3,2,192, + 0,3,2,216,0,3,2,240,0,3,3,8,0,3,3,32,0,3,3,56,0,3,3,80,0,3,3,104,0,3,3,128,0,3,3,152,0,3,3,176, + 0,3,3,200,0,3,3,224,0,3,3,248,0,3,4,16,0,3,4,40,0,3,4,64,0,3,4,88,0,3,4,112,0,3,4,136,0,3,4,160, + 0,3,4,184,0,3,4,208,0,3,4,232,0,3,5,0,0,3,5,24,0,3,5,48,0,3,5,72,0,3,5,96,0,3,5,120,0,3,5,144, + 0,3,5,168,0,3,5,192,0,3,5,236,0,3,6,40,0,3,6,64,0,3,6,88,0,3,6,112,0,3,6,136,0,3,6,160,0,3,6,184, + 0,3,6,208,0,3,6,232,0,3,7,0,0,3,7,24,0,3,7,52,0,3,7,76,0,3,7,104,0,3,7,132,0,3,7,156,0,3,7,180, + 0,3,7,204,0,3,7,228,0,3,7,252,0,3,8,20,0,3,8,44,0,3,8,68,0,3,8,96,0,3,8,124,0,3,8,152,0,3,8,176, + 0,3,8,204,0,3,8,232,0,3,9,0,0,3,9,24,0,3,9,48,0,3,9,72,0,3,9,96,0,3,9,120,0,3,9,144,0,3,9,168, + 0,3,9,196,0,3,9,224,0,3,9,252,0,3,10,20,0,3,10,48,0,3,10,76,0,3,10,104,0,3,10,132,0,3,10,156,0,3,10,180, + 0,3,10,204,0,3,10,228,0,3,10,252,0,3,11,20,0,3,11,44,0,3,11,68,0,3,11,96,0,3,11,124,0,3,11,152,0,3,11,176, + 0,3,11,204,0,3,11,232,0,3,12,4,0,3,12,32,0,3,12,56,0,3,12,80,0,3,12,104,0,3,12,128,0,3,12,152,0,3,12,176, + 0,3,12,200,0,3,12,224,0,3,12,252,0,3,13,20,0,3,13,48,0,3,13,76,0,3,13,100,0,3,13,124,0,3,13,148,0,3,13,172, + 0,3,13,196,0,3,13,220,0,3,13,244,0,3,14,12,0,3,14,40,0,3,14,64,0,3,14,92,0,3,14,120,0,3,14,144,0,3,14,168, + 0,3,14,192,0,3,14,216,0,3,14,240,0,3,15,8,0,3,15,32,0,3,15,56,0,3,15,80,0,3,15,108,0,3,15,136,0,3,15,160, + 0,3,15,188,0,3,15,216,0,3,15,244,0,3,16,16,0,3,16,40,0,3,16,56,0,3,16,80,0,3,16,96,0,3,16,120,0,3,16,136, + 0,3,16,160,0,3,16,176,0,3,16,200,0,3,16,216,0,3,16,240,0,3,17,0,0,3,17,24,0,3,17,40,0,3,17,64,0,3,17,88, + 0,3,17,112,0,3,17,136,0,3,17,160,0,3,17,184,0,3,17,208,0,3,17,232,0,3,18,0,0,3,18,24,0,3,18,48,0,3,18,72, + 0,3,18,96,0,3,18,120,0,3,18,144,0,3,18,168,0,3,18,192,0,3,18,216,0,3,18,240,0,3,19,8,0,3,19,32,0,3,19,56, + 0,3,19,80,0,3,19,104,0,3,19,128,0,3,19,152,0,3,19,176,0,3,19,200,0,3,19,224,0,3,19,248,0,3,20,16,0,3,20,40, + 0,3,20,64,0,3,20,88,0,3,20,112,0,3,20,136,0,3,20,160,0,3,20,184,0,3,20,208,0,3,20,232,0,3,21,0,0,3,21,24, + 0,3,21,48,0,3,21,72,0,3,21,96,0,3,21,120,0,3,21,144,0,3,21,168,0,3,21,192,0,3,21,216,0,3,21,240,0,3,22,8, + 0,3,22,32,0,3,22,56,0,3,22,80,0,3,22,104,0,3,22,128,0,3,22,152,0,3,22,168,0,3,22,192,0,3,22,208,0,3,22,224, + 0,3,23,80,0,3,23,96,0,3,23,120,0,3,23,144,0,3,23,168,0,3,23,192,0,3,23,216,0,3,23,240,0,3,24,12,0,3,24,28, + 0,3,24,56,0,3,24,72,0,3,24,96,0,3,24,124,0,3,24,148,0,3,24,172,0,3,24,196,0,3,24,220,0,3,24,244,0,3,25,4, + 0,3,25,28,0,3,25,52,0,3,25,76,0,3,25,100,0,3,25,128,0,3,25,144,0,3,25,172,0,3,25,196,0,3,25,220,0,3,25,244, + 0,3,26,12,0,3,26,36,0,3,26,52,0,3,26,76,0,3,26,100,0,3,26,124,0,3,26,148,0,3,26,172,0,3,26,196,0,3,26,224, + 0,3,26,240,0,3,27,12,0,3,27,36,0,3,27,52,0,3,27,68,0,3,27,92,0,3,27,116,0,3,27,140,0,3,27,164,0,3,27,188, + 0,3,27,216,0,3,27,232,0,3,28,4,0,3,28,20,0,3,28,44,0,3,28,60,0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168, + 0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,168, + 0,3,28,168,0,3,28,168,0,3,28,168,0,3,28,212,0,3,28,228,0,3,29,16,0,3,29,60,0,3,29,104,0,3,29,144,0,3,29,168, + 0,3,29,192,0,3,29,252,0,3,30,56,0,3,30,112,0,3,30,148,0,3,30,240,0,3,31,76,0,3,31,168,0,3,31,220,0,3,32,52, + 0,3,32,184,0,3,32,248,0,3,33,20,0,3,33,60,0,3,33,124,0,3,33,208,0,3,33,232,0,3,33,232,0,3,33,232,0,3,33,232, + 0,3,33,232,0,3,33,232,0,3,33,232,0,3,33,232,0,3,33,232,0,3,35,116,0,3,36,132,0,3,36,164,0,3,36,188,0,3,36,220, + 0,3,36,248,0,3,37,16,0,3,37,48,0,3,37,84,0,3,37,196,0,3,38,56,0,3,38,104,0,3,38,132,0,3,39,0,0,3,39,20, + 0,3,39,116,0,3,39,212,0,3,40,0,0,3,40,36,0,3,40,64,0,3,40,136,0,3,40,184,0,3,40,232,0,3,41,0,0,3,41,24, + 0,3,41,52,0,3,41,160,0,3,41,216,0,3,42,8,0,3,42,56,0,3,42,76,0,3,42,124,0,3,42,148,0,3,42,176,0,3,42,212, + 0,3,43,52,0,3,43,72,0,3,43,156,0,3,43,208,0,3,43,248,0,3,44,56,0,3,44,132,0,3,44,168,0,3,44,228,0,3,45,72, + 0,3,45,120,0,3,45,180,0,3,45,180,0,3,45,180,0,3,45,180,0,3,45,180,0,3,45,180,0,3,45,180,0,3,45,180,0,3,45,180, + 0,3,45,180,0,3,45,180,0,3,45,180,0,3,45,180,0,3,46,8,0,3,46,76,0,3,47,88,0,3,47,188,0,3,48,76,0,3,48,116, + 0,3,49,36,0,3,49,176,0,3,49,228,0,3,50,0,0,3,50,40,0,3,50,96,0,3,50,156,0,3,51,16,0,3,51,36,0,3,51,56, + 0,3,51,76,0,3,51,96,0,3,51,116,0,3,51,136,0,3,51,156,0,3,51,176,0,3,51,196,0,3,51,216,0,3,51,236,0,3,52,0, + 0,3,52,20,0,3,52,40,0,3,52,60,0,3,52,80,0,3,52,100,0,3,52,120,0,3,52,140,0,3,52,160,0,3,52,180,0,3,52,200, + 0,3,52,220,0,3,52,240,0,3,53,4,0,3,53,24,0,3,53,44,0,3,53,64,0,3,53,180,0,3,54,100,0,3,54,244,0,3,55,52, + 0,3,55,156,0,3,56,32,0,3,56,164,0,3,57,136,0,3,58,88,0,3,59,4,0,3,59,104,0,3,59,128,0,3,61,52,0,3,61,124, + 0,3,61,212,0,3,63,96,0,3,63,252,0,3,64,148,0,3,65,40,0,3,65,148,0,3,66,52,0,3,66,196,0,3,66,248,0,3,67,120, + 0,3,67,224,0,3,68,4,0,3,68,36,0,3,68,76,0,3,68,116,0,3,68,172,0,3,68,240,0,3,69,40,0,3,69,232,0,3,70,192, + 0,3,71,56,0,3,71,80,0,3,72,120,0,3,73,20,0,3,73,172,0,3,73,188,0,3,73,208,0,3,73,232,0,3,75,40,0,3,76,24, + 0,3,76,104,0,3,76,196,0,3,77,36,0,3,77,208,0,3,78,100,0,3,79,68,0,3,79,196,0,3,80,64,0,3,80,132,0,3,83,44, + 0,3,83,212,0,3,84,136,0,3,84,248,0,3,85,152,0,3,86,176,0,3,87,172,0,3,88,92,0,3,89,116,0,3,90,28,0,3,90,188, + 0,3,91,28,0,3,91,168,0,3,91,252,0,3,92,60,0,3,92,168,0,3,92,184,0,3,92,200,0,3,93,188,0,3,93,240,0,3,94,0, + 0,3,94,16,0,3,95,8,0,3,95,204,0,3,96,84,0,3,96,208,0,3,97,152,0,3,98,120,0,3,98,164,0,3,99,232,0,3,100,60, + 0,3,100,224,0,3,101,112,0,3,101,252,0,3,102,116,0,3,102,188,0,3,103,48,0,3,103,180,0,3,104,72,0,3,104,188,0,3,104,236, + 0,3,105,48,0,3,105,132,0,3,105,244,0,3,106,44,0,3,106,100,0,3,106,144,0,3,107,20,0,3,107,196,0,3,108,100,0,3,108,156, + 0,3,109,4,0,3,109,156,0,3,109,236,0,3,110,12,0,3,110,44,0,3,110,84,0,3,110,116,0,3,110,148,0,3,110,180,0,3,110,212, + 0,3,110,244,0,3,111,20,0,3,111,52,0,3,111,84,0,3,111,116,0,3,111,148,0,3,111,180,0,3,111,212,0,3,111,236,0,3,111,252, + 0,3,112,20,0,3,112,52,0,3,112,76,0,3,112,92,0,3,112,116,0,3,112,148,0,3,112,188,0,3,112,212,0,3,112,228,0,3,112,252, + 0,3,113,28,0,3,113,44,0,3,113,60,0,3,113,76,0,3,113,92,0,3,113,108,0,3,113,132,0,3,113,164,0,3,113,188,0,3,113,204, + 0,3,113,228,0,3,114,4,0,3,114,44,0,3,114,68,0,3,114,84,0,3,114,108,0,3,114,140,0,3,114,156,0,3,114,172,0,3,114,188, + 0,3,114,204,0,3,115,80,0,3,116,204,0,3,117,172,0,3,117,188,0,3,117,204,0,3,118,56,0,3,118,88,0,3,119,8,0,3,119,184, + 0,3,120,104,0,3,121,24,0,3,122,56,0,3,123,92,0,3,123,140,0,3,123,188,0,3,123,236,0,3,124,28,0,3,124,104,0,3,124,180, + 0,3,125,92,0,3,126,4,0,3,126,80,0,3,126,156,0,3,126,232,0,3,127,52,0,3,127,124,0,3,127,200,0,3,128,4,0,3,128,64, + 0,3,129,4,0,3,129,64,0,3,129,148,0,3,130,20,0,3,130,160,0,3,131,100,0,3,132,40,0,3,133,60,0,3,133,156,0,3,133,228, + 0,3,134,28,0,3,134,84,0,3,134,140,0,3,134,196,0,3,134,252,0,3,135,52,0,3,135,184,0,3,136,56,0,3,136,116,0,3,136,224, + 0,3,137,136,0,3,138,48,0,3,138,160,0,3,139,16,0,3,139,56,0,3,139,96,0,3,139,212,0,3,140,68,0,3,140,104,0,3,140,140, + 0,3,140,168,0,3,140,196,0,3,140,224,0,3,141,40,0,3,141,112,0,3,141,184,0,3,142,0,0,3,142,28,0,3,142,56,0,3,142,160, + 0,3,143,32,0,3,143,136,0,3,143,200,0,3,144,8,0,3,144,72,0,3,144,136,0,3,144,228,0,3,145,64,0,3,145,128,0,3,145,192, + 0,3,146,0,0,3,146,64,0,3,146,128,0,3,146,192,0,3,147,28,0,3,147,120,0,3,147,208,0,3,148,40,0,3,148,112,0,3,148,184, + 0,3,149,4,0,3,149,80,0,3,149,140,0,3,149,200,0,3,150,12,0,3,150,80,0,3,150,144,0,3,150,208,0,3,151,52,0,3,151,136, + 0,3,151,232,0,3,152,72,0,3,152,180,0,3,153,52,0,3,153,136,0,3,153,204,0,3,154,16,0,3,154,108,0,3,155,72,0,3,155,100, + 0,3,155,196,0,3,156,8,0,3,156,80,0,3,156,172,0,3,157,4,0,3,157,96,0,3,157,208,0,3,158,4,0,3,158,56,0,3,158,136, + 0,3,158,196,0,3,159,152,0,3,160,48,0,3,160,100,0,3,160,204,0,3,161,140,0,3,161,240,0,3,162,32,0,3,162,132,0,3,163,40, + 0,3,163,124,0,3,163,224,0,3,164,132,0,3,164,216,0,3,165,0,0,3,165,68,0,3,165,136,0,3,166,32,0,3,166,76,0,3,166,136, + 0,3,167,28,0,3,167,44,0,3,167,64,0,3,167,140,0,3,167,160,0,3,167,176,0,3,168,16,0,3,168,40,0,3,168,64,0,3,168,216, + 0,3,169,144,0,3,169,176,0,3,169,212,0,3,170,128,0,3,171,44,0,3,171,72,0,3,171,180,0,3,171,220,0,3,172,160,0,3,172,204, + 0,3,172,244,0,3,173,52,0,3,173,116,0,3,173,196,0,3,173,220,0,3,173,252,0,3,174,200,0,3,176,0,0,3,177,168,0,3,178,72, + 0,3,179,16,0,3,179,216,0,3,179,252,0,3,180,32,0,3,180,60,0,3,180,104,0,3,180,128,0,3,180,180,0,3,180,228,0,3,181,4, + 0,3,181,100,0,3,181,196,0,3,182,64,0,3,182,136,0,3,182,232,0,3,183,72,0,3,183,180,0,3,184,28,0,3,184,156,0,3,185,16, + 0,3,185,164,0,3,186,52,0,3,187,40,0,3,187,200,0,3,188,120,0,3,189,96,0,3,189,212,0,3,190,44,0,3,190,232,0,3,191,92, + 0,3,191,116,0,3,191,148,0,3,191,180,0,3,191,212,0,3,191,248,0,3,192,24,0,3,192,116,0,3,192,224,0,3,193,40,0,3,193,108, + 0,3,193,172,0,3,193,248,0,3,194,60,0,3,195,28,0,3,195,160,0,3,196,44,0,3,196,184,0,3,197,16,0,3,197,112,0,3,197,220, + 0,3,198,108,0,3,198,248,0,3,199,64,0,3,199,128,0,3,199,232,0,3,200,76,0,3,200,148,0,3,200,216,0,3,201,96,0,3,201,204, + 0,3,202,32,0,3,202,116,0,3,202,224,0,3,203,76,0,3,203,204,0,3,204,68,0,3,204,248,0,3,205,172,0,3,205,240,0,3,206,56, + 0,3,206,196,0,3,207,76,0,3,207,136,0,3,207,192,0,3,208,20,0,3,208,100,0,3,208,244,0,3,209,128,0,3,209,240,0,3,210,96, + 0,3,210,164,0,3,210,232,0,3,211,84,0,3,211,192,0,3,212,20,0,3,212,100,0,3,212,224,0,3,213,96,0,3,213,204,0,3,214,56, + 0,3,214,152,0,3,214,176,0,3,215,16,0,3,215,80,0,3,215,148,0,3,215,200,0,3,215,252,0,3,216,36,0,3,216,72,0,3,217,20, + 0,3,217,200,0,3,218,152,0,3,219,84,0,3,220,8,0,3,220,240,0,3,221,212,0,3,222,148,0,3,223,72,0,3,223,152,0,3,223,212, + 0,3,224,56,0,3,224,112,0,3,224,172,0,3,224,208,0,3,224,248,0,3,225,28,0,3,225,64,0,3,225,112,0,3,225,160,0,3,225,208, + 0,3,226,16,0,3,226,76,0,3,226,144,0,3,226,236,0,3,227,64,0,3,227,172,0,3,228,48,0,3,228,184,0,3,228,232,0,3,229,20, + 0,3,229,76,0,3,229,132,0,3,229,240,0,3,230,92,0,3,230,172,0,3,230,240,0,3,231,20,0,3,231,72,0,3,231,128,0,3,231,180, + 0,3,232,8,0,3,232,56,0,3,232,100,0,3,232,144,0,3,232,244,0,3,233,84,0,3,233,100,0,3,233,144,0,3,233,196,0,3,234,48, + 0,3,234,116,0,3,234,180,0,3,234,244,0,3,235,32,0,3,235,80,0,3,235,180,0,3,235,236,0,3,236,36,0,3,236,168,0,3,237,44, + 0,3,237,164,0,3,238,28,0,3,238,120,0,3,238,220,0,3,239,20,0,3,239,72,0,3,239,176,0,3,240,16,0,3,240,104,0,3,240,188, + 0,3,240,244,0,3,241,44,0,3,241,128,0,3,241,212,0,3,242,104,0,3,242,252,0,3,243,100,0,3,243,204,0,3,244,24,0,3,244,100, + 0,3,244,220,0,3,245,84,0,3,245,220,0,3,246,100,0,3,246,188,0,3,247,20,0,3,247,136,0,3,247,248,0,3,248,28,0,3,248,60, + 0,3,248,96,0,3,248,132,0,3,248,248,0,3,249,96,0,3,249,184,0,3,249,208,0,3,250,68,0,3,250,164,0,3,251,24,0,3,251,132, + 0,3,251,248,0,3,252,96,0,3,252,188,0,3,253,48,0,3,253,148,0,3,253,200,0,3,254,64,0,3,254,108,0,3,254,164,0,3,254,212, + 0,3,255,0,0,3,255,24,0,3,255,56,0,3,255,144,0,3,255,176,0,3,255,208,0,3,255,240,0,4,0,16,0,4,0,56,0,4,0,96, + 0,4,0,136,0,4,0,176,0,4,0,208,0,4,1,36,0,4,2,32,0,4,2,68,0,4,2,104,0,4,2,136,0,4,2,168,0,4,2,200, + 0,4,3,32,0,4,3,120,0,4,3,196,0,4,3,252,0,4,4,104,0,4,4,200,0,4,9,128,0,4,9,236,0,4,10,96,0,4,10,112, + 0,4,10,128,0,4,10,144,0,4,10,160,0,4,10,208,0,4,11,28,0,4,11,96,0,4,11,152,0,4,11,180,0,4,11,236,0,4,12,36, + 0,4,12,64,0,4,12,120,0,4,12,152,0,4,12,180,0,4,12,216,0,4,12,252,0,4,13,24,0,4,13,56,0,4,13,108,0,4,13,196, + 0,4,13,252,0,4,14,24,0,4,14,80,0,4,14,168,0,4,14,220,0,4,14,248,0,4,15,76,0,4,15,120,0,4,16,32,0,4,16,48, + 0,4,16,156,0,4,17,16,0,4,17,56,0,4,18,168,0,4,20,172,0,4,23,60,0,4,24,204,0,4,26,216,0,4,29,60,0,4,30,180, + 0,4,33,176,0,4,36,24,0,4,38,132,0,4,38,160,0,4,38,188,0,4,38,216,0,4,38,244,0,4,39,40,0,4,39,96,0,4,39,152, + 0,4,39,212,0,4,40,12,0,4,40,76,0,4,40,148,0,4,40,224,0,4,41,4,0,4,41,40,0,4,41,76,0,4,41,112,0,4,41,148, + 0,4,41,184,0,4,41,220,0,4,42,0,0,4,42,32,0,4,42,68,0,4,42,104,0,4,42,140,0,4,42,172,0,4,42,204,0,4,42,236, + 0,4,43,16,0,4,43,56,0,4,43,96,0,4,43,140,0,4,43,184,0,4,43,224,0,4,44,16,0,4,44,60,0,4,44,100,0,4,44,140, + 0,4,44,180,0,4,44,224,0,4,45,12,0,4,45,52,0,4,45,100,0,4,45,144,0,4,45,184,0,4,45,224,0,4,46,12,0,4,46,56, + 0,4,46,96,0,4,46,136,0,4,46,180,0,4,46,224,0,4,47,8,0,4,47,44,0,4,47,88,0,4,47,132,0,4,47,172,0,4,47,212, + 0,4,48,0,0,4,48,44,0,4,48,84,0,4,48,132,0,4,48,184,0,4,48,236,0,4,49,32,0,4,49,84,0,4,49,136,0,4,49,188, + 0,4,49,244,0,4,50,44,0,4,50,100,0,4,50,156,0,4,50,208,0,4,51,4,0,4,51,56,0,4,51,108,0,4,51,160,0,4,51,196, + 0,4,51,240,0,4,52,28,0,4,52,72,0,4,52,112,0,4,52,152,0,4,52,196,0,4,52,240,0,4,53,36,0,4,53,80,0,4,53,124, + 0,4,53,176,0,4,53,220,0,4,54,8,0,4,54,60,0,4,54,104,0,4,54,148,0,4,54,200,0,4,54,248,0,4,55,44,0,4,55,112, + 0,4,55,160,0,4,55,212,0,4,56,20,0,4,56,72,0,4,56,120,0,4,56,184,0,4,56,236,0,4,57,28,0,4,57,92,0,4,57,164, + 0,4,57,232,0,4,58,68,0,4,58,120,0,4,58,176,0,4,58,224,0,4,59,20,0,4,59,52,0,4,59,80,0,4,59,144,0,4,59,172, + 0,4,59,200,0,4,59,228,0,4,60,0,0,4,60,28,0,4,60,56,0,4,60,84,0,4,60,112,0,4,60,148,0,4,60,188,0,4,60,224, + 0,4,61,8,0,4,61,28,0,4,61,56,0,4,61,84,0,4,61,112,0,4,61,140,0,4,61,168,0,4,61,196,0,4,61,224,0,4,61,252, + 0,4,62,24,0,4,62,52,0,4,62,80,0,4,62,108,0,4,62,136,0,4,62,164,0,4,62,192,0,4,62,212,0,4,63,136,0,4,66,156, + 0,4,67,68,0,4,67,88,0,4,67,108,0,4,67,136,0,4,67,164,0,4,67,192,0,4,67,228,0,4,68,12,0,4,68,48,0,4,68,84, + 0,4,68,112,0,4,68,152,0,4,68,188,0,4,68,216,0,4,69,4,0,4,69,88,0,4,69,112,0,4,69,200,0,4,70,40,0,4,71,100, + 0,4,71,236,0,4,72,116,0,4,74,52,0,4,74,80,0,4,74,124,0,4,74,152,0,4,74,196,0,4,74,224,0,4,75,12,0,4,75,44, + 0,4,75,96,0,4,75,124,0,4,75,164,0,4,75,192,0,4,75,232,0,4,76,4,0,4,76,48,0,4,76,76,0,4,76,120,0,4,76,148, + 0,4,76,192,0,4,76,220,0,4,77,8,0,4,77,36,0,4,77,80,0,4,77,108,0,4,77,152,0,4,77,180,0,4,77,224,0,4,77,252, + 0,4,78,40,0,4,78,72,0,4,78,124,0,4,78,192,0,4,79,80,0,4,79,164,0,4,80,12,0,4,81,4,0,4,81,184,0,4,82,116, + 0,4,82,216,0,4,83,48,0,4,83,136,0,4,83,228,0,4,84,64,0,4,84,168,0,4,84,248,0,4,85,32,0,4,85,72,0,4,85,132, + 0,4,85,252,0,4,86,80,0,4,86,164,0,4,86,208,0,4,86,252,0,4,87,40,0,4,87,88,0,4,87,156,0,4,87,224,0,4,87,252, + 0,4,88,24,0,4,88,48,0,4,88,72,0,4,88,144,0,4,88,188,0,4,88,232,0,4,89,16,0,4,89,56,0,4,89,116,0,4,89,184, + 0,4,89,228,0,4,90,12,0,4,90,120,0,4,90,184,0,4,90,248,0,4,91,56,0,4,91,120,0,4,91,248,0,4,92,120,0,4,92,248, + 0,4,93,120,0,4,93,160,0,4,93,200,0,4,93,240,0,4,94,28,0,4,94,56,0,4,94,100,0,4,94,128,0,4,94,168,0,4,95,152, + 0,4,96,4,0,4,96,188,0,4,105,160,0,4,108,132,0,4,108,188,0,4,109,32,0,4,109,112,0,4,109,212,0,4,110,104,0,4,111,52, + 0,4,112,0,0,4,112,100,0,4,113,8,0,4,115,140,0,4,118,108,0,4,118,164,0,4,119,28,0,4,119,144,0,4,119,232,0,4,121,72, + 0,4,122,244,0,4,123,60,0,4,123,112,0,4,124,100,0,4,125,56,0,4,125,208,0,4,126,104,0,4,127,44,0,4,127,244,0,4,128,184, + 0,4,129,124,0,4,133,4,0,4,133,128,0,4,134,164,0,4,136,68,0,4,139,172,0,4,140,44,0,4,140,180,0,4,141,40,0,4,141,140, + 0,4,142,16,0,4,142,160,0,4,143,232,0,4,145,24,0,4,145,180,0,4,146,72,0,4,146,252,0,4,147,28,0,4,147,60,0,4,147,92, + 0,4,147,124,0,4,147,156,0,4,147,188,0,4,147,220,0,4,147,252,0,4,149,112,0,4,150,76,0,4,151,40,0,4,151,212,0,4,152,240, + 0,4,153,132,0,4,154,20,0,4,154,204,0,4,155,68,0,4,155,188,0,4,156,48,0,4,156,136,0,4,156,228,0,4,157,120,0,4,158,36, + 0,4,158,140,0,4,159,0,0,4,159,152,0,4,159,252,0,4,160,188,0,4,161,156,0,4,162,108,0,4,162,224,0,4,163,132,0,4,163,224, + 0,4,164,124,0,4,165,104,0,4,165,232,0,4,167,16,0,4,169,60,0,4,169,216,0,4,170,244,0,4,172,60,0,4,173,80,0,4,174,228, + 0,4,175,220,0,4,176,92,0,4,177,36,0,4,178,12,0,4,178,160,0,4,179,20,0,4,179,184,0,4,180,0,0,4,180,160,0,4,181,104, + 0,4,181,188,0,4,181,236,0,4,183,16,0,4,183,252,0,4,184,60,0,4,184,152,0,4,184,252,0,4,185,92,0,4,185,176,0,4,185,252, + 0,4,186,144,0,4,187,80,0,4,188,56,0,4,190,68,0,4,191,56,0,4,192,92,0,4,193,152,0,4,194,152,0,4,195,188,0,4,196,240, + 0,4,197,224,0,4,198,180,0,4,199,192,0,4,200,248,0,4,202,80,0,4,203,84,0,4,203,240,0,4,204,96,0,4,205,20,0,4,206,8, + 0,4,207,64,0,4,208,188,0,4,210,124,0,4,211,24,0,4,211,216,0,4,212,64,0,4,212,204,0,4,212,232,0,4,213,16,0,4,213,40, + 0,4,213,64,0,4,213,88,0,4,213,112,0,4,213,240,0,4,214,64,0,4,214,196,0,4,215,188,0,4,216,104,0,4,217,140,0,4,218,72, + 0,4,218,208,0,4,219,116,0,4,220,124,0,4,222,100,0,4,225,40,0,4,226,232,0,4,227,108,0,4,227,184,0,4,228,152,0,4,229,128, + 0,4,230,104,0,4,230,248,0,4,231,216,0,4,232,236,0,4,233,200,0,4,234,164,0,4,235,24,0,4,235,96,0,4,235,216,0,4,236,220, + 0,4,238,40,0,4,239,108,0,4,239,168,0,4,240,44,0,4,240,132,0,4,240,224,0,4,241,56,0,4,241,168,0,4,242,16,0,4,242,120, + 0,4,242,224,0,4,243,136,0,4,244,104,0,4,245,124,0,4,246,236,0,4,247,132,0,4,249,20,0,4,250,120,0,4,252,4,0,4,255,196, + 0,5,1,80,0,5,2,200,0,5,3,84,0,5,4,4,0,5,6,188,0,5,8,92,0,5,9,116,0,5,10,96,0,5,11,116,0,5,12,92, + 0,5,12,228,0,5,13,72,0,5,13,176,0,5,13,244,0,5,14,52,0,5,15,0,0,5,15,248,0,5,16,120,0,5,16,172,0,5,16,232, + 0,5,17,44,0,5,17,92,0,5,17,188,0,5,18,60,0,5,19,32,0,5,19,184,0,5,20,116,0,5,21,244,0,5,23,120,0,5,26,216, + 0,5,27,56,0,5,27,232,0,5,28,80,0,5,28,220,0,5,29,108,0,5,30,44,0,5,30,184,0,5,31,56,0,5,31,180,0,5,32,36, + 0,5,32,120,0,5,32,224,0,5,33,68,0,5,33,156,0,5,34,96,0,5,34,164,0,5,34,252,0,5,35,76,0,5,35,188,0,5,36,120, + 0,5,38,36,0,5,40,24,0,5,41,68,0,5,43,116,0,5,44,212,0,5,47,76,0,5,52,160,0,5,53,216,0,5,56,40,0,5,56,236, + 0,5,57,180,0,5,58,136,0,5,60,12,0,5,61,140,0,5,62,236,0,5,64,76,0,5,65,152,0,5,67,4,0,5,67,112,0,5,67,220, + 0,5,68,68,0,5,68,172,0,5,69,16,0,5,69,44,0,5,69,72,0,5,69,100,0,5,69,164,0,5,69,240,0,5,70,8,0,5,70,32, + 0,5,70,252,0,5,71,148,0,5,72,80,0,5,72,192,0,5,73,52,0,5,74,84,0,5,75,60,0,5,75,168,0,5,76,24,0,5,76,84, + 0,5,76,144,0,5,76,184,0,5,76,228,0,5,77,12,0,5,77,56,0,5,77,96,0,5,77,140,0,5,77,184,0,5,77,228,0,5,78,72, + 0,5,78,172,0,5,79,40,0,5,79,212,0,5,81,20,0,5,81,156,0,5,82,180,0,5,84,72,0,5,84,188,0,5,87,8,0,5,88,148, + 0,5,90,8,0,5,90,220,0,5,91,224,0,5,92,248,0,5,93,212,0,5,94,212,0,5,95,236,0,5,96,184,0,5,97,228,0,5,98,252, + 0,5,100,44,0,5,100,172,0,5,101,92,0,5,102,36,0,5,102,176,0,5,103,96,0,5,104,40,0,5,104,160,0,5,105,120,0,5,106,64, + 0,5,107,4,0,5,107,52,0,5,107,96,0,5,107,140,0,5,107,184,0,5,107,232,0,5,108,116,0,5,108,156,0,5,108,196,0,5,109,24, + 0,5,109,108,0,5,109,148,0,5,109,196,0,5,109,244,0,5,110,20,0,5,110,100,0,5,110,180,0,5,110,224,0,5,111,16,0,5,111,88, + 0,5,111,160,0,5,111,244,0,5,112,68,0,5,112,144,0,5,112,224,0,5,113,56,0,5,113,144,0,5,113,252,0,5,114,160,0,5,114,248, + 0,5,115,64,0,5,115,152,0,5,116,36,0,5,116,164,0,5,117,48,0,5,118,0,0,5,118,144,0,5,119,184,0,5,120,228,0,5,121,112, + 0,5,121,208,0,5,122,48,0,5,122,108,0,5,122,160,0,5,122,212,0,5,122,252,0,5,123,36,0,5,123,60,0,5,123,84,0,5,123,172, + 0,5,124,0,0,5,124,196,0,5,125,132,0,5,126,128,0,5,127,48,0,5,127,224,0,5,129,0,0,5,129,64,0,5,129,128,0,5,129,220, + 0,5,130,24,0,5,130,84,0,5,130,160,0,5,130,236,0,5,131,112,0,5,131,112,0,5,131,132,0,5,131,152,0,5,131,180,0,5,131,200, + 0,5,131,228,0,5,132,0,0,5,132,36,0,5,132,56,0,5,132,84,0,5,132,112,0,5,132,148,0,5,132,176,0,5,132,212,0,5,132,248, + 0,5,133,36,0,5,133,56,0,5,133,84,0,5,133,112,0,5,133,148,0,5,133,176,0,5,133,212,0,5,133,248,0,5,134,36,0,5,134,64, + 0,5,134,100,0,5,134,136,0,5,134,180,0,5,134,216,0,5,135,4,0,5,135,48,0,5,135,100,0,5,135,120,0,5,135,148,0,5,135,176, + 0,5,135,212,0,5,135,240,0,5,136,20,0,5,136,56,0,5,136,100,0,5,136,128,0,5,136,164,0,5,136,200,0,5,136,244,0,5,137,24, + 0,5,137,68,0,5,137,112,0,5,137,164,0,5,137,192,0,5,137,228,0,5,138,8,0,5,138,52,0,5,138,88,0,5,138,132,0,5,138,176, + 0,5,138,228,0,5,139,8,0,5,139,52,0,5,139,96,0,5,139,148,0,5,139,192,0,5,139,244,0,5,140,40,0,5,140,100,0,5,140,120, + 0,5,140,148,0,5,140,176,0,5,140,212,0,5,140,240,0,5,141,20,0,5,141,56,0,5,141,100,0,5,141,128,0,5,141,164,0,5,141,200, + 0,5,141,244,0,5,142,24,0,5,142,68,0,5,142,112,0,5,142,164,0,5,142,192,0,5,142,228,0,5,143,8,0,5,143,52,0,5,143,88, + 0,5,143,132,0,5,143,176,0,5,143,228,0,5,144,8,0,5,144,52,0,5,144,96,0,5,144,148,0,5,144,192,0,5,144,244,0,5,145,40, + 0,5,145,100,0,5,145,128,0,5,145,164,0,5,145,200,0,5,145,244,0,5,146,24,0,5,146,68,0,5,146,112,0,5,146,164,0,5,146,200, + 0,5,146,244,0,5,147,32,0,5,147,84,0,5,147,128,0,5,147,180,0,5,147,232,0,5,148,36,0,5,148,72,0,5,148,116,0,5,148,160, + 0,5,148,212,0,5,149,0,0,5,149,52,0,5,149,104,0,5,149,164,0,5,149,208,0,5,150,4,0,5,150,56,0,5,150,116,0,5,150,168, + 0,5,150,228,0,5,151,32,0,5,151,100,0,5,151,120,0,5,151,148,0,5,151,176,0,5,151,212,0,5,151,240,0,5,152,20,0,5,152,56, + 0,5,152,100,0,5,152,128,0,5,152,164,0,5,152,200,0,5,152,244,0,5,153,24,0,5,153,68,0,5,153,112,0,5,153,164,0,5,153,192, + 0,5,153,228,0,5,154,8,0,5,154,52,0,5,154,88,0,5,154,132,0,5,154,176,0,5,154,228,0,5,155,8,0,5,155,52,0,5,155,96, + 0,5,155,148,0,5,155,192,0,5,155,244,0,5,156,40,0,5,156,100,0,5,156,128,0,5,156,164,0,5,156,200,0,5,156,244,0,5,157,24, + 0,5,157,68,0,5,157,112,0,5,157,164,0,5,157,200,0,5,157,244,0,5,158,32,0,5,158,84,0,5,158,128,0,5,158,180,0,5,158,232, + 0,5,159,36,0,5,159,72,0,5,159,116,0,5,159,160,0,5,159,212,0,5,160,0,0,5,160,52,0,5,160,104,0,5,160,164,0,5,160,208, + 0,5,161,4,0,5,161,56,0,5,161,116,0,5,161,168,0,5,161,228,0,5,162,32,0,5,162,100,0,5,162,128,0,5,162,164,0,5,162,200, + 0,5,162,244,0,5,163,24,0,5,163,68,0,5,163,112,0,5,163,164,0,5,163,200,0,5,163,244,0,5,164,32,0,5,164,84,0,5,164,128, + 0,5,164,180,0,5,164,232,0,5,165,36,0,5,165,72,0,5,165,116,0,5,165,160,0,5,165,212,0,5,166,0,0,5,166,52,0,5,166,104, + 0,5,166,164,0,5,166,208,0,5,167,4,0,5,167,56,0,5,167,116,0,5,167,168,0,5,167,228,0,5,168,32,0,5,168,100,0,5,168,136, + 0,5,168,180,0,5,168,224,0,5,169,20,0,5,169,64,0,5,169,116,0,5,169,168,0,5,169,228,0,5,170,16,0,5,170,68,0,5,170,120, + 0,5,170,180,0,5,170,232,0,5,171,36,0,5,171,96,0,5,171,164,0,5,171,208,0,5,172,4,0,5,172,56,0,5,172,116,0,5,172,168, + 0,5,172,228,0,5,173,32,0,5,173,100,0,5,173,152,0,5,173,212,0,5,174,16,0,5,174,84,0,5,174,144,0,5,174,212,0,5,175,24, + 0,5,175,100,0,5,175,176,0,5,175,252,0,5,176,68,0,5,176,136,0,5,177,84,0,5,178,28,0,5,179,0,0,5,179,224,0,5,180,44, + 0,5,180,104,0,5,180,164,0,5,180,216,0,5,181,12,0,5,181,52,0,5,181,104,0,5,181,156,0,5,181,188,0,5,182,4,0,5,182,92, + 0,5,183,28,0,5,183,240,0,5,184,212,0,5,184,252,0,5,185,100,0,5,185,224,0,5,186,76,0,5,186,248,0,5,187,152,0,5,188,12, + 0,5,188,156,0,5,189,48,0,5,189,212,0,5,190,88,0,5,190,240,0,5,191,108,0,5,191,244,0,5,192,120,0,5,192,216,0,5,193,56, + 0,5,193,72,0,5,193,96,0,5,193,128,0,5,193,188,0,5,193,244,0,5,194,12,0,5,194,36,0,5,194,60,0,5,194,84,0,5,194,108, + 0,5,194,132,0,5,195,84,0,5,196,32,0,5,196,112,0,5,196,192,0,5,197,132,0,5,198,64,0,5,198,164,0,5,199,0,0,5,199,132, + 0,5,200,4,0,5,200,148,0,5,201,36,0,5,201,128,0,5,201,228,0,5,202,76,0,5,202,176,0,5,202,236,0,5,203,40,0,5,203,64, + 0,5,203,88,0,5,203,156,0,5,203,228,0,5,204,44,0,5,204,124,0,5,204,244,0,5,205,112,0,5,206,4,0,5,206,156,0,5,207,32, + 0,5,207,104,0,5,207,172,0,5,208,16,0,5,208,112,0,5,208,196,0,5,209,24,0,5,209,144,0,5,210,4,0,5,210,228,0,5,211,196, + 0,5,212,148,0,5,213,100,0,5,213,176,0,5,213,248,0,5,214,64,0,5,214,136,0,5,214,208,0,5,215,24,0,5,215,116,0,5,215,156, + 0,5,215,196,0,5,215,236,0,5,216,24,0,5,216,68,0,5,216,112,0,5,216,156,0,5,216,212,0,5,217,12,0,5,217,64,0,5,217,120, + 0,5,217,176,0,5,217,228,0,5,218,16,0,5,218,60,0,5,218,104,0,5,218,144,0,5,218,192,0,5,218,240,0,5,219,32,0,5,219,80, + 0,5,219,252,0,5,220,32,0,5,220,92,0,5,220,160,0,5,220,200,0,5,220,244,0,5,221,48,0,5,221,84,0,5,221,144,0,5,221,216, + 0,5,222,24,0,5,222,136,0,5,222,228,0,5,224,32,0,5,224,208,0,5,225,44,0,5,225,60,0,5,225,140,0,5,225,204,0,5,226,12, + 0,5,226,64,0,5,226,116,0,5,227,12,0,5,227,92,0,5,227,148,0,5,227,244,0,5,228,64,0,5,228,176,0,5,229,16,0,5,229,112, + 0,5,229,152,0,5,229,192,0,5,230,64,0,5,230,140,0,5,231,8,0,5,231,60,0,5,231,80,0,5,231,124,0,5,232,40,0,5,232,128, + 0,5,232,232,0,5,233,92,0,5,233,208,0,5,234,108,0,5,234,180,0,5,235,28,0,5,235,152,0,5,236,20,0,5,236,80,0,5,236,180, + 0,5,237,48,0,5,237,188,0,5,238,28,0,5,238,124,0,5,238,188,0,5,239,44,0,5,239,152,0,5,239,224,0,5,240,76,0,5,240,184, + 0,5,241,92,0,5,241,188,0,5,241,252,0,5,242,64,0,5,242,148,0,5,242,228,0,5,243,68,0,5,243,164,0,5,244,12,0,5,244,128, + 0,5,244,196,0,5,245,56,0,5,245,152,0,5,245,244,0,5,246,80,0,5,246,160,0,5,246,236,0,5,247,120,0,5,247,236,0,5,248,180, + 0,5,249,152,0,5,250,64,0,5,250,232,0,5,251,160,0,5,251,248,0,5,252,8,0,5,252,24,0,5,252,40,0,5,252,56,0,5,253,36, + 0,5,253,168,0,5,254,56,0,5,254,152,0,5,255,40,0,5,255,248,0,6,1,0,0,6,1,100,0,6,1,204,0,6,2,44,0,6,2,244, + 0,6,3,96,0,6,3,204,0,6,4,40,0,6,4,56,0,6,4,140,0,6,5,84,0,6,6,16,0,6,6,32,0,6,6,96,0,6,6,112, + 0,6,6,240,0,6,7,76,0,6,7,236,0,6,8,184,0,6,9,96,0,6,10,68,0,6,10,164,0,6,10,252,0,6,11,132,0,6,12,80, + 0,6,13,52,0,6,14,56,0,6,14,140,0,6,14,156,0,6,15,216,0,6,16,88,0,6,16,104,0,6,16,172,0,6,17,24,0,6,17,220, + 0,6,18,48,0,6,19,28,0,6,19,92,0,6,19,216,0,6,19,240,0,6,20,16,0,6,20,48,0,6,20,80,0,6,20,112,0,6,20,128, + 0,6,20,152,0,6,20,176,0,6,20,200,0,6,20,224,0,6,20,248,0,6,21,16,0,6,21,40,0,6,21,64,0,6,21,88,0,6,21,112, + 0,6,21,136,0,6,21,160,0,6,21,184,0,6,21,208,0,6,21,232,0,6,22,0,0,6,22,24,0,6,22,48,0,6,22,72,0,6,22,96, + 0,6,22,120,0,6,22,144,0,6,22,168,0,6,22,192,0,6,22,216,0,6,22,240,0,6,23,8,0,6,23,32,0,6,23,56,0,6,23,80, + 0,6,23,104,0,6,23,128,0,6,23,152,0,6,23,176,0,6,23,200,0,6,23,224,0,6,23,248,0,6,24,16,0,6,24,40,0,6,24,64, + 0,6,24,88,0,6,24,112,0,6,24,136,0,6,24,160,0,6,24,184,0,6,24,208,0,6,24,232,0,6,25,0,0,6,25,24,0,6,25,48, + 0,6,25,72,0,6,25,96,0,6,25,120,0,6,25,144,0,6,25,168,0,6,25,192,0,6,25,216,0,6,25,240,0,6,26,8,0,6,26,32, + 0,6,26,56,0,6,26,80,0,6,26,104,0,6,26,128,0,6,26,144,0,6,26,160,0,6,26,232,0,6,26,248,0,6,27,8,0,6,27,44, + 0,6,27,60,0,6,27,76,0,6,27,132,0,6,27,148,0,6,27,164,0,6,27,180,0,6,27,196,0,6,27,212,0,6,27,228,0,6,27,244, + 0,6,28,4,0,6,28,20,0,6,28,36,0,6,28,52,0,6,28,152,0,6,28,168,0,6,28,184,0,6,28,200,0,6,28,216,0,6,29,20, + 0,6,29,36,0,6,29,52,0,6,29,68,0,6,29,180,0,6,29,196,0,6,29,212,0,6,29,228,0,6,30,20,0,6,30,36,0,6,30,52, + 0,6,30,68,0,6,30,176,0,6,30,192,0,6,31,48,0,6,31,76,0,6,31,112,0,6,31,136,0,6,31,160,0,6,31,212,0,6,32,0, + 0,6,32,44,0,6,32,84,0,6,32,100,0,6,32,116,0,6,32,132,0,6,32,148,0,6,33,112,0,6,34,32,0,6,34,56,0,6,34,80, + 0,6,34,200,0,6,35,48,0,6,35,128,0,6,36,8,0,6,36,104,0,6,36,196,0,6,37,4,0,6,37,68,0,6,37,136,0,6,37,200, + 0,6,37,224,0,6,37,248,0,6,38,108,0,6,38,224,0,6,39,0,0,6,39,32,0,6,40,168,0,6,41,8,0,6,41,108,0,6,41,164, + 0,6,41,228,0,6,42,92,0,6,42,108,0,6,42,148,0,6,42,188,0,6,42,228,0,6,43,12,0,6,43,52,0,6,43,92,0,6,43,132, + 0,6,43,172,0,6,43,212,0,6,43,248,0,6,44,24,0,6,44,60,0,6,44,96,0,6,44,132,0,6,44,164,0,6,44,208,0,6,44,252, + 0,6,45,40,0,6,45,84,0,6,45,104,0,6,45,172,0,6,45,240,0,6,46,32,0,6,46,80,0,6,46,148,0,6,46,236,0,6,47,112, + 0,6,48,0,0,6,48,16,0,6,48,160,0,6,48,204,0,6,48,220,0,6,49,64,0,6,50,28,0,6,50,164,0,6,51,84,0,6,51,176, + 0,6,52,68,0,6,52,140,0,6,53,8,0,6,53,100,0,6,53,244,0,6,54,88,0,6,54,240,0,6,55,0,0,6,55,16,0,6,55,88, + 0,6,55,160,0,6,55,204,0,6,55,244,0,6,56,36,0,6,56,80,0,6,56,216,0,6,57,92,0,6,58,20,0,6,58,184,0,6,59,20, + 0,6,59,128,0,6,59,248,0,6,60,144,0,6,61,28,0,6,61,132,0,6,61,224,0,6,62,72,0,6,62,160,0,6,63,12,0,6,63,44, + 0,6,63,76,0,6,63,148,0,6,63,216,0,6,63,232,0,6,64,16,0,6,64,108,0,6,64,192,0,6,64,208,0,6,65,48,0,6,65,108, + 0,6,65,184,0,6,66,72,0,6,66,252,0,6,67,92,0,6,67,184,0,6,68,36,0,6,68,148,0,6,69,40,0,6,69,128,0,6,70,24, + 0,6,70,172,0,6,70,244,0,6,71,4,0,6,71,48,0,6,71,120,0,6,71,180,0,6,71,208,0,6,72,28,0,6,72,72,0,6,72,104, + 0,6,72,140,0,6,72,176,0,6,72,212,0,6,72,244,0,6,73,8,0,6,73,28,0,6,73,48,0,6,73,68,0,6,73,104,0,6,73,124, + 0,6,73,144,0,6,73,164,0,6,73,184,0,6,73,220,0,6,73,240,0,6,74,4,0,6,74,24,0,6,74,44,0,6,74,80,0,6,74,100, + 0,6,74,120,0,6,74,140,0,6,74,168,0,6,74,208,0,6,77,124,0,6,80,44,0,6,82,216,0,6,85,136,0,6,85,220,0,6,86,68, + 0,6,86,184,0,6,87,96,0,6,87,188,0,6,88,44,0,6,88,176,0,6,89,48,0,6,89,132,0,6,89,232,0,6,90,152,0,6,91,4, + 0,6,91,100,0,6,91,216,0,6,92,60,0,6,92,148,0,6,93,32,0,6,93,112,0,6,93,240,0,6,94,88,0,6,95,8,0,6,95,104, + 0,6,95,252,0,6,96,100,0,6,96,216,0,6,97,64,0,6,97,192,0,6,98,20,0,6,98,136,0,6,99,0,0,6,99,84,0,6,99,204, + 0,6,100,60,0,6,100,180,0,6,101,44,0,6,101,144,0,6,102,0,0,6,102,132,0,6,103,24,0,6,103,164,0,6,104,116,0,6,104,200, + 0,6,105,40,0,6,105,152,0,6,105,240,0,6,106,84,0,6,106,184,0,6,107,24,0,6,107,124,0,6,107,236,0,6,108,92,0,6,108,180, + 0,6,109,12,0,6,109,112,0,6,109,232,0,6,110,104,0,6,110,248,0,6,111,112,0,6,111,248,0,6,112,112,0,6,112,244,0,6,113,132, + 0,6,113,252,0,6,114,132,0,6,115,8,0,6,115,124,0,6,116,44,0,6,116,208,0,6,117,80,0,6,118,48,0,6,118,240,0,6,119,112, + 0,6,120,104,0,6,121,52,0,6,121,220,0,6,122,120,0,6,123,40,0,6,123,240,0,6,124,8,0,6,124,60,0,6,124,84,0,6,124,160, + 0,6,125,12,0,6,125,52,0,6,125,132,0,6,125,216,0,6,126,4,0,6,126,76,0,6,126,136,0,6,126,232,0,6,127,16,0,6,127,40, + 0,6,127,64,0,6,127,96,0,6,127,128,0,6,127,152,0,6,127,176,0,6,127,200,0,6,127,224,0,6,127,248,0,6,128,16,0,6,128,40, + 0,6,128,68,0,6,128,92,0,6,128,116,0,6,128,144,0,6,128,168,0,6,128,192,0,6,128,216,0,6,128,240,0,6,129,8,0,6,129,32, + 0,6,129,56,0,6,129,80,0,6,129,104,0,6,129,128,0,6,129,152,0,6,129,176,0,6,129,200,0,6,129,224,0,6,129,248,0,6,130,16, + 0,6,130,40,0,6,130,172,0,6,130,196,0,6,130,220,0,6,130,244,0,6,131,12,0,6,131,36,0,6,131,60,0,6,131,84,0,6,131,108, + 0,6,131,132,0,6,131,156,0,6,131,180,0,6,131,204,0,6,131,228,0,6,131,252,0,6,132,20,0,6,132,44,0,6,132,68,0,6,132,92, + 0,6,132,116,0,6,132,140,0,6,132,164,0,6,132,188,0,6,132,212,0,6,132,236,0,6,133,4,0,6,133,28,0,6,133,52,0,6,133,76, + 0,6,133,100,0,6,133,124,0,6,133,148,0,6,133,172,0,6,133,196,0,6,133,220,0,6,133,244,0,6,134,12,0,6,134,36,0,6,134,60, + 0,6,134,84,0,6,134,108,0,6,134,132,0,6,134,156,0,6,134,180,0,6,134,204,0,6,134,228,0,6,134,252,0,6,135,20,0,6,135,44, + 0,6,135,68,0,6,135,92,0,6,135,116,0,6,135,140,0,6,135,164,0,6,135,188,0,6,135,212,0,6,135,236,0,6,136,4,0,6,136,28, + 0,6,136,52,0,6,136,76,0,6,136,92,0,6,137,8,0,6,137,24,0,6,137,40,0,6,137,64,0,6,137,88,0,6,137,112,0,6,137,136, + 0,6,137,160,0,6,137,184,0,6,137,208,0,6,137,232,0,6,138,0,0,6,138,24,0,6,138,48,0,6,138,72,0,6,138,88,0,6,138,208, + 0,6,138,232,0,6,139,0,0,6,139,24,0,6,139,48,0,6,139,64,0,6,139,228,0,6,139,244,0,6,140,4,0,6,140,28,0,6,140,52, + 0,6,140,76,0,6,140,100,0,6,140,124,0,6,140,148,0,6,140,196,0,6,141,4,0,6,141,20,0,6,141,36,0,6,141,60,0,6,141,84, + 0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84, + 0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,84,0,6,141,124,0,6,141,164,0,6,141,236,0,6,142,52, + 0,6,142,72,0,6,142,96,0,6,142,116,0,6,142,168,0,6,142,188,0,6,142,208,0,6,142,232,0,6,142,252,0,6,143,20,0,6,143,40, + 0,6,143,64,0,6,143,84,0,6,143,108,0,6,143,128,0,6,143,152,0,6,143,168,0,6,143,192,0,6,143,216,0,6,143,240,0,6,144,8, + 0,6,144,32,0,6,144,56,0,6,144,80,0,6,144,104,0,6,144,128,0,6,144,152,0,6,144,176,0,6,144,200,0,6,144,216,0,6,145,12, + 0,6,145,36,0,6,145,60,0,6,145,84,0,6,145,108,0,6,145,132,0,6,145,156,0,6,145,180,0,6,145,204,0,6,145,228,0,6,145,252, + 0,6,146,20,0,6,146,44,0,6,146,68,0,6,146,92,0,6,146,116,0,6,146,140,0,6,146,164,0,6,146,188,0,6,146,204,0,6,147,96, + 0,6,147,200,0,6,148,76,0,6,148,100,0,6,148,124,0,6,148,148,0,6,148,172,0,6,148,188,0,6,149,32,0,6,149,56,0,6,149,80, + 0,6,149,96,0,6,149,180,0,6,149,204,0,6,149,228,0,6,149,244,0,6,150,200,0,6,151,88,0,6,151,248,0,6,152,16,0,6,152,40, + 0,6,152,64,0,6,152,88,0,6,152,104,0,6,153,68,0,6,153,208,0,6,154,116,0,6,154,140,0,6,154,164,0,6,154,188,0,6,154,212, + 0,6,154,228,0,6,155,104,0,6,155,212,0,6,156,88,0,6,156,112,0,6,156,136,0,6,156,160,0,6,156,184,0,6,156,200,0,6,157,80, + 0,6,157,168,0,6,158,56,0,6,158,80,0,6,158,104,0,6,158,128,0,6,158,152,0,6,158,176,0,6,158,200,0,6,158,224,0,6,158,248, + 0,6,159,16,0,6,159,40,0,6,159,64,0,6,159,88,0,6,159,104,0,6,160,52,0,6,160,160,0,6,161,40,0,6,161,56,0,6,161,172, + 0,6,161,224,0,6,162,36,0,6,162,52,0,6,162,212,0,6,163,68,0,6,163,212,0,6,163,236,0,6,164,4,0,6,164,28,0,6,164,52, + 0,6,164,68,0,6,164,188,0,6,165,120,0,6,166,8,0,6,166,24,0,6,166,172,0,6,166,188,0,6,167,96,0,6,167,120,0,6,167,144, + 0,6,167,168,0,6,167,192,0,6,167,216,0,6,167,240,0,6,168,8,0,6,168,32,0,6,168,56,0,6,168,80,0,6,168,164,0,6,169,12, + 0,6,169,12,0,6,169,12,0,6,169,12,0,6,169,12,0,6,169,12,0,6,169,152,0,6,169,212,0,6,170,76,0,6,170,120,0,6,170,200, + 0,6,171,8,0,6,171,56,0,6,171,100,0,6,171,160,0,6,172,60,0,6,172,88,0,6,172,144,0,6,172,184,0,6,172,248,0,6,173,40, + 0,6,173,132,0,6,174,20,0,6,174,92,0,6,174,148,0,6,174,252,0,6,175,84,0,6,175,140,0,6,175,184,0,6,175,224,0,6,176,36, + 0,6,176,160,0,6,176,216,0,6,177,88,0,6,177,156,0,6,177,228,0,6,178,8,0,6,178,80,0,6,178,96,0,6,178,140,0,6,178,156, + 0,6,178,208,0,6,179,8,0,6,179,36,0,6,179,64,0,6,179,92,0,6,179,120,0,6,179,148,0,6,179,188,0,6,179,228,0,6,180,16, + 0,6,180,56,0,6,180,96,0,6,180,140,0,6,180,180,0,6,180,220,0,6,181,4,0,6,181,44,0,6,181,84,0,6,181,128,0,6,181,168, + 0,6,181,208,0,6,181,252,0,6,182,36,0,6,182,76,0,6,182,116,0,6,182,156,0,6,182,196,0,6,182,240,0,6,183,24,0,6,183,64, + 0,6,183,108,0,6,183,148,0,6,183,188,0,6,183,228,0,6,184,12,0,6,184,52,0,6,184,96,0,6,184,136,0,6,184,176,0,6,184,220, + 0,6,185,4,0,6,185,44,0,6,185,84,0,6,185,124,0,6,185,164,0,6,185,208,0,6,185,248,0,6,186,32,0,6,186,76,0,6,186,116, + 0,6,186,156,0,6,186,196,0,6,186,236,0,6,187,20,0,6,187,64,0,6,187,104,0,6,187,144,0,6,187,188,0,6,187,228,0,6,188,12, + 0,6,188,52,0,6,188,92,0,6,188,132,0,6,188,176,0,6,188,216,0,6,189,0,0,6,189,44,0,6,189,84,0,6,189,124,0,6,189,164, + 0,6,189,204,0,6,189,244,0,6,190,32,0,6,190,72,0,6,190,112,0,6,190,156,0,6,190,196,0,6,190,236,0,6,191,20,0,6,191,60, + 0,6,191,100,0,6,191,144,0,6,191,184,0,6,191,224,0,6,192,12,0,6,192,52,0,6,192,92,0,6,192,132,0,6,192,208,0,6,193,96, + 0,6,193,204,0,6,194,12,0,6,194,72,0,6,194,212,0,6,195,16,0,6,195,92,0,6,195,160,0,6,195,208,0,6,196,44,0,6,196,200, + 0,6,197,100,0,6,197,156,0,6,198,16,0,6,198,76,0,6,198,180,0,6,199,8,0,6,199,80,0,6,199,244,0,6,200,144,0,6,201,8, + 0,6,201,164,0,6,202,28,0,6,202,132,0,6,203,76,0,6,203,192,0,6,203,248,0,6,204,84,0,6,204,152,0,6,204,228,0,6,205,160, + 0,6,206,20,0,6,206,160,0,6,207,60,0,6,207,216,0,6,208,36,0,6,208,240,0,6,209,76,0,6,209,192,0,6,209,252,0,6,210,92, + 0,6,210,176,0,6,211,0,0,6,211,68,0,6,211,84,0,6,211,100,0,6,211,116,0,6,211,132,0,6,211,148,0,6,211,164,0,6,211,180, + 0,6,211,196,0,6,211,212,0,6,211,228,0,6,211,244,0,6,212,4,0,6,212,20,0,6,212,36,0,6,212,52,0,6,212,68,0,6,212,84, + 0,6,212,100,0,6,212,116,0,6,212,132,0,6,212,148,0,6,212,164,0,6,212,180,0,6,212,196,0,6,212,212,0,6,212,228,0,6,212,244, + 0,6,213,4,0,6,213,20,0,6,213,36,0,6,213,52,0,6,213,68,0,6,213,84,0,6,213,100,0,6,213,116,0,6,213,132,0,6,213,148, + 0,6,213,164,0,6,213,180,0,6,213,196,0,6,213,212,0,6,213,228,0,6,213,244,0,6,214,4,0,6,214,20,0,6,214,36,0,6,214,52, + 0,6,214,68,0,6,214,84,0,6,214,100,0,6,214,116,0,6,214,132,0,6,214,240,0,6,215,48,0,6,215,192,0,6,216,84,0,6,216,160, + 0,6,217,16,0,6,217,156,0,6,217,216,0,6,218,180,0,6,219,64,0,6,219,80,0,6,219,96,0,6,219,112,0,6,219,128,0,6,219,144, + 0,6,219,160,0,6,219,176,0,6,219,192,0,6,219,208,0,6,219,224,0,6,220,12,0,6,220,68,0,6,220,192,0,6,221,124,0,6,222,120, + 0,6,223,180,0,6,225,48,0,6,226,228,0,6,227,96,0,6,228,28,0,6,229,28,0,6,230,88,0,6,231,212,0,6,233,144,0,6,235,132, + 0,6,236,64,0,6,237,60,0,6,238,120,0,6,239,244,0,6,241,164,0,6,243,160,0,6,245,212,0,6,246,208,0,6,248,12,0,6,249,140, + 0,6,251,72,0,6,253,68,0,6,255,128,0,7,1,244,0,7,3,40,0,7,4,156,0,7,6,92,0,7,8,88,0,7,10,148,0,7,13,16, + 0,7,15,196,0,7,17,60,0,7,18,248,0,7,20,248,0,7,23,52,0,7,25,176,0,7,28,108,0,7,31,96,0,7,33,32,0,7,35,40, + 0,7,37,112,0,7,39,248,0,7,42,188,0,7,45,196,0,7,48,244,0,7,49,32,0,7,49,88,0,7,49,212,0,7,50,144,0,7,51,140, + 0,7,52,200,0,7,54,68,0,7,55,248,0,7,56,116,0,7,57,48,0,7,58,48,0,7,59,108,0,7,60,232,0,7,62,164,0,7,64,152, + 0,7,65,84,0,7,66,80,0,7,67,140,0,7,69,8,0,7,70,196,0,7,72,192,0,7,74,244,0,7,75,240,0,7,77,44,0,7,78,172, + 0,7,80,104,0,7,82,100,0,7,84,160,0,7,87,20,0,7,88,72,0,7,89,188,0,7,91,120,0,7,93,116,0,7,95,176,0,7,98,28, + 0,7,100,208,0,7,102,72,0,7,104,4,0,7,105,244,0,7,108,48,0,7,110,172,0,7,113,104,0,7,116,92,0,7,118,32,0,7,120,40, + 0,7,122,112,0,7,124,244,0,7,127,184,0,7,130,168,0,7,133,216,0,7,134,52,0,7,134,240,0,7,135,204,0,7,136,200,0,7,137,136, + 0,7,138,116,0,7,139,140,0,7,140,56,0,7,141,108,0,7,142,128,0,7,143,112,0,7,144,36,0,7,144,252,0,7,145,220,0,7,146,152, + 0,7,147,80,0,7,148,40,0,7,149,32,0,7,149,220,0,7,150,196,0,7,151,216,0,7,152,128,0,7,153,176,0,7,154,192,0,7,155,172, + 0,7,156,92,0,7,157,48,0,7,158,12,0,7,158,196,0,7,159,84,0,7,160,4,0,7,160,212,0,7,161,100,0,7,162,36,0,7,163,12, + 0,7,163,140,0,7,164,148,0,7,165,124,0,7,166,64,0,7,166,200,0,7,167,116,0,7,168,40,0,7,168,180,0,7,169,48,0,7,170,8, + 0,7,171,0,0,7,172,24,0,7,172,240,0,7,173,248,0,7,175,40,0,7,175,240,0,7,177,64,0,7,178,112,0,7,179,124,0,7,180,76, + 0,7,181,64,0,7,182,60,0,7,183,16,0,7,183,180,0,7,185,188,0,7,188,164,0,7,190,204,0,7,192,236,0,7,193,236,0,7,194,236, + 0,7,196,132,0,7,197,100,0,7,198,68,0,7,199,72,0,7,200,28,0,7,201,88,0,7,202,100,0,7,203,60,0,7,204,28,0,7,205,40, + 0,7,206,8,0,7,207,48,0,7,208,4,0,7,208,172,0,7,209,100,0,7,209,248,0,7,210,184,0,7,211,172,0,7,212,100,0,7,213,28, + 0,7,214,20,0,7,214,232,0,7,215,252,0,7,216,212,0,7,217,172,0,7,218,132,0,7,219,84,0,7,220,32,0,7,221,32,0,7,222,80, + 0,7,223,80,0,7,224,132,0,7,225,148,0,7,226,104,0,7,227,76,0,7,228,44,0,7,229,44,0,7,231,40,0,7,232,20,0,7,233,40, + 0,7,233,252,0,7,235,72,0,7,236,12,0,7,236,240,0,7,237,240,0,7,239,188,0,7,240,252,0,7,242,124,0,7,243,156,0,7,244,112, + 0,7,245,24,0,7,245,248,0,7,248,64,0,7,250,196,0,7,253,52,0,7,255,60,0,8,1,116,0,8,3,180,0,8,6,4,0,8,7,196, + 0,8,9,132,0,8,9,168,0,8,10,116,0,8,11,16,0,8,11,224,0,8,12,136,0,8,13,36,0,8,13,208,0,8,14,4,0,8,14,164, + 0,8,15,4,0,8,15,64,0,8,15,108,0,8,15,132,0,8,15,168,0,8,15,216,0,8,16,8,0,8,16,44,0,8,16,100,0,8,16,224, + 0,8,16,240,0,8,17,0,0,8,17,192,0,8,18,92,0,8,18,252,0,8,19,196,0,8,19,212,0,8,19,228,0,8,19,252,0,8,20,20, + 0,8,20,100,0,8,20,132,0,8,20,164,0,8,20,196,0,8,20,220,0,8,20,244,0,8,21,12,0,8,21,36,0,8,21,60,0,8,21,84, + 0,8,21,108,0,8,21,132,0,8,21,156,0,8,21,180,0,8,21,204,0,8,21,228,0,8,22,4,0,8,22,36,0,8,22,68,0,8,22,100, + 0,8,22,244,0,8,23,84,0,8,23,164,0,8,23,192,0,8,23,220,0,8,23,248,0,8,24,20,0,8,24,48,0,8,24,76,0,8,24,104, + 0,8,24,132,0,8,24,160,0,8,24,188,0,8,24,216,0,8,24,244,0,8,25,16,0,8,25,44,0,8,25,72,0,8,25,100,0,8,25,128, + 0,8,25,156,0,8,25,184,0,8,25,212,0,8,25,236,0,8,26,8,0,8,26,64,0,8,26,88,0,8,26,172,0,8,26,196,0,8,26,220, + 0,8,26,244,0,8,27,12,0,8,27,44,0,8,27,76,0,8,27,100,0,8,27,200,0,8,27,216,0,8,27,232,0,8,27,248,0,8,28,16, + 0,8,28,60,0,8,28,148,0,8,28,172,0,8,28,196,0,8,28,232,0,8,29,64,0,8,29,92,0,8,29,116,0,8,29,140,0,8,29,164, + 0,8,29,188,0,8,29,212,0,8,29,236,0,8,30,4,0,8,30,28,0,8,30,84,0,8,30,148,0,8,30,204,0,8,31,92,0,8,31,252, + 0,8,32,140,0,8,32,244,0,8,33,100,0,8,33,204,0,8,33,252,0,8,34,44,0,8,34,88,0,8,34,168,0,8,35,0,0,8,35,76, + 0,8,35,152,0,8,35,228,0,8,36,44,0,8,36,212,0,8,37,132,0,8,38,40,0,8,38,132,0,8,38,220,0,8,39,52,0,8,39,204, + 0,8,40,112,0,8,41,12,0,8,41,104,0,8,41,204,0,8,42,40,0,8,42,132,0,8,42,232,0,8,43,68,0,8,43,196,0,8,44,72, + 0,8,44,204,0,8,45,88,0,8,45,240,0,8,46,124,0,8,46,224,0,8,47,76,0,8,47,176,0,8,48,84,0,8,49,0,0,8,49,164, + 0,8,50,8,0,8,50,116,0,8,50,216,0,8,51,100,0,8,51,248,0,8,52,132,0,8,52,216,0,8,53,52,0,8,53,136,0,8,54,0, + 0,8,54,128,0,8,54,248,0,8,55,160,0,8,56,80,0,8,56,248,0,8,57,92,0,8,57,200,0,8,58,44,0,8,58,196,0,8,59,104, + 0,8,60,0,0,8,60,80,0,8,60,168,0,8,60,248,0,8,61,108,0,8,61,228,0,8,62,88,0,8,62,220,0,8,63,100,0,8,63,232, + 0,8,64,56,0,8,64,144,0,8,64,224,0,8,65,56,0,8,65,152,0,8,65,240,0,8,66,92,0,8,66,208,0,8,67,60,0,8,68,0, + 0,8,68,204,0,8,69,144,0,8,70,24,0,8,70,164,0,8,71,44,0,8,71,64,0,8,71,100,0,8,71,136,0,8,71,172,0,8,71,208, + 0,8,71,244,0,8,72,24,0,8,72,60,0,8,72,96,0,8,72,204,0,8,73,8,0,8,73,68,0,8,73,176,0,8,73,200,0,8,73,224, + 0,8,74,0,0,8,74,24,0,8,74,48,0,8,74,72,0,8,74,96,0,8,74,128,0,8,74,152,0,8,74,176,0,8,74,208,0,8,74,240, + 0,8,75,16,0,8,75,40,0,8,75,64,0,8,75,88,0,8,75,120,0,8,75,152,0,8,75,184,0,8,75,208,0,8,75,232,0,8,76,0, + 0,8,76,24,0,8,76,48,0,8,76,72,0,8,76,96,0,8,76,120,0,8,76,144,0,8,76,168,0,8,76,192,0,8,76,216,0,8,76,240, + 0,8,77,8,0,8,77,32,0,8,77,64,0,8,77,96,0,8,77,128,0,8,77,152,0,8,77,176,0,8,77,200,0,8,77,224,0,8,77,248, + 0,8,78,16,0,8,78,40,0,8,78,64,0,8,78,88,0,8,79,4,0,8,79,116,0,8,79,248,0,8,80,16,0,8,80,40,0,8,80,64, + 0,8,80,88,0,8,80,112,0,8,80,136,0,8,80,160,0,8,80,184,0,8,80,208,0,8,80,232,0,8,81,0,0,8,81,24,0,8,81,48, + 0,8,81,72,0,8,81,96,0,8,81,120,0,8,81,144,0,8,81,168,0,8,81,192,0,8,81,216,0,8,81,240,0,8,82,8,0,8,82,32, + 0,8,82,56,0,8,82,80,0,8,82,104,0,8,82,128,0,8,82,160,0,8,82,192,0,8,82,224,0,8,83,0,0,8,83,32,0,8,83,64, + 0,8,83,88,0,8,83,112,0,8,83,136,0,1,0,0,23,220,3,84,0,43,0,104,0,12,0,2,0,16,0,153,0,8,0,0,4,21,2,22, + 0,8,0,4,0,0,0,26,1,62,0,1,0,0,0,0,0,0,0,152,1,50,0,1,0,0,0,0,0,1,0,11,1,227,0,1,0,0,0,0, + 0,2,0,4,1,249,0,1,0,0,0,0,0,3,0,11,2,22,0,1,0,0,0,0,0,4,0,11,2,58,0,1,0,0,0,0,0,5,0,12, + 2,96,0,1,0,0,0,0,0,6,0,10,2,131,0,1,0,0,0,0,0,8,0,17,2,178,0,1,0,0,0,0,0,11,0,29,3,0,0,1, + 0,0,0,0,0,13,18,157,40,90,0,1,0,0,0,0,0,14,0,52,59,98,0,1,0,0,0,0,0,16,0,11,59,175,0,1,0,0,0,0, + 0,17,0,4,59,197,0,3,0,1,4,9,0,0,1,48,0,0,0,3,0,1,4,9,0,1,0,22,1,203,0,3,0,1,4,9,0,2,0,8, + 1,239,0,3,0,1,4,9,0,3,0,22,1,254,0,3,0,1,4,9,0,4,0,22,2,34,0,3,0,1,4,9,0,5,0,24,2,70,0,3, + 0,1,4,9,0,6,0,20,2,109,0,3,0,1,4,9,0,8,0,34,2,142,0,3,0,1,4,9,0,11,0,58,2,196,0,3,0,1,4,9, + 0,13,37,58,3,30,0,3,0,1,4,9,0,14,0,104,58,248,0,3,0,1,4,9,0,16,0,22,59,151,0,3,0,1,4,9,0,17,0,8, + 59,187,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,48,0,51,0,32, + 0,98,0,121,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,44,0,32,0,73,0,110,0,99,0,46,0,32,0,65, + 0,108,0,108,0,32,0,82,0,105,0,103,0,104,0,116,0,115,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,46,0,10, + 0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,48,0,54,0,32,0,98, + 0,121,0,32,0,84,0,97,0,118,0,109,0,106,0,111,0,110,0,103,0,32,0,66,0,97,0,104,0,46,0,32,0,65,0,108,0,108,0,32, + 0,82,0,105,0,103,0,104,0,116,0,115,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,46,0,10,0,68,0,101,0,106, + 0,97,0,86,0,117,0,32,0,99,0,104,0,97,0,110,0,103,0,101,0,115,0,32,0,97,0,114,0,101,0,32,0,105,0,110,0,32,0,112, + 0,117,0,98,0,108,0,105,0,99,0,32,0,100,0,111,0,109,0,97,0,105,0,110,0,10,0,0,67,111,112,121,114,105,103,104,116,32,40,99, + 41,32,50,48,48,51,32,98,121,32,66,105,116,115,116,114,101,97,109,44,32,73,110,99,46,32,65,108,108,32,82,105,103,104,116,115,32,82,101,115, + 101,114,118,101,100,46,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,48,54,32,98,121,32,84,97,118,109,106,111,110,103,32,66,97, + 104,46,32,65,108,108,32,82,105,103,104,116,115,32,82,101,115,101,114,118,101,100,46,10,68,101,106,97,86,117,32,99,104,97,110,103,101,115,32,97, + 114,101,32,105,110,32,112,117,98,108,105,99,32,100,111,109,97,105,110,10,0,0,68,0,101,0,106,0,97,0,86,0,117,0,32,0,83,0,97,0, + 110,0,115,0,0,68,101,106,97,86,117,32,83,97,110,115,0,0,66,0,111,0,111,0,107,0,0,66,111,111,107,0,0,68,0,101,0,106,0,97, + 0,86,0,117,0,32,0,83,0,97,0,110,0,115,0,0,68,101,106,97,86,117,32,83,97,110,115,0,0,68,0,101,0,106,0,97,0,86,0,117, + 0,32,0,83,0,97,0,110,0,115,0,0,68,101,106,97,86,117,32,83,97,110,115,0,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,32, + 0,50,0,46,0,51,0,52,0,0,86,101,114,115,105,111,110,32,50,46,51,52,0,0,68,0,101,0,106,0,97,0,86,0,117,0,83,0,97,0, + 110,0,115,0,0,68,101,106,97,86,117,83,97,110,115,0,0,68,0,101,0,106,0,97,0,86,0,117,0,32,0,102,0,111,0,110,0,116,0,115, + 0,32,0,116,0,101,0,97,0,109,0,0,68,101,106,97,86,117,32,102,111,110,116,115,32,116,101,97,109,0,0,104,0,116,0,116,0,112,0,58, + 0,47,0,47,0,100,0,101,0,106,0,97,0,118,0,117,0,46,0,115,0,111,0,117,0,114,0,99,0,101,0,102,0,111,0,114,0,103,0,101, + 0,46,0,110,0,101,0,116,0,0,104,116,116,112,58,47,47,100,101,106,97,118,117,46,115,111,117,114,99,101,102,111,114,103,101,46,110,101,116,0, + 0,70,0,111,0,110,0,116,0,115,0,32,0,97,0,114,0,101,0,32,0,40,0,99,0,41,0,32,0,66,0,105,0,116,0,115,0,116,0,114, + 0,101,0,97,0,109,0,32,0,40,0,115,0,101,0,101,0,32,0,98,0,101,0,108,0,111,0,119,0,41,0,46,0,32,0,68,0,101,0,106, + 0,97,0,86,0,117,0,32,0,99,0,104,0,97,0,110,0,103,0,101,0,115,0,32,0,97,0,114,0,101,0,32,0,105,0,110,0,32,0,112, + 0,117,0,98,0,108,0,105,0,99,0,32,0,100,0,111,0,109,0,97,0,105,0,110,0,46,0,32,0,71,0,108,0,121,0,112,0,104,0,115, + 0,32,0,105,0,109,0,112,0,111,0,114,0,116,0,101,0,100,0,32,0,102,0,114,0,111,0,109,0,32,0,65,0,114,0,101,0,118,0,32, + 0,102,0,111,0,110,0,116,0,115,0,32,0,97,0,114,0,101,0,32,0,40,0,99,0,41,0,32,0,84,0,97,0,118,0,109,0,106,0,117, + 0,110,0,103,0,32,0,66,0,97,0,104,0,32,0,40,0,115,0,101,0,101,0,32,0,98,0,101,0,108,0,111,0,119,0,41,0,10,0,10, + 0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,86,0,101,0,114,0,97,0,32,0,70,0,111,0,110,0,116,0,115, + 0,32,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,10,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45, + 0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45, + 0,45,0,10,0,10,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32,0,50,0,48,0,48, + 0,51,0,32,0,98,0,121,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,44,0,32,0,73,0,110,0,99,0,46, + 0,32,0,65,0,108,0,108,0,32,0,82,0,105,0,103,0,104,0,116,0,115,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101,0,100, + 0,46,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,86,0,101,0,114,0,97,0,32,0,105,0,115,0,10, + 0,97,0,32,0,116,0,114,0,97,0,100,0,101,0,109,0,97,0,114,0,107,0,32,0,111,0,102,0,32,0,66,0,105,0,116,0,115,0,116, + 0,114,0,101,0,97,0,109,0,44,0,32,0,73,0,110,0,99,0,46,0,10,0,10,0,80,0,101,0,114,0,109,0,105,0,115,0,115,0,105, + 0,111,0,110,0,32,0,105,0,115,0,32,0,104,0,101,0,114,0,101,0,98,0,121,0,32,0,103,0,114,0,97,0,110,0,116,0,101,0,100, + 0,44,0,32,0,102,0,114,0,101,0,101,0,32,0,111,0,102,0,32,0,99,0,104,0,97,0,114,0,103,0,101,0,44,0,32,0,116,0,111, + 0,32,0,97,0,110,0,121,0,32,0,112,0,101,0,114,0,115,0,111,0,110,0,32,0,111,0,98,0,116,0,97,0,105,0,110,0,105,0,110, + 0,103,0,32,0,97,0,32,0,99,0,111,0,112,0,121,0,10,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,102,0,111,0,110,0,116, + 0,115,0,32,0,97,0,99,0,99,0,111,0,109,0,112,0,97,0,110,0,121,0,105,0,110,0,103,0,32,0,116,0,104,0,105,0,115,0,32, + 0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,40,0,34,0,70,0,111,0,110,0,116,0,115,0,34,0,41,0,32,0,97,0,110, + 0,100,0,32,0,97,0,115,0,115,0,111,0,99,0,105,0,97,0,116,0,101,0,100,0,10,0,100,0,111,0,99,0,117,0,109,0,101,0,110, + 0,116,0,97,0,116,0,105,0,111,0,110,0,32,0,102,0,105,0,108,0,101,0,115,0,32,0,40,0,116,0,104,0,101,0,32,0,34,0,70, + 0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,34,0,41,0,44,0,32,0,116,0,111,0,32,0,114, + 0,101,0,112,0,114,0,111,0,100,0,117,0,99,0,101,0,32,0,97,0,110,0,100,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98, + 0,117,0,116,0,101,0,32,0,116,0,104,0,101,0,10,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114, + 0,101,0,44,0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,105,0,110,0,103,0,32,0,119,0,105,0,116,0,104,0,111,0,117,0,116, + 0,32,0,108,0,105,0,109,0,105,0,116,0,97,0,116,0,105,0,111,0,110,0,32,0,116,0,104,0,101,0,32,0,114,0,105,0,103,0,104, + 0,116,0,115,0,32,0,116,0,111,0,32,0,117,0,115,0,101,0,44,0,32,0,99,0,111,0,112,0,121,0,44,0,32,0,109,0,101,0,114, + 0,103,0,101,0,44,0,10,0,112,0,117,0,98,0,108,0,105,0,115,0,104,0,44,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98, + 0,117,0,116,0,101,0,44,0,32,0,97,0,110,0,100,0,47,0,111,0,114,0,32,0,115,0,101,0,108,0,108,0,32,0,99,0,111,0,112, + 0,105,0,101,0,115,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116, + 0,119,0,97,0,114,0,101,0,44,0,32,0,97,0,110,0,100,0,32,0,116,0,111,0,32,0,112,0,101,0,114,0,109,0,105,0,116,0,10, + 0,112,0,101,0,114,0,115,0,111,0,110,0,115,0,32,0,116,0,111,0,32,0,119,0,104,0,111,0,109,0,32,0,116,0,104,0,101,0,32, + 0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,105,0,115,0,32,0,102,0,117,0,114, + 0,110,0,105,0,115,0,104,0,101,0,100,0,32,0,116,0,111,0,32,0,100,0,111,0,32,0,115,0,111,0,44,0,32,0,115,0,117,0,98, + 0,106,0,101,0,99,0,116,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,10,0,102,0,111,0,108,0,108,0,111,0,119,0,105,0,110, + 0,103,0,32,0,99,0,111,0,110,0,100,0,105,0,116,0,105,0,111,0,110,0,115,0,58,0,10,0,10,0,84,0,104,0,101,0,32,0,97, + 0,98,0,111,0,118,0,101,0,32,0,99,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,97,0,110,0,100,0,32,0,116, + 0,114,0,97,0,100,0,101,0,109,0,97,0,114,0,107,0,32,0,110,0,111,0,116,0,105,0,99,0,101,0,115,0,32,0,97,0,110,0,100, + 0,32,0,116,0,104,0,105,0,115,0,32,0,112,0,101,0,114,0,109,0,105,0,115,0,115,0,105,0,111,0,110,0,32,0,110,0,111,0,116, + 0,105,0,99,0,101,0,32,0,115,0,104,0,97,0,108,0,108,0,10,0,98,0,101,0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,101, + 0,100,0,32,0,105,0,110,0,32,0,97,0,108,0,108,0,32,0,99,0,111,0,112,0,105,0,101,0,115,0,32,0,111,0,102,0,32,0,111, + 0,110,0,101,0,32,0,111,0,114,0,32,0,109,0,111,0,114,0,101,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111, + 0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,116,0,121,0,112,0,101,0,102,0,97,0,99,0,101, + 0,115,0,46,0,10,0,10,0,84,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114, + 0,101,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,44,0,32,0,97, + 0,108,0,116,0,101,0,114,0,101,0,100,0,44,0,32,0,111,0,114,0,32,0,97,0,100,0,100,0,101,0,100,0,32,0,116,0,111,0,44, + 0,32,0,97,0,110,0,100,0,32,0,105,0,110,0,32,0,112,0,97,0,114,0,116,0,105,0,99,0,117,0,108,0,97,0,114,0,10,0,116, + 0,104,0,101,0,32,0,100,0,101,0,115,0,105,0,103,0,110,0,115,0,32,0,111,0,102,0,32,0,103,0,108,0,121,0,112,0,104,0,115, + 0,32,0,111,0,114,0,32,0,99,0,104,0,97,0,114,0,97,0,99,0,116,0,101,0,114,0,115,0,32,0,105,0,110,0,32,0,116,0,104, + 0,101,0,32,0,70,0,111,0,110,0,116,0,115,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,109,0,111,0,100,0,105,0,102, + 0,105,0,101,0,100,0,32,0,97,0,110,0,100,0,10,0,97,0,100,0,100,0,105,0,116,0,105,0,111,0,110,0,97,0,108,0,32,0,103, + 0,108,0,121,0,112,0,104,0,115,0,32,0,111,0,114,0,32,0,99,0,104,0,97,0,114,0,97,0,99,0,116,0,101,0,114,0,115,0,32, + 0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,97,0,100,0,100,0,101,0,100,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,32, + 0,70,0,111,0,110,0,116,0,115,0,44,0,32,0,111,0,110,0,108,0,121,0,32,0,105,0,102,0,32,0,116,0,104,0,101,0,32,0,102, + 0,111,0,110,0,116,0,115,0,10,0,97,0,114,0,101,0,32,0,114,0,101,0,110,0,97,0,109,0,101,0,100,0,32,0,116,0,111,0,32, + 0,110,0,97,0,109,0,101,0,115,0,32,0,110,0,111,0,116,0,32,0,99,0,111,0,110,0,116,0,97,0,105,0,110,0,105,0,110,0,103, + 0,32,0,101,0,105,0,116,0,104,0,101,0,114,0,32,0,116,0,104,0,101,0,32,0,119,0,111,0,114,0,100,0,115,0,32,0,34,0,66, + 0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,34,0,32,0,111,0,114,0,32,0,116,0,104,0,101,0,32,0,119,0,111,0,114, + 0,100,0,10,0,34,0,86,0,101,0,114,0,97,0,34,0,46,0,10,0,10,0,84,0,104,0,105,0,115,0,32,0,76,0,105,0,99,0,101, + 0,110,0,115,0,101,0,32,0,98,0,101,0,99,0,111,0,109,0,101,0,115,0,32,0,110,0,117,0,108,0,108,0,32,0,97,0,110,0,100, + 0,32,0,118,0,111,0,105,0,100,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,32,0,101,0,120,0,116,0,101,0,110,0,116,0,32, + 0,97,0,112,0,112,0,108,0,105,0,99,0,97,0,98,0,108,0,101,0,32,0,116,0,111,0,32,0,70,0,111,0,110,0,116,0,115,0,32, + 0,111,0,114,0,32,0,70,0,111,0,110,0,116,0,10,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,116,0,104,0,97, + 0,116,0,32,0,104,0,97,0,115,0,32,0,98,0,101,0,101,0,110,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32, + 0,97,0,110,0,100,0,32,0,105,0,115,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,100,0,32,0,117, + 0,110,0,100,0,101,0,114,0,32,0,116,0,104,0,101,0,32,0,34,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,10, + 0,86,0,101,0,114,0,97,0,34,0,32,0,110,0,97,0,109,0,101,0,115,0,46,0,10,0,10,0,84,0,104,0,101,0,32,0,70,0,111, + 0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,115, + 0,111,0,108,0,100,0,32,0,97,0,115,0,32,0,112,0,97,0,114,0,116,0,32,0,111,0,102,0,32,0,97,0,32,0,108,0,97,0,114, + 0,103,0,101,0,114,0,32,0,115,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,112,0,97,0,99,0,107,0,97,0,103,0,101, + 0,32,0,98,0,117,0,116,0,32,0,110,0,111,0,10,0,99,0,111,0,112,0,121,0,32,0,111,0,102,0,32,0,111,0,110,0,101,0,32, + 0,111,0,114,0,32,0,109,0,111,0,114,0,101,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32, + 0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,116,0,121,0,112,0,101,0,102,0,97,0,99,0,101,0,115,0,32,0,109, + 0,97,0,121,0,32,0,98,0,101,0,32,0,115,0,111,0,108,0,100,0,32,0,98,0,121,0,32,0,105,0,116,0,115,0,101,0,108,0,102, + 0,46,0,10,0,10,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69, + 0,32,0,73,0,83,0,32,0,80,0,82,0,79,0,86,0,73,0,68,0,69,0,68,0,32,0,34,0,65,0,83,0,32,0,73,0,83,0,34, + 0,44,0,32,0,87,0,73,0,84,0,72,0,79,0,85,0,84,0,32,0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,89,0,32,0,79, + 0,70,0,32,0,65,0,78,0,89,0,32,0,75,0,73,0,78,0,68,0,44,0,32,0,69,0,88,0,80,0,82,0,69,0,83,0,83,0,10, + 0,79,0,82,0,32,0,73,0,77,0,80,0,76,0,73,0,69,0,68,0,44,0,32,0,73,0,78,0,67,0,76,0,85,0,68,0,73,0,78, + 0,71,0,32,0,66,0,85,0,84,0,32,0,78,0,79,0,84,0,32,0,76,0,73,0,77,0,73,0,84,0,69,0,68,0,32,0,84,0,79, + 0,32,0,65,0,78,0,89,0,32,0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,73,0,69,0,83,0,32,0,79,0,70,0,32,0,77, + 0,69,0,82,0,67,0,72,0,65,0,78,0,84,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,44,0,10,0,70,0,73,0,84,0,78, + 0,69,0,83,0,83,0,32,0,70,0,79,0,82,0,32,0,65,0,32,0,80,0,65,0,82,0,84,0,73,0,67,0,85,0,76,0,65,0,82, + 0,32,0,80,0,85,0,82,0,80,0,79,0,83,0,69,0,32,0,65,0,78,0,68,0,32,0,78,0,79,0,78,0,73,0,78,0,70,0,82, + 0,73,0,78,0,71,0,69,0,77,0,69,0,78,0,84,0,32,0,79,0,70,0,32,0,67,0,79,0,80,0,89,0,82,0,73,0,71,0,72, + 0,84,0,44,0,32,0,80,0,65,0,84,0,69,0,78,0,84,0,44,0,10,0,84,0,82,0,65,0,68,0,69,0,77,0,65,0,82,0,75, + 0,44,0,32,0,79,0,82,0,32,0,79,0,84,0,72,0,69,0,82,0,32,0,82,0,73,0,71,0,72,0,84,0,46,0,32,0,73,0,78, + 0,32,0,78,0,79,0,32,0,69,0,86,0,69,0,78,0,84,0,32,0,83,0,72,0,65,0,76,0,76,0,32,0,66,0,73,0,84,0,83, + 0,84,0,82,0,69,0,65,0,77,0,32,0,79,0,82,0,32,0,84,0,72,0,69,0,32,0,71,0,78,0,79,0,77,0,69,0,10,0,70, + 0,79,0,85,0,78,0,68,0,65,0,84,0,73,0,79,0,78,0,32,0,66,0,69,0,32,0,76,0,73,0,65,0,66,0,76,0,69,0,32, + 0,70,0,79,0,82,0,32,0,65,0,78,0,89,0,32,0,67,0,76,0,65,0,73,0,77,0,44,0,32,0,68,0,65,0,77,0,65,0,71, + 0,69,0,83,0,32,0,79,0,82,0,32,0,79,0,84,0,72,0,69,0,82,0,32,0,76,0,73,0,65,0,66,0,73,0,76,0,73,0,84, + 0,89,0,44,0,32,0,73,0,78,0,67,0,76,0,85,0,68,0,73,0,78,0,71,0,10,0,65,0,78,0,89,0,32,0,71,0,69,0,78, + 0,69,0,82,0,65,0,76,0,44,0,32,0,83,0,80,0,69,0,67,0,73,0,65,0,76,0,44,0,32,0,73,0,78,0,68,0,73,0,82, + 0,69,0,67,0,84,0,44,0,32,0,73,0,78,0,67,0,73,0,68,0,69,0,78,0,84,0,65,0,76,0,44,0,32,0,79,0,82,0,32, + 0,67,0,79,0,78,0,83,0,69,0,81,0,85,0,69,0,78,0,84,0,73,0,65,0,76,0,32,0,68,0,65,0,77,0,65,0,71,0,69, + 0,83,0,44,0,10,0,87,0,72,0,69,0,84,0,72,0,69,0,82,0,32,0,73,0,78,0,32,0,65,0,78,0,32,0,65,0,67,0,84, + 0,73,0,79,0,78,0,32,0,79,0,70,0,32,0,67,0,79,0,78,0,84,0,82,0,65,0,67,0,84,0,44,0,32,0,84,0,79,0,82, + 0,84,0,32,0,79,0,82,0,32,0,79,0,84,0,72,0,69,0,82,0,87,0,73,0,83,0,69,0,44,0,32,0,65,0,82,0,73,0,83, + 0,73,0,78,0,71,0,32,0,70,0,82,0,79,0,77,0,44,0,32,0,79,0,85,0,84,0,32,0,79,0,70,0,10,0,84,0,72,0,69, + 0,32,0,85,0,83,0,69,0,32,0,79,0,82,0,32,0,73,0,78,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,32,0,84,0,79, + 0,32,0,85,0,83,0,69,0,32,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65, + 0,82,0,69,0,32,0,79,0,82,0,32,0,70,0,82,0,79,0,77,0,32,0,79,0,84,0,72,0,69,0,82,0,32,0,68,0,69,0,65, + 0,76,0,73,0,78,0,71,0,83,0,32,0,73,0,78,0,32,0,84,0,72,0,69,0,10,0,70,0,79,0,78,0,84,0,32,0,83,0,79, + 0,70,0,84,0,87,0,65,0,82,0,69,0,46,0,10,0,10,0,69,0,120,0,99,0,101,0,112,0,116,0,32,0,97,0,115,0,32,0,99, + 0,111,0,110,0,116,0,97,0,105,0,110,0,101,0,100,0,32,0,105,0,110,0,32,0,116,0,104,0,105,0,115,0,32,0,110,0,111,0,116, + 0,105,0,99,0,101,0,44,0,32,0,116,0,104,0,101,0,32,0,110,0,97,0,109,0,101,0,115,0,32,0,111,0,102,0,32,0,71,0,110, + 0,111,0,109,0,101,0,44,0,32,0,116,0,104,0,101,0,32,0,71,0,110,0,111,0,109,0,101,0,10,0,70,0,111,0,117,0,110,0,100, + 0,97,0,116,0,105,0,111,0,110,0,44,0,32,0,97,0,110,0,100,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109, + 0,32,0,73,0,110,0,99,0,46,0,44,0,32,0,115,0,104,0,97,0,108,0,108,0,32,0,110,0,111,0,116,0,32,0,98,0,101,0,32, + 0,117,0,115,0,101,0,100,0,32,0,105,0,110,0,32,0,97,0,100,0,118,0,101,0,114,0,116,0,105,0,115,0,105,0,110,0,103,0,32, + 0,111,0,114,0,10,0,111,0,116,0,104,0,101,0,114,0,119,0,105,0,115,0,101,0,32,0,116,0,111,0,32,0,112,0,114,0,111,0,109, + 0,111,0,116,0,101,0,32,0,116,0,104,0,101,0,32,0,115,0,97,0,108,0,101,0,44,0,32,0,117,0,115,0,101,0,32,0,111,0,114, + 0,32,0,111,0,116,0,104,0,101,0,114,0,32,0,100,0,101,0,97,0,108,0,105,0,110,0,103,0,115,0,32,0,105,0,110,0,32,0,116, + 0,104,0,105,0,115,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,10,0,119,0,105, + 0,116,0,104,0,111,0,117,0,116,0,32,0,112,0,114,0,105,0,111,0,114,0,32,0,119,0,114,0,105,0,116,0,116,0,101,0,110,0,32, + 0,97,0,117,0,116,0,104,0,111,0,114,0,105,0,122,0,97,0,116,0,105,0,111,0,110,0,32,0,102,0,114,0,111,0,109,0,32,0,116, + 0,104,0,101,0,32,0,71,0,110,0,111,0,109,0,101,0,32,0,70,0,111,0,117,0,110,0,100,0,97,0,116,0,105,0,111,0,110,0,32, + 0,111,0,114,0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,10,0,73,0,110,0,99,0,46,0,44,0,32,0,114, + 0,101,0,115,0,112,0,101,0,99,0,116,0,105,0,118,0,101,0,108,0,121,0,46,0,32,0,70,0,111,0,114,0,32,0,102,0,117,0,114, + 0,116,0,104,0,101,0,114,0,32,0,105,0,110,0,102,0,111,0,114,0,109,0,97,0,116,0,105,0,111,0,110,0,44,0,32,0,99,0,111, + 0,110,0,116,0,97,0,99,0,116,0,58,0,32,0,102,0,111,0,110,0,116,0,115,0,32,0,97,0,116,0,32,0,103,0,110,0,111,0,109, + 0,101,0,32,0,100,0,111,0,116,0,10,0,111,0,114,0,103,0,46,0,32,0,10,0,10,0,65,0,114,0,101,0,118,0,32,0,70,0,111, + 0,110,0,116,0,115,0,32,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,10,0,45,0,45,0,45,0,45,0,45,0,45, + 0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45,0,45, + 0,45,0,45,0,45,0,45,0,10,0,10,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,40,0,99,0,41,0,32, + 0,50,0,48,0,48,0,54,0,32,0,98,0,121,0,32,0,84,0,97,0,118,0,109,0,106,0,111,0,110,0,103,0,32,0,66,0,97,0,104, + 0,46,0,32,0,65,0,108,0,108,0,32,0,82,0,105,0,103,0,104,0,116,0,115,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101, + 0,100,0,46,0,10,0,10,0,80,0,101,0,114,0,109,0,105,0,115,0,115,0,105,0,111,0,110,0,32,0,105,0,115,0,32,0,104,0,101, + 0,114,0,101,0,98,0,121,0,32,0,103,0,114,0,97,0,110,0,116,0,101,0,100,0,44,0,32,0,102,0,114,0,101,0,101,0,32,0,111, + 0,102,0,32,0,99,0,104,0,97,0,114,0,103,0,101,0,44,0,32,0,116,0,111,0,32,0,97,0,110,0,121,0,32,0,112,0,101,0,114, + 0,115,0,111,0,110,0,32,0,111,0,98,0,116,0,97,0,105,0,110,0,105,0,110,0,103,0,10,0,97,0,32,0,99,0,111,0,112,0,121, + 0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,102,0,111,0,110,0,116,0,115,0,32,0,97,0,99,0,99,0,111,0,109,0,112, + 0,97,0,110,0,121,0,105,0,110,0,103,0,32,0,116,0,104,0,105,0,115,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32, + 0,40,0,34,0,70,0,111,0,110,0,116,0,115,0,34,0,41,0,32,0,97,0,110,0,100,0,10,0,97,0,115,0,115,0,111,0,99,0,105, + 0,97,0,116,0,101,0,100,0,32,0,100,0,111,0,99,0,117,0,109,0,101,0,110,0,116,0,97,0,116,0,105,0,111,0,110,0,32,0,102, + 0,105,0,108,0,101,0,115,0,32,0,40,0,116,0,104,0,101,0,32,0,34,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116, + 0,119,0,97,0,114,0,101,0,34,0,41,0,44,0,32,0,116,0,111,0,32,0,114,0,101,0,112,0,114,0,111,0,100,0,117,0,99,0,101, + 0,10,0,97,0,110,0,100,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,32,0,116,0,104,0,101,0,32, + 0,109,0,111,0,100,0,105,0,102,0,105,0,99,0,97,0,116,0,105,0,111,0,110,0,115,0,32,0,116,0,111,0,32,0,116,0,104,0,101, + 0,32,0,66,0,105,0,116,0,115,0,116,0,114,0,101,0,97,0,109,0,32,0,86,0,101,0,114,0,97,0,32,0,70,0,111,0,110,0,116, + 0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,10,0,105,0,110,0,99,0,108,0,117,0,100,0,105,0,110,0,103, + 0,32,0,119,0,105,0,116,0,104,0,111,0,117,0,116,0,32,0,108,0,105,0,109,0,105,0,116,0,97,0,116,0,105,0,111,0,110,0,32, + 0,116,0,104,0,101,0,32,0,114,0,105,0,103,0,104,0,116,0,115,0,32,0,116,0,111,0,32,0,117,0,115,0,101,0,44,0,32,0,99, + 0,111,0,112,0,121,0,44,0,32,0,109,0,101,0,114,0,103,0,101,0,44,0,32,0,112,0,117,0,98,0,108,0,105,0,115,0,104,0,44, + 0,10,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,44,0,32,0,97,0,110,0,100,0,47,0,111,0,114,0,32, + 0,115,0,101,0,108,0,108,0,32,0,99,0,111,0,112,0,105,0,101,0,115,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70, + 0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,32,0,97,0,110,0,100,0,32,0,116,0,111, + 0,32,0,112,0,101,0,114,0,109,0,105,0,116,0,10,0,112,0,101,0,114,0,115,0,111,0,110,0,115,0,32,0,116,0,111,0,32,0,119, + 0,104,0,111,0,109,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114, + 0,101,0,32,0,105,0,115,0,32,0,102,0,117,0,114,0,110,0,105,0,115,0,104,0,101,0,100,0,32,0,116,0,111,0,32,0,100,0,111, + 0,32,0,115,0,111,0,44,0,32,0,115,0,117,0,98,0,106,0,101,0,99,0,116,0,32,0,116,0,111,0,10,0,116,0,104,0,101,0,32, + 0,102,0,111,0,108,0,108,0,111,0,119,0,105,0,110,0,103,0,32,0,99,0,111,0,110,0,100,0,105,0,116,0,105,0,111,0,110,0,115, + 0,58,0,10,0,10,0,84,0,104,0,101,0,32,0,97,0,98,0,111,0,118,0,101,0,32,0,99,0,111,0,112,0,121,0,114,0,105,0,103, + 0,104,0,116,0,32,0,97,0,110,0,100,0,32,0,116,0,114,0,97,0,100,0,101,0,109,0,97,0,114,0,107,0,32,0,110,0,111,0,116, + 0,105,0,99,0,101,0,115,0,32,0,97,0,110,0,100,0,32,0,116,0,104,0,105,0,115,0,32,0,112,0,101,0,114,0,109,0,105,0,115, + 0,115,0,105,0,111,0,110,0,32,0,110,0,111,0,116,0,105,0,99,0,101,0,10,0,115,0,104,0,97,0,108,0,108,0,32,0,98,0,101, + 0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,101,0,100,0,32,0,105,0,110,0,32,0,97,0,108,0,108,0,32,0,99,0,111,0,112, + 0,105,0,101,0,115,0,32,0,111,0,102,0,32,0,111,0,110,0,101,0,32,0,111,0,114,0,32,0,109,0,111,0,114,0,101,0,32,0,111, + 0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,10, + 0,116,0,121,0,112,0,101,0,102,0,97,0,99,0,101,0,115,0,46,0,10,0,10,0,84,0,104,0,101,0,32,0,70,0,111,0,110,0,116, + 0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,109,0,111,0,100, + 0,105,0,102,0,105,0,101,0,100,0,44,0,32,0,97,0,108,0,116,0,101,0,114,0,101,0,100,0,44,0,32,0,111,0,114,0,32,0,97, + 0,100,0,100,0,101,0,100,0,32,0,116,0,111,0,44,0,32,0,97,0,110,0,100,0,32,0,105,0,110,0,10,0,112,0,97,0,114,0,116, + 0,105,0,99,0,117,0,108,0,97,0,114,0,32,0,116,0,104,0,101,0,32,0,100,0,101,0,115,0,105,0,103,0,110,0,115,0,32,0,111, + 0,102,0,32,0,103,0,108,0,121,0,112,0,104,0,115,0,32,0,111,0,114,0,32,0,99,0,104,0,97,0,114,0,97,0,99,0,116,0,101, + 0,114,0,115,0,32,0,105,0,110,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,115,0,32,0,109,0,97,0,121,0,32, + 0,98,0,101,0,10,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,97,0,110,0,100,0,32,0,97,0,100,0,100,0,105, + 0,116,0,105,0,111,0,110,0,97,0,108,0,32,0,103,0,108,0,121,0,112,0,104,0,115,0,32,0,111,0,114,0,32,0,99,0,104,0,97, + 0,114,0,97,0,99,0,116,0,101,0,114,0,115,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,97,0,100,0,100,0,101,0,100, + 0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,10,0,70,0,111,0,110,0,116,0,115,0,44,0,32,0,111,0,110,0,108,0,121,0,32, + 0,105,0,102,0,32,0,116,0,104,0,101,0,32,0,102,0,111,0,110,0,116,0,115,0,32,0,97,0,114,0,101,0,32,0,114,0,101,0,110, + 0,97,0,109,0,101,0,100,0,32,0,116,0,111,0,32,0,110,0,97,0,109,0,101,0,115,0,32,0,110,0,111,0,116,0,32,0,99,0,111, + 0,110,0,116,0,97,0,105,0,110,0,105,0,110,0,103,0,32,0,101,0,105,0,116,0,104,0,101,0,114,0,10,0,116,0,104,0,101,0,32, + 0,119,0,111,0,114,0,100,0,115,0,32,0,34,0,84,0,97,0,118,0,109,0,106,0,111,0,110,0,103,0,32,0,66,0,97,0,104,0,34, + 0,32,0,111,0,114,0,32,0,116,0,104,0,101,0,32,0,119,0,111,0,114,0,100,0,32,0,34,0,65,0,114,0,101,0,118,0,34,0,46, + 0,10,0,10,0,84,0,104,0,105,0,115,0,32,0,76,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,98,0,101,0,99,0,111,0,109, + 0,101,0,115,0,32,0,110,0,117,0,108,0,108,0,32,0,97,0,110,0,100,0,32,0,118,0,111,0,105,0,100,0,32,0,116,0,111,0,32, + 0,116,0,104,0,101,0,32,0,101,0,120,0,116,0,101,0,110,0,116,0,32,0,97,0,112,0,112,0,108,0,105,0,99,0,97,0,98,0,108, + 0,101,0,32,0,116,0,111,0,32,0,70,0,111,0,110,0,116,0,115,0,10,0,111,0,114,0,32,0,70,0,111,0,110,0,116,0,32,0,83, + 0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,116,0,104,0,97,0,116,0,32,0,104,0,97,0,115,0,32,0,98,0,101,0,101, + 0,110,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,97,0,110,0,100,0,32,0,105,0,115,0,32,0,100,0,105, + 0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,100,0,32,0,117,0,110,0,100,0,101,0,114,0,32,0,116,0,104,0,101,0,32, + 0,10,0,34,0,84,0,97,0,118,0,109,0,106,0,111,0,110,0,103,0,32,0,66,0,97,0,104,0,32,0,65,0,114,0,101,0,118,0,34, + 0,32,0,110,0,97,0,109,0,101,0,115,0,46,0,10,0,10,0,84,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111, + 0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,115,0,111,0,108,0,100,0,32,0,97, + 0,115,0,32,0,112,0,97,0,114,0,116,0,32,0,111,0,102,0,32,0,97,0,32,0,108,0,97,0,114,0,103,0,101,0,114,0,32,0,115, + 0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,112,0,97,0,99,0,107,0,97,0,103,0,101,0,32,0,98,0,117,0,116,0,10, + 0,110,0,111,0,32,0,99,0,111,0,112,0,121,0,32,0,111,0,102,0,32,0,111,0,110,0,101,0,32,0,111,0,114,0,32,0,109,0,111, + 0,114,0,101,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119, + 0,97,0,114,0,101,0,32,0,116,0,121,0,112,0,101,0,102,0,97,0,99,0,101,0,115,0,32,0,109,0,97,0,121,0,32,0,98,0,101, + 0,32,0,115,0,111,0,108,0,100,0,32,0,98,0,121,0,10,0,105,0,116,0,115,0,101,0,108,0,102,0,46,0,10,0,10,0,84,0,72, + 0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,32,0,73,0,83,0,32,0,80, + 0,82,0,79,0,86,0,73,0,68,0,69,0,68,0,32,0,34,0,65,0,83,0,32,0,73,0,83,0,34,0,44,0,32,0,87,0,73,0,84, + 0,72,0,79,0,85,0,84,0,32,0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,89,0,32,0,79,0,70,0,32,0,65,0,78,0,89, + 0,32,0,75,0,73,0,78,0,68,0,44,0,10,0,69,0,88,0,80,0,82,0,69,0,83,0,83,0,32,0,79,0,82,0,32,0,73,0,77, + 0,80,0,76,0,73,0,69,0,68,0,44,0,32,0,73,0,78,0,67,0,76,0,85,0,68,0,73,0,78,0,71,0,32,0,66,0,85,0,84, + 0,32,0,78,0,79,0,84,0,32,0,76,0,73,0,77,0,73,0,84,0,69,0,68,0,32,0,84,0,79,0,32,0,65,0,78,0,89,0,32, + 0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,73,0,69,0,83,0,32,0,79,0,70,0,10,0,77,0,69,0,82,0,67,0,72,0,65, + 0,78,0,84,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,44,0,32,0,70,0,73,0,84,0,78,0,69,0,83,0,83,0,32,0,70, + 0,79,0,82,0,32,0,65,0,32,0,80,0,65,0,82,0,84,0,73,0,67,0,85,0,76,0,65,0,82,0,32,0,80,0,85,0,82,0,80, + 0,79,0,83,0,69,0,32,0,65,0,78,0,68,0,32,0,78,0,79,0,78,0,73,0,78,0,70,0,82,0,73,0,78,0,71,0,69,0,77, + 0,69,0,78,0,84,0,10,0,79,0,70,0,32,0,67,0,79,0,80,0,89,0,82,0,73,0,71,0,72,0,84,0,44,0,32,0,80,0,65, + 0,84,0,69,0,78,0,84,0,44,0,32,0,84,0,82,0,65,0,68,0,69,0,77,0,65,0,82,0,75,0,44,0,32,0,79,0,82,0,32, + 0,79,0,84,0,72,0,69,0,82,0,32,0,82,0,73,0,71,0,72,0,84,0,46,0,32,0,73,0,78,0,32,0,78,0,79,0,32,0,69, + 0,86,0,69,0,78,0,84,0,32,0,83,0,72,0,65,0,76,0,76,0,10,0,84,0,65,0,86,0,77,0,74,0,79,0,78,0,71,0,32, + 0,66,0,65,0,72,0,32,0,66,0,69,0,32,0,76,0,73,0,65,0,66,0,76,0,69,0,32,0,70,0,79,0,82,0,32,0,65,0,78, + 0,89,0,32,0,67,0,76,0,65,0,73,0,77,0,44,0,32,0,68,0,65,0,77,0,65,0,71,0,69,0,83,0,32,0,79,0,82,0,32, + 0,79,0,84,0,72,0,69,0,82,0,32,0,76,0,73,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,44,0,10,0,73,0,78,0,67, + 0,76,0,85,0,68,0,73,0,78,0,71,0,32,0,65,0,78,0,89,0,32,0,71,0,69,0,78,0,69,0,82,0,65,0,76,0,44,0,32, + 0,83,0,80,0,69,0,67,0,73,0,65,0,76,0,44,0,32,0,73,0,78,0,68,0,73,0,82,0,69,0,67,0,84,0,44,0,32,0,73, + 0,78,0,67,0,73,0,68,0,69,0,78,0,84,0,65,0,76,0,44,0,32,0,79,0,82,0,32,0,67,0,79,0,78,0,83,0,69,0,81, + 0,85,0,69,0,78,0,84,0,73,0,65,0,76,0,10,0,68,0,65,0,77,0,65,0,71,0,69,0,83,0,44,0,32,0,87,0,72,0,69, + 0,84,0,72,0,69,0,82,0,32,0,73,0,78,0,32,0,65,0,78,0,32,0,65,0,67,0,84,0,73,0,79,0,78,0,32,0,79,0,70, + 0,32,0,67,0,79,0,78,0,84,0,82,0,65,0,67,0,84,0,44,0,32,0,84,0,79,0,82,0,84,0,32,0,79,0,82,0,32,0,79, + 0,84,0,72,0,69,0,82,0,87,0,73,0,83,0,69,0,44,0,32,0,65,0,82,0,73,0,83,0,73,0,78,0,71,0,10,0,70,0,82, + 0,79,0,77,0,44,0,32,0,79,0,85,0,84,0,32,0,79,0,70,0,32,0,84,0,72,0,69,0,32,0,85,0,83,0,69,0,32,0,79, + 0,82,0,32,0,73,0,78,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,32,0,84,0,79,0,32,0,85,0,83,0,69,0,32,0,84, + 0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,32,0,79,0,82,0,32, + 0,70,0,82,0,79,0,77,0,10,0,79,0,84,0,72,0,69,0,82,0,32,0,68,0,69,0,65,0,76,0,73,0,78,0,71,0,83,0,32, + 0,73,0,78,0,32,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69, + 0,46,0,10,0,10,0,69,0,120,0,99,0,101,0,112,0,116,0,32,0,97,0,115,0,32,0,99,0,111,0,110,0,116,0,97,0,105,0,110, + 0,101,0,100,0,32,0,105,0,110,0,32,0,116,0,104,0,105,0,115,0,32,0,110,0,111,0,116,0,105,0,99,0,101,0,44,0,32,0,116, + 0,104,0,101,0,32,0,110,0,97,0,109,0,101,0,32,0,111,0,102,0,32,0,84,0,97,0,118,0,109,0,106,0,111,0,110,0,103,0,32, + 0,66,0,97,0,104,0,32,0,115,0,104,0,97,0,108,0,108,0,32,0,110,0,111,0,116,0,10,0,98,0,101,0,32,0,117,0,115,0,101, + 0,100,0,32,0,105,0,110,0,32,0,97,0,100,0,118,0,101,0,114,0,116,0,105,0,115,0,105,0,110,0,103,0,32,0,111,0,114,0,32, + 0,111,0,116,0,104,0,101,0,114,0,119,0,105,0,115,0,101,0,32,0,116,0,111,0,32,0,112,0,114,0,111,0,109,0,111,0,116,0,101, + 0,32,0,116,0,104,0,101,0,32,0,115,0,97,0,108,0,101,0,44,0,32,0,117,0,115,0,101,0,32,0,111,0,114,0,32,0,111,0,116, + 0,104,0,101,0,114,0,10,0,100,0,101,0,97,0,108,0,105,0,110,0,103,0,115,0,32,0,105,0,110,0,32,0,116,0,104,0,105,0,115, + 0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,119,0,105,0,116,0,104,0,111, + 0,117,0,116,0,32,0,112,0,114,0,105,0,111,0,114,0,32,0,119,0,114,0,105,0,116,0,116,0,101,0,110,0,32,0,97,0,117,0,116, + 0,104,0,111,0,114,0,105,0,122,0,97,0,116,0,105,0,111,0,110,0,10,0,102,0,114,0,111,0,109,0,32,0,84,0,97,0,118,0,109, + 0,106,0,111,0,110,0,103,0,32,0,66,0,97,0,104,0,46,0,32,0,70,0,111,0,114,0,32,0,102,0,117,0,114,0,116,0,104,0,101, + 0,114,0,32,0,105,0,110,0,102,0,111,0,114,0,109,0,97,0,116,0,105,0,111,0,110,0,44,0,32,0,99,0,111,0,110,0,116,0,97, + 0,99,0,116,0,58,0,32,0,116,0,97,0,118,0,109,0,106,0,111,0,110,0,103,0,32,0,64,0,32,0,102,0,114,0,101,0,101,0,10, + 0,46,0,32,0,102,0,114,0,46,0,0,70,111,110,116,115,32,97,114,101,32,40,99,41,32,66,105,116,115,116,114,101,97,109,32,40,115,101,101, + 32,98,101,108,111,119,41,46,32,68,101,106,97,86,117,32,99,104,97,110,103,101,115,32,97,114,101,32,105,110,32,112,117,98,108,105,99,32,100,111, + 109,97,105,110,46,32,71,108,121,112,104,115,32,105,109,112,111,114,116,101,100,32,102,114,111,109,32,65,114,101,118,32,102,111,110,116,115,32,97,114, + 101,32,40,99,41,32,84,97,118,109,106,117,110,103,32,66,97,104,32,40,115,101,101,32,98,101,108,111,119,41,10,10,66,105,116,115,116,114,101,97, + 109,32,86,101,114,97,32,70,111,110,116,115,32,67,111,112,121,114,105,103,104,116,10,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, + 45,45,45,45,45,45,45,45,45,45,45,45,45,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,48,51,32,98,121,32,66,105,116, + 115,116,114,101,97,109,44,32,73,110,99,46,32,65,108,108,32,82,105,103,104,116,115,32,82,101,115,101,114,118,101,100,46,32,66,105,116,115,116,114, + 101,97,109,32,86,101,114,97,32,105,115,10,97,32,116,114,97,100,101,109,97,114,107,32,111,102,32,66,105,116,115,116,114,101,97,109,44,32,73,110, + 99,46,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111, + 102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121, + 10,111,102,32,116,104,101,32,102,111,110,116,115,32,97,99,99,111,109,112,97,110,121,105,110,103,32,116,104,105,115,32,108,105,99,101,110,115,101,32, + 40,34,70,111,110,116,115,34,41,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,10,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102, + 105,108,101,115,32,40,116,104,101,32,34,70,111,110,116,32,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,114,101,112,114,111,100,117,99,101, + 32,97,110,100,32,100,105,115,116,114,105,98,117,116,101,32,116,104,101,10,70,111,110,116,32,83,111,102,116,119,97,114,101,44,32,105,110,99,108,117, + 100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,32,116,111,32,117,115, + 101,44,32,99,111,112,121,44,32,109,101,114,103,101,44,10,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,97,110,100, + 47,111,114,32,115,101,108,108,32,99,111,112,105,101,115,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,44,32,97,110, + 100,32,116,111,32,112,101,114,109,105,116,10,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,70,111,110,116,32,83,111,102, + 116,119,97,114,101,32,105,115,32,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32, + 116,104,101,10,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112, + 121,114,105,103,104,116,32,97,110,100,32,116,114,97,100,101,109,97,114,107,32,110,111,116,105,99,101,115,32,97,110,100,32,116,104,105,115,32,112,101, + 114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,10,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108, + 32,99,111,112,105,101,115,32,111,102,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119, + 97,114,101,32,116,121,112,101,102,97,99,101,115,46,10,10,84,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,109,97,121,32,98,101, + 32,109,111,100,105,102,105,101,100,44,32,97,108,116,101,114,101,100,44,32,111,114,32,97,100,100,101,100,32,116,111,44,32,97,110,100,32,105,110,32, + 112,97,114,116,105,99,117,108,97,114,10,116,104,101,32,100,101,115,105,103,110,115,32,111,102,32,103,108,121,112,104,115,32,111,114,32,99,104,97,114, + 97,99,116,101,114,115,32,105,110,32,116,104,101,32,70,111,110,116,115,32,109,97,121,32,98,101,32,109,111,100,105,102,105,101,100,32,97,110,100,10, + 97,100,100,105,116,105,111,110,97,108,32,103,108,121,112,104,115,32,111,114,32,99,104,97,114,97,99,116,101,114,115,32,109,97,121,32,98,101,32,97, + 100,100,101,100,32,116,111,32,116,104,101,32,70,111,110,116,115,44,32,111,110,108,121,32,105,102,32,116,104,101,32,102,111,110,116,115,10,97,114,101, + 32,114,101,110,97,109,101,100,32,116,111,32,110,97,109,101,115,32,110,111,116,32,99,111,110,116,97,105,110,105,110,103,32,101,105,116,104,101,114,32, + 116,104,101,32,119,111,114,100,115,32,34,66,105,116,115,116,114,101,97,109,34,32,111,114,32,116,104,101,32,119,111,114,100,10,34,86,101,114,97,34, + 46,10,10,84,104,105,115,32,76,105,99,101,110,115,101,32,98,101,99,111,109,101,115,32,110,117,108,108,32,97,110,100,32,118,111,105,100,32,116,111, + 32,116,104,101,32,101,120,116,101,110,116,32,97,112,112,108,105,99,97,98,108,101,32,116,111,32,70,111,110,116,115,32,111,114,32,70,111,110,116,10, + 83,111,102,116,119,97,114,101,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,109,111,100,105,102,105,101,100,32,97,110,100,32,105,115,32,100, + 105,115,116,114,105,98,117,116,101,100,32,117,110,100,101,114,32,116,104,101,32,34,66,105,116,115,116,114,101,97,109,10,86,101,114,97,34,32,110,97, + 109,101,115,46,10,10,84,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,109,97,121,32,98,101,32,115,111,108,100,32,97,115,32,112, + 97,114,116,32,111,102,32,97,32,108,97,114,103,101,114,32,115,111,102,116,119,97,114,101,32,112,97,99,107,97,103,101,32,98,117,116,32,110,111,10, + 99,111,112,121,32,111,102,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101, + 32,116,121,112,101,102,97,99,101,115,32,109,97,121,32,98,101,32,115,111,108,100,32,98,121,32,105,116,115,101,108,102,46,10,10,84,72,69,32,70, + 79,78,84,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85, + 84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,10,79,82,32,73,77,80,76,73, + 69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,65,78,89,32,87,65,82, + 82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32, + 65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84, + 32,79,70,32,67,79,80,89,82,73,71,72,84,44,32,80,65,84,69,78,84,44,10,84,82,65,68,69,77,65,82,75,44,32,79,82,32,79,84,72, + 69,82,32,82,73,71,72,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,66,73,84,83,84,82,69,65,77,32,79,82, + 32,84,72,69,32,71,78,79,77,69,10,70,79,85,78,68,65,84,73,79,78,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32, + 67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,32,76,73,65,66,73,76,73,84,89,44,32,73,78,67,76,85, + 68,73,78,71,10,65,78,89,32,71,69,78,69,82,65,76,44,32,83,80,69,67,73,65,76,44,32,73,78,68,73,82,69,67,84,44,32,73,78,67, + 73,68,69,78,84,65,76,44,32,79,82,32,67,79,78,83,69,81,85,69,78,84,73,65,76,32,68,65,77,65,71,69,83,44,10,87,72,69,84,72, + 69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72, + 69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,32,79,85,84,32,79,70,10,84,72,69,32,85,83,69,32,79,82,32, + 73,78,65,66,73,76,73,84,89,32,84,79,32,85,83,69,32,84,72,69,32,70,79,78,84,32,83,79,70,84,87,65,82,69,32,79,82,32,70,82, + 79,77,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,70,79,78,84,32,83,79,70,84,87,65,82,69,46,10, + 10,69,120,99,101,112,116,32,97,115,32,99,111,110,116,97,105,110,101,100,32,105,110,32,116,104,105,115,32,110,111,116,105,99,101,44,32,116,104,101, + 32,110,97,109,101,115,32,111,102,32,71,110,111,109,101,44,32,116,104,101,32,71,110,111,109,101,10,70,111,117,110,100,97,116,105,111,110,44,32,97, + 110,100,32,66,105,116,115,116,114,101,97,109,32,73,110,99,46,44,32,115,104,97,108,108,32,110,111,116,32,98,101,32,117,115,101,100,32,105,110,32, + 97,100,118,101,114,116,105,115,105,110,103,32,111,114,10,111,116,104,101,114,119,105,115,101,32,116,111,32,112,114,111,109,111,116,101,32,116,104,101,32, + 115,97,108,101,44,32,117,115,101,32,111,114,32,111,116,104,101,114,32,100,101,97,108,105,110,103,115,32,105,110,32,116,104,105,115,32,70,111,110,116, + 32,83,111,102,116,119,97,114,101,10,119,105,116,104,111,117,116,32,112,114,105,111,114,32,119,114,105,116,116,101,110,32,97,117,116,104,111,114,105,122, + 97,116,105,111,110,32,102,114,111,109,32,116,104,101,32,71,110,111,109,101,32,70,111,117,110,100,97,116,105,111,110,32,111,114,32,66,105,116,115,116, + 114,101,97,109,10,73,110,99,46,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,70,111,114,32,102,117,114,116,104,101,114,32,105,110,102, + 111,114,109,97,116,105,111,110,44,32,99,111,110,116,97,99,116,58,32,102,111,110,116,115,32,97,116,32,103,110,111,109,101,32,100,111,116,10,111,114, + 103,46,32,10,10,65,114,101,118,32,70,111,110,116,115,32,67,111,112,121,114,105,103,104,116,10,45,45,45,45,45,45,45,45,45,45,45,45,45,45, + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,48,54,32,98,121,32, + 84,97,118,109,106,111,110,103,32,66,97,104,46,32,65,108,108,32,82,105,103,104,116,115,32,82,101,115,101,114,118,101,100,46,10,10,80,101,114,109, + 105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101, + 44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,10,97,32,99,111,112,121,32,111,102,32,116,104,101,32, + 102,111,110,116,115,32,97,99,99,111,109,112,97,110,121,105,110,103,32,116,104,105,115,32,108,105,99,101,110,115,101,32,40,34,70,111,110,116,115,34, + 41,32,97,110,100,10,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104, + 101,32,34,70,111,110,116,32,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,114,101,112,114,111,100,117,99,101,10,97,110,100,32,100,105,115, + 116,114,105,98,117,116,101,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,115,32,116,111,32,116,104,101,32,66,105,116,115,116,114,101, + 97,109,32,86,101,114,97,32,70,111,110,116,32,83,111,102,116,119,97,114,101,44,10,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116, + 32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,32,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,101,114, + 103,101,44,32,112,117,98,108,105,115,104,44,10,100,105,115,116,114,105,98,117,116,101,44,32,97,110,100,47,111,114,32,115,101,108,108,32,99,111,112, + 105,101,115,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,10, + 112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,105,115,32,102,117,114, + 110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,10,116,104,101,32,102,111,108,108,111,119,105,110, + 103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,97,110,100,32,116, + 114,97,100,101,109,97,114,107,32,110,111,116,105,99,101,115,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116, + 105,99,101,10,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,32,99,111,112,105,101,115,32,111,102,32,111, + 110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,10,116,121,112,101,102,97,99,101, + 115,46,10,10,84,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,109,97,121,32,98,101,32,109,111,100,105,102,105,101,100,44,32,97, + 108,116,101,114,101,100,44,32,111,114,32,97,100,100,101,100,32,116,111,44,32,97,110,100,32,105,110,10,112,97,114,116,105,99,117,108,97,114,32,116, + 104,101,32,100,101,115,105,103,110,115,32,111,102,32,103,108,121,112,104,115,32,111,114,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104, + 101,32,70,111,110,116,115,32,109,97,121,32,98,101,10,109,111,100,105,102,105,101,100,32,97,110,100,32,97,100,100,105,116,105,111,110,97,108,32,103, + 108,121,112,104,115,32,111,114,32,99,104,97,114,97,99,116,101,114,115,32,109,97,121,32,98,101,32,97,100,100,101,100,32,116,111,32,116,104,101,10, + 70,111,110,116,115,44,32,111,110,108,121,32,105,102,32,116,104,101,32,102,111,110,116,115,32,97,114,101,32,114,101,110,97,109,101,100,32,116,111,32, + 110,97,109,101,115,32,110,111,116,32,99,111,110,116,97,105,110,105,110,103,32,101,105,116,104,101,114,10,116,104,101,32,119,111,114,100,115,32,34,84, + 97,118,109,106,111,110,103,32,66,97,104,34,32,111,114,32,116,104,101,32,119,111,114,100,32,34,65,114,101,118,34,46,10,10,84,104,105,115,32,76, + 105,99,101,110,115,101,32,98,101,99,111,109,101,115,32,110,117,108,108,32,97,110,100,32,118,111,105,100,32,116,111,32,116,104,101,32,101,120,116,101, + 110,116,32,97,112,112,108,105,99,97,98,108,101,32,116,111,32,70,111,110,116,115,10,111,114,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32, + 116,104,97,116,32,104,97,115,32,98,101,101,110,32,109,111,100,105,102,105,101,100,32,97,110,100,32,105,115,32,100,105,115,116,114,105,98,117,116,101, + 100,32,117,110,100,101,114,32,116,104,101,32,10,34,84,97,118,109,106,111,110,103,32,66,97,104,32,65,114,101,118,34,32,110,97,109,101,115,46,10, + 10,84,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,109,97,121,32,98,101,32,115,111,108,100,32,97,115,32,112,97,114,116,32,111, + 102,32,97,32,108,97,114,103,101,114,32,115,111,102,116,119,97,114,101,32,112,97,99,107,97,103,101,32,98,117,116,10,110,111,32,99,111,112,121,32, + 111,102,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,116,121,112,101, + 102,97,99,101,115,32,109,97,121,32,98,101,32,115,111,108,100,32,98,121,10,105,116,115,101,108,102,46,10,10,84,72,69,32,70,79,78,84,32,83, + 79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82, + 82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,10,69,88,80,82,69,83,83,32,79,82,32,73,77,80,76,73,69,68,44,32,73, + 78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,65,78,89,32,87,65,82,82,65,78,84,73, + 69,83,32,79,70,10,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,32,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82, + 84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,10,79,70,32,67, + 79,80,89,82,73,71,72,84,44,32,80,65,84,69,78,84,44,32,84,82,65,68,69,77,65,82,75,44,32,79,82,32,79,84,72,69,82,32,82,73, + 71,72,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,10,84,65,86,77,74,79,78,71,32,66,65,72,32,66,69,32,76, + 73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,32,76,73, + 65,66,73,76,73,84,89,44,10,73,78,67,76,85,68,73,78,71,32,65,78,89,32,71,69,78,69,82,65,76,44,32,83,80,69,67,73,65,76,44, + 32,73,78,68,73,82,69,67,84,44,32,73,78,67,73,68,69,78,84,65,76,44,32,79,82,32,67,79,78,83,69,81,85,69,78,84,73,65,76,10, + 68,65,77,65,71,69,83,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67, + 84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,10,70,82,79,77,44,32,79,85,84,32, + 79,70,32,84,72,69,32,85,83,69,32,79,82,32,73,78,65,66,73,76,73,84,89,32,84,79,32,85,83,69,32,84,72,69,32,70,79,78,84,32, + 83,79,70,84,87,65,82,69,32,79,82,32,70,82,79,77,10,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,32,70, + 79,78,84,32,83,79,70,84,87,65,82,69,46,10,10,69,120,99,101,112,116,32,97,115,32,99,111,110,116,97,105,110,101,100,32,105,110,32,116,104, + 105,115,32,110,111,116,105,99,101,44,32,116,104,101,32,110,97,109,101,32,111,102,32,84,97,118,109,106,111,110,103,32,66,97,104,32,115,104,97,108, + 108,32,110,111,116,10,98,101,32,117,115,101,100,32,105,110,32,97,100,118,101,114,116,105,115,105,110,103,32,111,114,32,111,116,104,101,114,119,105,115, + 101,32,116,111,32,112,114,111,109,111,116,101,32,116,104,101,32,115,97,108,101,44,32,117,115,101,32,111,114,32,111,116,104,101,114,10,100,101,97,108, + 105,110,103,115,32,105,110,32,116,104,105,115,32,70,111,110,116,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114, + 32,119,114,105,116,116,101,110,32,97,117,116,104,111,114,105,122,97,116,105,111,110,10,102,114,111,109,32,84,97,118,109,106,111,110,103,32,66,97,104, + 46,32,70,111,114,32,102,117,114,116,104,101,114,32,105,110,102,111,114,109,97,116,105,111,110,44,32,99,111,110,116,97,99,116,58,32,116,97,118,109, + 106,111,110,103,32,64,32,102,114,101,101,10,46,32,102,114,46,0,0,104,0,116,0,116,0,112,0,58,0,47,0,47,0,100,0,101,0,106,0,97, + 0,118,0,117,0,46,0,115,0,111,0,117,0,114,0,99,0,101,0,102,0,111,0,114,0,103,0,101,0,46,0,110,0,101,0,116,0,47,0,119, + 0,105,0,107,0,105,0,47,0,105,0,110,0,100,0,101,0,120,0,46,0,112,0,104,0,112,0,47,0,76,0,105,0,99,0,101,0,110,0,115, + 0,101,0,0,104,116,116,112,58,47,47,100,101,106,97,118,117,46,115,111,117,114,99,101,102,111,114,103,101,46,110,101,116,47,119,105,107,105,47,105, + 110,100,101,120,46,112,104,112,47,76,105,99,101,110,115,101,0,0,68,0,101,0,106,0,97,0,86,0,117,0,32,0,83,0,97,0,110,0,115,0, + 0,68,101,106,97,86,117,32,83,97,110,115,0,0,66,0,111,0,111,0,107,0,0,66,111,111,107,0,0,2,0,0,0,0,0,0,255,126,0,90, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,220,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8, + 0,9,0,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,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0,48, + 0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0,58,0,59,0,60,0,61,0,62,0,63,0,64,0,65,0,66,0,67,0,68, + 0,69,0,70,0,71,0,72,0,73,0,74,0,75,0,76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88, + 0,89,0,90,0,91,0,92,0,93,0,94,0,95,0,96,0,97,0,172,0,163,0,132,0,133,0,189,0,150,0,232,0,134,0,142,0,139,0,157, + 0,169,0,164,1,2,0,138,0,218,0,131,0,147,0,242,0,243,0,141,0,151,0,136,0,195,0,222,0,241,0,158,0,170,0,245,0,244,0,246, + 0,162,0,173,0,201,0,199,0,174,0,98,0,99,0,144,0,100,0,203,0,101,0,200,0,202,0,207,0,204,0,205,0,206,0,233,0,102,0,211, + 0,208,0,209,0,175,0,103,0,240,0,145,0,214,0,212,0,213,0,104,0,235,0,237,0,137,0,106,0,105,0,107,0,109,0,108,0,110,0,160, + 0,111,0,113,0,112,0,114,0,115,0,117,0,116,0,118,0,119,0,234,0,120,0,122,0,121,0,123,0,125,0,124,0,184,0,161,0,127,0,126, + 0,128,0,129,0,236,0,238,0,186,1,3,1,4,1,5,1,6,1,7,1,8,0,253,0,254,1,9,1,10,1,11,1,12,0,255,1,0,1,13, + 1,14,1,15,1,1,1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,1,24,1,25,1,26,1,27,0,248,0,249,1,28,1,29,1,30, + 1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,0,250,0,215,1,44,1,45,1,46,1,47,1,48, + 1,49,1,50,1,51,1,52,1,53,1,54,1,55,1,56,1,57,1,58,0,226,0,227,1,59,1,60,1,61,1,62,1,63,1,64,1,65,1,66, + 1,67,1,68,1,69,1,70,1,71,1,72,1,73,0,176,0,177,1,74,1,75,1,76,1,77,1,78,1,79,1,80,1,81,1,82,1,83,0,251, + 0,252,0,228,0,229,1,84,1,85,1,86,1,87,1,88,1,89,1,90,1,91,1,92,1,93,1,94,1,95,1,96,1,97,1,98,1,99,1,100, + 1,101,1,102,1,103,1,104,1,105,0,187,1,106,1,107,1,108,1,109,0,230,0,231,1,110,1,111,1,112,1,113,1,114,1,115,1,116,1,117, + 1,118,1,119,1,120,1,121,1,122,1,123,1,124,1,125,1,126,1,127,1,128,0,166,1,129,1,130,1,131,1,132,1,133,1,134,1,135,1,136, + 1,137,1,138,1,139,1,140,1,141,1,142,1,143,1,144,1,145,1,146,1,147,1,148,1,149,1,150,1,151,1,152,1,153,1,154,1,155,1,156, + 1,157,1,158,1,159,1,160,1,161,1,162,1,163,1,164,1,165,1,166,1,167,1,168,1,169,1,170,1,171,1,172,1,173,1,174,1,175,1,176, + 1,177,1,178,1,179,1,180,1,181,1,182,1,183,1,184,1,185,1,186,1,187,1,188,1,189,1,190,1,191,1,192,1,193,1,194,1,195,1,196, + 1,197,1,198,1,199,1,200,1,201,1,202,1,203,1,204,1,205,1,206,1,207,1,208,1,209,1,210,1,211,1,212,1,213,1,214,1,215,1,216, + 1,217,1,218,1,219,1,220,1,221,1,222,1,223,1,224,1,225,1,226,1,227,1,228,1,229,1,230,1,231,1,232,1,233,1,234,1,235,1,236, + 1,237,1,238,1,239,1,240,1,241,1,242,1,243,1,244,1,245,1,246,1,247,1,248,1,249,1,250,1,251,1,252,1,253,1,254,1,255,2,0, + 2,1,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9,2,10,2,11,2,12,2,13,2,14,2,15,2,16,2,17,2,18,2,19,2,20, + 2,21,2,22,2,23,2,24,2,25,2,26,2,27,2,28,2,29,2,30,2,31,2,32,2,33,2,34,2,35,2,36,2,37,2,38,2,39,2,40, + 2,41,2,42,2,43,2,44,2,45,2,46,2,47,2,48,2,49,2,50,2,51,2,52,2,53,2,54,2,55,2,56,2,57,2,58,2,59,2,60, + 2,61,2,62,2,63,2,64,2,65,2,66,2,67,2,68,2,69,2,70,2,71,2,72,2,73,2,74,2,75,2,76,2,77,2,78,2,79,2,80, + 2,81,2,82,2,83,2,84,2,85,2,86,2,87,2,88,2,89,2,90,2,91,2,92,2,93,2,94,2,95,2,96,2,97,2,98,2,99,2,100, + 2,101,2,102,2,103,2,104,2,105,2,106,2,107,2,108,2,109,2,110,2,111,2,112,2,113,2,114,2,115,2,116,2,117,2,118,2,119,2,120, + 2,121,2,122,2,123,2,124,2,125,2,126,2,127,2,128,2,129,2,130,2,131,2,132,2,133,2,134,2,135,2,136,2,137,2,138,2,139,2,140, + 2,141,2,142,2,143,2,144,2,145,2,146,2,147,2,148,2,149,2,150,2,151,2,152,2,153,2,154,2,155,2,156,2,157,2,158,2,159,2,160, + 2,161,2,162,2,163,2,164,2,165,2,166,2,167,2,168,2,169,2,170,2,171,2,172,2,173,2,174,2,175,2,176,2,177,2,178,2,179,0,216, + 0,225,2,180,2,181,2,182,2,183,2,184,2,185,2,186,2,187,2,188,2,189,2,190,2,191,2,192,2,193,2,194,2,195,0,219,0,220,0,221, + 0,224,0,217,0,223,2,196,2,197,2,198,2,199,2,200,2,201,2,202,2,203,2,204,2,205,2,206,2,207,2,208,2,209,2,210,2,211,2,212, + 2,213,2,214,2,215,2,216,2,217,2,218,2,219,2,220,2,221,2,222,2,223,2,224,2,225,2,226,2,227,2,228,2,229,2,230,2,231,2,232, + 2,233,2,234,2,235,2,236,2,237,2,238,2,239,2,240,2,241,2,242,2,243,2,244,2,245,2,246,2,247,2,248,2,249,2,250,2,251,2,252, + 2,253,2,254,2,255,3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,3,9,3,10,3,11,3,12,3,13,3,14,3,15,3,16, + 3,17,3,18,3,19,3,20,3,21,3,22,3,23,3,24,3,25,3,26,3,27,3,28,3,29,3,30,3,31,3,32,3,33,3,34,3,35,3,36, + 3,37,3,38,3,39,3,40,3,41,3,42,3,43,3,44,3,45,3,46,3,47,3,48,3,49,3,50,3,51,3,52,3,53,3,54,3,55,3,56, + 3,57,3,58,3,59,3,60,3,61,3,62,3,63,3,64,3,65,3,66,3,67,3,68,3,69,3,70,3,71,3,72,3,73,3,74,3,75,3,76, + 3,77,3,78,3,79,3,80,3,81,3,82,3,83,3,84,3,85,3,86,3,87,3,88,3,89,3,90,3,91,3,92,3,93,3,94,3,95,3,96, + 0,159,3,97,3,98,3,99,3,100,3,101,3,102,3,103,3,104,3,105,3,106,3,107,3,108,3,109,3,110,3,111,3,112,3,113,3,114,3,115, + 3,116,3,117,3,118,0,155,3,119,3,120,3,121,3,122,3,123,3,124,3,125,3,126,3,127,3,128,3,129,3,130,3,131,3,132,3,133,3,134, + 3,135,3,136,3,137,3,138,3,139,3,140,3,141,3,142,3,143,3,144,3,145,3,146,3,147,3,148,3,149,3,150,3,151,3,152,3,153,3,154, + 3,155,3,156,3,157,3,158,3,159,3,160,3,161,3,162,3,163,3,164,3,165,3,166,3,167,3,168,3,169,3,170,3,171,3,172,3,173,3,174, + 3,175,3,176,3,177,3,178,3,179,3,180,3,181,3,182,3,183,3,184,3,185,3,186,3,187,3,188,3,189,3,190,3,191,3,192,3,193,3,194, + 3,195,3,196,3,197,3,198,3,199,3,200,3,201,3,202,3,203,3,204,3,205,3,206,3,207,3,208,3,209,3,210,3,211,3,212,3,213,3,214, + 3,215,3,216,3,217,3,218,3,219,3,220,3,221,3,222,3,223,3,224,3,225,3,226,3,227,3,228,3,229,3,230,3,231,3,232,3,233,3,234, + 3,235,3,236,3,237,3,238,3,239,3,240,3,241,3,242,3,243,3,244,3,245,3,246,3,247,3,248,3,249,3,250,3,251,3,252,3,253,3,254, + 3,255,4,0,4,1,4,2,4,3,4,4,4,5,4,6,4,7,4,8,4,9,4,10,4,11,4,12,4,13,4,14,4,15,4,16,4,17,4,18, + 4,19,4,20,4,21,4,22,4,23,4,24,4,25,4,26,4,27,4,28,4,29,4,30,4,31,4,32,4,33,4,34,4,35,4,36,4,37,4,38, + 4,39,4,40,4,41,4,42,4,43,4,44,4,45,4,46,4,47,4,48,4,49,4,50,4,51,4,52,4,53,4,54,4,55,4,56,4,57,4,58, + 4,59,4,60,4,61,4,62,4,63,4,64,4,65,4,66,4,67,4,68,4,69,4,70,4,71,4,72,4,73,4,74,4,75,4,76,4,77,4,78, + 4,79,4,80,4,81,4,82,4,83,4,84,4,85,4,86,4,87,4,88,4,89,4,90,4,91,4,92,4,93,4,94,4,95,4,96,4,97,4,98, + 4,99,4,100,4,101,4,102,4,103,4,104,4,105,4,106,4,107,4,108,4,109,4,110,4,111,4,112,4,113,4,114,4,115,4,116,4,117,4,118, + 4,119,4,120,4,121,4,122,4,123,4,124,4,125,4,126,4,127,4,128,4,129,4,130,4,131,4,132,4,133,4,134,4,135,4,136,4,137,4,138, + 4,139,4,140,4,141,4,142,4,143,4,144,4,145,4,146,4,147,4,148,4,149,4,150,4,151,4,152,4,153,4,154,4,155,4,156,4,157,4,158, + 4,159,4,160,4,161,4,162,4,163,4,164,4,165,4,166,4,167,4,168,4,169,4,170,4,171,4,172,4,173,4,174,4,175,4,176,4,177,4,178, + 4,179,4,180,4,181,4,182,4,183,4,184,4,185,4,186,4,187,4,188,4,189,4,190,4,191,4,192,4,193,4,194,4,195,4,196,4,197,4,198, + 4,199,4,200,4,201,4,202,4,203,4,204,4,205,4,206,4,207,4,208,4,209,4,210,4,211,4,212,4,213,4,214,4,215,4,216,4,217,4,218, + 4,219,4,220,4,221,4,222,4,223,4,224,4,225,4,226,4,227,4,228,4,229,4,230,4,231,4,232,4,233,4,234,4,235,4,236,4,237,4,238, + 4,239,4,240,4,241,4,242,4,243,4,244,4,245,4,246,4,247,4,248,4,249,4,250,4,251,4,252,4,253,4,254,4,255,5,0,5,1,5,2, + 5,3,5,4,5,5,5,6,5,7,5,8,5,9,5,10,5,11,5,12,5,13,5,14,5,15,5,16,5,17,5,18,5,19,5,20,5,21,5,22, + 5,23,5,24,5,25,5,26,5,27,5,28,5,29,5,30,5,31,5,32,5,33,5,34,5,35,5,36,5,37,5,38,5,39,5,40,5,41,5,42, + 5,43,5,44,5,45,5,46,5,47,5,48,5,49,5,50,5,51,5,52,5,53,5,54,5,55,5,56,5,57,5,58,5,59,5,60,5,61,5,62, + 5,63,5,64,5,65,5,66,5,67,5,68,5,69,5,70,5,71,5,72,5,73,5,74,5,75,5,76,5,77,5,78,5,79,5,80,5,81,5,82, + 5,83,5,84,5,85,5,86,5,87,5,88,5,89,5,90,5,91,5,92,5,93,5,94,5,95,5,96,5,97,5,98,5,99,5,100,5,101,5,102, + 5,103,5,104,5,105,5,106,5,107,5,108,5,109,5,110,5,111,5,112,5,113,5,114,5,115,5,116,5,117,5,118,5,119,5,120,5,121,5,122, + 5,123,5,124,5,125,5,126,5,127,5,128,5,129,5,130,5,131,5,132,5,133,5,134,5,135,5,136,5,137,5,138,5,139,5,140,5,141,5,142, + 5,143,5,144,5,145,5,146,5,147,5,148,5,149,5,150,5,151,5,152,5,153,5,154,5,155,5,156,5,157,5,158,5,159,5,160,5,161,5,162, + 5,163,5,164,5,165,5,166,5,167,5,168,5,169,5,170,5,171,5,172,5,173,5,174,5,175,5,176,5,177,5,178,5,179,5,180,5,181,5,182, + 5,183,5,184,5,185,5,186,5,187,5,188,5,189,5,190,5,191,5,192,5,193,5,194,5,195,5,196,5,197,5,198,5,199,5,200,5,201,5,202, + 5,203,5,204,5,205,5,206,5,207,5,208,5,209,5,210,5,211,5,212,5,213,5,214,5,215,5,216,5,217,5,218,5,219,5,220,5,221,5,222, + 5,223,5,224,5,225,5,226,5,227,5,228,5,229,5,230,5,231,5,232,5,233,5,234,5,235,5,236,5,237,5,238,5,239,5,240,5,241,5,242, + 5,243,5,244,5,245,5,246,5,247,5,248,5,249,5,250,5,251,5,252,5,253,5,254,5,255,6,0,6,1,6,2,6,3,6,4,6,5,6,6, + 6,7,6,8,6,9,6,10,6,11,6,12,6,13,6,14,6,15,6,16,6,17,6,18,6,19,6,20,6,21,6,22,6,23,6,24,6,25,6,26, + 6,27,6,28,6,29,6,30,6,31,6,32,6,33,6,34,6,35,6,36,6,37,6,38,6,39,6,40,6,41,6,42,6,43,6,44,6,45,6,46, + 6,47,6,48,6,49,6,50,6,51,6,52,6,53,6,54,6,55,6,56,6,57,6,58,6,59,6,60,6,61,6,62,6,63,6,64,6,65,6,66, + 6,67,6,68,6,69,6,70,6,71,6,72,6,73,6,74,6,75,6,76,6,77,6,78,6,79,6,80,6,81,6,82,6,83,6,84,6,85,6,86, + 6,87,6,88,6,89,6,90,6,91,6,92,6,93,6,94,6,95,6,96,6,97,6,98,6,99,6,100,6,101,6,102,6,103,6,104,6,105,6,106, + 6,107,6,108,6,109,6,110,6,111,6,112,6,113,6,114,6,115,6,116,6,117,6,118,6,119,6,120,6,121,6,122,6,123,6,124,6,125,6,126, + 6,127,6,128,6,129,6,130,6,131,6,132,6,133,6,134,6,135,6,136,6,137,6,138,6,139,6,140,6,141,6,142,6,143,6,144,6,145,6,146, + 6,147,6,148,6,149,6,150,6,151,6,152,6,153,6,154,6,155,6,156,6,157,6,158,6,159,6,160,6,161,6,162,6,163,6,164,6,165,6,166, + 6,167,6,168,6,169,6,170,6,171,6,172,6,173,6,174,6,175,6,176,6,177,6,178,6,179,6,180,6,181,6,182,6,183,6,184,6,185,6,186, + 6,187,6,188,6,189,6,190,6,191,6,192,6,193,6,194,6,195,6,196,6,197,6,198,6,199,6,200,6,201,6,202,6,203,6,204,6,205,6,206, + 6,207,6,208,6,209,6,210,6,211,6,212,6,213,6,214,6,215,6,216,6,217,6,218,6,219,6,220,6,221,6,222,6,223,6,224,6,225,6,226, + 6,227,6,228,6,229,6,230,6,231,6,232,6,233,6,234,6,235,6,236,6,237,6,238,6,239,6,240,6,241,6,242,6,243,6,244,6,245,6,246, + 6,247,6,248,6,249,6,250,6,251,6,252,6,253,6,254,6,255,7,0,7,1,7,2,7,3,7,4,7,5,7,6,7,7,7,8,7,9,7,10, + 7,11,7,12,7,13,7,14,7,15,7,16,7,17,7,18,7,19,7,20,7,21,7,22,7,23,7,24,7,25,7,26,7,27,7,28,7,29,7,30, + 7,31,7,32,7,33,7,34,7,35,7,36,7,37,7,38,7,39,7,40,7,41,7,42,7,43,7,44,7,45,7,46,7,47,7,48,7,49,7,50, + 7,51,7,52,7,53,7,54,7,55,7,56,7,57,7,58,7,59,7,60,7,61,7,62,7,63,7,64,7,65,7,66,7,67,7,68,7,69,7,70, + 7,71,7,72,7,73,7,74,7,75,7,76,7,77,7,78,7,79,7,80,7,81,7,82,7,83,7,84,7,85,7,86,7,87,7,88,7,89,7,90, + 7,91,7,92,7,93,7,94,7,95,7,96,7,97,7,98,7,99,7,100,7,101,7,102,7,103,7,104,7,105,7,106,7,107,7,108,7,109,7,110, + 7,111,7,112,7,113,7,114,7,115,7,116,7,117,7,118,7,119,7,120,7,121,7,122,7,123,7,124,7,125,7,126,7,127,7,128,7,129,7,130, + 7,131,7,132,7,133,7,134,7,135,7,136,7,137,7,138,7,139,7,140,7,141,7,142,7,143,7,144,7,145,7,146,7,147,7,148,7,149,7,150, + 7,151,7,152,7,153,7,154,7,155,7,156,7,157,7,158,7,159,7,160,7,161,7,162,7,163,7,164,7,165,7,166,7,167,7,168,7,169,7,170, + 7,171,7,172,7,173,7,174,7,175,7,176,7,177,7,178,7,179,7,180,7,181,7,182,7,183,7,184,7,185,7,186,7,187,7,188,7,189,7,190, + 7,191,7,192,7,193,7,194,7,195,7,196,7,197,7,198,7,199,7,200,7,201,7,202,7,203,7,204,7,205,7,206,7,207,7,208,7,209,7,210, + 7,211,7,212,7,213,7,214,7,215,7,216,7,217,7,218,7,219,7,220,7,221,7,222,7,223,7,224,7,225,7,226,7,227,7,228,7,229,7,230, + 7,231,7,232,7,233,7,234,7,235,7,236,7,237,7,238,7,239,7,240,7,241,7,242,7,243,7,244,7,245,7,246,7,247,7,248,7,249,7,250, + 7,251,7,252,7,253,7,254,7,255,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9,8,10,8,11,8,12,8,13,8,14, + 8,15,8,16,8,17,8,18,8,19,8,20,8,21,8,22,8,23,8,24,8,25,8,26,8,27,8,28,8,29,8,30,8,31,8,32,8,33,8,34, + 8,35,8,36,8,37,8,38,8,39,8,40,8,41,8,42,8,43,8,44,8,45,8,46,8,47,8,48,8,49,8,50,8,51,8,52,8,53,8,54, + 8,55,8,56,8,57,8,58,8,59,8,60,8,61,8,62,8,63,8,64,8,65,8,66,8,67,8,68,8,69,8,70,8,71,8,72,8,73,8,74, + 8,75,8,76,8,77,8,78,8,79,8,80,8,81,8,82,8,83,8,84,8,85,8,86,8,87,8,88,8,89,8,90,8,91,8,92,8,93,8,94, + 8,95,8,96,8,97,8,98,8,99,8,100,8,101,8,102,8,103,8,104,8,105,8,106,8,107,8,108,8,109,8,110,8,111,8,112,8,113,8,114, + 8,115,8,116,8,117,8,118,8,119,8,120,8,121,8,122,8,123,8,124,8,125,8,126,8,127,8,128,8,129,8,130,8,131,8,132,8,133,8,134, + 8,135,8,136,8,137,8,138,8,139,8,140,8,141,8,142,8,143,8,144,8,145,8,146,8,147,8,148,8,149,8,150,8,151,8,152,8,153,8,154, + 8,155,8,156,8,157,8,158,8,159,8,160,8,161,8,162,8,163,8,164,8,165,8,166,8,167,8,168,8,169,8,170,8,171,8,172,8,173,8,174, + 8,175,8,176,8,177,8,178,8,179,8,180,8,181,8,182,8,183,8,184,8,185,8,186,8,187,8,188,8,189,8,190,8,191,8,192,8,193,8,194, + 8,195,8,196,8,197,8,198,8,199,8,200,8,201,8,202,8,203,8,204,8,205,8,206,8,207,8,208,8,209,8,210,8,211,8,212,8,213,8,214, + 8,215,8,216,8,217,8,218,8,219,8,220,8,221,8,222,8,223,8,224,8,225,8,226,8,227,8,228,8,229,8,230,8,231,8,232,8,233,8,234, + 8,235,8,236,8,237,8,238,8,239,8,240,8,241,8,242,8,243,8,244,8,245,8,246,8,247,8,248,8,249,8,250,8,251,8,252,8,253,8,254, + 8,255,9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9,9,10,9,11,9,12,9,13,9,14,9,15,9,16,9,17,9,18, + 9,19,9,20,9,21,9,22,9,23,9,24,9,25,9,26,9,27,9,28,9,29,9,30,9,31,9,32,9,33,9,34,9,35,9,36,9,37,9,38, + 9,39,9,40,9,41,9,42,9,43,9,44,9,45,9,46,9,47,9,48,9,49,9,50,9,51,9,52,9,53,9,54,9,55,9,56,9,57,9,58, + 9,59,9,60,9,61,9,62,9,63,9,64,9,65,9,66,9,67,9,68,9,69,9,70,9,71,9,72,9,73,9,74,9,75,9,76,9,77,9,78, + 9,79,9,80,9,81,9,82,9,83,9,84,9,85,9,86,9,87,9,88,9,89,9,90,9,91,9,92,9,93,9,94,9,95,9,96,9,97,9,98, + 9,99,9,100,9,101,9,102,9,103,9,104,9,105,9,106,9,107,9,108,9,109,9,110,9,111,9,112,9,113,9,114,9,115,9,116,9,117,9,118, + 9,119,9,120,9,121,9,122,9,123,9,124,9,125,9,126,9,127,9,128,9,129,9,130,9,131,9,132,9,133,9,134,9,135,9,136,9,137,9,138, + 9,139,9,140,9,141,9,142,9,143,9,144,9,145,9,146,9,147,9,148,9,149,9,150,9,151,9,152,9,153,9,154,9,155,9,156,9,157,9,158, + 9,159,9,160,9,161,9,162,9,163,9,164,9,165,9,166,9,167,9,168,9,169,9,170,9,171,9,172,9,173,9,174,9,175,9,176,9,177,9,178, + 9,179,9,180,9,181,9,182,9,183,9,184,9,185,9,186,9,187,9,188,9,189,9,190,9,191,9,192,9,193,9,194,9,195,9,196,9,197,9,198, + 9,199,9,200,9,201,9,202,9,203,9,204,9,205,9,206,9,207,9,208,9,209,9,210,9,211,9,212,9,213,9,214,9,215,9,216,9,217,9,218, + 9,219,9,220,9,221,9,222,9,223,9,224,9,225,9,226,9,227,9,228,9,229,9,230,9,231,9,232,9,233,9,234,9,235,9,236,9,237,9,238, + 9,239,9,240,9,241,9,242,9,243,9,244,9,245,9,246,9,247,9,248,9,249,9,250,9,251,9,252,9,253,9,254,9,255,10,0,10,1,10,2, + 10,3,10,4,10,5,10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13,10,14,10,15,10,16,10,17,10,18,10,19,10,20,10,21,10,22, + 10,23,10,24,10,25,10,26,10,27,10,28,10,29,10,30,10,31,10,32,10,33,10,34,10,35,10,36,10,37,10,38,10,39,10,40,10,41,10,42, + 10,43,10,44,10,45,10,46,10,47,10,48,10,49,10,50,10,51,10,52,10,53,10,54,10,55,10,56,10,57,10,58,10,59,10,60,10,61,10,62, + 10,63,10,64,10,65,10,66,10,67,10,68,10,69,10,70,10,71,10,72,10,73,10,74,10,75,10,76,10,77,10,78,10,79,10,80,10,81,10,82, + 10,83,10,84,10,85,10,86,10,87,10,88,10,89,10,90,10,91,10,92,10,93,10,94,10,95,10,96,10,97,10,98,10,99,10,100,10,101,10,102, + 10,103,10,104,10,105,10,106,10,107,10,108,10,109,10,110,10,111,10,112,10,113,10,114,10,115,10,116,10,117,10,118,10,119,10,120,10,121,10,122, + 10,123,10,124,10,125,10,126,10,127,10,128,10,129,10,130,10,131,10,132,10,133,10,134,10,135,10,136,10,137,10,138,10,139,10,140,10,141,10,142, + 10,143,10,144,10,145,10,146,10,147,10,148,10,149,10,150,10,151,10,152,10,153,10,154,10,155,10,156,10,157,10,158,10,159,10,160,10,161,10,162, + 10,163,10,164,10,165,10,166,10,167,10,168,10,169,10,170,10,171,10,172,10,173,10,174,10,175,10,176,10,177,10,178,10,179,10,180,10,181,10,182, + 10,183,10,184,10,185,10,186,10,187,10,188,10,189,10,190,10,191,10,192,10,193,10,194,10,195,10,196,10,197,10,198,10,199,10,200,10,201,10,202, + 10,203,10,204,10,205,10,206,10,207,10,208,10,209,10,210,10,211,10,212,10,213,10,214,10,215,10,216,10,217,10,218,10,219,10,220,10,221,10,222, + 10,223,10,224,10,225,10,226,10,227,10,228,10,229,10,230,10,231,10,232,10,233,10,234,10,235,10,236,10,237,10,238,10,239,10,240,10,241,10,242, + 10,243,10,244,10,245,10,246,10,247,10,248,10,249,10,250,10,251,10,252,10,253,10,254,10,255,11,0,11,1,11,2,11,3,11,4,11,5,11,6, + 11,7,11,8,11,9,11,10,11,11,11,12,11,13,11,14,11,15,11,16,11,17,11,18,0,178,0,179,11,19,11,20,11,21,0,182,0,183,0,196, + 11,22,0,180,0,181,0,197,11,23,0,130,0,194,0,135,11,24,11,25,11,26,0,171,11,27,11,28,11,29,11,30,11,31,11,32,11,33,11,34, + 11,35,0,198,11,36,11,37,11,38,11,39,11,40,11,41,11,42,11,43,0,190,0,191,11,44,11,45,11,46,11,47,11,48,11,49,11,50,11,51, + 11,52,0,188,11,53,11,54,11,55,11,56,11,57,11,58,11,59,11,60,11,61,11,62,11,63,11,64,11,65,11,66,11,67,11,68,11,69,11,70, + 11,71,11,72,11,73,11,74,11,75,11,76,11,77,11,78,11,79,11,80,11,81,11,82,11,83,11,84,11,85,11,86,11,87,11,88,11,89,11,90, + 11,91,11,92,11,93,11,94,11,95,11,96,11,97,11,98,11,99,11,100,11,101,11,102,11,103,11,104,11,105,11,106,11,107,11,108,11,109,11,110, + 11,111,11,112,11,113,11,114,11,115,11,116,11,117,11,118,11,119,11,120,11,121,11,122,11,123,11,124,11,125,11,126,11,127,11,128,11,129,11,130, + 11,131,11,132,11,133,11,134,11,135,0,247,11,136,11,137,11,138,11,139,11,140,11,141,11,142,11,143,11,144,11,145,11,146,11,147,11,148,11,149, + 11,150,11,151,11,152,11,153,11,154,11,155,11,156,11,157,11,158,11,159,11,160,11,161,11,162,11,163,11,164,11,165,11,166,11,167,11,168,11,169, + 11,170,11,171,11,172,11,173,11,174,11,175,11,176,11,177,11,178,11,179,11,180,11,181,11,182,11,183,11,184,11,185,11,186,11,187,11,188,11,189, + 11,190,11,191,11,192,11,193,11,194,11,195,11,196,0,140,11,197,11,198,11,199,11,200,11,201,11,202,11,203,11,204,11,205,11,206,11,207,11,208, + 11,209,11,210,11,211,11,212,11,213,11,214,11,215,11,216,11,217,11,218,11,219,11,220,11,221,11,222,11,223,11,224,11,225,11,226,11,227,11,228, + 11,229,11,230,11,231,11,232,11,233,11,234,11,235,11,236,11,237,11,238,11,239,11,240,11,241,11,242,11,243,11,244,11,245,11,246,11,247,11,248, + 11,249,11,250,11,251,11,252,11,253,11,254,11,255,12,0,12,1,12,2,12,3,12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11,12,12, + 12,13,12,14,12,15,12,16,12,17,12,18,12,19,12,20,12,21,12,22,12,23,12,24,12,25,12,26,12,27,12,28,12,29,12,30,12,31,12,32, + 12,33,12,34,12,35,12,36,12,37,12,38,12,39,12,40,12,41,12,42,12,43,12,44,12,45,12,46,12,47,12,48,12,49,12,50,12,51,12,52, + 12,53,12,54,12,55,12,56,12,57,12,58,12,59,12,60,12,61,12,62,12,63,12,64,12,65,12,66,12,67,12,68,12,69,12,70,12,71,12,72, + 12,73,12,74,12,75,12,76,12,77,12,78,12,79,12,80,12,81,12,82,12,83,12,84,12,85,12,86,12,87,12,88,12,89,12,90,12,91,12,92, + 12,93,12,94,12,95,12,96,12,97,12,98,12,99,12,100,12,101,12,102,12,103,12,104,12,105,12,106,12,107,12,108,12,109,12,110,12,111,12,112, + 12,113,12,114,12,115,12,116,12,117,12,118,12,119,12,120,12,121,12,122,12,123,12,124,12,125,12,126,12,127,12,128,12,129,12,130,12,131,12,132, + 12,133,12,134,12,135,12,136,12,137,12,138,12,139,12,140,12,141,12,142,12,143,12,144,12,145,12,146,12,147,12,148,12,149,12,150,0,152,12,151, + 12,152,12,153,0,168,12,154,12,155,12,156,12,157,12,158,12,159,12,160,12,161,0,154,12,162,0,153,0,239,12,163,12,164,12,165,12,166,12,167, + 12,168,12,169,0,165,12,170,12,171,12,172,0,146,12,173,12,174,12,175,12,176,12,177,12,178,12,179,12,180,12,181,12,182,12,183,12,184,0,156, + 12,185,12,186,12,187,12,188,12,189,12,190,12,191,12,192,12,193,12,194,12,195,12,196,12,197,12,198,12,199,12,200,12,201,12,202,12,203,12,204, + 12,205,12,206,12,207,12,208,12,209,12,210,12,211,12,212,0,167,12,213,12,214,12,215,12,216,12,217,12,218,12,219,12,220,12,221,12,222,12,223, + 12,224,12,225,12,226,12,227,12,228,12,229,12,230,12,231,12,232,12,233,12,234,12,235,0,143,12,236,12,237,12,238,0,148,0,149,12,239,12,240, + 12,241,12,242,12,243,12,244,12,245,12,246,12,247,12,248,12,249,12,250,12,251,12,252,12,253,12,254,12,255,13,0,13,1,13,2,13,3,13,4, + 13,5,13,6,13,7,13,8,13,9,13,10,13,11,13,12,13,13,13,14,13,15,13,16,13,17,13,18,13,19,13,20,13,21,13,22,13,23,13,24, + 13,25,13,26,13,27,13,28,13,29,13,30,13,31,13,32,13,33,13,34,13,35,13,36,13,37,13,38,13,39,13,40,13,41,13,42,13,43,13,44, + 13,45,13,46,13,47,13,48,13,49,13,50,13,51,13,52,13,53,13,54,13,55,13,56,13,57,13,58,13,59,13,60,13,61,13,62,13,63,13,64, + 13,65,13,66,13,67,13,68,13,69,13,70,13,71,13,72,13,73,13,74,13,75,13,76,13,77,13,78,13,79,13,80,13,81,13,82,13,83,13,84, + 13,85,13,86,13,87,13,88,13,89,13,90,13,91,13,92,13,93,13,94,13,95,13,96,13,97,13,98,13,99,13,100,13,101,13,102,13,103,13,104, + 13,105,13,106,13,107,13,108,13,109,13,110,13,111,13,112,13,113,13,114,13,115,13,116,13,117,13,118,13,119,13,120,13,121,13,122,13,123,13,124, + 13,125,13,126,13,127,13,128,13,129,13,130,13,131,13,132,13,133,13,134,13,135,13,136,13,137,13,138,13,139,13,140,13,141,13,142,13,143,13,144, + 13,145,13,146,13,147,13,148,13,149,13,150,13,151,13,152,13,153,13,154,13,155,13,156,13,157,13,158,13,159,13,160,13,161,13,162,13,163,13,164, + 13,165,13,166,13,167,13,168,13,169,13,170,13,171,13,172,13,173,13,174,13,175,13,176,13,177,13,178,13,179,13,180,13,181,13,182,13,183,13,184, + 13,185,13,186,13,187,13,188,13,189,13,190,13,191,13,192,13,193,13,194,13,195,13,196,13,197,13,198,13,199,13,200,13,201,13,202,13,203,13,204, + 13,205,13,206,13,207,13,208,13,209,13,210,13,211,13,212,13,213,13,214,13,215,13,216,13,217,13,218,13,219,13,220,13,221,13,222,13,223,13,224, + 13,225,13,226,13,227,13,228,13,229,13,230,13,231,13,232,13,233,13,234,13,235,13,236,13,237,13,238,13,239,13,240,13,241,13,242,13,243,13,244, + 13,245,13,246,13,247,13,248,13,249,13,250,13,251,13,252,13,253,13,254,13,255,14,0,14,1,14,2,14,3,14,4,14,5,14,6,14,7,14,8, + 14,9,14,10,14,11,14,12,14,13,14,14,14,15,14,16,14,17,14,18,14,19,14,20,14,21,14,22,14,23,14,24,14,25,14,26,14,27,14,28, + 14,29,14,30,14,31,14,32,14,33,14,34,14,35,14,36,14,37,14,38,14,39,14,40,14,41,14,42,14,43,14,44,14,45,14,46,14,47,14,48, + 14,49,14,50,14,51,14,52,14,53,14,54,14,55,14,56,14,57,14,58,14,59,14,60,14,61,14,62,14,63,14,64,14,65,14,66,14,67,14,68, + 14,69,14,70,14,71,14,72,14,73,14,74,14,75,14,76,14,77,14,78,14,79,14,80,14,81,14,82,14,83,14,84,14,85,14,86,14,87,14,88, + 14,89,14,90,14,91,14,92,14,93,14,94,14,95,14,96,14,97,14,98,14,99,14,100,14,101,14,102,14,103,14,104,14,105,14,106,14,107,14,108, + 14,109,14,110,14,111,14,112,14,113,14,114,14,115,14,116,14,117,14,118,14,119,14,120,14,121,14,122,14,123,14,124,14,125,14,126,14,127,14,128, + 14,129,14,130,14,131,14,132,14,133,14,134,14,135,14,136,14,137,14,138,14,139,14,140,14,141,14,142,14,143,14,144,14,145,14,146,14,147,14,148, + 14,149,14,150,14,151,14,152,14,153,14,154,14,155,14,156,14,157,14,158,14,159,0,185,14,160,14,161,14,162,14,163,14,164,14,165,14,166,14,167, + 14,168,14,169,14,170,14,171,14,172,14,173,14,174,14,175,14,176,14,177,14,178,14,179,14,180,14,181,14,182,14,183,14,184,14,185,14,186,14,187, + 14,188,14,189,14,190,14,191,14,192,14,193,14,194,14,195,14,196,14,197,14,198,14,199,14,200,14,201,14,202,14,203,14,204,14,205,14,206,14,207, + 14,208,14,209,14,210,14,211,14,212,14,213,14,214,14,215,14,216,14,217,14,218,14,219,14,220,14,221,14,222,14,223,14,224,14,225,14,226,14,227, + 14,228,14,229,14,230,14,231,14,232,14,233,14,234,14,235,14,236,14,237,14,238,14,239,14,240,14,241,14,242,14,243,14,244,14,245,14,246,14,247, + 14,248,14,249,14,250,14,251,14,252,14,253,14,254,14,255,15,0,15,1,15,2,15,3,15,4,15,5,15,6,15,7,15,8,15,9,15,10,15,11, + 15,12,15,13,15,14,15,15,15,16,15,17,15,18,15,19,15,20,15,21,15,22,15,23,15,24,15,25,15,26,15,27,15,28,15,29,15,30,15,31, + 15,32,15,33,15,34,15,35,15,36,15,37,15,38,15,39,15,40,15,41,15,42,15,43,15,44,15,45,15,46,15,47,15,48,15,49,15,50,15,51, + 15,52,15,53,15,54,15,55,15,56,15,57,15,58,15,59,15,60,15,61,15,62,15,63,15,64,15,65,15,66,15,67,15,68,15,69,15,70,15,71, + 15,72,15,73,15,74,15,75,15,76,15,77,15,78,15,79,15,80,15,81,15,82,15,83,15,84,15,85,15,86,15,87,15,88,15,89,15,90,15,91, + 15,92,15,93,15,94,15,95,15,96,15,97,15,98,15,99,15,100,15,101,15,102,15,103,15,104,15,105,15,106,15,107,15,108,15,109,15,110,15,111, + 15,112,15,113,15,114,15,115,15,116,15,117,15,118,15,119,15,120,15,121,15,122,15,123,15,124,15,125,15,126,15,127,15,128,15,129,15,130,15,131, + 15,132,15,133,15,134,15,135,15,136,15,137,15,138,15,139,15,140,15,141,15,142,15,143,15,144,15,145,15,146,15,147,15,148,15,149,15,150,15,151, + 15,152,15,153,15,154,15,155,15,156,15,157,15,158,15,159,15,160,15,161,15,162,15,163,15,164,15,165,15,166,15,167,15,168,15,169,15,170,15,171, + 15,172,15,173,15,174,15,175,15,176,15,177,15,178,15,179,15,180,15,181,15,182,15,183,15,184,15,185,15,186,15,187,15,188,15,189,15,190,15,191, + 15,192,15,193,15,194,15,195,15,196,15,197,15,198,15,199,15,200,15,201,15,202,15,203,15,204,15,205,15,206,15,207,15,208,15,209,15,210,15,211, + 15,212,15,213,15,214,15,215,15,216,15,217,15,218,15,219,15,220,15,221,15,222,15,223,15,224,15,225,15,226,15,227,15,228,15,229,15,230,15,231, + 15,232,15,233,15,234,15,235,15,236,15,237,15,238,15,239,15,240,15,241,15,242,15,243,15,244,15,245,15,246,15,247,15,248,15,249,15,250,15,251, + 15,252,15,253,15,254,15,255,16,0,16,1,16,2,16,3,16,4,16,5,16,6,16,7,16,8,16,9,16,10,16,11,16,12,16,13,16,14,16,15, + 16,16,16,17,16,18,16,19,16,20,16,21,16,22,16,23,16,24,16,25,16,26,16,27,16,28,16,29,16,30,16,31,16,32,16,33,16,34,16,35, + 16,36,16,37,16,38,16,39,16,40,16,41,16,42,16,43,16,44,16,45,16,46,16,47,16,48,16,49,16,50,16,51,16,52,16,53,16,54,16,55, + 16,56,16,57,16,58,16,59,16,60,16,61,16,62,16,63,16,64,16,65,16,66,16,67,16,68,16,69,16,70,16,71,16,72,16,73,16,74,16,75, + 16,76,16,77,16,78,16,79,16,80,16,81,16,82,16,83,16,84,16,85,16,86,16,87,16,88,16,89,16,90,16,91,16,92,16,93,16,94,16,95, + 16,96,16,97,16,98,16,99,16,100,16,101,16,102,16,103,16,104,16,105,16,106,16,107,16,108,16,109,16,110,16,111,16,112,16,113,16,114,16,115, + 16,116,16,117,16,118,16,119,16,120,16,121,16,122,16,123,16,124,16,125,16,126,16,127,16,128,16,129,16,130,16,131,16,132,16,133,16,134,16,135, + 16,136,16,137,16,138,16,139,16,140,16,141,16,142,16,143,16,144,16,145,16,146,16,147,16,148,16,149,16,150,16,151,16,152,16,153,16,154,16,155, + 16,156,16,157,16,158,16,159,16,160,16,161,16,162,16,163,16,164,16,165,16,166,16,167,16,168,16,169,16,170,16,171,16,172,16,173,16,174,16,175, + 16,176,16,177,16,178,16,179,16,180,16,181,16,182,16,183,16,184,16,185,16,186,16,187,16,188,16,189,16,190,16,191,16,192,16,193,16,194,16,195, + 16,196,16,197,16,198,16,199,16,200,16,201,16,202,16,203,16,204,16,205,16,206,16,207,16,208,16,209,16,210,16,211,16,212,16,213,16,214,16,215, + 16,216,16,217,16,218,16,219,16,220,16,221,16,222,16,223,16,224,16,225,16,226,16,227,16,228,16,229,16,230,16,231,16,232,16,233,16,234,16,235, + 16,236,16,237,16,238,16,239,16,240,16,241,16,242,16,243,16,244,16,245,16,246,16,247,16,248,16,249,16,250,16,251,16,252,16,253,16,254,16,255, + 17,0,17,1,17,2,17,3,17,4,17,5,17,6,17,7,17,8,17,9,17,10,17,11,17,12,17,13,17,14,17,15,17,16,17,17,17,18,17,19, + 17,20,17,21,17,22,17,23,17,24,17,25,17,26,17,27,17,28,17,29,17,30,17,31,17,32,17,33,17,34,17,35,17,36,17,37,17,38,17,39, + 17,40,17,41,17,42,17,43,17,44,17,45,17,46,17,47,17,48,17,49,17,50,17,51,17,52,17,53,17,54,17,55,17,56,17,57,17,58,17,59, + 17,60,17,61,17,62,17,63,17,64,17,65,17,66,17,67,17,68,17,69,17,70,17,71,17,72,17,73,17,74,17,75,17,76,17,77,17,78,17,79, + 17,80,17,81,17,82,17,83,17,84,17,85,17,86,17,87,17,88,17,89,17,90,17,91,17,92,17,93,17,94,17,95,17,96,17,97,17,98,17,99, + 17,100,17,101,17,102,17,103,17,104,17,105,17,106,17,107,17,108,17,109,17,110,17,111,17,112,17,113,17,114,17,115,17,116,17,117,17,118,17,119, + 17,120,17,121,17,122,17,123,17,124,17,125,17,126,17,127,17,128,17,129,17,130,17,131,17,132,17,133,17,134,17,135,17,136,17,137,17,138,17,139, + 17,140,17,141,17,142,17,143,17,144,17,145,17,146,17,147,17,148,17,149,17,150,17,151,17,152,17,153,17,154,17,155,17,156,17,157,17,158,17,159, + 17,160,17,161,17,162,17,163,17,164,17,165,17,166,17,167,17,168,17,169,17,170,17,171,17,172,17,173,17,174,17,175,17,176,17,177,17,178,17,179, + 17,180,17,181,17,182,17,183,17,184,17,185,17,186,17,187,17,188,17,189,17,190,17,191,17,192,17,193,17,194,17,195,17,196,17,197,17,198,17,199, + 17,200,17,201,17,202,17,203,17,204,17,205,17,206,17,207,17,208,17,209,17,210,17,211,17,212,17,213,17,214,17,215,17,216,17,217,17,218,17,219, + 17,220,17,221,17,222,17,223,17,224,17,225,17,226,17,227,17,228,17,229,17,230,17,231,17,232,17,233,17,234,17,235,17,236,17,237,17,238,17,239, + 17,240,17,241,17,242,17,243,17,244,17,245,17,246,17,247,17,248,17,249,17,250,17,251,17,252,17,253,17,254,17,255,18,0,18,1,18,2,18,3, + 18,4,18,5,18,6,18,7,18,8,18,9,18,10,18,11,18,12,18,13,18,14,18,15,18,16,18,17,18,18,18,19,18,20,18,21,18,22,18,23, + 18,24,18,25,18,26,18,27,18,28,18,29,18,30,18,31,18,32,18,33,18,34,18,35,18,36,18,37,18,38,18,39,18,40,18,41,18,42,18,43, + 18,44,18,45,18,46,18,47,18,48,18,49,18,50,18,51,18,52,18,53,18,54,18,55,18,56,18,57,18,58,18,59,18,60,18,61,18,62,18,63, + 18,64,18,65,18,66,18,67,18,68,18,69,18,70,18,71,18,72,18,73,18,74,18,75,18,76,18,77,18,78,18,79,18,80,18,81,18,82,18,83, + 18,84,18,85,18,86,18,87,18,88,18,89,18,90,18,91,18,92,18,93,18,94,18,95,18,96,18,97,18,98,18,99,18,100,18,101,18,102,18,103, + 18,104,18,105,18,106,18,107,18,108,18,109,18,110,18,111,18,112,18,113,18,114,18,115,18,116,18,117,18,118,18,119,18,120,18,121,18,122,18,123, + 18,124,18,125,18,126,18,127,18,128,18,129,18,130,18,131,18,132,18,133,18,134,18,135,18,136,18,137,18,138,18,139,18,140,18,141,18,142,18,143, + 18,144,18,145,18,146,18,147,18,148,18,149,18,150,18,151,18,152,18,153,18,154,18,155,18,156,18,157,18,158,18,159,18,160,18,161,18,162,18,163, + 18,164,18,165,18,166,18,167,18,168,18,169,18,170,18,171,18,172,18,173,18,174,18,175,18,176,18,177,18,178,18,179,18,180,18,181,18,182,18,183, + 18,184,18,185,18,186,18,187,18,188,18,189,18,190,18,191,18,192,18,193,18,194,18,195,18,196,18,197,18,198,18,199,18,200,18,201,18,202,18,203, + 18,204,18,205,18,206,18,207,18,208,18,209,18,210,18,211,18,212,18,213,18,214,18,215,18,216,18,217,18,218,18,219,18,220,18,221,18,222,18,223, + 18,224,18,225,18,226,18,227,18,228,18,229,18,230,18,231,18,232,18,233,18,234,18,235,18,236,18,237,18,238,18,239,18,240,18,241,18,242,18,243, + 18,244,18,245,18,246,18,247,18,248,18,249,18,250,18,251,18,252,18,253,18,254,18,255,19,0,19,1,19,2,19,3,19,4,19,5,19,6,19,7, + 19,8,19,9,19,10,19,11,19,12,19,13,19,14,19,15,19,16,19,17,19,18,19,19,19,20,19,21,19,22,19,23,19,24,19,25,19,26,19,27, + 19,28,19,29,19,30,19,31,19,32,19,33,19,34,19,35,19,36,19,37,19,38,19,39,19,40,19,41,19,42,19,43,19,44,19,45,19,46,19,47, + 19,48,19,49,19,50,19,51,19,52,19,53,19,54,19,55,19,56,19,57,19,58,19,59,19,60,19,61,19,62,19,63,19,64,19,65,19,66,19,67, + 19,68,19,69,19,70,19,71,19,72,19,73,19,74,19,75,19,76,19,77,19,78,19,79,19,80,19,81,19,82,19,83,19,84,19,85,19,86,19,87, + 19,88,19,89,19,90,19,91,19,92,19,93,19,94,19,95,19,96,19,97,19,98,19,99,19,100,19,101,19,102,19,103,19,104,19,105,19,106,19,107, + 19,108,19,109,19,110,19,111,19,112,19,113,19,114,19,115,19,116,19,117,19,118,19,119,19,120,19,121,19,122,19,123,19,124,19,125,19,126,19,127, + 19,128,19,129,19,130,19,131,19,132,19,133,19,134,19,135,19,136,19,137,19,138,19,139,19,140,19,141,19,142,19,143,19,144,19,145,19,146,19,147, + 19,148,19,149,19,150,19,151,19,152,19,153,19,154,19,155,19,156,19,157,19,158,19,159,19,160,19,161,19,162,19,163,19,164,19,165,19,166,19,167, + 19,168,0,192,0,193,19,169,19,170,19,171,19,172,19,173,19,174,19,175,19,176,19,177,19,178,19,179,19,180,19,181,19,182,19,183,19,184,19,185, + 19,186,19,187,19,188,19,189,19,190,19,191,19,192,19,193,19,194,19,195,19,196,19,197,19,198,19,199,19,200,19,201,19,202,19,203,19,204,19,205, + 19,206,19,207,19,208,19,209,19,210,19,211,19,212,19,213,19,214,19,215,19,216,19,217,19,218,19,219,19,220,19,221,19,222,19,223,19,224,19,225, + 19,226,19,227,19,228,19,229,19,230,19,231,19,232,19,233,19,234,19,235,19,236,19,237,19,238,19,239,19,240,19,241,19,242,19,243,19,244,19,245, + 19,246,19,247,19,248,19,249,19,250,19,251,19,252,19,253,19,254,19,255,20,0,20,1,20,2,20,3,20,4,20,5,20,6,20,7,20,8,20,9, + 20,10,20,11,20,12,20,13,20,14,20,15,20,16,20,17,20,18,20,19,20,20,20,21,20,22,20,23,20,24,20,25,20,26,20,27,20,28,20,29, + 20,30,20,31,20,32,20,33,20,34,20,35,20,36,20,37,20,38,20,39,20,40,20,41,20,42,20,43,20,44,20,45,20,46,20,47,20,48,20,49, + 20,50,20,51,20,52,20,53,20,54,20,55,20,56,20,57,20,58,20,59,20,60,20,61,20,62,20,63,20,64,20,65,20,66,20,67,20,68,20,69, + 20,70,20,71,20,72,20,73,20,74,20,75,20,76,20,77,20,78,20,79,20,80,20,81,20,82,20,83,20,84,20,85,20,86,20,87,20,88,20,89, + 20,90,20,91,20,92,20,93,20,94,20,95,20,96,20,97,20,98,20,99,20,100,20,101,20,102,20,103,20,104,20,105,20,106,20,107,20,108,20,109, + 20,110,20,111,20,112,20,113,20,114,20,115,20,116,20,117,20,118,20,119,20,120,20,121,20,122,20,123,20,124,20,125,20,126,20,127,20,128,20,129, + 20,130,20,131,20,132,20,133,20,134,20,135,20,136,20,137,20,138,20,139,20,140,20,141,20,142,20,143,20,144,20,145,20,146,20,147,20,148,20,149, + 20,150,20,151,20,152,20,153,20,154,20,155,20,156,20,157,20,158,20,159,20,160,20,161,20,162,20,163,20,164,20,165,20,166,20,167,20,168,20,169, + 20,170,20,171,20,172,20,173,20,174,20,175,20,176,20,177,20,178,20,179,20,180,20,181,20,182,20,183,20,184,20,185,20,186,20,187,20,188,20,189, + 20,190,20,191,20,192,20,193,20,194,20,195,20,196,20,197,20,198,20,199,20,200,20,201,20,202,20,203,20,204,20,205,20,206,20,207,20,208,20,209, + 20,210,20,211,20,212,20,213,20,214,20,215,20,216,20,217,20,218,20,219,20,220,20,221,20,222,20,223,20,224,20,225,20,226,20,227,20,228,20,229, + 20,230,20,231,20,232,20,233,20,234,20,235,20,236,20,237,20,238,20,239,20,240,20,241,20,242,20,243,20,244,20,245,20,246,20,247,20,248,20,249, + 20,250,20,251,20,252,20,253,20,254,20,255,21,0,21,1,21,2,21,3,21,4,21,5,21,6,21,7,21,8,21,9,21,10,21,11,21,12,21,13, + 21,14,21,15,21,16,21,17,21,18,21,19,21,20,21,21,21,22,21,23,21,24,21,25,21,26,21,27,21,28,21,29,21,30,21,31,21,32,21,33, + 21,34,21,35,21,36,21,37,21,38,21,39,21,40,21,41,21,42,21,43,21,44,21,45,21,46,21,47,21,48,21,49,21,50,21,51,21,52,21,53, + 21,54,21,55,21,56,21,57,21,58,21,59,21,60,21,61,21,62,21,63,21,64,21,65,21,66,21,67,21,68,21,69,21,70,21,71,21,72,21,73, + 21,74,21,75,21,76,21,77,21,78,21,79,21,80,21,81,21,82,21,83,21,84,21,85,21,86,21,87,21,88,21,89,21,90,21,91,21,92,21,93, + 21,94,21,95,21,96,21,97,21,98,21,99,21,100,21,101,21,102,21,103,21,104,21,105,21,106,21,107,21,108,21,109,21,110,21,111,21,112,21,113, + 21,114,21,115,21,116,21,117,21,118,21,119,21,120,21,121,21,122,21,123,21,124,21,125,21,126,21,127,21,128,21,129,21,130,21,131,21,132,21,133, + 21,134,21,135,21,136,21,137,21,138,21,139,21,140,21,141,21,142,21,143,21,144,21,145,21,146,21,147,21,148,21,149,21,150,21,151,21,152,21,153, + 21,154,21,155,21,156,21,157,21,158,21,159,21,160,21,161,21,162,21,163,21,164,21,165,21,166,21,167,21,168,21,169,21,170,21,171,21,172,21,173, + 21,174,21,175,21,176,21,177,21,178,21,179,21,180,21,181,21,182,21,183,21,184,21,185,21,186,21,187,21,188,21,189,21,190,21,191,21,192,21,193, + 21,194,21,195,21,196,21,197,21,198,21,199,21,200,21,201,21,202,21,203,21,204,21,205,21,206,21,207,21,208,21,209,21,210,21,211,21,212,21,213, + 21,214,21,215,21,216,21,217,21,218,21,219,21,220,21,221,21,222,21,223,21,224,21,225,21,226,21,227,21,228,21,229,21,230,21,231,21,232,21,233, + 21,234,21,235,21,236,21,237,21,238,21,239,21,240,21,241,21,242,21,243,21,244,21,245,21,246,21,247,21,248,21,249,21,250,21,251,21,252,21,253, + 21,254,21,255,22,0,22,1,22,2,22,3,22,4,22,5,22,6,22,7,22,8,22,9,22,10,22,11,22,12,22,13,22,14,22,15,22,16,22,17, + 22,18,22,19,22,20,22,21,22,22,22,23,22,24,22,25,22,26,22,27,22,28,22,29,22,30,22,31,22,32,22,33,22,34,22,35,22,36,22,37, + 22,38,22,39,22,40,22,41,22,42,22,43,22,44,22,45,22,46,22,47,22,48,22,49,22,50,22,51,22,52,22,53,22,54,22,55,22,56,22,57, + 22,58,22,59,22,60,22,61,22,62,22,63,22,64,22,65,22,66,22,67,22,68,22,69,22,70,22,71,22,72,22,73,22,74,22,75,22,76,22,77, + 22,78,22,79,22,80,22,81,22,82,22,83,22,84,22,85,22,86,22,87,22,88,22,89,22,90,22,91,22,92,22,93,22,94,22,95,22,96,22,97, + 22,98,22,99,22,100,22,101,22,102,22,103,22,104,22,105,22,106,22,107,22,108,22,109,22,110,22,111,22,112,22,113,22,114,22,115,22,116,22,117, + 22,118,22,119,22,120,22,121,22,122,22,123,22,124,22,125,22,126,22,127,22,128,22,129,22,130,22,131,22,132,22,133,22,134,22,135,22,136,22,137, + 22,138,22,139,22,140,22,141,22,142,22,143,22,144,22,145,22,146,22,147,22,148,22,149,22,150,22,151,22,152,22,153,22,154,22,155,22,156,22,157, + 22,158,22,159,22,160,22,161,22,162,22,163,22,164,22,165,22,166,22,167,22,168,22,169,22,170,22,171,22,172,22,173,22,174,22,175,22,176,22,177, + 22,178,22,179,22,180,22,181,22,182,22,183,22,184,22,185,22,186,22,187,22,188,22,189,22,190,22,191,22,192,22,193,22,194,22,195,22,196,22,197, + 22,198,22,199,22,200,22,201,22,202,22,203,22,204,22,205,22,206,22,207,22,208,22,209,22,210,22,211,22,212,22,213,22,214,22,215,22,216,22,217, + 22,218,22,219,22,220,22,221,22,222,22,223,22,224,22,225,22,226,22,227,22,228,22,229,22,230,22,231,22,232,22,233,22,234,22,235,22,236,22,237, + 22,238,22,239,22,240,22,241,22,242,22,243,22,244,22,245,22,246,22,247,22,248,22,249,22,250,22,251,22,252,22,253,22,254,22,255,23,0,23,1, + 23,2,23,3,23,4,23,5,23,6,23,7,23,8,23,9,23,10,23,11,23,12,23,13,23,14,23,15,23,16,23,17,23,18,23,19,23,20,23,21, + 23,22,23,23,23,24,23,25,23,26,23,27,23,28,23,29,23,30,23,31,23,32,23,33,23,34,23,35,23,36,23,37,23,38,23,39,23,40,23,41, + 23,42,23,43,23,44,23,45,23,46,23,47,23,48,23,49,23,50,23,51,23,52,23,53,23,54,23,55,23,56,23,57,23,58,23,59,23,60,23,61, + 23,62,23,63,23,64,23,65,23,66,23,67,23,68,23,69,23,70,23,71,23,72,23,73,23,74,23,75,23,76,23,77,23,78,23,79,23,80,23,81, + 23,82,23,83,23,84,23,85,23,86,23,87,23,88,23,89,23,90,23,91,23,92,23,93,23,94,23,95,23,96,23,97,23,98,23,99,23,100,23,101, + 23,102,23,103,23,104,23,105,23,106,23,107,23,108,23,109,23,110,23,111,23,112,23,113,23,114,23,115,23,116,23,117,23,118,23,119,23,120,23,121, + 23,122,23,123,23,124,23,125,23,126,23,127,23,128,23,129,23,130,23,131,23,132,23,133,23,134,23,135,23,136,23,137,23,138,23,139,23,140,23,141, + 23,142,23,143,23,144,23,145,23,146,23,147,23,148,23,149,23,150,23,151,23,152,23,153,23,154,23,155,23,156,23,157,23,158,23,159,23,160,23,161, + 23,162,23,163,23,164,23,165,23,166,23,167,23,168,23,169,23,170,23,171,23,172,23,173,23,174,23,175,23,176,23,177,23,178,23,179,23,180,23,181, + 23,182,23,183,23,184,23,185,23,186,23,187,23,188,23,189,23,190,23,191,23,192,23,193,23,194,23,195,23,196,23,197,23,198,23,199,23,200,23,201, + 23,202,23,203,23,204,23,205,23,206,23,207,23,208,23,209,23,210,23,211,23,212,23,213,23,214,23,215,23,216,23,217,23,218,23,219,23,220,9,115, + 102,116,104,121,112,104,101,110,7,65,109,97,99,114,111,110,7,97,109,97,99,114,111,110,6,65,98,114,101,118,101,6,97,98,114,101,118,101,7,65, + 111,103,111,110,101,107,7,97,111,103,111,110,101,107,11,67,99,105,114,99,117,109,102,108,101,120,11,99,99,105,114,99,117,109,102,108,101,120,10,67, + 100,111,116,97,99,99,101,110,116,10,99,100,111,116,97,99,99,101,110,116,6,68,99,97,114,111,110,6,100,99,97,114,111,110,6,68,99,114,111,97, + 116,7,69,109,97,99,114,111,110,7,101,109,97,99,114,111,110,6,69,98,114,101,118,101,6,101,98,114,101,118,101,10,69,100,111,116,97,99,99,101, + 110,116,10,101,100,111,116,97,99,99,101,110,116,7,69,111,103,111,110,101,107,7,101,111,103,111,110,101,107,6,69,99,97,114,111,110,6,101,99,97, + 114,111,110,11,71,99,105,114,99,117,109,102,108,101,120,11,103,99,105,114,99,117,109,102,108,101,120,10,71,100,111,116,97,99,99,101,110,116,10,103, + 100,111,116,97,99,99,101,110,116,12,71,99,111,109,109,97,97,99,99,101,110,116,12,103,99,111,109,109,97,97,99,99,101,110,116,11,72,99,105,114, + 99,117,109,102,108,101,120,11,104,99,105,114,99,117,109,102,108,101,120,4,72,98,97,114,4,104,98,97,114,6,73,116,105,108,100,101,6,105,116,105, + 108,100,101,7,73,109,97,99,114,111,110,7,105,109,97,99,114,111,110,6,73,98,114,101,118,101,6,105,98,114,101,118,101,7,73,111,103,111,110,101, + 107,7,105,111,103,111,110,101,107,2,73,74,2,105,106,11,74,99,105,114,99,117,109,102,108,101,120,11,106,99,105,114,99,117,109,102,108,101,120,12, + 75,99,111,109,109,97,97,99,99,101,110,116,12,107,99,111,109,109,97,97,99,99,101,110,116,12,107,103,114,101,101,110,108,97,110,100,105,99,6,76, + 97,99,117,116,101,6,108,97,99,117,116,101,12,76,99,111,109,109,97,97,99,99,101,110,116,12,108,99,111,109,109,97,97,99,99,101,110,116,6,76, + 99,97,114,111,110,6,108,99,97,114,111,110,4,76,100,111,116,4,108,100,111,116,6,78,97,99,117,116,101,6,110,97,99,117,116,101,12,78,99,111, + 109,109,97,97,99,99,101,110,116,12,110,99,111,109,109,97,97,99,99,101,110,116,6,78,99,97,114,111,110,6,110,99,97,114,111,110,11,110,97,112, + 111,115,116,114,111,112,104,101,3,69,110,103,3,101,110,103,7,79,109,97,99,114,111,110,7,111,109,97,99,114,111,110,6,79,98,114,101,118,101,6, + 111,98,114,101,118,101,13,79,104,117,110,103,97,114,117,109,108,97,117,116,13,111,104,117,110,103,97,114,117,109,108,97,117,116,6,82,97,99,117,116, + 101,6,114,97,99,117,116,101,12,82,99,111,109,109,97,97,99,99,101,110,116,12,114,99,111,109,109,97,97,99,99,101,110,116,6,82,99,97,114,111, + 110,6,114,99,97,114,111,110,6,83,97,99,117,116,101,6,115,97,99,117,116,101,11,83,99,105,114,99,117,109,102,108,101,120,11,115,99,105,114,99, + 117,109,102,108,101,120,12,84,99,111,109,109,97,97,99,99,101,110,116,12,116,99,111,109,109,97,97,99,99,101,110,116,6,84,99,97,114,111,110,6, + 116,99,97,114,111,110,4,84,98,97,114,4,116,98,97,114,6,85,116,105,108,100,101,6,117,116,105,108,100,101,7,85,109,97,99,114,111,110,7,117, + 109,97,99,114,111,110,6,85,98,114,101,118,101,6,117,98,114,101,118,101,5,85,114,105,110,103,5,117,114,105,110,103,13,85,104,117,110,103,97,114, + 117,109,108,97,117,116,13,117,104,117,110,103,97,114,117,109,108,97,117,116,7,85,111,103,111,110,101,107,7,117,111,103,111,110,101,107,11,87,99,105, + 114,99,117,109,102,108,101,120,11,119,99,105,114,99,117,109,102,108,101,120,11,89,99,105,114,99,117,109,102,108,101,120,11,121,99,105,114,99,117,109, + 102,108,101,120,6,90,97,99,117,116,101,6,122,97,99,117,116,101,10,90,100,111,116,97,99,99,101,110,116,10,122,100,111,116,97,99,99,101,110,116, + 5,108,111,110,103,115,7,117,110,105,48,49,56,48,7,117,110,105,48,49,56,49,7,117,110,105,48,49,56,50,7,117,110,105,48,49,56,51,7,117, + 110,105,48,49,56,52,7,117,110,105,48,49,56,53,7,117,110,105,48,49,56,54,7,117,110,105,48,49,56,55,7,117,110,105,48,49,56,56,7,117, + 110,105,48,49,56,57,7,117,110,105,48,49,56,65,7,117,110,105,48,49,56,66,7,117,110,105,48,49,56,67,7,117,110,105,48,49,56,68,7,117, + 110,105,48,49,56,69,7,117,110,105,48,49,56,70,7,117,110,105,48,49,57,48,7,117,110,105,48,49,57,49,7,117,110,105,48,49,57,51,7,117, + 110,105,48,49,57,52,7,117,110,105,48,49,57,53,7,117,110,105,48,49,57,54,7,117,110,105,48,49,57,55,7,117,110,105,48,49,57,56,7,117, + 110,105,48,49,57,57,7,117,110,105,48,49,57,65,7,117,110,105,48,49,57,66,7,117,110,105,48,49,57,67,7,117,110,105,48,49,57,68,7,117, + 110,105,48,49,57,69,7,117,110,105,48,49,57,70,5,79,104,111,114,110,5,111,104,111,114,110,7,117,110,105,48,49,65,50,7,117,110,105,48,49, + 65,51,7,117,110,105,48,49,65,52,7,117,110,105,48,49,65,53,7,117,110,105,48,49,65,54,7,117,110,105,48,49,65,55,7,117,110,105,48,49, + 65,56,7,117,110,105,48,49,65,57,7,117,110,105,48,49,65,65,7,117,110,105,48,49,65,66,7,117,110,105,48,49,65,67,7,117,110,105,48,49, + 65,68,7,117,110,105,48,49,65,69,5,85,104,111,114,110,5,117,104,111,114,110,7,117,110,105,48,49,66,49,7,117,110,105,48,49,66,50,7,117, + 110,105,48,49,66,51,7,117,110,105,48,49,66,52,7,117,110,105,48,49,66,53,7,117,110,105,48,49,66,54,7,117,110,105,48,49,66,55,7,117, + 110,105,48,49,66,56,7,117,110,105,48,49,66,57,7,117,110,105,48,49,66,65,7,117,110,105,48,49,66,66,7,117,110,105,48,49,66,67,7,117, + 110,105,48,49,66,68,7,117,110,105,48,49,66,69,7,117,110,105,48,49,66,70,7,117,110,105,48,49,67,48,7,117,110,105,48,49,67,49,7,117, + 110,105,48,49,67,50,7,117,110,105,48,49,67,51,7,117,110,105,48,49,67,52,7,117,110,105,48,49,67,53,7,117,110,105,48,49,67,54,7,117, + 110,105,48,49,67,55,7,117,110,105,48,49,67,56,7,117,110,105,48,49,67,57,7,117,110,105,48,49,67,65,7,117,110,105,48,49,67,66,7,117, + 110,105,48,49,67,67,7,117,110,105,48,49,67,68,7,117,110,105,48,49,67,69,7,117,110,105,48,49,67,70,7,117,110,105,48,49,68,48,7,117, + 110,105,48,49,68,49,7,117,110,105,48,49,68,50,7,117,110,105,48,49,68,51,7,117,110,105,48,49,68,52,7,117,110,105,48,49,68,53,7,117, + 110,105,48,49,68,54,7,117,110,105,48,49,68,55,7,117,110,105,48,49,68,56,7,117,110,105,48,49,68,57,7,117,110,105,48,49,68,65,7,117, + 110,105,48,49,68,66,7,117,110,105,48,49,68,67,7,117,110,105,48,49,68,68,7,117,110,105,48,49,68,69,7,117,110,105,48,49,68,70,7,117, + 110,105,48,49,69,48,7,117,110,105,48,49,69,49,7,117,110,105,48,49,69,50,7,117,110,105,48,49,69,51,7,117,110,105,48,49,69,52,7,117, + 110,105,48,49,69,53,6,71,99,97,114,111,110,6,103,99,97,114,111,110,7,117,110,105,48,49,69,56,7,117,110,105,48,49,69,57,7,117,110,105, + 48,49,69,65,7,117,110,105,48,49,69,66,7,117,110,105,48,49,69,67,7,117,110,105,48,49,69,68,7,117,110,105,48,49,69,69,7,117,110,105, + 48,49,69,70,7,117,110,105,48,49,70,48,7,117,110,105,48,49,70,49,7,117,110,105,48,49,70,50,7,117,110,105,48,49,70,51,7,117,110,105, + 48,49,70,52,7,117,110,105,48,49,70,53,7,117,110,105,48,49,70,54,7,117,110,105,48,49,70,55,7,117,110,105,48,49,70,56,7,117,110,105, + 48,49,70,57,10,65,114,105,110,103,97,99,117,116,101,10,97,114,105,110,103,97,99,117,116,101,7,65,69,97,99,117,116,101,7,97,101,97,99,117, + 116,101,11,79,115,108,97,115,104,97,99,117,116,101,11,111,115,108,97,115,104,97,99,117,116,101,7,117,110,105,48,50,48,48,7,117,110,105,48,50, + 48,49,7,117,110,105,48,50,48,50,7,117,110,105,48,50,48,51,7,117,110,105,48,50,48,52,7,117,110,105,48,50,48,53,7,117,110,105,48,50, + 48,54,7,117,110,105,48,50,48,55,7,117,110,105,48,50,48,56,7,117,110,105,48,50,48,57,7,117,110,105,48,50,48,65,7,117,110,105,48,50, + 48,66,7,117,110,105,48,50,48,67,7,117,110,105,48,50,48,68,7,117,110,105,48,50,48,69,7,117,110,105,48,50,48,70,7,117,110,105,48,50, + 49,48,7,117,110,105,48,50,49,49,7,117,110,105,48,50,49,50,7,117,110,105,48,50,49,51,7,117,110,105,48,50,49,52,7,117,110,105,48,50, + 49,53,7,117,110,105,48,50,49,54,7,117,110,105,48,50,49,55,12,83,99,111,109,109,97,97,99,99,101,110,116,12,115,99,111,109,109,97,97,99, + 99,101,110,116,7,117,110,105,48,50,49,65,7,117,110,105,48,50,49,66,7,117,110,105,48,50,49,67,7,117,110,105,48,50,49,68,7,117,110,105, + 48,50,49,69,7,117,110,105,48,50,49,70,7,117,110,105,48,50,50,48,7,117,110,105,48,50,50,49,7,117,110,105,48,50,50,50,7,117,110,105, + 48,50,50,51,7,117,110,105,48,50,50,52,7,117,110,105,48,50,50,53,7,117,110,105,48,50,50,54,7,117,110,105,48,50,50,55,7,117,110,105, + 48,50,50,56,7,117,110,105,48,50,50,57,7,117,110,105,48,50,50,65,7,117,110,105,48,50,50,66,7,117,110,105,48,50,50,67,7,117,110,105, + 48,50,50,68,7,117,110,105,48,50,50,69,7,117,110,105,48,50,50,70,7,117,110,105,48,50,51,48,7,117,110,105,48,50,51,49,7,117,110,105, + 48,50,51,50,7,117,110,105,48,50,51,51,7,117,110,105,48,50,51,52,7,117,110,105,48,50,51,53,7,117,110,105,48,50,51,54,8,100,111,116, + 108,101,115,115,106,7,117,110,105,48,50,51,56,7,117,110,105,48,50,51,57,7,117,110,105,48,50,51,65,7,117,110,105,48,50,51,66,7,117,110, + 105,48,50,51,67,7,117,110,105,48,50,51,68,7,117,110,105,48,50,51,69,7,117,110,105,48,50,51,70,7,117,110,105,48,50,52,48,7,117,110, + 105,48,50,52,49,7,117,110,105,48,50,52,50,7,117,110,105,48,50,52,51,7,117,110,105,48,50,52,52,7,117,110,105,48,50,52,53,7,117,110, + 105,48,50,52,54,7,117,110,105,48,50,52,55,7,117,110,105,48,50,52,56,7,117,110,105,48,50,52,57,7,117,110,105,48,50,52,65,7,117,110, + 105,48,50,52,66,7,117,110,105,48,50,52,67,7,117,110,105,48,50,52,68,7,117,110,105,48,50,52,69,7,117,110,105,48,50,52,70,7,117,110, + 105,48,50,53,48,7,117,110,105,48,50,53,49,7,117,110,105,48,50,53,50,7,117,110,105,48,50,53,51,7,117,110,105,48,50,53,52,7,117,110, + 105,48,50,53,53,7,117,110,105,48,50,53,54,7,117,110,105,48,50,53,55,7,117,110,105,48,50,53,56,7,117,110,105,48,50,53,57,7,117,110, + 105,48,50,53,65,7,117,110,105,48,50,53,66,7,117,110,105,48,50,53,67,7,117,110,105,48,50,53,68,7,117,110,105,48,50,53,69,7,117,110, + 105,48,50,53,70,7,117,110,105,48,50,54,48,7,117,110,105,48,50,54,49,7,117,110,105,48,50,54,50,7,117,110,105,48,50,54,51,7,117,110, + 105,48,50,54,52,7,117,110,105,48,50,54,53,7,117,110,105,48,50,54,54,7,117,110,105,48,50,54,55,7,117,110,105,48,50,54,56,7,117,110, + 105,48,50,54,57,7,117,110,105,48,50,54,65,7,117,110,105,48,50,54,66,7,117,110,105,48,50,54,67,7,117,110,105,48,50,54,68,7,117,110, + 105,48,50,54,69,7,117,110,105,48,50,54,70,7,117,110,105,48,50,55,48,7,117,110,105,48,50,55,49,7,117,110,105,48,50,55,50,7,117,110, + 105,48,50,55,51,7,117,110,105,48,50,55,52,7,117,110,105,48,50,55,53,7,117,110,105,48,50,55,54,7,117,110,105,48,50,55,55,7,117,110, + 105,48,50,55,56,7,117,110,105,48,50,55,57,7,117,110,105,48,50,55,65,7,117,110,105,48,50,55,66,7,117,110,105,48,50,55,67,7,117,110, + 105,48,50,55,68,7,117,110,105,48,50,55,69,7,117,110,105,48,50,55,70,7,117,110,105,48,50,56,48,7,117,110,105,48,50,56,49,7,117,110, + 105,48,50,56,50,7,117,110,105,48,50,56,51,7,117,110,105,48,50,56,52,7,117,110,105,48,50,56,53,7,117,110,105,48,50,56,54,7,117,110, + 105,48,50,56,55,7,117,110,105,48,50,56,56,7,117,110,105,48,50,56,57,7,117,110,105,48,50,56,65,7,117,110,105,48,50,56,66,7,117,110, + 105,48,50,56,67,7,117,110,105,48,50,56,68,7,117,110,105,48,50,56,69,7,117,110,105,48,50,56,70,7,117,110,105,48,50,57,48,7,117,110, + 105,48,50,57,49,7,117,110,105,48,50,57,50,7,117,110,105,48,50,57,51,7,117,110,105,48,50,57,52,7,117,110,105,48,50,57,53,7,117,110, + 105,48,50,57,54,7,117,110,105,48,50,57,55,7,117,110,105,48,50,57,56,7,117,110,105,48,50,57,57,7,117,110,105,48,50,57,65,7,117,110, + 105,48,50,57,66,7,117,110,105,48,50,57,67,7,117,110,105,48,50,57,68,7,117,110,105,48,50,57,69,7,117,110,105,48,50,57,70,7,117,110, + 105,48,50,65,48,7,117,110,105,48,50,65,49,7,117,110,105,48,50,65,50,7,117,110,105,48,50,65,51,7,117,110,105,48,50,65,52,7,117,110, + 105,48,50,65,53,7,117,110,105,48,50,65,54,7,117,110,105,48,50,65,55,7,117,110,105,48,50,65,56,7,117,110,105,48,50,65,57,7,117,110, + 105,48,50,65,65,7,117,110,105,48,50,65,66,7,117,110,105,48,50,65,67,7,117,110,105,48,50,65,68,7,117,110,105,48,50,65,69,7,117,110, + 105,48,50,65,70,7,117,110,105,48,50,66,48,7,117,110,105,48,50,66,49,7,117,110,105,48,50,66,50,7,117,110,105,48,50,66,51,7,117,110, + 105,48,50,66,52,7,117,110,105,48,50,66,53,7,117,110,105,48,50,66,54,7,117,110,105,48,50,66,55,7,117,110,105,48,50,66,56,7,117,110, + 105,48,50,66,57,7,117,110,105,48,50,66,65,7,117,110,105,48,50,66,66,7,117,110,105,48,50,66,67,7,117,110,105,48,50,66,68,7,117,110, + 105,48,50,66,69,7,117,110,105,48,50,66,70,7,117,110,105,48,50,67,48,7,117,110,105,48,50,67,49,7,117,110,105,48,50,67,50,7,117,110, + 105,48,50,67,51,7,117,110,105,48,50,67,52,7,117,110,105,48,50,67,53,7,117,110,105,48,50,67,56,7,117,110,105,48,50,67,57,7,117,110, + 105,48,50,67,65,7,117,110,105,48,50,67,66,7,117,110,105,48,50,67,67,7,117,110,105,48,50,67,68,7,117,110,105,48,50,67,69,7,117,110, + 105,48,50,67,70,7,117,110,105,48,50,68,48,7,117,110,105,48,50,68,49,7,117,110,105,48,50,68,50,7,117,110,105,48,50,68,51,7,117,110, + 105,48,50,68,52,7,117,110,105,48,50,68,53,7,117,110,105,48,50,68,54,7,117,110,105,48,50,68,55,7,117,110,105,48,50,68,69,7,117,110, + 105,48,50,68,70,7,117,110,105,48,50,69,48,7,117,110,105,48,50,69,49,7,117,110,105,48,50,69,50,7,117,110,105,48,50,69,51,7,117,110, + 105,48,50,69,52,7,117,110,105,48,50,69,53,7,117,110,105,48,50,69,54,7,117,110,105,48,50,69,55,7,117,110,105,48,50,69,56,7,117,110, + 105,48,50,69,57,7,117,110,105,48,50,69,67,7,117,110,105,48,50,69,68,7,117,110,105,48,50,69,69,7,117,110,105,48,50,70,51,7,117,110, + 105,48,50,70,55,9,103,114,97,118,101,99,111,109,98,9,97,99,117,116,101,99,111,109,98,7,117,110,105,48,51,48,50,9,116,105,108,100,101,99, + 111,109,98,7,117,110,105,48,51,48,52,7,117,110,105,48,51,48,53,7,117,110,105,48,51,48,54,7,117,110,105,48,51,48,55,7,117,110,105,48, + 51,48,56,13,104,111,111,107,97,98,111,118,101,99,111,109,98,7,117,110,105,48,51,48,65,7,117,110,105,48,51,48,66,7,117,110,105,48,51,48, + 67,7,117,110,105,48,51,48,68,7,117,110,105,48,51,48,69,7,117,110,105,48,51,48,70,7,117,110,105,48,51,49,48,7,117,110,105,48,51,49, + 49,7,117,110,105,48,51,49,50,7,117,110,105,48,51,49,51,7,117,110,105,48,51,49,52,7,117,110,105,48,51,49,53,7,117,110,105,48,51,49, + 54,7,117,110,105,48,51,49,55,7,117,110,105,48,51,49,56,7,117,110,105,48,51,49,57,7,117,110,105,48,51,49,65,7,117,110,105,48,51,49, + 66,7,117,110,105,48,51,49,67,7,117,110,105,48,51,49,68,7,117,110,105,48,51,49,69,7,117,110,105,48,51,49,70,7,117,110,105,48,51,50, + 48,7,117,110,105,48,51,50,49,7,117,110,105,48,51,50,50,12,100,111,116,98,101,108,111,119,99,111,109,98,7,117,110,105,48,51,50,52,7,117, + 110,105,48,51,50,53,7,117,110,105,48,51,50,54,7,117,110,105,48,51,50,55,7,117,110,105,48,51,50,56,7,117,110,105,48,51,50,57,7,117, + 110,105,48,51,50,65,7,117,110,105,48,51,50,66,7,117,110,105,48,51,50,67,7,117,110,105,48,51,50,68,7,117,110,105,48,51,50,69,7,117, + 110,105,48,51,50,70,7,117,110,105,48,51,51,48,7,117,110,105,48,51,51,49,7,117,110,105,48,51,51,50,7,117,110,105,48,51,51,51,7,117, + 110,105,48,51,51,52,7,117,110,105,48,51,51,53,7,117,110,105,48,51,51,54,7,117,110,105,48,51,51,55,7,117,110,105,48,51,51,56,7,117, + 110,105,48,51,51,57,7,117,110,105,48,51,51,65,7,117,110,105,48,51,51,66,7,117,110,105,48,51,51,67,7,117,110,105,48,51,51,68,7,117, + 110,105,48,51,51,69,7,117,110,105,48,51,51,70,7,117,110,105,48,51,52,48,7,117,110,105,48,51,52,49,7,117,110,105,48,51,52,50,7,117, + 110,105,48,51,52,51,7,117,110,105,48,51,52,52,7,117,110,105,48,51,52,53,7,117,110,105,48,51,52,54,7,117,110,105,48,51,52,55,7,117, + 110,105,48,51,52,56,7,117,110,105,48,51,52,57,7,117,110,105,48,51,52,65,7,117,110,105,48,51,52,66,7,117,110,105,48,51,52,67,7,117, + 110,105,48,51,52,68,7,117,110,105,48,51,52,69,7,117,110,105,48,51,52,70,7,117,110,105,48,51,53,49,7,117,110,105,48,51,53,50,7,117, + 110,105,48,51,53,51,7,117,110,105,48,51,53,55,7,117,110,105,48,51,53,56,7,117,110,105,48,51,53,65,7,117,110,105,48,51,53,67,7,117, + 110,105,48,51,53,68,7,117,110,105,48,51,53,69,7,117,110,105,48,51,53,70,7,117,110,105,48,51,54,48,7,117,110,105,48,51,54,49,7,117, + 110,105,48,51,54,50,7,117,110,105,48,51,55,48,7,117,110,105,48,51,55,49,7,117,110,105,48,51,55,50,7,117,110,105,48,51,55,51,7,117, + 110,105,48,51,55,52,7,117,110,105,48,51,55,53,7,117,110,105,48,51,55,54,7,117,110,105,48,51,55,55,7,117,110,105,48,51,55,65,7,117, + 110,105,48,51,55,66,7,117,110,105,48,51,55,67,7,117,110,105,48,51,55,68,7,117,110,105,48,51,55,69,5,116,111,110,111,115,13,100,105,101, + 114,101,115,105,115,116,111,110,111,115,10,65,108,112,104,97,116,111,110,111,115,9,97,110,111,116,101,108,101,105,97,12,69,112,115,105,108,111,110,116, + 111,110,111,115,8,69,116,97,116,111,110,111,115,9,73,111,116,97,116,111,110,111,115,12,79,109,105,99,114,111,110,116,111,110,111,115,12,85,112,115, + 105,108,111,110,116,111,110,111,115,10,79,109,101,103,97,116,111,110,111,115,17,105,111,116,97,100,105,101,114,101,115,105,115,116,111,110,111,115,5,65, + 108,112,104,97,4,66,101,116,97,5,71,97,109,109,97,7,117,110,105,48,51,57,52,7,69,112,115,105,108,111,110,4,90,101,116,97,3,69,116,97, + 5,84,104,101,116,97,4,73,111,116,97,5,75,97,112,112,97,6,76,97,109,98,100,97,2,77,117,2,78,117,2,88,105,7,79,109,105,99,114,111, + 110,2,80,105,3,82,104,111,5,83,105,103,109,97,3,84,97,117,7,85,112,115,105,108,111,110,3,80,104,105,3,67,104,105,3,80,115,105,12,73, + 111,116,97,100,105,101,114,101,115,105,115,15,85,112,115,105,108,111,110,100,105,101,114,101,115,105,115,10,97,108,112,104,97,116,111,110,111,115,12,101, + 112,115,105,108,111,110,116,111,110,111,115,8,101,116,97,116,111,110,111,115,9,105,111,116,97,116,111,110,111,115,20,117,112,115,105,108,111,110,100,105, + 101,114,101,115,105,115,116,111,110,111,115,5,97,108,112,104,97,4,98,101,116,97,5,103,97,109,109,97,5,100,101,108,116,97,7,101,112,115,105,108, + 111,110,4,122,101,116,97,3,101,116,97,5,116,104,101,116,97,4,105,111,116,97,5,107,97,112,112,97,6,108,97,109,98,100,97,7,117,110,105,48, + 51,66,67,2,110,117,2,120,105,7,111,109,105,99,114,111,110,3,114,104,111,6,115,105,103,109,97,49,5,115,105,103,109,97,3,116,97,117,7,117, + 112,115,105,108,111,110,3,112,104,105,3,99,104,105,3,112,115,105,5,111,109,101,103,97,12,105,111,116,97,100,105,101,114,101,115,105,115,15,117,112, + 115,105,108,111,110,100,105,101,114,101,115,105,115,12,111,109,105,99,114,111,110,116,111,110,111,115,12,117,112,115,105,108,111,110,116,111,110,111,115,10, + 111,109,101,103,97,116,111,110,111,115,7,117,110,105,48,51,67,70,7,117,110,105,48,51,68,48,6,116,104,101,116,97,49,8,85,112,115,105,108,111, + 110,49,7,117,110,105,48,51,68,51,7,117,110,105,48,51,68,52,4,112,104,105,49,6,111,109,101,103,97,49,7,117,110,105,48,51,68,55,7,117, + 110,105,48,51,68,56,7,117,110,105,48,51,68,57,7,117,110,105,48,51,68,65,7,117,110,105,48,51,68,66,7,117,110,105,48,51,68,67,7,117, + 110,105,48,51,68,68,7,117,110,105,48,51,68,69,7,117,110,105,48,51,68,70,7,117,110,105,48,51,69,48,7,117,110,105,48,51,69,49,7,117, + 110,105,48,51,69,50,7,117,110,105,48,51,69,51,7,117,110,105,48,51,69,52,7,117,110,105,48,51,69,53,7,117,110,105,48,51,69,54,7,117, + 110,105,48,51,69,55,7,117,110,105,48,51,69,56,7,117,110,105,48,51,69,57,7,117,110,105,48,51,69,65,7,117,110,105,48,51,69,66,7,117, + 110,105,48,51,69,67,7,117,110,105,48,51,69,68,7,117,110,105,48,51,69,69,7,117,110,105,48,51,69,70,7,117,110,105,48,51,70,48,7,117, + 110,105,48,51,70,49,7,117,110,105,48,51,70,50,7,117,110,105,48,51,70,51,7,117,110,105,48,51,70,52,7,117,110,105,48,51,70,53,7,117, + 110,105,48,51,70,54,7,117,110,105,48,51,70,55,7,117,110,105,48,51,70,56,7,117,110,105,48,51,70,57,7,117,110,105,48,51,70,65,7,117, + 110,105,48,51,70,66,7,117,110,105,48,51,70,67,7,117,110,105,48,51,70,68,7,117,110,105,48,51,70,69,7,117,110,105,48,51,70,70,7,117, + 110,105,48,52,48,48,7,117,110,105,48,52,48,49,7,117,110,105,48,52,48,50,7,117,110,105,48,52,48,51,7,117,110,105,48,52,48,52,7,117, + 110,105,48,52,48,53,7,117,110,105,48,52,48,54,7,117,110,105,48,52,48,55,7,117,110,105,48,52,48,56,7,117,110,105,48,52,48,57,7,117, + 110,105,48,52,48,65,7,117,110,105,48,52,48,66,7,117,110,105,48,52,48,67,7,117,110,105,48,52,48,68,7,117,110,105,48,52,48,69,7,117, + 110,105,48,52,48,70,7,117,110,105,48,52,49,48,7,117,110,105,48,52,49,49,7,117,110,105,48,52,49,50,7,117,110,105,48,52,49,51,7,117, + 110,105,48,52,49,52,7,117,110,105,48,52,49,53,7,117,110,105,48,52,49,54,7,117,110,105,48,52,49,55,7,117,110,105,48,52,49,56,7,117, + 110,105,48,52,49,57,7,117,110,105,48,52,49,65,7,117,110,105,48,52,49,66,7,117,110,105,48,52,49,67,7,117,110,105,48,52,49,68,7,117, + 110,105,48,52,49,69,7,117,110,105,48,52,49,70,7,117,110,105,48,52,50,48,7,117,110,105,48,52,50,49,7,117,110,105,48,52,50,50,7,117, + 110,105,48,52,50,51,7,117,110,105,48,52,50,52,7,117,110,105,48,52,50,53,7,117,110,105,48,52,50,54,7,117,110,105,48,52,50,55,7,117, + 110,105,48,52,50,56,7,117,110,105,48,52,50,57,7,117,110,105,48,52,50,65,7,117,110,105,48,52,50,66,7,117,110,105,48,52,50,67,7,117, + 110,105,48,52,50,68,7,117,110,105,48,52,50,69,7,117,110,105,48,52,50,70,7,117,110,105,48,52,51,48,7,117,110,105,48,52,51,49,7,117, + 110,105,48,52,51,50,7,117,110,105,48,52,51,51,7,117,110,105,48,52,51,52,7,117,110,105,48,52,51,53,7,117,110,105,48,52,51,54,7,117, + 110,105,48,52,51,55,7,117,110,105,48,52,51,56,7,117,110,105,48,52,51,57,7,117,110,105,48,52,51,65,7,117,110,105,48,52,51,66,7,117, + 110,105,48,52,51,67,7,117,110,105,48,52,51,68,7,117,110,105,48,52,51,69,7,117,110,105,48,52,51,70,7,117,110,105,48,52,52,48,7,117, + 110,105,48,52,52,49,7,117,110,105,48,52,52,50,7,117,110,105,48,52,52,51,7,117,110,105,48,52,52,52,7,117,110,105,48,52,52,53,7,117, + 110,105,48,52,52,54,7,117,110,105,48,52,52,55,7,117,110,105,48,52,52,56,7,117,110,105,48,52,52,57,7,117,110,105,48,52,52,65,7,117, + 110,105,48,52,52,66,7,117,110,105,48,52,52,67,7,117,110,105,48,52,52,68,7,117,110,105,48,52,52,69,7,117,110,105,48,52,52,70,7,117, + 110,105,48,52,53,48,7,117,110,105,48,52,53,49,7,117,110,105,48,52,53,50,7,117,110,105,48,52,53,51,7,117,110,105,48,52,53,52,7,117, + 110,105,48,52,53,53,7,117,110,105,48,52,53,54,7,117,110,105,48,52,53,55,7,117,110,105,48,52,53,56,7,117,110,105,48,52,53,57,7,117, + 110,105,48,52,53,65,7,117,110,105,48,52,53,66,7,117,110,105,48,52,53,67,7,117,110,105,48,52,53,68,7,117,110,105,48,52,53,69,7,117, + 110,105,48,52,53,70,7,117,110,105,48,52,54,48,7,117,110,105,48,52,54,49,7,117,110,105,48,52,54,50,7,117,110,105,48,52,54,51,7,117, + 110,105,48,52,54,52,7,117,110,105,48,52,54,53,7,117,110,105,48,52,54,54,7,117,110,105,48,52,54,55,7,117,110,105,48,52,54,56,7,117, + 110,105,48,52,54,57,7,117,110,105,48,52,54,65,7,117,110,105,48,52,54,66,7,117,110,105,48,52,54,67,7,117,110,105,48,52,54,68,7,117, + 110,105,48,52,54,69,7,117,110,105,48,52,54,70,7,117,110,105,48,52,55,48,7,117,110,105,48,52,55,49,7,117,110,105,48,52,55,50,7,117, + 110,105,48,52,55,51,7,117,110,105,48,52,55,52,7,117,110,105,48,52,55,53,7,117,110,105,48,52,55,54,7,117,110,105,48,52,55,55,7,117, + 110,105,48,52,55,56,7,117,110,105,48,52,55,57,7,117,110,105,48,52,55,65,7,117,110,105,48,52,55,66,7,117,110,105,48,52,55,67,7,117, + 110,105,48,52,55,68,7,117,110,105,48,52,55,69,7,117,110,105,48,52,55,70,7,117,110,105,48,52,56,48,7,117,110,105,48,52,56,49,7,117, + 110,105,48,52,56,50,7,117,110,105,48,52,56,51,7,117,110,105,48,52,56,52,7,117,110,105,48,52,56,53,7,117,110,105,48,52,56,54,7,117, + 110,105,48,52,56,55,7,117,110,105,48,52,56,56,7,117,110,105,48,52,56,57,7,117,110,105,48,52,56,65,7,117,110,105,48,52,56,66,7,117, + 110,105,48,52,56,67,7,117,110,105,48,52,56,68,7,117,110,105,48,52,56,69,7,117,110,105,48,52,56,70,7,117,110,105,48,52,57,48,7,117, + 110,105,48,52,57,49,7,117,110,105,48,52,57,50,7,117,110,105,48,52,57,51,7,117,110,105,48,52,57,52,7,117,110,105,48,52,57,53,7,117, + 110,105,48,52,57,54,7,117,110,105,48,52,57,55,7,117,110,105,48,52,57,56,7,117,110,105,48,52,57,57,7,117,110,105,48,52,57,65,7,117, + 110,105,48,52,57,66,7,117,110,105,48,52,57,67,7,117,110,105,48,52,57,68,7,117,110,105,48,52,57,69,7,117,110,105,48,52,57,70,7,117, + 110,105,48,52,65,48,7,117,110,105,48,52,65,49,7,117,110,105,48,52,65,50,7,117,110,105,48,52,65,51,7,117,110,105,48,52,65,52,7,117, + 110,105,48,52,65,53,7,117,110,105,48,52,65,54,7,117,110,105,48,52,65,55,7,117,110,105,48,52,65,56,7,117,110,105,48,52,65,57,7,117, + 110,105,48,52,65,65,7,117,110,105,48,52,65,66,7,117,110,105,48,52,65,67,7,117,110,105,48,52,65,68,7,117,110,105,48,52,65,69,7,117, + 110,105,48,52,65,70,7,117,110,105,48,52,66,48,7,117,110,105,48,52,66,49,7,117,110,105,48,52,66,50,7,117,110,105,48,52,66,51,7,117, + 110,105,48,52,66,52,7,117,110,105,48,52,66,53,7,117,110,105,48,52,66,54,7,117,110,105,48,52,66,55,7,117,110,105,48,52,66,56,7,117, + 110,105,48,52,66,57,7,117,110,105,48,52,66,65,7,117,110,105,48,52,66,66,7,117,110,105,48,52,66,67,7,117,110,105,48,52,66,68,7,117, + 110,105,48,52,66,69,7,117,110,105,48,52,66,70,7,117,110,105,48,52,67,48,7,117,110,105,48,52,67,49,7,117,110,105,48,52,67,50,7,117, + 110,105,48,52,67,51,7,117,110,105,48,52,67,52,7,117,110,105,48,52,67,53,7,117,110,105,48,52,67,54,7,117,110,105,48,52,67,55,7,117, + 110,105,48,52,67,56,7,117,110,105,48,52,67,57,7,117,110,105,48,52,67,65,7,117,110,105,48,52,67,66,7,117,110,105,48,52,67,67,7,117, + 110,105,48,52,67,68,7,117,110,105,48,52,67,69,7,117,110,105,48,52,67,70,7,117,110,105,48,52,68,48,7,117,110,105,48,52,68,49,7,117, + 110,105,48,52,68,50,7,117,110,105,48,52,68,51,7,117,110,105,48,52,68,52,7,117,110,105,48,52,68,53,7,117,110,105,48,52,68,54,7,117, + 110,105,48,52,68,55,7,117,110,105,48,52,68,56,7,117,110,105,48,52,68,57,7,117,110,105,48,52,68,65,7,117,110,105,48,52,68,66,7,117, + 110,105,48,52,68,67,7,117,110,105,48,52,68,68,7,117,110,105,48,52,68,69,7,117,110,105,48,52,68,70,7,117,110,105,48,52,69,48,7,117, + 110,105,48,52,69,49,7,117,110,105,48,52,69,50,7,117,110,105,48,52,69,51,7,117,110,105,48,52,69,52,7,117,110,105,48,52,69,53,7,117, + 110,105,48,52,69,54,7,117,110,105,48,52,69,55,7,117,110,105,48,52,69,56,7,117,110,105,48,52,69,57,7,117,110,105,48,52,69,65,7,117, + 110,105,48,52,69,66,7,117,110,105,48,52,69,67,7,117,110,105,48,52,69,68,7,117,110,105,48,52,69,69,7,117,110,105,48,52,69,70,7,117, + 110,105,48,52,70,48,7,117,110,105,48,52,70,49,7,117,110,105,48,52,70,50,7,117,110,105,48,52,70,51,7,117,110,105,48,52,70,52,7,117, + 110,105,48,52,70,53,7,117,110,105,48,52,70,54,7,117,110,105,48,52,70,55,7,117,110,105,48,52,70,56,7,117,110,105,48,52,70,57,7,117, + 110,105,48,52,70,65,7,117,110,105,48,52,70,66,7,117,110,105,48,52,70,67,7,117,110,105,48,52,70,68,7,117,110,105,48,52,70,69,7,117, + 110,105,48,52,70,70,7,117,110,105,48,53,48,48,7,117,110,105,48,53,48,49,7,117,110,105,48,53,48,50,7,117,110,105,48,53,48,51,7,117, + 110,105,48,53,48,52,7,117,110,105,48,53,48,53,7,117,110,105,48,53,48,54,7,117,110,105,48,53,48,55,7,117,110,105,48,53,48,56,7,117, + 110,105,48,53,48,57,7,117,110,105,48,53,48,65,7,117,110,105,48,53,48,66,7,117,110,105,48,53,48,67,7,117,110,105,48,53,48,68,7,117, + 110,105,48,53,48,69,7,117,110,105,48,53,48,70,7,117,110,105,48,53,49,48,7,117,110,105,48,53,49,49,7,117,110,105,48,53,49,50,7,117, + 110,105,48,53,49,51,7,117,110,105,48,53,49,52,7,117,110,105,48,53,49,53,7,117,110,105,48,53,49,54,7,117,110,105,48,53,49,55,7,117, + 110,105,48,53,49,56,7,117,110,105,48,53,49,57,7,117,110,105,48,53,49,65,7,117,110,105,48,53,49,66,7,117,110,105,48,53,49,67,7,117, + 110,105,48,53,49,68,7,117,110,105,48,53,49,69,7,117,110,105,48,53,49,70,7,117,110,105,48,53,50,48,7,117,110,105,48,53,50,49,7,117, + 110,105,48,53,50,50,7,117,110,105,48,53,50,51,7,117,110,105,48,53,50,52,7,117,110,105,48,53,50,53,7,117,110,105,48,53,51,49,7,117, + 110,105,48,53,51,50,7,117,110,105,48,53,51,51,7,117,110,105,48,53,51,52,7,117,110,105,48,53,51,53,7,117,110,105,48,53,51,54,7,117, + 110,105,48,53,51,55,7,117,110,105,48,53,51,56,7,117,110,105,48,53,51,57,7,117,110,105,48,53,51,65,7,117,110,105,48,53,51,66,7,117, + 110,105,48,53,51,67,7,117,110,105,48,53,51,68,7,117,110,105,48,53,51,69,7,117,110,105,48,53,51,70,7,117,110,105,48,53,52,48,7,117, + 110,105,48,53,52,49,7,117,110,105,48,53,52,50,7,117,110,105,48,53,52,51,7,117,110,105,48,53,52,52,7,117,110,105,48,53,52,53,7,117, + 110,105,48,53,52,54,7,117,110,105,48,53,52,55,7,117,110,105,48,53,52,56,7,117,110,105,48,53,52,57,7,117,110,105,48,53,52,65,7,117, + 110,105,48,53,52,66,7,117,110,105,48,53,52,67,7,117,110,105,48,53,52,68,7,117,110,105,48,53,52,69,7,117,110,105,48,53,52,70,7,117, + 110,105,48,53,53,48,7,117,110,105,48,53,53,49,7,117,110,105,48,53,53,50,7,117,110,105,48,53,53,51,7,117,110,105,48,53,53,52,7,117, + 110,105,48,53,53,53,7,117,110,105,48,53,53,54,7,117,110,105,48,53,53,57,7,117,110,105,48,53,53,65,7,117,110,105,48,53,53,66,7,117, + 110,105,48,53,53,67,7,117,110,105,48,53,53,68,7,117,110,105,48,53,53,69,7,117,110,105,48,53,53,70,7,117,110,105,48,53,54,49,7,117, + 110,105,48,53,54,50,7,117,110,105,48,53,54,51,7,117,110,105,48,53,54,52,7,117,110,105,48,53,54,53,7,117,110,105,48,53,54,54,7,117, + 110,105,48,53,54,55,7,117,110,105,48,53,54,56,7,117,110,105,48,53,54,57,7,117,110,105,48,53,54,65,7,117,110,105,48,53,54,66,7,117, + 110,105,48,53,54,67,7,117,110,105,48,53,54,68,7,117,110,105,48,53,54,69,7,117,110,105,48,53,54,70,7,117,110,105,48,53,55,48,7,117, + 110,105,48,53,55,49,7,117,110,105,48,53,55,50,7,117,110,105,48,53,55,51,7,117,110,105,48,53,55,52,7,117,110,105,48,53,55,53,7,117, + 110,105,48,53,55,54,7,117,110,105,48,53,55,55,7,117,110,105,48,53,55,56,7,117,110,105,48,53,55,57,7,117,110,105,48,53,55,65,7,117, + 110,105,48,53,55,66,7,117,110,105,48,53,55,67,7,117,110,105,48,53,55,68,7,117,110,105,48,53,55,69,7,117,110,105,48,53,55,70,7,117, + 110,105,48,53,56,48,7,117,110,105,48,53,56,49,7,117,110,105,48,53,56,50,7,117,110,105,48,53,56,51,7,117,110,105,48,53,56,52,7,117, + 110,105,48,53,56,53,7,117,110,105,48,53,56,54,7,117,110,105,48,53,56,55,7,117,110,105,48,53,56,57,7,117,110,105,48,53,56,65,7,117, + 110,105,48,53,66,48,7,117,110,105,48,53,66,49,7,117,110,105,48,53,66,50,7,117,110,105,48,53,66,51,7,117,110,105,48,53,66,52,7,117, + 110,105,48,53,66,53,7,117,110,105,48,53,66,54,7,117,110,105,48,53,66,55,7,117,110,105,48,53,66,56,7,117,110,105,48,53,66,57,7,117, + 110,105,48,53,66,65,7,117,110,105,48,53,66,66,7,117,110,105,48,53,66,67,7,117,110,105,48,53,66,68,7,117,110,105,48,53,66,69,7,117, + 110,105,48,53,66,70,7,117,110,105,48,53,67,48,7,117,110,105,48,53,67,49,7,117,110,105,48,53,67,50,7,117,110,105,48,53,67,51,7,117, + 110,105,48,53,67,54,7,117,110,105,48,53,67,55,7,117,110,105,48,53,68,48,7,117,110,105,48,53,68,49,7,117,110,105,48,53,68,50,7,117, + 110,105,48,53,68,51,7,117,110,105,48,53,68,52,7,117,110,105,48,53,68,53,7,117,110,105,48,53,68,54,7,117,110,105,48,53,68,55,7,117, + 110,105,48,53,68,56,7,117,110,105,48,53,68,57,7,117,110,105,48,53,68,65,7,117,110,105,48,53,68,66,7,117,110,105,48,53,68,67,7,117, + 110,105,48,53,68,68,7,117,110,105,48,53,68,69,7,117,110,105,48,53,68,70,7,117,110,105,48,53,69,48,7,117,110,105,48,53,69,49,7,117, + 110,105,48,53,69,50,7,117,110,105,48,53,69,51,7,117,110,105,48,53,69,52,7,117,110,105,48,53,69,53,7,117,110,105,48,53,69,54,7,117, + 110,105,48,53,69,55,7,117,110,105,48,53,69,56,7,117,110,105,48,53,69,57,7,117,110,105,48,53,69,65,7,117,110,105,48,53,70,48,7,117, + 110,105,48,53,70,49,7,117,110,105,48,53,70,50,7,117,110,105,48,53,70,51,7,117,110,105,48,53,70,52,7,117,110,105,48,54,48,54,7,117, + 110,105,48,54,48,55,7,117,110,105,48,54,48,57,7,117,110,105,48,54,48,65,7,117,110,105,48,54,48,67,7,117,110,105,48,54,49,53,7,117, + 110,105,48,54,49,66,7,117,110,105,48,54,49,70,7,117,110,105,48,54,50,49,7,117,110,105,48,54,50,50,7,117,110,105,48,54,50,51,7,117, + 110,105,48,54,50,52,7,117,110,105,48,54,50,53,7,117,110,105,48,54,50,54,7,117,110,105,48,54,50,55,7,117,110,105,48,54,50,56,7,117, + 110,105,48,54,50,57,7,117,110,105,48,54,50,65,7,117,110,105,48,54,50,66,7,117,110,105,48,54,50,67,7,117,110,105,48,54,50,68,7,117, + 110,105,48,54,50,69,7,117,110,105,48,54,50,70,7,117,110,105,48,54,51,48,7,117,110,105,48,54,51,49,7,117,110,105,48,54,51,50,7,117, + 110,105,48,54,51,51,7,117,110,105,48,54,51,52,7,117,110,105,48,54,51,53,7,117,110,105,48,54,51,54,7,117,110,105,48,54,51,55,7,117, + 110,105,48,54,51,56,7,117,110,105,48,54,51,57,7,117,110,105,48,54,51,65,7,117,110,105,48,54,52,48,7,117,110,105,48,54,52,49,7,117, + 110,105,48,54,52,50,7,117,110,105,48,54,52,51,7,117,110,105,48,54,52,52,7,117,110,105,48,54,52,53,7,117,110,105,48,54,52,54,7,117, + 110,105,48,54,52,55,7,117,110,105,48,54,52,56,7,117,110,105,48,54,52,57,7,117,110,105,48,54,52,65,7,117,110,105,48,54,52,66,7,117, + 110,105,48,54,52,67,7,117,110,105,48,54,52,68,7,117,110,105,48,54,52,69,7,117,110,105,48,54,52,70,7,117,110,105,48,54,53,48,7,117, + 110,105,48,54,53,49,7,117,110,105,48,54,53,50,7,117,110,105,48,54,53,51,7,117,110,105,48,54,53,52,7,117,110,105,48,54,53,53,7,117, + 110,105,48,54,53,55,7,117,110,105,48,54,53,65,7,117,110,105,48,54,54,48,7,117,110,105,48,54,54,49,7,117,110,105,48,54,54,50,7,117, + 110,105,48,54,54,51,7,117,110,105,48,54,54,52,7,117,110,105,48,54,54,53,7,117,110,105,48,54,54,54,7,117,110,105,48,54,54,55,7,117, + 110,105,48,54,54,56,7,117,110,105,48,54,54,57,7,117,110,105,48,54,54,65,7,117,110,105,48,54,54,66,7,117,110,105,48,54,54,67,7,117, + 110,105,48,54,54,68,7,117,110,105,48,54,54,69,7,117,110,105,48,54,54,70,7,117,110,105,48,54,55,48,7,117,110,105,48,54,55,52,7,117, + 110,105,48,54,55,57,7,117,110,105,48,54,55,65,7,117,110,105,48,54,55,66,7,117,110,105,48,54,55,67,7,117,110,105,48,54,55,68,7,117, + 110,105,48,54,55,69,7,117,110,105,48,54,55,70,7,117,110,105,48,54,56,48,7,117,110,105,48,54,56,49,7,117,110,105,48,54,56,50,7,117, + 110,105,48,54,56,51,7,117,110,105,48,54,56,52,7,117,110,105,48,54,56,53,7,117,110,105,48,54,56,54,7,117,110,105,48,54,56,55,7,117, + 110,105,48,54,56,56,7,117,110,105,48,54,56,57,7,117,110,105,48,54,56,65,7,117,110,105,48,54,56,66,7,117,110,105,48,54,56,67,7,117, + 110,105,48,54,56,68,7,117,110,105,48,54,56,69,7,117,110,105,48,54,56,70,7,117,110,105,48,54,57,48,7,117,110,105,48,54,57,49,7,117, + 110,105,48,54,57,50,7,117,110,105,48,54,57,51,7,117,110,105,48,54,57,52,7,117,110,105,48,54,57,53,7,117,110,105,48,54,57,54,7,117, + 110,105,48,54,57,55,7,117,110,105,48,54,57,56,7,117,110,105,48,54,57,57,7,117,110,105,48,54,57,65,7,117,110,105,48,54,57,66,7,117, + 110,105,48,54,57,67,7,117,110,105,48,54,57,68,7,117,110,105,48,54,57,69,7,117,110,105,48,54,57,70,7,117,110,105,48,54,65,48,7,117, + 110,105,48,54,65,49,7,117,110,105,48,54,65,50,7,117,110,105,48,54,65,51,7,117,110,105,48,54,65,52,7,117,110,105,48,54,65,53,7,117, + 110,105,48,54,65,54,7,117,110,105,48,54,65,55,7,117,110,105,48,54,65,56,7,117,110,105,48,54,65,57,7,117,110,105,48,54,65,65,7,117, + 110,105,48,54,65,66,7,117,110,105,48,54,65,67,7,117,110,105,48,54,65,68,7,117,110,105,48,54,65,69,7,117,110,105,48,54,65,70,7,117, + 110,105,48,54,66,48,7,117,110,105,48,54,66,49,7,117,110,105,48,54,66,50,7,117,110,105,48,54,66,51,7,117,110,105,48,54,66,52,7,117, + 110,105,48,54,66,53,7,117,110,105,48,54,66,54,7,117,110,105,48,54,66,55,7,117,110,105,48,54,66,56,7,117,110,105,48,54,66,57,7,117, + 110,105,48,54,66,65,7,117,110,105,48,54,66,66,7,117,110,105,48,54,66,67,7,117,110,105,48,54,66,68,7,117,110,105,48,54,66,69,7,117, + 110,105,48,54,66,70,7,117,110,105,48,54,67,54,7,117,110,105,48,54,67,67,7,117,110,105,48,54,67,69,7,117,110,105,48,54,68,53,7,117, + 110,105,48,54,70,48,7,117,110,105,48,54,70,49,7,117,110,105,48,54,70,50,7,117,110,105,48,54,70,51,7,117,110,105,48,54,70,52,7,117, + 110,105,48,54,70,53,7,117,110,105,48,54,70,54,7,117,110,105,48,54,70,55,7,117,110,105,48,54,70,56,7,117,110,105,48,54,70,57,7,117, + 110,105,48,55,67,48,7,117,110,105,48,55,67,49,7,117,110,105,48,55,67,50,7,117,110,105,48,55,67,51,7,117,110,105,48,55,67,52,7,117, + 110,105,48,55,67,53,7,117,110,105,48,55,67,54,7,117,110,105,48,55,67,55,7,117,110,105,48,55,67,56,7,117,110,105,48,55,67,57,7,117, + 110,105,48,55,67,65,7,117,110,105,48,55,67,66,7,117,110,105,48,55,67,67,7,117,110,105,48,55,67,68,7,117,110,105,48,55,67,69,7,117, + 110,105,48,55,67,70,7,117,110,105,48,55,68,48,7,117,110,105,48,55,68,49,7,117,110,105,48,55,68,50,7,117,110,105,48,55,68,51,7,117, + 110,105,48,55,68,52,7,117,110,105,48,55,68,53,7,117,110,105,48,55,68,54,7,117,110,105,48,55,68,55,7,117,110,105,48,55,68,56,7,117, + 110,105,48,55,68,57,7,117,110,105,48,55,68,65,7,117,110,105,48,55,68,66,7,117,110,105,48,55,68,67,7,117,110,105,48,55,68,68,7,117, + 110,105,48,55,68,69,7,117,110,105,48,55,68,70,7,117,110,105,48,55,69,48,7,117,110,105,48,55,69,49,7,117,110,105,48,55,69,50,7,117, + 110,105,48,55,69,51,7,117,110,105,48,55,69,52,7,117,110,105,48,55,69,53,7,117,110,105,48,55,69,54,7,117,110,105,48,55,69,55,7,117, + 110,105,48,55,69,66,7,117,110,105,48,55,69,67,7,117,110,105,48,55,69,68,7,117,110,105,48,55,69,69,7,117,110,105,48,55,69,70,7,117, + 110,105,48,55,70,48,7,117,110,105,48,55,70,49,7,117,110,105,48,55,70,50,7,117,110,105,48,55,70,51,7,117,110,105,48,55,70,52,7,117, + 110,105,48,55,70,53,7,117,110,105,48,55,70,56,7,117,110,105,48,55,70,57,7,117,110,105,48,55,70,65,7,117,110,105,48,69,51,70,7,117, + 110,105,48,69,56,49,7,117,110,105,48,69,56,50,7,117,110,105,48,69,56,52,7,117,110,105,48,69,56,55,7,117,110,105,48,69,56,56,7,117, + 110,105,48,69,56,65,7,117,110,105,48,69,56,68,7,117,110,105,48,69,57,52,7,117,110,105,48,69,57,53,7,117,110,105,48,69,57,54,7,117, + 110,105,48,69,57,55,7,117,110,105,48,69,57,57,7,117,110,105,48,69,57,65,7,117,110,105,48,69,57,66,7,117,110,105,48,69,57,67,7,117, + 110,105,48,69,57,68,7,117,110,105,48,69,57,69,7,117,110,105,48,69,57,70,7,117,110,105,48,69,65,49,7,117,110,105,48,69,65,50,7,117, + 110,105,48,69,65,51,7,117,110,105,48,69,65,53,7,117,110,105,48,69,65,55,7,117,110,105,48,69,65,65,7,117,110,105,48,69,65,66,7,117, + 110,105,48,69,65,68,7,117,110,105,48,69,65,69,7,117,110,105,48,69,65,70,7,117,110,105,48,69,66,48,7,117,110,105,48,69,66,49,7,117, + 110,105,48,69,66,50,7,117,110,105,48,69,66,51,7,117,110,105,48,69,66,52,7,117,110,105,48,69,66,53,7,117,110,105,48,69,66,54,7,117, + 110,105,48,69,66,55,7,117,110,105,48,69,66,56,7,117,110,105,48,69,66,57,7,117,110,105,48,69,66,66,7,117,110,105,48,69,66,67,7,117, + 110,105,48,69,66,68,7,117,110,105,48,69,67,48,7,117,110,105,48,69,67,49,7,117,110,105,48,69,67,50,7,117,110,105,48,69,67,51,7,117, + 110,105,48,69,67,52,7,117,110,105,48,69,67,54,7,117,110,105,48,69,67,56,7,117,110,105,48,69,67,57,7,117,110,105,48,69,67,65,7,117, + 110,105,48,69,67,66,7,117,110,105,48,69,67,67,7,117,110,105,48,69,67,68,7,117,110,105,48,69,68,48,7,117,110,105,48,69,68,49,7,117, + 110,105,48,69,68,50,7,117,110,105,48,69,68,51,7,117,110,105,48,69,68,52,7,117,110,105,48,69,68,53,7,117,110,105,48,69,68,54,7,117, + 110,105,48,69,68,55,7,117,110,105,48,69,68,56,7,117,110,105,48,69,68,57,7,117,110,105,48,69,68,67,7,117,110,105,48,69,68,68,7,117, + 110,105,49,48,65,48,7,117,110,105,49,48,65,49,7,117,110,105,49,48,65,50,7,117,110,105,49,48,65,51,7,117,110,105,49,48,65,52,7,117, + 110,105,49,48,65,53,7,117,110,105,49,48,65,54,7,117,110,105,49,48,65,55,7,117,110,105,49,48,65,56,7,117,110,105,49,48,65,57,7,117, + 110,105,49,48,65,65,7,117,110,105,49,48,65,66,7,117,110,105,49,48,65,67,7,117,110,105,49,48,65,68,7,117,110,105,49,48,65,69,7,117, + 110,105,49,48,65,70,7,117,110,105,49,48,66,48,7,117,110,105,49,48,66,49,7,117,110,105,49,48,66,50,7,117,110,105,49,48,66,51,7,117, + 110,105,49,48,66,52,7,117,110,105,49,48,66,53,7,117,110,105,49,48,66,54,7,117,110,105,49,48,66,55,7,117,110,105,49,48,66,56,7,117, + 110,105,49,48,66,57,7,117,110,105,49,48,66,65,7,117,110,105,49,48,66,66,7,117,110,105,49,48,66,67,7,117,110,105,49,48,66,68,7,117, + 110,105,49,48,66,69,7,117,110,105,49,48,66,70,7,117,110,105,49,48,67,48,7,117,110,105,49,48,67,49,7,117,110,105,49,48,67,50,7,117, + 110,105,49,48,67,51,7,117,110,105,49,48,67,52,7,117,110,105,49,48,67,53,7,117,110,105,49,48,68,48,7,117,110,105,49,48,68,49,7,117, + 110,105,49,48,68,50,7,117,110,105,49,48,68,51,7,117,110,105,49,48,68,52,7,117,110,105,49,48,68,53,7,117,110,105,49,48,68,54,7,117, + 110,105,49,48,68,55,7,117,110,105,49,48,68,56,7,117,110,105,49,48,68,57,7,117,110,105,49,48,68,65,7,117,110,105,49,48,68,66,7,117, + 110,105,49,48,68,67,7,117,110,105,49,48,68,68,7,117,110,105,49,48,68,69,7,117,110,105,49,48,68,70,7,117,110,105,49,48,69,48,7,117, + 110,105,49,48,69,49,7,117,110,105,49,48,69,50,7,117,110,105,49,48,69,51,7,117,110,105,49,48,69,52,7,117,110,105,49,48,69,53,7,117, + 110,105,49,48,69,54,7,117,110,105,49,48,69,55,7,117,110,105,49,48,69,56,7,117,110,105,49,48,69,57,7,117,110,105,49,48,69,65,7,117, + 110,105,49,48,69,66,7,117,110,105,49,48,69,67,7,117,110,105,49,48,69,68,7,117,110,105,49,48,69,69,7,117,110,105,49,48,69,70,7,117, + 110,105,49,48,70,48,7,117,110,105,49,48,70,49,7,117,110,105,49,48,70,50,7,117,110,105,49,48,70,51,7,117,110,105,49,48,70,52,7,117, + 110,105,49,48,70,53,7,117,110,105,49,48,70,54,7,117,110,105,49,48,70,55,7,117,110,105,49,48,70,56,7,117,110,105,49,48,70,57,7,117, + 110,105,49,48,70,65,7,117,110,105,49,48,70,66,7,117,110,105,49,48,70,67,7,117,110,105,49,52,48,49,7,117,110,105,49,52,48,50,7,117, + 110,105,49,52,48,51,7,117,110,105,49,52,48,52,7,117,110,105,49,52,48,53,7,117,110,105,49,52,48,54,7,117,110,105,49,52,48,55,7,117, + 110,105,49,52,48,57,7,117,110,105,49,52,48,65,7,117,110,105,49,52,48,66,7,117,110,105,49,52,48,67,7,117,110,105,49,52,48,68,7,117, + 110,105,49,52,48,69,7,117,110,105,49,52,48,70,7,117,110,105,49,52,49,48,7,117,110,105,49,52,49,49,7,117,110,105,49,52,49,50,7,117, + 110,105,49,52,49,51,7,117,110,105,49,52,49,52,7,117,110,105,49,52,49,53,7,117,110,105,49,52,49,54,7,117,110,105,49,52,49,55,7,117, + 110,105,49,52,49,56,7,117,110,105,49,52,49,57,7,117,110,105,49,52,49,65,7,117,110,105,49,52,49,66,7,117,110,105,49,52,49,68,7,117, + 110,105,49,52,49,69,7,117,110,105,49,52,49,70,7,117,110,105,49,52,50,48,7,117,110,105,49,52,50,49,7,117,110,105,49,52,50,50,7,117, + 110,105,49,52,50,51,7,117,110,105,49,52,50,52,7,117,110,105,49,52,50,53,7,117,110,105,49,52,50,54,7,117,110,105,49,52,50,55,7,117, + 110,105,49,52,50,56,7,117,110,105,49,52,50,57,7,117,110,105,49,52,50,65,7,117,110,105,49,52,50,66,7,117,110,105,49,52,50,67,7,117, + 110,105,49,52,50,68,7,117,110,105,49,52,50,69,7,117,110,105,49,52,50,70,7,117,110,105,49,52,51,48,7,117,110,105,49,52,51,49,7,117, + 110,105,49,52,51,50,7,117,110,105,49,52,51,51,7,117,110,105,49,52,51,52,7,117,110,105,49,52,51,53,7,117,110,105,49,52,51,55,7,117, + 110,105,49,52,51,56,7,117,110,105,49,52,51,57,7,117,110,105,49,52,51,65,7,117,110,105,49,52,51,66,7,117,110,105,49,52,51,67,7,117, + 110,105,49,52,51,68,7,117,110,105,49,52,51,69,7,117,110,105,49,52,51,70,7,117,110,105,49,52,52,48,7,117,110,105,49,52,52,49,7,117, + 110,105,49,52,52,50,7,117,110,105,49,52,52,51,7,117,110,105,49,52,52,52,7,117,110,105,49,52,52,53,7,117,110,105,49,52,52,54,7,117, + 110,105,49,52,52,55,7,117,110,105,49,52,52,56,7,117,110,105,49,52,52,57,7,117,110,105,49,52,52,65,7,117,110,105,49,52,52,67,7,117, + 110,105,49,52,52,68,7,117,110,105,49,52,52,69,7,117,110,105,49,52,52,70,7,117,110,105,49,52,53,48,7,117,110,105,49,52,53,49,7,117, + 110,105,49,52,53,50,7,117,110,105,49,52,53,52,7,117,110,105,49,52,53,53,7,117,110,105,49,52,53,54,7,117,110,105,49,52,53,55,7,117, + 110,105,49,52,53,56,7,117,110,105,49,52,53,57,7,117,110,105,49,52,53,65,7,117,110,105,49,52,53,66,7,117,110,105,49,52,53,67,7,117, + 110,105,49,52,53,68,7,117,110,105,49,52,53,69,7,117,110,105,49,52,53,70,7,117,110,105,49,52,54,48,7,117,110,105,49,52,54,49,7,117, + 110,105,49,52,54,50,7,117,110,105,49,52,54,51,7,117,110,105,49,52,54,52,7,117,110,105,49,52,54,53,7,117,110,105,49,52,54,54,7,117, + 110,105,49,52,54,55,7,117,110,105,49,52,54,56,7,117,110,105,49,52,54,57,7,117,110,105,49,52,54,65,7,117,110,105,49,52,54,66,7,117, + 110,105,49,52,54,67,7,117,110,105,49,52,54,68,7,117,110,105,49,52,54,69,7,117,110,105,49,52,54,70,7,117,110,105,49,52,55,48,7,117, + 110,105,49,52,55,49,7,117,110,105,49,52,55,50,7,117,110,105,49,52,55,51,7,117,110,105,49,52,55,52,7,117,110,105,49,52,55,53,7,117, + 110,105,49,52,55,54,7,117,110,105,49,52,55,55,7,117,110,105,49,52,55,56,7,117,110,105,49,52,55,57,7,117,110,105,49,52,55,65,7,117, + 110,105,49,52,55,66,7,117,110,105,49,52,55,67,7,117,110,105,49,52,55,68,7,117,110,105,49,52,55,69,7,117,110,105,49,52,55,70,7,117, + 110,105,49,52,56,48,7,117,110,105,49,52,56,49,7,117,110,105,49,52,56,50,7,117,110,105,49,52,56,51,7,117,110,105,49,52,56,52,7,117, + 110,105,49,52,56,53,7,117,110,105,49,52,56,54,7,117,110,105,49,52,56,55,7,117,110,105,49,52,56,56,7,117,110,105,49,52,56,57,7,117, + 110,105,49,52,56,65,7,117,110,105,49,52,56,66,7,117,110,105,49,52,56,67,7,117,110,105,49,52,56,68,7,117,110,105,49,52,56,69,7,117, + 110,105,49,52,56,70,7,117,110,105,49,52,57,48,7,117,110,105,49,52,57,49,7,117,110,105,49,52,57,50,7,117,110,105,49,52,57,51,7,117, + 110,105,49,52,57,52,7,117,110,105,49,52,57,53,7,117,110,105,49,52,57,54,7,117,110,105,49,52,57,55,7,117,110,105,49,52,57,56,7,117, + 110,105,49,52,57,57,7,117,110,105,49,52,57,65,7,117,110,105,49,52,57,66,7,117,110,105,49,52,57,67,7,117,110,105,49,52,57,68,7,117, + 110,105,49,52,57,69,7,117,110,105,49,52,57,70,7,117,110,105,49,52,65,48,7,117,110,105,49,52,65,49,7,117,110,105,49,52,65,50,7,117, + 110,105,49,52,65,51,7,117,110,105,49,52,65,52,7,117,110,105,49,52,65,53,7,117,110,105,49,52,65,54,7,117,110,105,49,52,65,55,7,117, + 110,105,49,52,65,56,7,117,110,105,49,52,65,57,7,117,110,105,49,52,65,65,7,117,110,105,49,52,65,66,7,117,110,105,49,52,65,67,7,117, + 110,105,49,52,65,68,7,117,110,105,49,52,65,69,7,117,110,105,49,52,65,70,7,117,110,105,49,52,66,48,7,117,110,105,49,52,66,49,7,117, + 110,105,49,52,66,50,7,117,110,105,49,52,66,51,7,117,110,105,49,52,66,52,7,117,110,105,49,52,66,53,7,117,110,105,49,52,66,54,7,117, + 110,105,49,52,66,55,7,117,110,105,49,52,66,56,7,117,110,105,49,52,66,57,7,117,110,105,49,52,66,65,7,117,110,105,49,52,66,66,7,117, + 110,105,49,52,66,67,7,117,110,105,49,52,66,68,7,117,110,105,49,52,67,48,7,117,110,105,49,52,67,49,7,117,110,105,49,52,67,50,7,117, + 110,105,49,52,67,51,7,117,110,105,49,52,67,52,7,117,110,105,49,52,67,53,7,117,110,105,49,52,67,54,7,117,110,105,49,52,67,55,7,117, + 110,105,49,52,67,56,7,117,110,105,49,52,67,57,7,117,110,105,49,52,67,65,7,117,110,105,49,52,67,66,7,117,110,105,49,52,67,67,7,117, + 110,105,49,52,67,68,7,117,110,105,49,52,67,69,7,117,110,105,49,52,67,70,7,117,110,105,49,52,68,48,7,117,110,105,49,52,68,49,7,117, + 110,105,49,52,68,50,7,117,110,105,49,52,68,51,7,117,110,105,49,52,68,52,7,117,110,105,49,52,68,53,7,117,110,105,49,52,68,54,7,117, + 110,105,49,52,68,55,7,117,110,105,49,52,68,56,7,117,110,105,49,52,68,57,7,117,110,105,49,52,68,65,7,117,110,105,49,52,68,66,7,117, + 110,105,49,52,68,67,7,117,110,105,49,52,68,68,7,117,110,105,49,52,68,69,7,117,110,105,49,52,68,70,7,117,110,105,49,52,69,48,7,117, + 110,105,49,52,69,49,7,117,110,105,49,52,69,50,7,117,110,105,49,52,69,51,7,117,110,105,49,52,69,52,7,117,110,105,49,52,69,53,7,117, + 110,105,49,52,69,54,7,117,110,105,49,52,69,55,7,117,110,105,49,52,69,56,7,117,110,105,49,52,69,57,7,117,110,105,49,52,69,65,7,117, + 110,105,49,52,69,67,7,117,110,105,49,52,69,68,7,117,110,105,49,52,69,69,7,117,110,105,49,52,69,70,7,117,110,105,49,52,70,48,7,117, + 110,105,49,52,70,49,7,117,110,105,49,52,70,50,7,117,110,105,49,52,70,51,7,117,110,105,49,52,70,52,7,117,110,105,49,52,70,53,7,117, + 110,105,49,52,70,54,7,117,110,105,49,52,70,55,7,117,110,105,49,52,70,56,7,117,110,105,49,52,70,57,7,117,110,105,49,52,70,65,7,117, + 110,105,49,52,70,66,7,117,110,105,49,52,70,67,7,117,110,105,49,52,70,68,7,117,110,105,49,52,70,69,7,117,110,105,49,52,70,70,7,117, + 110,105,49,53,48,48,7,117,110,105,49,53,48,49,7,117,110,105,49,53,48,50,7,117,110,105,49,53,48,51,7,117,110,105,49,53,48,52,7,117, + 110,105,49,53,48,53,7,117,110,105,49,53,48,54,7,117,110,105,49,53,48,55,7,117,110,105,49,53,49,48,7,117,110,105,49,53,49,49,7,117, + 110,105,49,53,49,50,7,117,110,105,49,53,49,51,7,117,110,105,49,53,49,52,7,117,110,105,49,53,49,53,7,117,110,105,49,53,49,54,7,117, + 110,105,49,53,49,55,7,117,110,105,49,53,49,56,7,117,110,105,49,53,49,57,7,117,110,105,49,53,49,65,7,117,110,105,49,53,49,66,7,117, + 110,105,49,53,49,67,7,117,110,105,49,53,49,68,7,117,110,105,49,53,49,69,7,117,110,105,49,53,49,70,7,117,110,105,49,53,50,48,7,117, + 110,105,49,53,50,49,7,117,110,105,49,53,50,50,7,117,110,105,49,53,50,51,7,117,110,105,49,53,50,52,7,117,110,105,49,53,50,53,7,117, + 110,105,49,53,50,54,7,117,110,105,49,53,50,55,7,117,110,105,49,53,50,56,7,117,110,105,49,53,50,57,7,117,110,105,49,53,50,65,7,117, + 110,105,49,53,50,66,7,117,110,105,49,53,50,67,7,117,110,105,49,53,50,68,7,117,110,105,49,53,50,69,7,117,110,105,49,53,50,70,7,117, + 110,105,49,53,51,48,7,117,110,105,49,53,51,49,7,117,110,105,49,53,51,50,7,117,110,105,49,53,51,51,7,117,110,105,49,53,51,52,7,117, + 110,105,49,53,51,53,7,117,110,105,49,53,51,54,7,117,110,105,49,53,51,55,7,117,110,105,49,53,51,56,7,117,110,105,49,53,51,57,7,117, + 110,105,49,53,51,65,7,117,110,105,49,53,51,66,7,117,110,105,49,53,51,67,7,117,110,105,49,53,51,68,7,117,110,105,49,53,51,69,7,117, + 110,105,49,53,52,48,7,117,110,105,49,53,52,49,7,117,110,105,49,53,52,50,7,117,110,105,49,53,52,51,7,117,110,105,49,53,52,52,7,117, + 110,105,49,53,52,53,7,117,110,105,49,53,52,54,7,117,110,105,49,53,52,55,7,117,110,105,49,53,52,56,7,117,110,105,49,53,52,57,7,117, + 110,105,49,53,52,65,7,117,110,105,49,53,52,66,7,117,110,105,49,53,52,67,7,117,110,105,49,53,52,68,7,117,110,105,49,53,52,69,7,117, + 110,105,49,53,52,70,7,117,110,105,49,53,53,48,7,117,110,105,49,53,53,50,7,117,110,105,49,53,53,51,7,117,110,105,49,53,53,52,7,117, + 110,105,49,53,53,53,7,117,110,105,49,53,53,54,7,117,110,105,49,53,53,55,7,117,110,105,49,53,53,56,7,117,110,105,49,53,53,57,7,117, + 110,105,49,53,53,65,7,117,110,105,49,53,53,66,7,117,110,105,49,53,53,67,7,117,110,105,49,53,53,68,7,117,110,105,49,53,53,69,7,117, + 110,105,49,53,53,70,7,117,110,105,49,53,54,48,7,117,110,105,49,53,54,49,7,117,110,105,49,53,54,50,7,117,110,105,49,53,54,51,7,117, + 110,105,49,53,54,52,7,117,110,105,49,53,54,53,7,117,110,105,49,53,54,54,7,117,110,105,49,53,54,55,7,117,110,105,49,53,54,56,7,117, + 110,105,49,53,54,57,7,117,110,105,49,53,54,65,7,117,110,105,49,53,55,52,7,117,110,105,49,53,55,53,7,117,110,105,49,53,55,54,7,117, + 110,105,49,53,55,55,7,117,110,105,49,53,55,56,7,117,110,105,49,53,55,57,7,117,110,105,49,53,55,65,7,117,110,105,49,53,55,66,7,117, + 110,105,49,53,55,67,7,117,110,105,49,53,55,68,7,117,110,105,49,53,55,69,7,117,110,105,49,53,55,70,7,117,110,105,49,53,56,48,7,117, + 110,105,49,53,56,49,7,117,110,105,49,53,56,50,7,117,110,105,49,53,56,51,7,117,110,105,49,53,56,52,7,117,110,105,49,53,56,53,7,117, + 110,105,49,53,56,65,7,117,110,105,49,53,56,66,7,117,110,105,49,53,56,67,7,117,110,105,49,53,56,68,7,117,110,105,49,53,56,69,7,117, + 110,105,49,53,56,70,7,117,110,105,49,53,57,48,7,117,110,105,49,53,57,49,7,117,110,105,49,53,57,50,7,117,110,105,49,53,57,51,7,117, + 110,105,49,53,57,52,7,117,110,105,49,53,57,53,7,117,110,105,49,53,57,54,7,117,110,105,49,53,65,48,7,117,110,105,49,53,65,49,7,117, + 110,105,49,53,65,50,7,117,110,105,49,53,65,51,7,117,110,105,49,53,65,52,7,117,110,105,49,53,65,53,7,117,110,105,49,53,65,54,7,117, + 110,105,49,53,65,55,7,117,110,105,49,53,65,56,7,117,110,105,49,53,65,57,7,117,110,105,49,53,65,65,7,117,110,105,49,53,65,66,7,117, + 110,105,49,53,65,67,7,117,110,105,49,53,65,68,7,117,110,105,49,53,65,69,7,117,110,105,49,53,65,70,7,117,110,105,49,53,68,69,7,117, + 110,105,49,53,69,49,7,117,110,105,49,54,52,54,7,117,110,105,49,54,52,55,7,117,110,105,49,54,54,69,7,117,110,105,49,54,54,70,7,117, + 110,105,49,54,55,48,7,117,110,105,49,54,55,49,7,117,110,105,49,54,55,50,7,117,110,105,49,54,55,51,7,117,110,105,49,54,55,52,7,117, + 110,105,49,54,55,53,7,117,110,105,49,54,55,54,7,117,110,105,49,54,56,48,7,117,110,105,49,54,56,49,7,117,110,105,49,54,56,50,7,117, + 110,105,49,54,56,51,7,117,110,105,49,54,56,52,7,117,110,105,49,54,56,53,7,117,110,105,49,54,56,54,7,117,110,105,49,54,56,55,7,117, + 110,105,49,54,56,56,7,117,110,105,49,54,56,57,7,117,110,105,49,54,56,65,7,117,110,105,49,54,56,66,7,117,110,105,49,54,56,67,7,117, + 110,105,49,54,56,68,7,117,110,105,49,54,56,69,7,117,110,105,49,54,56,70,7,117,110,105,49,54,57,48,7,117,110,105,49,54,57,49,7,117, + 110,105,49,54,57,50,7,117,110,105,49,54,57,51,7,117,110,105,49,54,57,52,7,117,110,105,49,54,57,53,7,117,110,105,49,54,57,54,7,117, + 110,105,49,54,57,55,7,117,110,105,49,54,57,56,7,117,110,105,49,54,57,57,7,117,110,105,49,54,57,65,7,117,110,105,49,54,57,66,7,117, + 110,105,49,54,57,67,7,117,110,105,49,68,48,48,7,117,110,105,49,68,48,49,7,117,110,105,49,68,48,50,7,117,110,105,49,68,48,51,7,117, + 110,105,49,68,48,52,7,117,110,105,49,68,48,53,7,117,110,105,49,68,48,54,7,117,110,105,49,68,48,55,7,117,110,105,49,68,48,56,7,117, + 110,105,49,68,48,57,7,117,110,105,49,68,48,65,7,117,110,105,49,68,48,66,7,117,110,105,49,68,48,67,7,117,110,105,49,68,48,68,7,117, + 110,105,49,68,48,69,7,117,110,105,49,68,48,70,7,117,110,105,49,68,49,48,7,117,110,105,49,68,49,49,7,117,110,105,49,68,49,50,7,117, + 110,105,49,68,49,51,7,117,110,105,49,68,49,52,7,117,110,105,49,68,49,54,7,117,110,105,49,68,49,55,7,117,110,105,49,68,49,56,7,117, + 110,105,49,68,49,57,7,117,110,105,49,68,49,65,7,117,110,105,49,68,49,66,7,117,110,105,49,68,49,67,7,117,110,105,49,68,49,68,7,117, + 110,105,49,68,49,69,7,117,110,105,49,68,49,70,7,117,110,105,49,68,50,48,7,117,110,105,49,68,50,49,7,117,110,105,49,68,50,50,7,117, + 110,105,49,68,50,51,7,117,110,105,49,68,50,54,7,117,110,105,49,68,50,55,7,117,110,105,49,68,50,56,7,117,110,105,49,68,50,57,7,117, + 110,105,49,68,50,65,7,117,110,105,49,68,50,66,7,117,110,105,49,68,50,67,7,117,110,105,49,68,50,68,7,117,110,105,49,68,50,69,7,117, + 110,105,49,68,51,48,7,117,110,105,49,68,51,49,7,117,110,105,49,68,51,50,7,117,110,105,49,68,51,51,7,117,110,105,49,68,51,52,7,117, + 110,105,49,68,51,53,7,117,110,105,49,68,51,54,7,117,110,105,49,68,51,55,7,117,110,105,49,68,51,56,7,117,110,105,49,68,51,57,7,117, + 110,105,49,68,51,65,7,117,110,105,49,68,51,66,7,117,110,105,49,68,51,67,7,117,110,105,49,68,51,68,7,117,110,105,49,68,51,69,7,117, + 110,105,49,68,51,70,7,117,110,105,49,68,52,48,7,117,110,105,49,68,52,49,7,117,110,105,49,68,52,50,7,117,110,105,49,68,52,51,7,117, + 110,105,49,68,52,52,7,117,110,105,49,68,52,53,7,117,110,105,49,68,52,54,7,117,110,105,49,68,52,55,7,117,110,105,49,68,52,56,7,117, + 110,105,49,68,52,57,7,117,110,105,49,68,52,65,7,117,110,105,49,68,52,66,7,117,110,105,49,68,52,67,7,117,110,105,49,68,52,68,7,117, + 110,105,49,68,52,69,7,117,110,105,49,68,52,70,7,117,110,105,49,68,53,48,7,117,110,105,49,68,53,49,7,117,110,105,49,68,53,50,7,117, + 110,105,49,68,53,51,7,117,110,105,49,68,53,52,7,117,110,105,49,68,53,53,7,117,110,105,49,68,53,54,7,117,110,105,49,68,53,55,7,117, + 110,105,49,68,53,56,7,117,110,105,49,68,53,57,7,117,110,105,49,68,53,65,7,117,110,105,49,68,53,66,7,117,110,105,49,68,53,68,7,117, + 110,105,49,68,53,69,7,117,110,105,49,68,53,70,7,117,110,105,49,68,54,48,7,117,110,105,49,68,54,49,7,117,110,105,49,68,54,50,7,117, + 110,105,49,68,54,51,7,117,110,105,49,68,54,52,7,117,110,105,49,68,54,53,7,117,110,105,49,68,54,54,7,117,110,105,49,68,54,55,7,117, + 110,105,49,68,54,56,7,117,110,105,49,68,54,57,7,117,110,105,49,68,54,65,7,117,110,105,49,68,55,55,7,117,110,105,49,68,55,56,7,117, + 110,105,49,68,55,66,7,117,110,105,49,68,55,68,7,117,110,105,49,68,56,53,7,117,110,105,49,68,57,66,7,117,110,105,49,68,57,67,7,117, + 110,105,49,68,57,68,7,117,110,105,49,68,57,69,7,117,110,105,49,68,57,70,7,117,110,105,49,68,65,48,7,117,110,105,49,68,65,49,7,117, + 110,105,49,68,65,50,7,117,110,105,49,68,65,51,7,117,110,105,49,68,65,52,7,117,110,105,49,68,65,53,7,117,110,105,49,68,65,54,7,117, + 110,105,49,68,65,55,7,117,110,105,49,68,65,56,7,117,110,105,49,68,65,57,7,117,110,105,49,68,65,65,7,117,110,105,49,68,65,66,7,117, + 110,105,49,68,65,67,7,117,110,105,49,68,65,68,7,117,110,105,49,68,65,69,7,117,110,105,49,68,65,70,7,117,110,105,49,68,66,48,7,117, + 110,105,49,68,66,49,7,117,110,105,49,68,66,50,7,117,110,105,49,68,66,51,7,117,110,105,49,68,66,52,7,117,110,105,49,68,66,53,7,117, + 110,105,49,68,66,54,7,117,110,105,49,68,66,55,7,117,110,105,49,68,66,56,7,117,110,105,49,68,66,57,7,117,110,105,49,68,66,65,7,117, + 110,105,49,68,66,66,7,117,110,105,49,68,66,67,7,117,110,105,49,68,66,68,7,117,110,105,49,68,66,69,7,117,110,105,49,68,66,70,7,117, + 110,105,49,68,67,52,7,117,110,105,49,68,67,53,7,117,110,105,49,68,67,54,7,117,110,105,49,68,67,55,7,117,110,105,49,68,67,56,7,117, + 110,105,49,68,67,57,7,117,110,105,49,69,48,48,7,117,110,105,49,69,48,49,7,117,110,105,49,69,48,50,7,117,110,105,49,69,48,51,7,117, + 110,105,49,69,48,52,7,117,110,105,49,69,48,53,7,117,110,105,49,69,48,54,7,117,110,105,49,69,48,55,7,117,110,105,49,69,48,56,7,117, + 110,105,49,69,48,57,7,117,110,105,49,69,48,65,7,117,110,105,49,69,48,66,7,117,110,105,49,69,48,67,7,117,110,105,49,69,48,68,7,117, + 110,105,49,69,48,69,7,117,110,105,49,69,48,70,7,117,110,105,49,69,49,48,7,117,110,105,49,69,49,49,7,117,110,105,49,69,49,50,7,117, + 110,105,49,69,49,51,7,117,110,105,49,69,49,52,7,117,110,105,49,69,49,53,7,117,110,105,49,69,49,54,7,117,110,105,49,69,49,55,7,117, + 110,105,49,69,49,56,7,117,110,105,49,69,49,57,7,117,110,105,49,69,49,65,7,117,110,105,49,69,49,66,7,117,110,105,49,69,49,67,7,117, + 110,105,49,69,49,68,7,117,110,105,49,69,49,69,7,117,110,105,49,69,49,70,7,117,110,105,49,69,50,48,7,117,110,105,49,69,50,49,7,117, + 110,105,49,69,50,50,7,117,110,105,49,69,50,51,7,117,110,105,49,69,50,52,7,117,110,105,49,69,50,53,7,117,110,105,49,69,50,54,7,117, + 110,105,49,69,50,55,7,117,110,105,49,69,50,56,7,117,110,105,49,69,50,57,7,117,110,105,49,69,50,65,7,117,110,105,49,69,50,66,7,117, + 110,105,49,69,50,67,7,117,110,105,49,69,50,68,7,117,110,105,49,69,50,69,7,117,110,105,49,69,50,70,7,117,110,105,49,69,51,48,7,117, + 110,105,49,69,51,49,7,117,110,105,49,69,51,50,7,117,110,105,49,69,51,51,7,117,110,105,49,69,51,52,7,117,110,105,49,69,51,53,7,117, + 110,105,49,69,51,54,7,117,110,105,49,69,51,55,7,117,110,105,49,69,51,56,7,117,110,105,49,69,51,57,7,117,110,105,49,69,51,65,7,117, + 110,105,49,69,51,66,7,117,110,105,49,69,51,67,7,117,110,105,49,69,51,68,7,117,110,105,49,69,51,69,7,117,110,105,49,69,51,70,7,117, + 110,105,49,69,52,48,7,117,110,105,49,69,52,49,7,117,110,105,49,69,52,50,7,117,110,105,49,69,52,51,7,117,110,105,49,69,52,52,7,117, + 110,105,49,69,52,53,7,117,110,105,49,69,52,54,7,117,110,105,49,69,52,55,7,117,110,105,49,69,52,56,7,117,110,105,49,69,52,57,7,117, + 110,105,49,69,52,65,7,117,110,105,49,69,52,66,7,117,110,105,49,69,52,67,7,117,110,105,49,69,52,68,7,117,110,105,49,69,52,69,7,117, + 110,105,49,69,52,70,7,117,110,105,49,69,53,48,7,117,110,105,49,69,53,49,7,117,110,105,49,69,53,50,7,117,110,105,49,69,53,51,7,117, + 110,105,49,69,53,52,7,117,110,105,49,69,53,53,7,117,110,105,49,69,53,54,7,117,110,105,49,69,53,55,7,117,110,105,49,69,53,56,7,117, + 110,105,49,69,53,57,7,117,110,105,49,69,53,65,7,117,110,105,49,69,53,66,7,117,110,105,49,69,53,67,7,117,110,105,49,69,53,68,7,117, + 110,105,49,69,53,69,7,117,110,105,49,69,53,70,7,117,110,105,49,69,54,48,7,117,110,105,49,69,54,49,7,117,110,105,49,69,54,50,7,117, + 110,105,49,69,54,51,7,117,110,105,49,69,54,52,7,117,110,105,49,69,54,53,7,117,110,105,49,69,54,54,7,117,110,105,49,69,54,55,7,117, + 110,105,49,69,54,56,7,117,110,105,49,69,54,57,7,117,110,105,49,69,54,65,7,117,110,105,49,69,54,66,7,117,110,105,49,69,54,67,7,117, + 110,105,49,69,54,68,7,117,110,105,49,69,54,69,7,117,110,105,49,69,54,70,7,117,110,105,49,69,55,48,7,117,110,105,49,69,55,49,7,117, + 110,105,49,69,55,50,7,117,110,105,49,69,55,51,7,117,110,105,49,69,55,52,7,117,110,105,49,69,55,53,7,117,110,105,49,69,55,54,7,117, + 110,105,49,69,55,55,7,117,110,105,49,69,55,56,7,117,110,105,49,69,55,57,7,117,110,105,49,69,55,65,7,117,110,105,49,69,55,66,7,117, + 110,105,49,69,55,67,7,117,110,105,49,69,55,68,7,117,110,105,49,69,55,69,7,117,110,105,49,69,55,70,6,87,103,114,97,118,101,6,119,103, + 114,97,118,101,6,87,97,99,117,116,101,6,119,97,99,117,116,101,9,87,100,105,101,114,101,115,105,115,9,119,100,105,101,114,101,115,105,115,7,117, + 110,105,49,69,56,54,7,117,110,105,49,69,56,55,7,117,110,105,49,69,56,56,7,117,110,105,49,69,56,57,7,117,110,105,49,69,56,65,7,117, + 110,105,49,69,56,66,7,117,110,105,49,69,56,67,7,117,110,105,49,69,56,68,7,117,110,105,49,69,56,69,7,117,110,105,49,69,56,70,7,117, + 110,105,49,69,57,48,7,117,110,105,49,69,57,49,7,117,110,105,49,69,57,50,7,117,110,105,49,69,57,51,7,117,110,105,49,69,57,52,7,117, + 110,105,49,69,57,53,7,117,110,105,49,69,57,54,7,117,110,105,49,69,57,55,7,117,110,105,49,69,57,56,7,117,110,105,49,69,57,57,7,117, + 110,105,49,69,57,65,7,117,110,105,49,69,57,66,7,117,110,105,49,69,57,67,7,117,110,105,49,69,57,68,7,117,110,105,49,69,57,69,7,117, + 110,105,49,69,57,70,7,117,110,105,49,69,65,48,7,117,110,105,49,69,65,49,7,117,110,105,49,69,65,50,7,117,110,105,49,69,65,51,7,117, + 110,105,49,69,65,52,7,117,110,105,49,69,65,53,7,117,110,105,49,69,65,54,7,117,110,105,49,69,65,55,7,117,110,105,49,69,65,56,7,117, + 110,105,49,69,65,57,7,117,110,105,49,69,65,65,7,117,110,105,49,69,65,66,7,117,110,105,49,69,65,67,7,117,110,105,49,69,65,68,7,117, + 110,105,49,69,65,69,7,117,110,105,49,69,65,70,7,117,110,105,49,69,66,48,7,117,110,105,49,69,66,49,7,117,110,105,49,69,66,50,7,117, + 110,105,49,69,66,51,7,117,110,105,49,69,66,52,7,117,110,105,49,69,66,53,7,117,110,105,49,69,66,54,7,117,110,105,49,69,66,55,7,117, + 110,105,49,69,66,56,7,117,110,105,49,69,66,57,7,117,110,105,49,69,66,65,7,117,110,105,49,69,66,66,7,117,110,105,49,69,66,67,7,117, + 110,105,49,69,66,68,7,117,110,105,49,69,66,69,7,117,110,105,49,69,66,70,7,117,110,105,49,69,67,48,7,117,110,105,49,69,67,49,7,117, + 110,105,49,69,67,50,7,117,110,105,49,69,67,51,7,117,110,105,49,69,67,52,7,117,110,105,49,69,67,53,7,117,110,105,49,69,67,54,7,117, + 110,105,49,69,67,55,7,117,110,105,49,69,67,56,7,117,110,105,49,69,67,57,7,117,110,105,49,69,67,65,7,117,110,105,49,69,67,66,7,117, + 110,105,49,69,67,67,7,117,110,105,49,69,67,68,7,117,110,105,49,69,67,69,7,117,110,105,49,69,67,70,7,117,110,105,49,69,68,48,7,117, + 110,105,49,69,68,49,7,117,110,105,49,69,68,50,7,117,110,105,49,69,68,51,7,117,110,105,49,69,68,52,7,117,110,105,49,69,68,53,7,117, + 110,105,49,69,68,54,7,117,110,105,49,69,68,55,7,117,110,105,49,69,68,56,7,117,110,105,49,69,68,57,7,117,110,105,49,69,68,65,7,117, + 110,105,49,69,68,66,7,117,110,105,49,69,68,67,7,117,110,105,49,69,68,68,7,117,110,105,49,69,68,69,7,117,110,105,49,69,68,70,7,117, + 110,105,49,69,69,48,7,117,110,105,49,69,69,49,7,117,110,105,49,69,69,50,7,117,110,105,49,69,69,51,7,117,110,105,49,69,69,52,7,117, + 110,105,49,69,69,53,7,117,110,105,49,69,69,54,7,117,110,105,49,69,69,55,7,117,110,105,49,69,69,56,7,117,110,105,49,69,69,57,7,117, + 110,105,49,69,69,65,7,117,110,105,49,69,69,66,7,117,110,105,49,69,69,67,7,117,110,105,49,69,69,68,7,117,110,105,49,69,69,69,7,117, + 110,105,49,69,69,70,7,117,110,105,49,69,70,48,7,117,110,105,49,69,70,49,6,89,103,114,97,118,101,6,121,103,114,97,118,101,7,117,110,105, + 49,69,70,52,7,117,110,105,49,69,70,53,7,117,110,105,49,69,70,54,7,117,110,105,49,69,70,55,7,117,110,105,49,69,70,56,7,117,110,105, + 49,69,70,57,7,117,110,105,49,69,70,65,7,117,110,105,49,69,70,66,7,117,110,105,49,70,48,48,7,117,110,105,49,70,48,49,7,117,110,105, + 49,70,48,50,7,117,110,105,49,70,48,51,7,117,110,105,49,70,48,52,7,117,110,105,49,70,48,53,7,117,110,105,49,70,48,54,7,117,110,105, + 49,70,48,55,7,117,110,105,49,70,48,56,7,117,110,105,49,70,48,57,7,117,110,105,49,70,48,65,7,117,110,105,49,70,48,66,7,117,110,105, + 49,70,48,67,7,117,110,105,49,70,48,68,7,117,110,105,49,70,48,69,7,117,110,105,49,70,48,70,7,117,110,105,49,70,49,48,7,117,110,105, + 49,70,49,49,7,117,110,105,49,70,49,50,7,117,110,105,49,70,49,51,7,117,110,105,49,70,49,52,7,117,110,105,49,70,49,53,7,117,110,105, + 49,70,49,56,7,117,110,105,49,70,49,57,7,117,110,105,49,70,49,65,7,117,110,105,49,70,49,66,7,117,110,105,49,70,49,67,7,117,110,105, + 49,70,49,68,7,117,110,105,49,70,50,48,7,117,110,105,49,70,50,49,7,117,110,105,49,70,50,50,7,117,110,105,49,70,50,51,7,117,110,105, + 49,70,50,52,7,117,110,105,49,70,50,53,7,117,110,105,49,70,50,54,7,117,110,105,49,70,50,55,7,117,110,105,49,70,50,56,7,117,110,105, + 49,70,50,57,7,117,110,105,49,70,50,65,7,117,110,105,49,70,50,66,7,117,110,105,49,70,50,67,7,117,110,105,49,70,50,68,7,117,110,105, + 49,70,50,69,7,117,110,105,49,70,50,70,7,117,110,105,49,70,51,48,7,117,110,105,49,70,51,49,7,117,110,105,49,70,51,50,7,117,110,105, + 49,70,51,51,7,117,110,105,49,70,51,52,7,117,110,105,49,70,51,53,7,117,110,105,49,70,51,54,7,117,110,105,49,70,51,55,7,117,110,105, + 49,70,51,56,7,117,110,105,49,70,51,57,7,117,110,105,49,70,51,65,7,117,110,105,49,70,51,66,7,117,110,105,49,70,51,67,7,117,110,105, + 49,70,51,68,7,117,110,105,49,70,51,69,7,117,110,105,49,70,51,70,7,117,110,105,49,70,52,48,7,117,110,105,49,70,52,49,7,117,110,105, + 49,70,52,50,7,117,110,105,49,70,52,51,7,117,110,105,49,70,52,52,7,117,110,105,49,70,52,53,7,117,110,105,49,70,52,56,7,117,110,105, + 49,70,52,57,7,117,110,105,49,70,52,65,7,117,110,105,49,70,52,66,7,117,110,105,49,70,52,67,7,117,110,105,49,70,52,68,7,117,110,105, + 49,70,53,48,7,117,110,105,49,70,53,49,7,117,110,105,49,70,53,50,7,117,110,105,49,70,53,51,7,117,110,105,49,70,53,52,7,117,110,105, + 49,70,53,53,7,117,110,105,49,70,53,54,7,117,110,105,49,70,53,55,7,117,110,105,49,70,53,57,7,117,110,105,49,70,53,66,7,117,110,105, + 49,70,53,68,7,117,110,105,49,70,53,70,7,117,110,105,49,70,54,48,7,117,110,105,49,70,54,49,7,117,110,105,49,70,54,50,7,117,110,105, + 49,70,54,51,7,117,110,105,49,70,54,52,7,117,110,105,49,70,54,53,7,117,110,105,49,70,54,54,7,117,110,105,49,70,54,55,7,117,110,105, + 49,70,54,56,7,117,110,105,49,70,54,57,7,117,110,105,49,70,54,65,7,117,110,105,49,70,54,66,7,117,110,105,49,70,54,67,7,117,110,105, + 49,70,54,68,7,117,110,105,49,70,54,69,7,117,110,105,49,70,54,70,7,117,110,105,49,70,55,48,7,117,110,105,49,70,55,49,7,117,110,105, + 49,70,55,50,7,117,110,105,49,70,55,51,7,117,110,105,49,70,55,52,7,117,110,105,49,70,55,53,7,117,110,105,49,70,55,54,7,117,110,105, + 49,70,55,55,7,117,110,105,49,70,55,56,7,117,110,105,49,70,55,57,7,117,110,105,49,70,55,65,7,117,110,105,49,70,55,66,7,117,110,105, + 49,70,55,67,7,117,110,105,49,70,55,68,7,117,110,105,49,70,56,48,7,117,110,105,49,70,56,49,7,117,110,105,49,70,56,50,7,117,110,105, + 49,70,56,51,7,117,110,105,49,70,56,52,7,117,110,105,49,70,56,53,7,117,110,105,49,70,56,54,7,117,110,105,49,70,56,55,7,117,110,105, + 49,70,56,56,7,117,110,105,49,70,56,57,7,117,110,105,49,70,56,65,7,117,110,105,49,70,56,66,7,117,110,105,49,70,56,67,7,117,110,105, + 49,70,56,68,7,117,110,105,49,70,56,69,7,117,110,105,49,70,56,70,7,117,110,105,49,70,57,48,7,117,110,105,49,70,57,49,7,117,110,105, + 49,70,57,50,7,117,110,105,49,70,57,51,7,117,110,105,49,70,57,52,7,117,110,105,49,70,57,53,7,117,110,105,49,70,57,54,7,117,110,105, + 49,70,57,55,7,117,110,105,49,70,57,56,7,117,110,105,49,70,57,57,7,117,110,105,49,70,57,65,7,117,110,105,49,70,57,66,7,117,110,105, + 49,70,57,67,7,117,110,105,49,70,57,68,7,117,110,105,49,70,57,69,7,117,110,105,49,70,57,70,7,117,110,105,49,70,65,48,7,117,110,105, + 49,70,65,49,7,117,110,105,49,70,65,50,7,117,110,105,49,70,65,51,7,117,110,105,49,70,65,52,7,117,110,105,49,70,65,53,7,117,110,105, + 49,70,65,54,7,117,110,105,49,70,65,55,7,117,110,105,49,70,65,56,7,117,110,105,49,70,65,57,7,117,110,105,49,70,65,65,7,117,110,105, + 49,70,65,66,7,117,110,105,49,70,65,67,7,117,110,105,49,70,65,68,7,117,110,105,49,70,65,69,7,117,110,105,49,70,65,70,7,117,110,105, + 49,70,66,48,7,117,110,105,49,70,66,49,7,117,110,105,49,70,66,50,7,117,110,105,49,70,66,51,7,117,110,105,49,70,66,52,7,117,110,105, + 49,70,66,54,7,117,110,105,49,70,66,55,7,117,110,105,49,70,66,56,7,117,110,105,49,70,66,57,7,117,110,105,49,70,66,65,7,117,110,105, + 49,70,66,66,7,117,110,105,49,70,66,67,7,117,110,105,49,70,66,68,7,117,110,105,49,70,66,69,7,117,110,105,49,70,66,70,7,117,110,105, + 49,70,67,48,7,117,110,105,49,70,67,49,7,117,110,105,49,70,67,50,7,117,110,105,49,70,67,51,7,117,110,105,49,70,67,52,7,117,110,105, + 49,70,67,54,7,117,110,105,49,70,67,55,7,117,110,105,49,70,67,56,7,117,110,105,49,70,67,57,7,117,110,105,49,70,67,65,7,117,110,105, + 49,70,67,66,7,117,110,105,49,70,67,67,7,117,110,105,49,70,67,68,7,117,110,105,49,70,67,69,7,117,110,105,49,70,67,70,7,117,110,105, + 49,70,68,48,7,117,110,105,49,70,68,49,7,117,110,105,49,70,68,50,7,117,110,105,49,70,68,51,7,117,110,105,49,70,68,54,7,117,110,105, + 49,70,68,55,7,117,110,105,49,70,68,56,7,117,110,105,49,70,68,57,7,117,110,105,49,70,68,65,7,117,110,105,49,70,68,66,7,117,110,105, + 49,70,68,68,7,117,110,105,49,70,68,69,7,117,110,105,49,70,68,70,7,117,110,105,49,70,69,48,7,117,110,105,49,70,69,49,7,117,110,105, + 49,70,69,50,7,117,110,105,49,70,69,51,7,117,110,105,49,70,69,52,7,117,110,105,49,70,69,53,7,117,110,105,49,70,69,54,7,117,110,105, + 49,70,69,55,7,117,110,105,49,70,69,56,7,117,110,105,49,70,69,57,7,117,110,105,49,70,69,65,7,117,110,105,49,70,69,66,7,117,110,105, + 49,70,69,67,7,117,110,105,49,70,69,68,7,117,110,105,49,70,69,69,7,117,110,105,49,70,69,70,7,117,110,105,49,70,70,50,7,117,110,105, + 49,70,70,51,7,117,110,105,49,70,70,52,7,117,110,105,49,70,70,54,7,117,110,105,49,70,70,55,7,117,110,105,49,70,70,56,7,117,110,105, + 49,70,70,57,7,117,110,105,49,70,70,65,7,117,110,105,49,70,70,66,7,117,110,105,49,70,70,67,7,117,110,105,49,70,70,68,7,117,110,105, + 49,70,70,69,7,117,110,105,50,48,48,48,7,117,110,105,50,48,48,49,7,117,110,105,50,48,48,50,7,117,110,105,50,48,48,51,7,117,110,105, + 50,48,48,52,7,117,110,105,50,48,48,53,7,117,110,105,50,48,48,54,7,117,110,105,50,48,48,55,7,117,110,105,50,48,48,56,7,117,110,105, + 50,48,48,57,7,117,110,105,50,48,48,65,7,117,110,105,50,48,48,66,7,117,110,105,50,48,48,67,7,117,110,105,50,48,48,68,7,117,110,105, + 50,48,48,69,7,117,110,105,50,48,48,70,7,117,110,105,50,48,49,48,7,117,110,105,50,48,49,49,10,102,105,103,117,114,101,100,97,115,104,7, + 117,110,105,50,48,49,53,7,117,110,105,50,48,49,54,13,117,110,100,101,114,115,99,111,114,101,100,98,108,13,113,117,111,116,101,114,101,118,101,114, + 115,101,100,7,117,110,105,50,48,49,70,7,117,110,105,50,48,50,51,14,111,110,101,100,111,116,101,110,108,101,97,100,101,114,14,116,119,111,100,111, + 116,101,110,108,101,97,100,101,114,7,117,110,105,50,48,50,55,7,117,110,105,50,48,50,56,7,117,110,105,50,48,50,57,7,117,110,105,50,48,50, + 65,7,117,110,105,50,48,50,66,7,117,110,105,50,48,50,67,7,117,110,105,50,48,50,68,7,117,110,105,50,48,50,69,7,117,110,105,50,48,50, + 70,7,117,110,105,50,48,51,49,6,109,105,110,117,116,101,6,115,101,99,111,110,100,7,117,110,105,50,48,51,52,7,117,110,105,50,48,51,53,7, + 117,110,105,50,48,51,54,7,117,110,105,50,48,51,55,7,117,110,105,50,48,51,56,7,117,110,105,50,48,51,66,9,101,120,99,108,97,109,100,98, + 108,7,117,110,105,50,48,51,68,7,117,110,105,50,48,51,69,7,117,110,105,50,48,51,70,7,117,110,105,50,48,52,48,7,117,110,105,50,48,52, + 49,7,117,110,105,50,48,52,50,7,117,110,105,50,48,52,51,7,117,110,105,50,48,52,53,7,117,110,105,50,48,52,54,7,117,110,105,50,48,52, + 55,7,117,110,105,50,48,52,56,7,117,110,105,50,48,52,57,7,117,110,105,50,48,52,65,7,117,110,105,50,48,52,66,7,117,110,105,50,48,52, + 67,7,117,110,105,50,48,52,68,7,117,110,105,50,48,52,69,7,117,110,105,50,48,52,70,7,117,110,105,50,48,53,48,7,117,110,105,50,48,53, + 49,7,117,110,105,50,48,53,50,7,117,110,105,50,48,53,51,7,117,110,105,50,48,53,52,7,117,110,105,50,48,53,53,7,117,110,105,50,48,53, + 54,7,117,110,105,50,48,53,55,7,117,110,105,50,48,53,56,7,117,110,105,50,48,53,57,7,117,110,105,50,48,53,65,7,117,110,105,50,48,53, + 66,7,117,110,105,50,48,53,67,7,117,110,105,50,48,53,68,7,117,110,105,50,48,53,69,7,117,110,105,50,48,53,70,7,117,110,105,50,48,54, + 48,7,117,110,105,50,48,54,49,7,117,110,105,50,48,54,50,7,117,110,105,50,48,54,51,7,117,110,105,50,48,54,52,7,117,110,105,50,48,54, + 65,7,117,110,105,50,48,54,66,7,117,110,105,50,48,54,67,7,117,110,105,50,48,54,68,7,117,110,105,50,48,54,69,7,117,110,105,50,48,54, + 70,7,117,110,105,50,48,55,48,7,117,110,105,50,48,55,49,7,117,110,105,50,48,55,52,7,117,110,105,50,48,55,53,7,117,110,105,50,48,55, + 54,7,117,110,105,50,48,55,55,7,117,110,105,50,48,55,56,7,117,110,105,50,48,55,57,7,117,110,105,50,48,55,65,7,117,110,105,50,48,55, + 66,7,117,110,105,50,48,55,67,7,117,110,105,50,48,55,68,7,117,110,105,50,48,55,69,7,117,110,105,50,48,55,70,7,117,110,105,50,48,56, + 48,7,117,110,105,50,48,56,49,7,117,110,105,50,48,56,50,7,117,110,105,50,48,56,51,7,117,110,105,50,48,56,52,7,117,110,105,50,48,56, + 53,7,117,110,105,50,48,56,54,7,117,110,105,50,48,56,55,7,117,110,105,50,48,56,56,7,117,110,105,50,48,56,57,7,117,110,105,50,48,56, + 65,7,117,110,105,50,48,56,66,7,117,110,105,50,48,56,67,7,117,110,105,50,48,56,68,7,117,110,105,50,48,56,69,7,117,110,105,50,48,57, + 48,7,117,110,105,50,48,57,49,7,117,110,105,50,48,57,50,7,117,110,105,50,48,57,51,7,117,110,105,50,48,57,52,7,117,110,105,50,48,57, + 53,7,117,110,105,50,48,57,54,7,117,110,105,50,48,57,55,7,117,110,105,50,48,57,56,7,117,110,105,50,48,57,57,7,117,110,105,50,48,57, + 65,7,117,110,105,50,48,57,66,7,117,110,105,50,48,57,67,7,117,110,105,50,48,65,48,13,99,111,108,111,110,109,111,110,101,116,97,114,121,7, + 117,110,105,50,48,65,50,4,108,105,114,97,7,117,110,105,50,48,65,53,7,117,110,105,50,48,65,54,6,112,101,115,101,116,97,7,117,110,105,50, + 48,65,56,7,117,110,105,50,48,65,57,7,117,110,105,50,48,65,65,4,100,111,110,103,4,69,117,114,111,7,117,110,105,50,48,65,68,7,117,110, + 105,50,48,65,69,7,117,110,105,50,48,65,70,7,117,110,105,50,48,66,48,7,117,110,105,50,48,66,49,7,117,110,105,50,48,66,50,7,117,110, + 105,50,48,66,51,7,117,110,105,50,48,66,52,7,117,110,105,50,48,66,53,7,117,110,105,50,48,66,56,7,117,110,105,50,48,66,57,7,117,110, + 105,50,48,66,65,7,117,110,105,50,48,68,48,7,117,110,105,50,48,68,49,7,117,110,105,50,48,68,54,7,117,110,105,50,48,68,55,7,117,110, + 105,50,48,68,66,7,117,110,105,50,48,68,67,7,117,110,105,50,48,69,49,7,117,110,105,50,49,48,48,7,117,110,105,50,49,48,49,7,117,110, + 105,50,49,48,50,7,117,110,105,50,49,48,51,7,117,110,105,50,49,48,52,7,117,110,105,50,49,48,53,7,117,110,105,50,49,48,54,7,117,110, + 105,50,49,48,55,7,117,110,105,50,49,48,56,7,117,110,105,50,49,48,57,7,117,110,105,50,49,48,66,7,117,110,105,50,49,48,67,7,117,110, + 105,50,49,48,68,7,117,110,105,50,49,48,69,7,117,110,105,50,49,48,70,7,117,110,105,50,49,49,48,8,73,102,114,97,107,116,117,114,7,117, + 110,105,50,49,49,50,7,117,110,105,50,49,49,51,7,117,110,105,50,49,49,52,7,117,110,105,50,49,49,53,7,117,110,105,50,49,49,54,7,117, + 110,105,50,49,49,55,11,119,101,105,101,114,115,116,114,97,115,115,7,117,110,105,50,49,49,57,7,117,110,105,50,49,49,65,7,117,110,105,50,49, + 49,66,8,82,102,114,97,107,116,117,114,7,117,110,105,50,49,49,68,12,112,114,101,115,99,114,105,112,116,105,111,110,7,117,110,105,50,49,49,70, + 7,117,110,105,50,49,50,48,7,117,110,105,50,49,50,49,7,117,110,105,50,49,50,51,7,117,110,105,50,49,50,52,7,117,110,105,50,49,50,53, + 7,117,110,105,50,49,50,54,7,117,110,105,50,49,50,55,7,117,110,105,50,49,50,56,7,117,110,105,50,49,50,57,7,117,110,105,50,49,50,65, + 7,117,110,105,50,49,50,66,7,117,110,105,50,49,50,67,7,117,110,105,50,49,50,68,9,101,115,116,105,109,97,116,101,100,7,117,110,105,50,49, + 50,70,7,117,110,105,50,49,51,48,7,117,110,105,50,49,51,49,7,117,110,105,50,49,51,50,7,117,110,105,50,49,51,51,7,117,110,105,50,49, + 51,52,5,97,108,101,112,104,7,117,110,105,50,49,51,54,7,117,110,105,50,49,51,55,7,117,110,105,50,49,51,56,7,117,110,105,50,49,51,57, + 7,117,110,105,50,49,51,65,7,117,110,105,50,49,51,66,7,117,110,105,50,49,51,67,7,117,110,105,50,49,51,68,7,117,110,105,50,49,51,69, + 7,117,110,105,50,49,51,70,7,117,110,105,50,49,52,48,7,117,110,105,50,49,52,49,7,117,110,105,50,49,52,50,7,117,110,105,50,49,52,51, + 7,117,110,105,50,49,52,52,7,117,110,105,50,49,52,53,7,117,110,105,50,49,52,54,7,117,110,105,50,49,52,55,7,117,110,105,50,49,52,56, + 7,117,110,105,50,49,52,57,7,117,110,105,50,49,52,66,7,117,110,105,50,49,52,69,7,117,110,105,50,49,53,48,7,117,110,105,50,49,53,49, + 7,117,110,105,50,49,53,50,8,111,110,101,116,104,105,114,100,9,116,119,111,116,104,105,114,100,115,7,117,110,105,50,49,53,53,7,117,110,105,50, + 49,53,54,7,117,110,105,50,49,53,55,7,117,110,105,50,49,53,56,7,117,110,105,50,49,53,57,7,117,110,105,50,49,53,65,9,111,110,101,101, + 105,103,104,116,104,12,116,104,114,101,101,101,105,103,104,116,104,115,11,102,105,118,101,101,105,103,104,116,104,115,12,115,101,118,101,110,101,105,103,104, + 116,104,115,7,117,110,105,50,49,53,70,7,117,110,105,50,49,54,48,7,117,110,105,50,49,54,49,7,117,110,105,50,49,54,50,7,117,110,105,50, + 49,54,51,7,117,110,105,50,49,54,52,7,117,110,105,50,49,54,53,7,117,110,105,50,49,54,54,7,117,110,105,50,49,54,55,7,117,110,105,50, + 49,54,56,7,117,110,105,50,49,54,57,7,117,110,105,50,49,54,65,7,117,110,105,50,49,54,66,7,117,110,105,50,49,54,67,7,117,110,105,50, + 49,54,68,7,117,110,105,50,49,54,69,7,117,110,105,50,49,54,70,7,117,110,105,50,49,55,48,7,117,110,105,50,49,55,49,7,117,110,105,50, + 49,55,50,7,117,110,105,50,49,55,51,7,117,110,105,50,49,55,52,7,117,110,105,50,49,55,53,7,117,110,105,50,49,55,54,7,117,110,105,50, + 49,55,55,7,117,110,105,50,49,55,56,7,117,110,105,50,49,55,57,7,117,110,105,50,49,55,65,7,117,110,105,50,49,55,66,7,117,110,105,50, + 49,55,67,7,117,110,105,50,49,55,68,7,117,110,105,50,49,55,69,7,117,110,105,50,49,55,70,7,117,110,105,50,49,56,48,7,117,110,105,50, + 49,56,49,7,117,110,105,50,49,56,50,7,117,110,105,50,49,56,51,7,117,110,105,50,49,56,52,7,117,110,105,50,49,56,53,7,117,110,105,50, + 49,56,57,9,97,114,114,111,119,108,101,102,116,7,97,114,114,111,119,117,112,10,97,114,114,111,119,114,105,103,104,116,9,97,114,114,111,119,100,111, + 119,110,9,97,114,114,111,119,98,111,116,104,9,97,114,114,111,119,117,112,100,110,7,117,110,105,50,49,57,54,7,117,110,105,50,49,57,55,7,117, + 110,105,50,49,57,56,7,117,110,105,50,49,57,57,7,117,110,105,50,49,57,65,7,117,110,105,50,49,57,66,7,117,110,105,50,49,57,67,7,117, + 110,105,50,49,57,68,7,117,110,105,50,49,57,69,7,117,110,105,50,49,57,70,7,117,110,105,50,49,65,48,7,117,110,105,50,49,65,49,7,117, + 110,105,50,49,65,50,7,117,110,105,50,49,65,51,7,117,110,105,50,49,65,52,7,117,110,105,50,49,65,53,7,117,110,105,50,49,65,54,7,117, + 110,105,50,49,65,55,12,97,114,114,111,119,117,112,100,110,98,115,101,7,117,110,105,50,49,65,57,7,117,110,105,50,49,65,65,7,117,110,105,50, + 49,65,66,7,117,110,105,50,49,65,67,7,117,110,105,50,49,65,68,7,117,110,105,50,49,65,69,7,117,110,105,50,49,65,70,7,117,110,105,50, + 49,66,48,7,117,110,105,50,49,66,49,7,117,110,105,50,49,66,50,7,117,110,105,50,49,66,51,7,117,110,105,50,49,66,52,14,99,97,114,114, + 105,97,103,101,114,101,116,117,114,110,7,117,110,105,50,49,66,54,7,117,110,105,50,49,66,55,7,117,110,105,50,49,66,56,7,117,110,105,50,49, + 66,57,7,117,110,105,50,49,66,65,7,117,110,105,50,49,66,66,7,117,110,105,50,49,66,67,7,117,110,105,50,49,66,68,7,117,110,105,50,49, + 66,69,7,117,110,105,50,49,66,70,7,117,110,105,50,49,67,48,7,117,110,105,50,49,67,49,7,117,110,105,50,49,67,50,7,117,110,105,50,49, + 67,51,7,117,110,105,50,49,67,52,7,117,110,105,50,49,67,53,7,117,110,105,50,49,67,54,7,117,110,105,50,49,67,55,7,117,110,105,50,49, + 67,56,7,117,110,105,50,49,67,57,7,117,110,105,50,49,67,65,7,117,110,105,50,49,67,66,7,117,110,105,50,49,67,67,7,117,110,105,50,49, + 67,68,7,117,110,105,50,49,67,69,7,117,110,105,50,49,67,70,12,97,114,114,111,119,100,98,108,108,101,102,116,10,97,114,114,111,119,100,98,108, + 117,112,13,97,114,114,111,119,100,98,108,114,105,103,104,116,12,97,114,114,111,119,100,98,108,100,111,119,110,12,97,114,114,111,119,100,98,108,98,111, + 116,104,7,117,110,105,50,49,68,53,7,117,110,105,50,49,68,54,7,117,110,105,50,49,68,55,7,117,110,105,50,49,68,56,7,117,110,105,50,49, + 68,57,7,117,110,105,50,49,68,65,7,117,110,105,50,49,68,66,7,117,110,105,50,49,68,67,7,117,110,105,50,49,68,68,7,117,110,105,50,49, + 68,69,7,117,110,105,50,49,68,70,7,117,110,105,50,49,69,48,7,117,110,105,50,49,69,49,7,117,110,105,50,49,69,50,7,117,110,105,50,49, + 69,51,7,117,110,105,50,49,69,52,7,117,110,105,50,49,69,53,7,117,110,105,50,49,69,54,7,117,110,105,50,49,69,55,7,117,110,105,50,49, + 69,56,7,117,110,105,50,49,69,57,7,117,110,105,50,49,69,65,7,117,110,105,50,49,69,66,7,117,110,105,50,49,69,67,7,117,110,105,50,49, + 69,68,7,117,110,105,50,49,69,69,7,117,110,105,50,49,69,70,7,117,110,105,50,49,70,48,7,117,110,105,50,49,70,49,7,117,110,105,50,49, + 70,50,7,117,110,105,50,49,70,51,7,117,110,105,50,49,70,52,7,117,110,105,50,49,70,53,7,117,110,105,50,49,70,54,7,117,110,105,50,49, + 70,55,7,117,110,105,50,49,70,56,7,117,110,105,50,49,70,57,7,117,110,105,50,49,70,65,7,117,110,105,50,49,70,66,7,117,110,105,50,49, + 70,67,7,117,110,105,50,49,70,68,7,117,110,105,50,49,70,69,7,117,110,105,50,49,70,70,9,117,110,105,118,101,114,115,97,108,7,117,110,105, + 50,50,48,49,11,101,120,105,115,116,101,110,116,105,97,108,7,117,110,105,50,50,48,52,8,101,109,112,116,121,115,101,116,8,103,114,97,100,105,101, + 110,116,7,101,108,101,109,101,110,116,10,110,111,116,101,108,101,109,101,110,116,7,117,110,105,50,50,48,65,8,115,117,99,104,116,104,97,116,7,117, + 110,105,50,50,48,67,7,117,110,105,50,50,48,68,7,117,110,105,50,50,48,69,7,117,110,105,50,50,49,48,7,117,110,105,50,50,49,51,7,117, + 110,105,50,50,49,52,7,117,110,105,50,50,49,53,7,117,110,105,50,50,49,54,12,97,115,116,101,114,105,115,107,109,97,116,104,7,117,110,105,50, + 50,49,56,7,117,110,105,50,50,49,57,7,117,110,105,50,50,49,66,7,117,110,105,50,50,49,67,12,112,114,111,112,111,114,116,105,111,110,97,108, + 10,111,114,116,104,111,103,111,110,97,108,5,97,110,103,108,101,7,117,110,105,50,50,50,49,7,117,110,105,50,50,50,50,7,117,110,105,50,50,50, + 51,7,117,110,105,50,50,50,52,7,117,110,105,50,50,50,53,7,117,110,105,50,50,50,54,10,108,111,103,105,99,97,108,97,110,100,9,108,111,103, + 105,99,97,108,111,114,12,105,110,116,101,114,115,101,99,116,105,111,110,5,117,110,105,111,110,7,117,110,105,50,50,50,67,7,117,110,105,50,50,50, + 68,7,117,110,105,50,50,50,69,7,117,110,105,50,50,50,70,7,117,110,105,50,50,51,48,7,117,110,105,50,50,51,49,7,117,110,105,50,50,51, + 50,7,117,110,105,50,50,51,51,9,116,104,101,114,101,102,111,114,101,7,117,110,105,50,50,51,53,7,117,110,105,50,50,51,54,7,117,110,105,50, + 50,51,55,7,117,110,105,50,50,51,56,7,117,110,105,50,50,51,57,7,117,110,105,50,50,51,65,7,117,110,105,50,50,51,66,7,115,105,109,105, + 108,97,114,7,117,110,105,50,50,51,68,7,117,110,105,50,50,51,69,7,117,110,105,50,50,51,70,7,117,110,105,50,50,52,48,7,117,110,105,50, + 50,52,49,7,117,110,105,50,50,52,50,7,117,110,105,50,50,52,51,7,117,110,105,50,50,52,52,9,99,111,110,103,114,117,101,110,116,7,117,110, + 105,50,50,52,54,7,117,110,105,50,50,52,55,7,117,110,105,50,50,52,57,7,117,110,105,50,50,52,65,7,117,110,105,50,50,52,66,7,117,110, + 105,50,50,52,67,7,117,110,105,50,50,52,68,7,117,110,105,50,50,52,69,7,117,110,105,50,50,52,70,7,117,110,105,50,50,53,48,7,117,110, + 105,50,50,53,49,7,117,110,105,50,50,53,50,7,117,110,105,50,50,53,51,7,117,110,105,50,50,53,52,7,117,110,105,50,50,53,53,7,117,110, + 105,50,50,53,54,7,117,110,105,50,50,53,55,7,117,110,105,50,50,53,56,7,117,110,105,50,50,53,57,7,117,110,105,50,50,53,65,7,117,110, + 105,50,50,53,66,7,117,110,105,50,50,53,67,7,117,110,105,50,50,53,68,7,117,110,105,50,50,53,69,7,117,110,105,50,50,53,70,11,101,113, + 117,105,118,97,108,101,110,99,101,7,117,110,105,50,50,54,50,7,117,110,105,50,50,54,51,7,117,110,105,50,50,54,54,7,117,110,105,50,50,54, + 55,7,117,110,105,50,50,54,56,7,117,110,105,50,50,54,57,7,117,110,105,50,50,54,65,7,117,110,105,50,50,54,66,7,117,110,105,50,50,54, + 67,7,117,110,105,50,50,54,68,7,117,110,105,50,50,54,69,7,117,110,105,50,50,54,70,7,117,110,105,50,50,55,48,7,117,110,105,50,50,55, + 49,7,117,110,105,50,50,55,50,7,117,110,105,50,50,55,51,7,117,110,105,50,50,55,52,7,117,110,105,50,50,55,53,7,117,110,105,50,50,55, + 54,7,117,110,105,50,50,55,55,7,117,110,105,50,50,55,56,7,117,110,105,50,50,55,57,7,117,110,105,50,50,55,65,7,117,110,105,50,50,55, + 66,7,117,110,105,50,50,55,67,7,117,110,105,50,50,55,68,7,117,110,105,50,50,55,69,7,117,110,105,50,50,55,70,7,117,110,105,50,50,56, + 48,7,117,110,105,50,50,56,49,12,112,114,111,112,101,114,115,117,98,115,101,116,14,112,114,111,112,101,114,115,117,112,101,114,115,101,116,9,110,111, + 116,115,117,98,115,101,116,7,117,110,105,50,50,56,53,12,114,101,102,108,101,120,115,117,98,115,101,116,14,114,101,102,108,101,120,115,117,112,101,114, + 115,101,116,7,117,110,105,50,50,56,56,7,117,110,105,50,50,56,57,7,117,110,105,50,50,56,65,7,117,110,105,50,50,56,66,7,117,110,105,50, + 50,56,67,7,117,110,105,50,50,56,68,7,117,110,105,50,50,56,69,7,117,110,105,50,50,56,70,7,117,110,105,50,50,57,48,7,117,110,105,50, + 50,57,49,7,117,110,105,50,50,57,50,7,117,110,105,50,50,57,51,7,117,110,105,50,50,57,52,10,99,105,114,99,108,101,112,108,117,115,7,117, + 110,105,50,50,57,54,14,99,105,114,99,108,101,109,117,108,116,105,112,108,121,7,117,110,105,50,50,57,56,7,117,110,105,50,50,57,57,7,117,110, + 105,50,50,57,65,7,117,110,105,50,50,57,66,7,117,110,105,50,50,57,67,7,117,110,105,50,50,57,68,7,117,110,105,50,50,57,69,7,117,110, + 105,50,50,57,70,7,117,110,105,50,50,65,48,7,117,110,105,50,50,65,49,7,117,110,105,50,50,65,50,7,117,110,105,50,50,65,51,7,117,110, + 105,50,50,65,52,13,112,101,114,112,101,110,100,105,99,117,108,97,114,7,117,110,105,50,50,65,54,7,117,110,105,50,50,65,55,7,117,110,105,50, + 50,65,56,7,117,110,105,50,50,65,57,7,117,110,105,50,50,65,65,7,117,110,105,50,50,65,66,7,117,110,105,50,50,65,67,7,117,110,105,50, + 50,65,68,7,117,110,105,50,50,65,69,7,117,110,105,50,50,65,70,7,117,110,105,50,50,66,48,7,117,110,105,50,50,66,49,7,117,110,105,50, + 50,66,50,7,117,110,105,50,50,66,51,7,117,110,105,50,50,66,52,7,117,110,105,50,50,66,53,7,117,110,105,50,50,66,54,7,117,110,105,50, + 50,66,55,7,117,110,105,50,50,66,56,7,117,110,105,50,50,66,57,7,117,110,105,50,50,66,65,7,117,110,105,50,50,66,66,7,117,110,105,50, + 50,66,67,7,117,110,105,50,50,66,68,7,117,110,105,50,50,66,69,7,117,110,105,50,50,66,70,7,117,110,105,50,50,67,48,7,117,110,105,50, + 50,67,49,7,117,110,105,50,50,67,50,7,117,110,105,50,50,67,51,7,117,110,105,50,50,67,52,7,100,111,116,109,97,116,104,7,117,110,105,50, + 50,67,54,7,117,110,105,50,50,67,55,7,117,110,105,50,50,67,56,7,117,110,105,50,50,67,57,7,117,110,105,50,50,67,65,7,117,110,105,50, + 50,67,66,7,117,110,105,50,50,67,67,7,117,110,105,50,50,67,68,7,117,110,105,50,50,67,69,7,117,110,105,50,50,67,70,7,117,110,105,50, + 50,68,48,7,117,110,105,50,50,68,49,7,117,110,105,50,50,68,50,7,117,110,105,50,50,68,51,7,117,110,105,50,50,68,52,7,117,110,105,50, + 50,68,53,7,117,110,105,50,50,68,54,7,117,110,105,50,50,68,55,7,117,110,105,50,50,68,56,7,117,110,105,50,50,68,57,7,117,110,105,50, + 50,68,65,7,117,110,105,50,50,68,66,7,117,110,105,50,50,68,67,7,117,110,105,50,50,68,68,7,117,110,105,50,50,68,69,7,117,110,105,50, + 50,68,70,7,117,110,105,50,50,69,48,7,117,110,105,50,50,69,49,7,117,110,105,50,50,69,50,7,117,110,105,50,50,69,51,7,117,110,105,50, + 50,69,52,7,117,110,105,50,50,69,53,7,117,110,105,50,50,69,54,7,117,110,105,50,50,69,55,7,117,110,105,50,50,69,56,7,117,110,105,50, + 50,69,57,7,117,110,105,50,50,69,65,7,117,110,105,50,50,69,66,7,117,110,105,50,50,69,67,7,117,110,105,50,50,69,68,7,117,110,105,50, + 50,69,69,7,117,110,105,50,50,69,70,7,117,110,105,50,50,70,48,7,117,110,105,50,50,70,49,7,117,110,105,50,50,70,50,7,117,110,105,50, + 50,70,51,7,117,110,105,50,50,70,52,7,117,110,105,50,50,70,53,7,117,110,105,50,50,70,54,7,117,110,105,50,50,70,55,7,117,110,105,50, + 50,70,56,7,117,110,105,50,50,70,57,7,117,110,105,50,50,70,65,7,117,110,105,50,50,70,66,7,117,110,105,50,50,70,67,7,117,110,105,50, + 50,70,68,7,117,110,105,50,50,70,69,7,117,110,105,50,50,70,70,7,117,110,105,50,51,48,48,7,117,110,105,50,51,48,49,5,104,111,117,115, + 101,7,117,110,105,50,51,48,51,7,117,110,105,50,51,48,52,7,117,110,105,50,51,48,53,7,117,110,105,50,51,48,54,7,117,110,105,50,51,48, + 55,7,117,110,105,50,51,48,56,7,117,110,105,50,51,48,57,7,117,110,105,50,51,48,65,7,117,110,105,50,51,48,66,7,117,110,105,50,51,48, + 67,7,117,110,105,50,51,48,68,7,117,110,105,50,51,48,69,7,117,110,105,50,51,48,70,13,114,101,118,108,111,103,105,99,97,108,110,111,116,7, + 117,110,105,50,51,49,49,7,117,110,105,50,51,49,56,7,117,110,105,50,51,49,57,7,117,110,105,50,51,49,67,7,117,110,105,50,51,49,68,7, + 117,110,105,50,51,49,69,7,117,110,105,50,51,49,70,10,105,110,116,101,103,114,97,108,116,112,10,105,110,116,101,103,114,97,108,98,116,7,117,110, + 105,50,51,50,52,7,117,110,105,50,51,50,53,7,117,110,105,50,51,50,54,7,117,110,105,50,51,50,55,7,117,110,105,50,51,50,56,7,117,110, + 105,50,51,50,66,7,117,110,105,50,51,50,67,7,117,110,105,50,51,55,51,7,117,110,105,50,51,55,52,7,117,110,105,50,51,55,53,7,117,110, + 105,50,51,55,65,7,117,110,105,50,51,55,68,7,117,110,105,50,51,56,55,7,117,110,105,50,51,57,52,7,117,110,105,50,51,57,66,7,117,110, + 105,50,51,57,67,7,117,110,105,50,51,57,68,7,117,110,105,50,51,57,69,7,117,110,105,50,51,57,70,7,117,110,105,50,51,65,48,7,117,110, + 105,50,51,65,49,7,117,110,105,50,51,65,50,7,117,110,105,50,51,65,51,7,117,110,105,50,51,65,52,7,117,110,105,50,51,65,53,7,117,110, + 105,50,51,65,54,7,117,110,105,50,51,65,55,7,117,110,105,50,51,65,56,7,117,110,105,50,51,65,57,7,117,110,105,50,51,65,65,7,117,110, + 105,50,51,65,66,7,117,110,105,50,51,65,67,7,117,110,105,50,51,65,68,7,117,110,105,50,51,65,69,7,117,110,105,50,51,67,69,7,117,110, + 105,50,51,67,70,7,117,110,105,50,51,69,51,7,117,110,105,50,51,69,53,7,117,110,105,50,51,69,56,7,117,110,105,50,52,50,50,7,117,110, + 105,50,52,50,51,7,117,110,105,50,52,54,48,7,117,110,105,50,52,54,49,7,117,110,105,50,52,54,50,7,117,110,105,50,52,54,51,7,117,110, + 105,50,52,54,52,7,117,110,105,50,52,54,53,7,117,110,105,50,52,54,54,7,117,110,105,50,52,54,55,7,117,110,105,50,52,54,56,7,117,110, + 105,50,52,54,57,8,83,70,49,48,48,48,48,48,7,117,110,105,50,53,48,49,8,83,70,49,49,48,48,48,48,7,117,110,105,50,53,48,51,7, + 117,110,105,50,53,48,52,7,117,110,105,50,53,48,53,7,117,110,105,50,53,48,54,7,117,110,105,50,53,48,55,7,117,110,105,50,53,48,56,7, + 117,110,105,50,53,48,57,7,117,110,105,50,53,48,65,7,117,110,105,50,53,48,66,8,83,70,48,49,48,48,48,48,7,117,110,105,50,53,48,68, + 7,117,110,105,50,53,48,69,7,117,110,105,50,53,48,70,8,83,70,48,51,48,48,48,48,7,117,110,105,50,53,49,49,7,117,110,105,50,53,49, + 50,7,117,110,105,50,53,49,51,8,83,70,48,50,48,48,48,48,7,117,110,105,50,53,49,53,7,117,110,105,50,53,49,54,7,117,110,105,50,53, + 49,55,8,83,70,48,52,48,48,48,48,7,117,110,105,50,53,49,57,7,117,110,105,50,53,49,65,7,117,110,105,50,53,49,66,8,83,70,48,56, + 48,48,48,48,7,117,110,105,50,53,49,68,7,117,110,105,50,53,49,69,7,117,110,105,50,53,49,70,7,117,110,105,50,53,50,48,7,117,110,105, + 50,53,50,49,7,117,110,105,50,53,50,50,7,117,110,105,50,53,50,51,8,83,70,48,57,48,48,48,48,7,117,110,105,50,53,50,53,7,117,110, + 105,50,53,50,54,7,117,110,105,50,53,50,55,7,117,110,105,50,53,50,56,7,117,110,105,50,53,50,57,7,117,110,105,50,53,50,65,7,117,110, + 105,50,53,50,66,8,83,70,48,54,48,48,48,48,7,117,110,105,50,53,50,68,7,117,110,105,50,53,50,69,7,117,110,105,50,53,50,70,7,117, + 110,105,50,53,51,48,7,117,110,105,50,53,51,49,7,117,110,105,50,53,51,50,7,117,110,105,50,53,51,51,8,83,70,48,55,48,48,48,48,7, + 117,110,105,50,53,51,53,7,117,110,105,50,53,51,54,7,117,110,105,50,53,51,55,7,117,110,105,50,53,51,56,7,117,110,105,50,53,51,57,7, + 117,110,105,50,53,51,65,7,117,110,105,50,53,51,66,8,83,70,48,53,48,48,48,48,7,117,110,105,50,53,51,68,7,117,110,105,50,53,51,69, + 7,117,110,105,50,53,51,70,7,117,110,105,50,53,52,48,7,117,110,105,50,53,52,49,7,117,110,105,50,53,52,50,7,117,110,105,50,53,52,51, + 7,117,110,105,50,53,52,52,7,117,110,105,50,53,52,53,7,117,110,105,50,53,52,54,7,117,110,105,50,53,52,55,7,117,110,105,50,53,52,56, + 7,117,110,105,50,53,52,57,7,117,110,105,50,53,52,65,7,117,110,105,50,53,52,66,7,117,110,105,50,53,52,67,7,117,110,105,50,53,52,68, + 7,117,110,105,50,53,52,69,7,117,110,105,50,53,52,70,8,83,70,52,51,48,48,48,48,8,83,70,50,52,48,48,48,48,8,83,70,53,49,48, + 48,48,48,8,83,70,53,50,48,48,48,48,8,83,70,51,57,48,48,48,48,8,83,70,50,50,48,48,48,48,8,83,70,50,49,48,48,48,48,8, + 83,70,50,53,48,48,48,48,8,83,70,53,48,48,48,48,48,8,83,70,52,57,48,48,48,48,8,83,70,51,56,48,48,48,48,8,83,70,50,56, + 48,48,48,48,8,83,70,50,55,48,48,48,48,8,83,70,50,54,48,48,48,48,8,83,70,51,54,48,48,48,48,8,83,70,51,55,48,48,48,48, + 8,83,70,52,50,48,48,48,48,8,83,70,49,57,48,48,48,48,8,83,70,50,48,48,48,48,48,8,83,70,50,51,48,48,48,48,8,83,70,52, + 55,48,48,48,48,8,83,70,52,56,48,48,48,48,8,83,70,52,49,48,48,48,48,8,83,70,52,53,48,48,48,48,8,83,70,52,54,48,48,48, + 48,8,83,70,52,48,48,48,48,48,8,83,70,53,52,48,48,48,48,8,83,70,53,51,48,48,48,48,8,83,70,52,52,48,48,48,48,7,117,110, + 105,50,53,54,68,7,117,110,105,50,53,54,69,7,117,110,105,50,53,54,70,7,117,110,105,50,53,55,48,7,117,110,105,50,53,55,49,7,117,110, + 105,50,53,55,50,7,117,110,105,50,53,55,51,7,117,110,105,50,53,55,52,7,117,110,105,50,53,55,53,7,117,110,105,50,53,55,54,7,117,110, + 105,50,53,55,55,7,117,110,105,50,53,55,56,7,117,110,105,50,53,55,57,7,117,110,105,50,53,55,65,7,117,110,105,50,53,55,66,7,117,110, + 105,50,53,55,67,7,117,110,105,50,53,55,68,7,117,110,105,50,53,55,69,7,117,110,105,50,53,55,70,7,117,112,98,108,111,99,107,7,117,110, + 105,50,53,56,49,7,117,110,105,50,53,56,50,7,117,110,105,50,53,56,51,7,100,110,98,108,111,99,107,7,117,110,105,50,53,56,53,7,117,110, + 105,50,53,56,54,7,117,110,105,50,53,56,55,5,98,108,111,99,107,7,117,110,105,50,53,56,57,7,117,110,105,50,53,56,65,7,117,110,105,50, + 53,56,66,7,108,102,98,108,111,99,107,7,117,110,105,50,53,56,68,7,117,110,105,50,53,56,69,7,117,110,105,50,53,56,70,7,114,116,98,108, + 111,99,107,7,108,116,115,104,97,100,101,5,115,104,97,100,101,7,100,107,115,104,97,100,101,7,117,110,105,50,53,57,52,7,117,110,105,50,53,57, + 53,7,117,110,105,50,53,57,54,7,117,110,105,50,53,57,55,7,117,110,105,50,53,57,56,7,117,110,105,50,53,57,57,7,117,110,105,50,53,57, + 65,7,117,110,105,50,53,57,66,7,117,110,105,50,53,57,67,7,117,110,105,50,53,57,68,7,117,110,105,50,53,57,69,7,117,110,105,50,53,57, + 70,9,102,105,108,108,101,100,98,111,120,6,72,50,50,48,55,51,7,117,110,105,50,53,65,50,7,117,110,105,50,53,65,51,7,117,110,105,50,53, + 65,52,7,117,110,105,50,53,65,53,7,117,110,105,50,53,65,54,7,117,110,105,50,53,65,55,7,117,110,105,50,53,65,56,7,117,110,105,50,53, + 65,57,6,72,49,56,53,52,51,6,72,49,56,53,53,49,10,102,105,108,108,101,100,114,101,99,116,7,117,110,105,50,53,65,68,7,117,110,105,50, + 53,65,69,7,117,110,105,50,53,65,70,7,117,110,105,50,53,66,48,7,117,110,105,50,53,66,49,7,116,114,105,97,103,117,112,7,117,110,105,50, + 53,66,51,7,117,110,105,50,53,66,52,7,117,110,105,50,53,66,53,7,117,110,105,50,53,66,54,7,117,110,105,50,53,66,55,7,117,110,105,50, + 53,66,56,7,117,110,105,50,53,66,57,7,116,114,105,97,103,114,116,7,117,110,105,50,53,66,66,7,116,114,105,97,103,100,110,7,117,110,105,50, + 53,66,68,7,117,110,105,50,53,66,69,7,117,110,105,50,53,66,70,7,117,110,105,50,53,67,48,7,117,110,105,50,53,67,49,7,117,110,105,50, + 53,67,50,7,117,110,105,50,53,67,51,7,116,114,105,97,103,108,102,7,117,110,105,50,53,67,53,7,117,110,105,50,53,67,54,7,117,110,105,50, + 53,67,55,7,117,110,105,50,53,67,56,7,117,110,105,50,53,67,57,6,99,105,114,99,108,101,7,117,110,105,50,53,67,67,7,117,110,105,50,53, + 67,68,7,117,110,105,50,53,67,69,6,72,49,56,53,51,51,7,117,110,105,50,53,68,48,7,117,110,105,50,53,68,49,7,117,110,105,50,53,68, + 50,7,117,110,105,50,53,68,51,7,117,110,105,50,53,68,52,7,117,110,105,50,53,68,53,7,117,110,105,50,53,68,54,7,117,110,105,50,53,68, + 55,9,105,110,118,98,117,108,108,101,116,9,105,110,118,99,105,114,99,108,101,7,117,110,105,50,53,68,65,7,117,110,105,50,53,68,66,7,117,110, + 105,50,53,68,67,7,117,110,105,50,53,68,68,7,117,110,105,50,53,68,69,7,117,110,105,50,53,68,70,7,117,110,105,50,53,69,48,7,117,110, + 105,50,53,69,49,7,117,110,105,50,53,69,50,7,117,110,105,50,53,69,51,7,117,110,105,50,53,69,52,7,117,110,105,50,53,69,53,10,111,112, + 101,110,98,117,108,108,101,116,7,117,110,105,50,53,69,55,7,117,110,105,50,53,69,56,7,117,110,105,50,53,69,57,7,117,110,105,50,53,69,65, + 7,117,110,105,50,53,69,66,7,117,110,105,50,53,69,67,7,117,110,105,50,53,69,68,7,117,110,105,50,53,69,69,7,117,110,105,50,53,69,70, + 7,117,110,105,50,53,70,48,7,117,110,105,50,53,70,49,7,117,110,105,50,53,70,50,7,117,110,105,50,53,70,51,7,117,110,105,50,53,70,52, + 7,117,110,105,50,53,70,53,7,117,110,105,50,53,70,54,7,117,110,105,50,53,70,55,7,117,110,105,50,53,70,56,7,117,110,105,50,53,70,57, + 7,117,110,105,50,53,70,65,7,117,110,105,50,53,70,66,7,117,110,105,50,53,70,67,7,117,110,105,50,53,70,68,7,117,110,105,50,53,70,69, + 7,117,110,105,50,53,70,70,7,117,110,105,50,54,48,48,7,117,110,105,50,54,48,49,7,117,110,105,50,54,48,50,7,117,110,105,50,54,48,51, + 7,117,110,105,50,54,48,52,7,117,110,105,50,54,48,53,7,117,110,105,50,54,48,54,7,117,110,105,50,54,48,55,7,117,110,105,50,54,48,56, + 7,117,110,105,50,54,48,57,7,117,110,105,50,54,48,65,7,117,110,105,50,54,48,66,7,117,110,105,50,54,48,67,7,117,110,105,50,54,48,68, + 7,117,110,105,50,54,48,69,7,117,110,105,50,54,48,70,7,117,110,105,50,54,49,48,7,117,110,105,50,54,49,49,7,117,110,105,50,54,49,50, + 7,117,110,105,50,54,49,51,7,117,110,105,50,54,49,52,7,117,110,105,50,54,49,53,7,117,110,105,50,54,49,54,7,117,110,105,50,54,49,55, + 7,117,110,105,50,54,49,56,7,117,110,105,50,54,49,57,7,117,110,105,50,54,49,65,7,117,110,105,50,54,49,66,7,117,110,105,50,54,49,67, + 7,117,110,105,50,54,49,68,7,117,110,105,50,54,49,69,7,117,110,105,50,54,49,70,7,117,110,105,50,54,50,48,7,117,110,105,50,54,50,49, + 7,117,110,105,50,54,50,50,7,117,110,105,50,54,50,51,7,117,110,105,50,54,50,52,7,117,110,105,50,54,50,53,7,117,110,105,50,54,50,54, + 7,117,110,105,50,54,50,55,7,117,110,105,50,54,50,56,7,117,110,105,50,54,50,57,7,117,110,105,50,54,50,65,7,117,110,105,50,54,50,66, + 7,117,110,105,50,54,50,67,7,117,110,105,50,54,50,68,7,117,110,105,50,54,50,69,7,117,110,105,50,54,50,70,7,117,110,105,50,54,51,48, + 7,117,110,105,50,54,51,49,7,117,110,105,50,54,51,50,7,117,110,105,50,54,51,51,7,117,110,105,50,54,51,52,7,117,110,105,50,54,51,53, + 7,117,110,105,50,54,51,54,7,117,110,105,50,54,51,55,7,117,110,105,50,54,51,56,7,117,110,105,50,54,51,57,9,115,109,105,108,101,102,97, + 99,101,12,105,110,118,115,109,105,108,101,102,97,99,101,3,115,117,110,7,117,110,105,50,54,51,68,7,117,110,105,50,54,51,69,7,117,110,105,50, + 54,51,70,6,102,101,109,97,108,101,7,117,110,105,50,54,52,49,4,109,97,108,101,7,117,110,105,50,54,52,51,7,117,110,105,50,54,52,52,7, + 117,110,105,50,54,52,53,7,117,110,105,50,54,52,54,7,117,110,105,50,54,52,55,7,117,110,105,50,54,52,56,7,117,110,105,50,54,52,57,7, + 117,110,105,50,54,52,65,7,117,110,105,50,54,52,66,7,117,110,105,50,54,52,67,7,117,110,105,50,54,52,68,7,117,110,105,50,54,52,69,7, + 117,110,105,50,54,52,70,7,117,110,105,50,54,53,48,7,117,110,105,50,54,53,49,7,117,110,105,50,54,53,50,7,117,110,105,50,54,53,51,7, + 117,110,105,50,54,53,52,7,117,110,105,50,54,53,53,7,117,110,105,50,54,53,54,7,117,110,105,50,54,53,55,7,117,110,105,50,54,53,56,7, + 117,110,105,50,54,53,57,7,117,110,105,50,54,53,65,7,117,110,105,50,54,53,66,7,117,110,105,50,54,53,67,7,117,110,105,50,54,53,68,7, + 117,110,105,50,54,53,69,7,117,110,105,50,54,53,70,5,115,112,97,100,101,7,117,110,105,50,54,54,49,7,117,110,105,50,54,54,50,4,99,108, + 117,98,7,117,110,105,50,54,54,52,5,104,101,97,114,116,7,100,105,97,109,111,110,100,7,117,110,105,50,54,54,55,7,117,110,105,50,54,54,56, + 7,117,110,105,50,54,54,57,11,109,117,115,105,99,97,108,110,111,116,101,14,109,117,115,105,99,97,108,110,111,116,101,100,98,108,7,117,110,105,50, + 54,54,67,7,117,110,105,50,54,54,68,7,117,110,105,50,54,54,69,7,117,110,105,50,54,54,70,7,117,110,105,50,54,55,48,7,117,110,105,50, + 54,55,49,7,117,110,105,50,54,55,50,7,117,110,105,50,54,55,51,7,117,110,105,50,54,55,52,7,117,110,105,50,54,55,53,7,117,110,105,50, + 54,55,54,7,117,110,105,50,54,55,55,7,117,110,105,50,54,55,56,7,117,110,105,50,54,55,57,7,117,110,105,50,54,55,65,7,117,110,105,50, + 54,55,66,7,117,110,105,50,54,55,67,7,117,110,105,50,54,55,68,7,117,110,105,50,54,55,69,7,117,110,105,50,54,55,70,7,117,110,105,50, + 54,56,48,7,117,110,105,50,54,56,49,7,117,110,105,50,54,56,50,7,117,110,105,50,54,56,51,7,117,110,105,50,54,56,52,7,117,110,105,50, + 54,56,53,7,117,110,105,50,54,56,54,7,117,110,105,50,54,56,55,7,117,110,105,50,54,56,56,7,117,110,105,50,54,56,57,7,117,110,105,50, + 54,56,65,7,117,110,105,50,54,56,66,7,117,110,105,50,54,56,67,7,117,110,105,50,54,56,68,7,117,110,105,50,54,56,69,7,117,110,105,50, + 54,56,70,7,117,110,105,50,54,57,48,7,117,110,105,50,54,57,49,7,117,110,105,50,54,57,50,7,117,110,105,50,54,57,51,7,117,110,105,50, + 54,57,52,7,117,110,105,50,54,57,53,7,117,110,105,50,54,57,54,7,117,110,105,50,54,57,55,7,117,110,105,50,54,57,56,7,117,110,105,50, + 54,57,57,7,117,110,105,50,54,57,65,7,117,110,105,50,54,57,66,7,117,110,105,50,54,57,67,7,117,110,105,50,54,65,48,7,117,110,105,50, + 54,65,49,7,117,110,105,50,54,65,50,7,117,110,105,50,54,65,51,7,117,110,105,50,54,65,52,7,117,110,105,50,54,65,53,7,117,110,105,50, + 54,65,54,7,117,110,105,50,54,65,55,7,117,110,105,50,54,65,56,7,117,110,105,50,54,65,57,7,117,110,105,50,54,65,65,7,117,110,105,50, + 54,65,66,7,117,110,105,50,54,65,67,7,117,110,105,50,54,65,68,7,117,110,105,50,54,65,69,7,117,110,105,50,54,65,70,7,117,110,105,50, + 54,66,48,7,117,110,105,50,54,66,49,7,117,110,105,50,54,66,50,7,117,110,105,50,54,66,51,7,117,110,105,50,54,66,52,7,117,110,105,50, + 54,66,53,7,117,110,105,50,54,66,54,7,117,110,105,50,54,66,55,7,117,110,105,50,54,66,56,7,117,110,105,50,54,67,48,7,117,110,105,50, + 54,67,49,7,117,110,105,50,54,67,50,7,117,110,105,50,54,67,51,7,117,110,105,50,54,69,50,7,117,110,105,50,55,48,49,7,117,110,105,50, + 55,48,50,7,117,110,105,50,55,48,51,7,117,110,105,50,55,48,52,7,117,110,105,50,55,48,54,7,117,110,105,50,55,48,55,7,117,110,105,50, + 55,48,56,7,117,110,105,50,55,48,57,7,117,110,105,50,55,48,67,7,117,110,105,50,55,48,68,7,117,110,105,50,55,48,69,7,117,110,105,50, + 55,48,70,7,117,110,105,50,55,49,48,7,117,110,105,50,55,49,49,7,117,110,105,50,55,49,50,7,117,110,105,50,55,49,51,7,117,110,105,50, + 55,49,52,7,117,110,105,50,55,49,53,7,117,110,105,50,55,49,54,7,117,110,105,50,55,49,55,7,117,110,105,50,55,49,56,7,117,110,105,50, + 55,49,57,7,117,110,105,50,55,49,65,7,117,110,105,50,55,49,66,7,117,110,105,50,55,49,67,7,117,110,105,50,55,49,68,7,117,110,105,50, + 55,49,69,7,117,110,105,50,55,49,70,7,117,110,105,50,55,50,48,7,117,110,105,50,55,50,49,7,117,110,105,50,55,50,50,7,117,110,105,50, + 55,50,51,7,117,110,105,50,55,50,52,7,117,110,105,50,55,50,53,7,117,110,105,50,55,50,54,7,117,110,105,50,55,50,55,7,117,110,105,50, + 55,50,57,7,117,110,105,50,55,50,65,7,117,110,105,50,55,50,66,7,117,110,105,50,55,50,67,7,117,110,105,50,55,50,68,7,117,110,105,50, + 55,50,69,7,117,110,105,50,55,50,70,7,117,110,105,50,55,51,48,7,117,110,105,50,55,51,49,7,117,110,105,50,55,51,50,7,117,110,105,50, + 55,51,51,7,117,110,105,50,55,51,52,7,117,110,105,50,55,51,53,7,117,110,105,50,55,51,54,7,117,110,105,50,55,51,55,7,117,110,105,50, + 55,51,56,7,117,110,105,50,55,51,57,7,117,110,105,50,55,51,65,7,117,110,105,50,55,51,66,7,117,110,105,50,55,51,67,7,117,110,105,50, + 55,51,68,7,117,110,105,50,55,51,69,7,117,110,105,50,55,51,70,7,117,110,105,50,55,52,48,7,117,110,105,50,55,52,49,7,117,110,105,50, + 55,52,50,7,117,110,105,50,55,52,51,7,117,110,105,50,55,52,52,7,117,110,105,50,55,52,53,7,117,110,105,50,55,52,54,7,117,110,105,50, + 55,52,55,7,117,110,105,50,55,52,56,7,117,110,105,50,55,52,57,7,117,110,105,50,55,52,65,7,117,110,105,50,55,52,66,7,117,110,105,50, + 55,52,68,7,117,110,105,50,55,52,70,7,117,110,105,50,55,53,48,7,117,110,105,50,55,53,49,7,117,110,105,50,55,53,50,7,117,110,105,50, + 55,53,54,7,117,110,105,50,55,53,56,7,117,110,105,50,55,53,57,7,117,110,105,50,55,53,65,7,117,110,105,50,55,53,66,7,117,110,105,50, + 55,53,67,7,117,110,105,50,55,53,68,7,117,110,105,50,55,53,69,7,117,110,105,50,55,54,49,7,117,110,105,50,55,54,50,7,117,110,105,50, + 55,54,51,7,117,110,105,50,55,54,52,7,117,110,105,50,55,54,53,7,117,110,105,50,55,54,54,7,117,110,105,50,55,54,55,7,117,110,105,50, + 55,54,56,7,117,110,105,50,55,54,57,7,117,110,105,50,55,54,65,7,117,110,105,50,55,54,66,7,117,110,105,50,55,54,67,7,117,110,105,50, + 55,54,68,7,117,110,105,50,55,54,69,7,117,110,105,50,55,54,70,7,117,110,105,50,55,55,48,7,117,110,105,50,55,55,49,7,117,110,105,50, + 55,55,50,7,117,110,105,50,55,55,51,7,117,110,105,50,55,55,52,7,117,110,105,50,55,55,53,7,117,110,105,50,55,55,54,7,117,110,105,50, + 55,55,55,7,117,110,105,50,55,55,56,7,117,110,105,50,55,55,57,7,117,110,105,50,55,55,65,7,117,110,105,50,55,55,66,7,117,110,105,50, + 55,55,67,7,117,110,105,50,55,55,68,7,117,110,105,50,55,55,69,7,117,110,105,50,55,55,70,7,117,110,105,50,55,56,48,7,117,110,105,50, + 55,56,49,7,117,110,105,50,55,56,50,7,117,110,105,50,55,56,51,7,117,110,105,50,55,56,52,7,117,110,105,50,55,56,53,7,117,110,105,50, + 55,56,54,7,117,110,105,50,55,56,55,7,117,110,105,50,55,56,56,7,117,110,105,50,55,56,57,7,117,110,105,50,55,56,65,7,117,110,105,50, + 55,56,66,7,117,110,105,50,55,56,67,7,117,110,105,50,55,56,68,7,117,110,105,50,55,56,69,7,117,110,105,50,55,56,70,7,117,110,105,50, + 55,57,48,7,117,110,105,50,55,57,49,7,117,110,105,50,55,57,50,7,117,110,105,50,55,57,51,7,117,110,105,50,55,57,52,7,117,110,105,50, + 55,57,56,7,117,110,105,50,55,57,57,7,117,110,105,50,55,57,65,7,117,110,105,50,55,57,66,7,117,110,105,50,55,57,67,7,117,110,105,50, + 55,57,68,7,117,110,105,50,55,57,69,7,117,110,105,50,55,57,70,7,117,110,105,50,55,65,48,7,117,110,105,50,55,65,49,7,117,110,105,50, + 55,65,50,7,117,110,105,50,55,65,51,7,117,110,105,50,55,65,52,7,117,110,105,50,55,65,53,7,117,110,105,50,55,65,54,7,117,110,105,50, + 55,65,55,7,117,110,105,50,55,65,56,7,117,110,105,50,55,65,57,7,117,110,105,50,55,65,65,7,117,110,105,50,55,65,66,7,117,110,105,50, + 55,65,67,7,117,110,105,50,55,65,68,7,117,110,105,50,55,65,69,7,117,110,105,50,55,65,70,7,117,110,105,50,55,66,49,7,117,110,105,50, + 55,66,50,7,117,110,105,50,55,66,51,7,117,110,105,50,55,66,52,7,117,110,105,50,55,66,53,7,117,110,105,50,55,66,54,7,117,110,105,50, + 55,66,55,7,117,110,105,50,55,66,56,7,117,110,105,50,55,66,57,7,117,110,105,50,55,66,65,7,117,110,105,50,55,66,66,7,117,110,105,50, + 55,66,67,7,117,110,105,50,55,66,68,7,117,110,105,50,55,66,69,7,117,110,105,50,55,67,53,7,117,110,105,50,55,67,54,7,117,110,105,50, + 55,69,48,7,117,110,105,50,55,69,54,7,117,110,105,50,55,69,55,7,117,110,105,50,55,69,56,7,117,110,105,50,55,69,57,7,117,110,105,50, + 55,69,65,7,117,110,105,50,55,69,66,7,117,110,105,50,55,70,48,7,117,110,105,50,55,70,49,7,117,110,105,50,55,70,50,7,117,110,105,50, + 55,70,51,7,117,110,105,50,55,70,52,7,117,110,105,50,55,70,53,7,117,110,105,50,55,70,54,7,117,110,105,50,55,70,55,7,117,110,105,50, + 55,70,56,7,117,110,105,50,55,70,57,7,117,110,105,50,55,70,65,7,117,110,105,50,55,70,66,7,117,110,105,50,55,70,67,7,117,110,105,50, + 55,70,68,7,117,110,105,50,55,70,69,7,117,110,105,50,55,70,70,7,117,110,105,50,56,48,48,7,117,110,105,50,56,48,49,7,117,110,105,50, + 56,48,50,7,117,110,105,50,56,48,51,7,117,110,105,50,56,48,52,7,117,110,105,50,56,48,53,7,117,110,105,50,56,48,54,7,117,110,105,50, + 56,48,55,7,117,110,105,50,56,48,56,7,117,110,105,50,56,48,57,7,117,110,105,50,56,48,65,7,117,110,105,50,56,48,66,7,117,110,105,50, + 56,48,67,7,117,110,105,50,56,48,68,7,117,110,105,50,56,48,69,7,117,110,105,50,56,48,70,7,117,110,105,50,56,49,48,7,117,110,105,50, + 56,49,49,7,117,110,105,50,56,49,50,7,117,110,105,50,56,49,51,7,117,110,105,50,56,49,52,7,117,110,105,50,56,49,53,7,117,110,105,50, + 56,49,54,7,117,110,105,50,56,49,55,7,117,110,105,50,56,49,56,7,117,110,105,50,56,49,57,7,117,110,105,50,56,49,65,7,117,110,105,50, + 56,49,66,7,117,110,105,50,56,49,67,7,117,110,105,50,56,49,68,7,117,110,105,50,56,49,69,7,117,110,105,50,56,49,70,7,117,110,105,50, + 56,50,48,7,117,110,105,50,56,50,49,7,117,110,105,50,56,50,50,7,117,110,105,50,56,50,51,7,117,110,105,50,56,50,52,7,117,110,105,50, + 56,50,53,7,117,110,105,50,56,50,54,7,117,110,105,50,56,50,55,7,117,110,105,50,56,50,56,7,117,110,105,50,56,50,57,7,117,110,105,50, + 56,50,65,7,117,110,105,50,56,50,66,7,117,110,105,50,56,50,67,7,117,110,105,50,56,50,68,7,117,110,105,50,56,50,69,7,117,110,105,50, + 56,50,70,7,117,110,105,50,56,51,48,7,117,110,105,50,56,51,49,7,117,110,105,50,56,51,50,7,117,110,105,50,56,51,51,7,117,110,105,50, + 56,51,52,7,117,110,105,50,56,51,53,7,117,110,105,50,56,51,54,7,117,110,105,50,56,51,55,7,117,110,105,50,56,51,56,7,117,110,105,50, + 56,51,57,7,117,110,105,50,56,51,65,7,117,110,105,50,56,51,66,7,117,110,105,50,56,51,67,7,117,110,105,50,56,51,68,7,117,110,105,50, + 56,51,69,7,117,110,105,50,56,51,70,7,117,110,105,50,56,52,48,7,117,110,105,50,56,52,49,7,117,110,105,50,56,52,50,7,117,110,105,50, + 56,52,51,7,117,110,105,50,56,52,52,7,117,110,105,50,56,52,53,7,117,110,105,50,56,52,54,7,117,110,105,50,56,52,55,7,117,110,105,50, + 56,52,56,7,117,110,105,50,56,52,57,7,117,110,105,50,56,52,65,7,117,110,105,50,56,52,66,7,117,110,105,50,56,52,67,7,117,110,105,50, + 56,52,68,7,117,110,105,50,56,52,69,7,117,110,105,50,56,52,70,7,117,110,105,50,56,53,48,7,117,110,105,50,56,53,49,7,117,110,105,50, + 56,53,50,7,117,110,105,50,56,53,51,7,117,110,105,50,56,53,52,7,117,110,105,50,56,53,53,7,117,110,105,50,56,53,54,7,117,110,105,50, + 56,53,55,7,117,110,105,50,56,53,56,7,117,110,105,50,56,53,57,7,117,110,105,50,56,53,65,7,117,110,105,50,56,53,66,7,117,110,105,50, + 56,53,67,7,117,110,105,50,56,53,68,7,117,110,105,50,56,53,69,7,117,110,105,50,56,53,70,7,117,110,105,50,56,54,48,7,117,110,105,50, + 56,54,49,7,117,110,105,50,56,54,50,7,117,110,105,50,56,54,51,7,117,110,105,50,56,54,52,7,117,110,105,50,56,54,53,7,117,110,105,50, + 56,54,54,7,117,110,105,50,56,54,55,7,117,110,105,50,56,54,56,7,117,110,105,50,56,54,57,7,117,110,105,50,56,54,65,7,117,110,105,50, + 56,54,66,7,117,110,105,50,56,54,67,7,117,110,105,50,56,54,68,7,117,110,105,50,56,54,69,7,117,110,105,50,56,54,70,7,117,110,105,50, + 56,55,48,7,117,110,105,50,56,55,49,7,117,110,105,50,56,55,50,7,117,110,105,50,56,55,51,7,117,110,105,50,56,55,52,7,117,110,105,50, + 56,55,53,7,117,110,105,50,56,55,54,7,117,110,105,50,56,55,55,7,117,110,105,50,56,55,56,7,117,110,105,50,56,55,57,7,117,110,105,50, + 56,55,65,7,117,110,105,50,56,55,66,7,117,110,105,50,56,55,67,7,117,110,105,50,56,55,68,7,117,110,105,50,56,55,69,7,117,110,105,50, + 56,55,70,7,117,110,105,50,56,56,48,7,117,110,105,50,56,56,49,7,117,110,105,50,56,56,50,7,117,110,105,50,56,56,51,7,117,110,105,50, + 56,56,52,7,117,110,105,50,56,56,53,7,117,110,105,50,56,56,54,7,117,110,105,50,56,56,55,7,117,110,105,50,56,56,56,7,117,110,105,50, + 56,56,57,7,117,110,105,50,56,56,65,7,117,110,105,50,56,56,66,7,117,110,105,50,56,56,67,7,117,110,105,50,56,56,68,7,117,110,105,50, + 56,56,69,7,117,110,105,50,56,56,70,7,117,110,105,50,56,57,48,7,117,110,105,50,56,57,49,7,117,110,105,50,56,57,50,7,117,110,105,50, + 56,57,51,7,117,110,105,50,56,57,52,7,117,110,105,50,56,57,53,7,117,110,105,50,56,57,54,7,117,110,105,50,56,57,55,7,117,110,105,50, + 56,57,56,7,117,110,105,50,56,57,57,7,117,110,105,50,56,57,65,7,117,110,105,50,56,57,66,7,117,110,105,50,56,57,67,7,117,110,105,50, + 56,57,68,7,117,110,105,50,56,57,69,7,117,110,105,50,56,57,70,7,117,110,105,50,56,65,48,7,117,110,105,50,56,65,49,7,117,110,105,50, + 56,65,50,7,117,110,105,50,56,65,51,7,117,110,105,50,56,65,52,7,117,110,105,50,56,65,53,7,117,110,105,50,56,65,54,7,117,110,105,50, + 56,65,55,7,117,110,105,50,56,65,56,7,117,110,105,50,56,65,57,7,117,110,105,50,56,65,65,7,117,110,105,50,56,65,66,7,117,110,105,50, + 56,65,67,7,117,110,105,50,56,65,68,7,117,110,105,50,56,65,69,7,117,110,105,50,56,65,70,7,117,110,105,50,56,66,48,7,117,110,105,50, + 56,66,49,7,117,110,105,50,56,66,50,7,117,110,105,50,56,66,51,7,117,110,105,50,56,66,52,7,117,110,105,50,56,66,53,7,117,110,105,50, + 56,66,54,7,117,110,105,50,56,66,55,7,117,110,105,50,56,66,56,7,117,110,105,50,56,66,57,7,117,110,105,50,56,66,65,7,117,110,105,50, + 56,66,66,7,117,110,105,50,56,66,67,7,117,110,105,50,56,66,68,7,117,110,105,50,56,66,69,7,117,110,105,50,56,66,70,7,117,110,105,50, + 56,67,48,7,117,110,105,50,56,67,49,7,117,110,105,50,56,67,50,7,117,110,105,50,56,67,51,7,117,110,105,50,56,67,52,7,117,110,105,50, + 56,67,53,7,117,110,105,50,56,67,54,7,117,110,105,50,56,67,55,7,117,110,105,50,56,67,56,7,117,110,105,50,56,67,57,7,117,110,105,50, + 56,67,65,7,117,110,105,50,56,67,66,7,117,110,105,50,56,67,67,7,117,110,105,50,56,67,68,7,117,110,105,50,56,67,69,7,117,110,105,50, + 56,67,70,7,117,110,105,50,56,68,48,7,117,110,105,50,56,68,49,7,117,110,105,50,56,68,50,7,117,110,105,50,56,68,51,7,117,110,105,50, + 56,68,52,7,117,110,105,50,56,68,53,7,117,110,105,50,56,68,54,7,117,110,105,50,56,68,55,7,117,110,105,50,56,68,56,7,117,110,105,50, + 56,68,57,7,117,110,105,50,56,68,65,7,117,110,105,50,56,68,66,7,117,110,105,50,56,68,67,7,117,110,105,50,56,68,68,7,117,110,105,50, + 56,68,69,7,117,110,105,50,56,68,70,7,117,110,105,50,56,69,48,7,117,110,105,50,56,69,49,7,117,110,105,50,56,69,50,7,117,110,105,50, + 56,69,51,7,117,110,105,50,56,69,52,7,117,110,105,50,56,69,53,7,117,110,105,50,56,69,54,7,117,110,105,50,56,69,55,7,117,110,105,50, + 56,69,56,7,117,110,105,50,56,69,57,7,117,110,105,50,56,69,65,7,117,110,105,50,56,69,66,7,117,110,105,50,56,69,67,7,117,110,105,50, + 56,69,68,7,117,110,105,50,56,69,69,7,117,110,105,50,56,69,70,7,117,110,105,50,56,70,48,7,117,110,105,50,56,70,49,7,117,110,105,50, + 56,70,50,7,117,110,105,50,56,70,51,7,117,110,105,50,56,70,52,7,117,110,105,50,56,70,53,7,117,110,105,50,56,70,54,7,117,110,105,50, + 56,70,55,7,117,110,105,50,56,70,56,7,117,110,105,50,56,70,57,7,117,110,105,50,56,70,65,7,117,110,105,50,56,70,66,7,117,110,105,50, + 56,70,67,7,117,110,105,50,56,70,68,7,117,110,105,50,56,70,69,7,117,110,105,50,56,70,70,7,117,110,105,50,57,48,54,7,117,110,105,50, + 57,48,55,7,117,110,105,50,57,48,65,7,117,110,105,50,57,48,66,7,117,110,105,50,57,52,48,7,117,110,105,50,57,52,49,7,117,110,105,50, + 57,56,51,7,117,110,105,50,57,56,52,7,117,110,105,50,57,67,69,7,117,110,105,50,57,67,70,7,117,110,105,50,57,68,48,7,117,110,105,50, + 57,68,49,7,117,110,105,50,57,68,50,7,117,110,105,50,57,68,51,7,117,110,105,50,57,68,52,7,117,110,105,50,57,68,53,7,117,110,105,50, + 57,69,66,7,117,110,105,50,57,70,65,7,117,110,105,50,57,70,66,7,117,110,105,50,65,48,48,7,117,110,105,50,65,48,49,7,117,110,105,50, + 65,48,50,7,117,110,105,50,65,48,67,7,117,110,105,50,65,48,68,7,117,110,105,50,65,48,69,7,117,110,105,50,65,48,70,7,117,110,105,50, + 65,49,48,7,117,110,105,50,65,49,49,7,117,110,105,50,65,49,50,7,117,110,105,50,65,49,51,7,117,110,105,50,65,49,52,7,117,110,105,50, + 65,49,53,7,117,110,105,50,65,49,54,7,117,110,105,50,65,49,55,7,117,110,105,50,65,49,56,7,117,110,105,50,65,49,57,7,117,110,105,50, + 65,49,65,7,117,110,105,50,65,49,66,7,117,110,105,50,65,49,67,7,117,110,105,50,65,50,70,7,117,110,105,50,65,54,65,7,117,110,105,50, + 65,54,66,7,117,110,105,50,65,55,68,7,117,110,105,50,65,55,69,7,117,110,105,50,65,55,70,7,117,110,105,50,65,56,48,7,117,110,105,50, + 65,56,49,7,117,110,105,50,65,56,50,7,117,110,105,50,65,56,51,7,117,110,105,50,65,56,52,7,117,110,105,50,65,56,53,7,117,110,105,50, + 65,56,54,7,117,110,105,50,65,56,55,7,117,110,105,50,65,56,56,7,117,110,105,50,65,56,57,7,117,110,105,50,65,56,65,7,117,110,105,50, + 65,56,66,7,117,110,105,50,65,56,67,7,117,110,105,50,65,56,68,7,117,110,105,50,65,56,69,7,117,110,105,50,65,56,70,7,117,110,105,50, + 65,57,48,7,117,110,105,50,65,57,49,7,117,110,105,50,65,57,50,7,117,110,105,50,65,57,51,7,117,110,105,50,65,57,52,7,117,110,105,50, + 65,57,53,7,117,110,105,50,65,57,54,7,117,110,105,50,65,57,55,7,117,110,105,50,65,57,56,7,117,110,105,50,65,57,57,7,117,110,105,50, + 65,57,65,7,117,110,105,50,65,57,66,7,117,110,105,50,65,57,67,7,117,110,105,50,65,57,68,7,117,110,105,50,65,57,69,7,117,110,105,50, + 65,57,70,7,117,110,105,50,65,65,48,7,117,110,105,50,65,65,69,7,117,110,105,50,65,65,70,7,117,110,105,50,65,66,48,7,117,110,105,50, + 65,66,49,7,117,110,105,50,65,66,50,7,117,110,105,50,65,66,51,7,117,110,105,50,65,66,52,7,117,110,105,50,65,66,53,7,117,110,105,50, + 65,66,54,7,117,110,105,50,65,66,55,7,117,110,105,50,65,66,56,7,117,110,105,50,65,66,57,7,117,110,105,50,65,66,65,7,117,110,105,50, + 65,70,57,7,117,110,105,50,65,70,65,7,117,110,105,50,66,48,48,7,117,110,105,50,66,48,49,7,117,110,105,50,66,48,50,7,117,110,105,50, + 66,48,51,7,117,110,105,50,66,48,52,7,117,110,105,50,66,48,53,7,117,110,105,50,66,48,54,7,117,110,105,50,66,48,55,7,117,110,105,50, + 66,48,56,7,117,110,105,50,66,48,57,7,117,110,105,50,66,48,65,7,117,110,105,50,66,48,66,7,117,110,105,50,66,48,67,7,117,110,105,50, + 66,48,68,7,117,110,105,50,66,48,69,7,117,110,105,50,66,48,70,7,117,110,105,50,66,49,48,7,117,110,105,50,66,49,49,7,117,110,105,50, + 66,49,50,7,117,110,105,50,66,49,51,7,117,110,105,50,66,49,52,7,117,110,105,50,66,49,53,7,117,110,105,50,66,49,54,7,117,110,105,50, + 66,49,55,7,117,110,105,50,66,49,56,7,117,110,105,50,66,49,57,7,117,110,105,50,66,49,65,7,117,110,105,50,66,49,70,7,117,110,105,50, + 66,50,48,7,117,110,105,50,66,50,49,7,117,110,105,50,66,50,50,7,117,110,105,50,66,50,51,7,117,110,105,50,66,50,52,7,117,110,105,50, + 66,53,51,7,117,110,105,50,66,53,52,7,117,110,105,50,67,54,48,7,117,110,105,50,67,54,49,7,117,110,105,50,67,54,50,7,117,110,105,50, + 67,54,51,7,117,110,105,50,67,54,52,7,117,110,105,50,67,54,53,7,117,110,105,50,67,54,54,7,117,110,105,50,67,54,55,7,117,110,105,50, + 67,54,56,7,117,110,105,50,67,54,57,7,117,110,105,50,67,54,65,7,117,110,105,50,67,54,66,7,117,110,105,50,67,54,67,7,117,110,105,50, + 67,54,68,7,117,110,105,50,67,54,69,7,117,110,105,50,67,54,70,7,117,110,105,50,67,55,48,7,117,110,105,50,67,55,49,7,117,110,105,50, + 67,55,50,7,117,110,105,50,67,55,51,7,117,110,105,50,67,55,52,7,117,110,105,50,67,55,53,7,117,110,105,50,67,55,54,7,117,110,105,50, + 67,55,55,7,117,110,105,50,67,55,57,7,117,110,105,50,67,55,65,7,117,110,105,50,67,55,66,7,117,110,105,50,67,55,67,7,117,110,105,50, + 67,55,68,7,117,110,105,50,67,55,69,7,117,110,105,50,67,55,70,7,117,110,105,50,68,48,48,7,117,110,105,50,68,48,49,7,117,110,105,50, + 68,48,50,7,117,110,105,50,68,48,51,7,117,110,105,50,68,48,52,7,117,110,105,50,68,48,53,7,117,110,105,50,68,48,54,7,117,110,105,50, + 68,48,55,7,117,110,105,50,68,48,56,7,117,110,105,50,68,48,57,7,117,110,105,50,68,48,65,7,117,110,105,50,68,48,66,7,117,110,105,50, + 68,48,67,7,117,110,105,50,68,48,68,7,117,110,105,50,68,48,69,7,117,110,105,50,68,48,70,7,117,110,105,50,68,49,48,7,117,110,105,50, + 68,49,49,7,117,110,105,50,68,49,50,7,117,110,105,50,68,49,51,7,117,110,105,50,68,49,52,7,117,110,105,50,68,49,53,7,117,110,105,50, + 68,49,54,7,117,110,105,50,68,49,55,7,117,110,105,50,68,49,56,7,117,110,105,50,68,49,57,7,117,110,105,50,68,49,65,7,117,110,105,50, + 68,49,66,7,117,110,105,50,68,49,67,7,117,110,105,50,68,49,68,7,117,110,105,50,68,49,69,7,117,110,105,50,68,49,70,7,117,110,105,50, + 68,50,48,7,117,110,105,50,68,50,49,7,117,110,105,50,68,50,50,7,117,110,105,50,68,50,51,7,117,110,105,50,68,50,52,7,117,110,105,50, + 68,50,53,7,117,110,105,50,68,51,48,7,117,110,105,50,68,51,49,7,117,110,105,50,68,51,50,7,117,110,105,50,68,51,51,7,117,110,105,50, + 68,51,52,7,117,110,105,50,68,51,53,7,117,110,105,50,68,51,54,7,117,110,105,50,68,51,55,7,117,110,105,50,68,51,56,7,117,110,105,50, + 68,51,57,7,117,110,105,50,68,51,65,7,117,110,105,50,68,51,66,7,117,110,105,50,68,51,67,7,117,110,105,50,68,51,68,7,117,110,105,50, + 68,51,69,7,117,110,105,50,68,51,70,7,117,110,105,50,68,52,48,7,117,110,105,50,68,52,49,7,117,110,105,50,68,52,50,7,117,110,105,50, + 68,52,51,7,117,110,105,50,68,52,52,7,117,110,105,50,68,52,53,7,117,110,105,50,68,52,54,7,117,110,105,50,68,52,55,7,117,110,105,50, + 68,52,56,7,117,110,105,50,68,52,57,7,117,110,105,50,68,52,65,7,117,110,105,50,68,52,66,7,117,110,105,50,68,52,67,7,117,110,105,50, + 68,52,68,7,117,110,105,50,68,52,69,7,117,110,105,50,68,52,70,7,117,110,105,50,68,53,48,7,117,110,105,50,68,53,49,7,117,110,105,50, + 68,53,50,7,117,110,105,50,68,53,51,7,117,110,105,50,68,53,52,7,117,110,105,50,68,53,53,7,117,110,105,50,68,53,54,7,117,110,105,50, + 68,53,55,7,117,110,105,50,68,53,56,7,117,110,105,50,68,53,57,7,117,110,105,50,68,53,65,7,117,110,105,50,68,53,66,7,117,110,105,50, + 68,53,67,7,117,110,105,50,68,53,68,7,117,110,105,50,68,53,69,7,117,110,105,50,68,53,70,7,117,110,105,50,68,54,48,7,117,110,105,50, + 68,54,49,7,117,110,105,50,68,54,50,7,117,110,105,50,68,54,51,7,117,110,105,50,68,54,52,7,117,110,105,50,68,54,53,7,117,110,105,50, + 68,54,70,7,117,110,105,50,69,49,56,7,117,110,105,50,69,49,69,7,117,110,105,50,69,50,50,7,117,110,105,50,69,50,51,7,117,110,105,50, + 69,50,52,7,117,110,105,50,69,50,53,7,117,110,105,50,69,50,69,7,117,110,105,52,68,67,48,7,117,110,105,52,68,67,49,7,117,110,105,52, + 68,67,50,7,117,110,105,52,68,67,51,7,117,110,105,52,68,67,52,7,117,110,105,52,68,67,53,7,117,110,105,52,68,67,54,7,117,110,105,52, + 68,67,55,7,117,110,105,52,68,67,56,7,117,110,105,52,68,67,57,7,117,110,105,52,68,67,65,7,117,110,105,52,68,67,66,7,117,110,105,52, + 68,67,67,7,117,110,105,52,68,67,68,7,117,110,105,52,68,67,69,7,117,110,105,52,68,67,70,7,117,110,105,52,68,68,48,7,117,110,105,52, + 68,68,49,7,117,110,105,52,68,68,50,7,117,110,105,52,68,68,51,7,117,110,105,52,68,68,52,7,117,110,105,52,68,68,53,7,117,110,105,52, + 68,68,54,7,117,110,105,52,68,68,55,7,117,110,105,52,68,68,56,7,117,110,105,52,68,68,57,7,117,110,105,52,68,68,65,7,117,110,105,52, + 68,68,66,7,117,110,105,52,68,68,67,7,117,110,105,52,68,68,68,7,117,110,105,52,68,68,69,7,117,110,105,52,68,68,70,7,117,110,105,52, + 68,69,48,7,117,110,105,52,68,69,49,7,117,110,105,52,68,69,50,7,117,110,105,52,68,69,51,7,117,110,105,52,68,69,52,7,117,110,105,52, + 68,69,53,7,117,110,105,52,68,69,54,7,117,110,105,52,68,69,55,7,117,110,105,52,68,69,56,7,117,110,105,52,68,69,57,7,117,110,105,52, + 68,69,65,7,117,110,105,52,68,69,66,7,117,110,105,52,68,69,67,7,117,110,105,52,68,69,68,7,117,110,105,52,68,69,69,7,117,110,105,52, + 68,69,70,7,117,110,105,52,68,70,48,7,117,110,105,52,68,70,49,7,117,110,105,52,68,70,50,7,117,110,105,52,68,70,51,7,117,110,105,52, + 68,70,52,7,117,110,105,52,68,70,53,7,117,110,105,52,68,70,54,7,117,110,105,52,68,70,55,7,117,110,105,52,68,70,56,7,117,110,105,52, + 68,70,57,7,117,110,105,52,68,70,65,7,117,110,105,52,68,70,66,7,117,110,105,52,68,70,67,7,117,110,105,52,68,70,68,7,117,110,105,52, + 68,70,69,7,117,110,105,52,68,70,70,7,117,110,105,65,52,68,48,7,117,110,105,65,52,68,49,7,117,110,105,65,52,68,50,7,117,110,105,65, + 52,68,51,7,117,110,105,65,52,68,52,7,117,110,105,65,52,68,53,7,117,110,105,65,52,68,54,7,117,110,105,65,52,68,55,7,117,110,105,65, + 52,68,56,7,117,110,105,65,52,68,57,7,117,110,105,65,52,68,65,7,117,110,105,65,52,68,66,7,117,110,105,65,52,68,67,7,117,110,105,65, + 52,68,68,7,117,110,105,65,52,68,69,7,117,110,105,65,52,68,70,7,117,110,105,65,52,69,48,7,117,110,105,65,52,69,49,7,117,110,105,65, + 52,69,50,7,117,110,105,65,52,69,51,7,117,110,105,65,52,69,52,7,117,110,105,65,52,69,53,7,117,110,105,65,52,69,54,7,117,110,105,65, + 52,69,55,7,117,110,105,65,52,69,56,7,117,110,105,65,52,69,57,7,117,110,105,65,52,69,65,7,117,110,105,65,52,69,66,7,117,110,105,65, + 52,69,67,7,117,110,105,65,52,69,68,7,117,110,105,65,52,69,69,7,117,110,105,65,52,69,70,7,117,110,105,65,52,70,48,7,117,110,105,65, + 52,70,49,7,117,110,105,65,52,70,50,7,117,110,105,65,52,70,51,7,117,110,105,65,52,70,52,7,117,110,105,65,52,70,53,7,117,110,105,65, + 52,70,54,7,117,110,105,65,52,70,55,7,117,110,105,65,52,70,56,7,117,110,105,65,52,70,57,7,117,110,105,65,52,70,65,7,117,110,105,65, + 52,70,66,7,117,110,105,65,52,70,67,7,117,110,105,65,52,70,68,7,117,110,105,65,52,70,69,7,117,110,105,65,52,70,70,7,117,110,105,65, + 54,52,52,7,117,110,105,65,54,52,53,7,117,110,105,65,54,52,54,7,117,110,105,65,54,52,55,7,117,110,105,65,54,52,67,7,117,110,105,65, + 54,52,68,7,117,110,105,65,54,53,48,7,117,110,105,65,54,53,49,7,117,110,105,65,54,53,52,7,117,110,105,65,54,53,53,7,117,110,105,65, + 54,53,54,7,117,110,105,65,54,53,55,7,117,110,105,65,54,54,50,7,117,110,105,65,54,54,51,7,117,110,105,65,54,54,52,7,117,110,105,65, + 54,54,53,7,117,110,105,65,54,54,54,7,117,110,105,65,54,54,55,7,117,110,105,65,54,54,56,7,117,110,105,65,54,54,57,7,117,110,105,65, + 54,54,65,7,117,110,105,65,54,54,66,7,117,110,105,65,54,54,67,7,117,110,105,65,54,54,68,7,117,110,105,65,54,54,69,7,117,110,105,65, + 54,56,65,7,117,110,105,65,54,56,66,7,117,110,105,65,54,56,67,7,117,110,105,65,54,56,68,7,117,110,105,65,54,57,52,7,117,110,105,65, + 54,57,53,7,117,110,105,65,55,48,56,7,117,110,105,65,55,48,57,7,117,110,105,65,55,48,65,7,117,110,105,65,55,48,66,7,117,110,105,65, + 55,48,67,7,117,110,105,65,55,48,68,7,117,110,105,65,55,48,69,7,117,110,105,65,55,48,70,7,117,110,105,65,55,49,48,7,117,110,105,65, + 55,49,49,7,117,110,105,65,55,49,50,7,117,110,105,65,55,49,51,7,117,110,105,65,55,49,52,7,117,110,105,65,55,49,53,7,117,110,105,65, + 55,49,54,7,117,110,105,65,55,49,66,7,117,110,105,65,55,49,67,7,117,110,105,65,55,49,68,7,117,110,105,65,55,49,69,7,117,110,105,65, + 55,49,70,7,117,110,105,65,55,50,50,7,117,110,105,65,55,50,51,7,117,110,105,65,55,50,52,7,117,110,105,65,55,50,53,7,117,110,105,65, + 55,50,54,7,117,110,105,65,55,50,55,7,117,110,105,65,55,50,56,7,117,110,105,65,55,50,57,7,117,110,105,65,55,50,65,7,117,110,105,65, + 55,50,66,7,117,110,105,65,55,51,48,7,117,110,105,65,55,51,49,7,117,110,105,65,55,51,50,7,117,110,105,65,55,51,51,7,117,110,105,65, + 55,51,52,7,117,110,105,65,55,51,53,7,117,110,105,65,55,51,54,7,117,110,105,65,55,51,55,7,117,110,105,65,55,51,56,7,117,110,105,65, + 55,51,57,7,117,110,105,65,55,51,65,7,117,110,105,65,55,51,66,7,117,110,105,65,55,51,67,7,117,110,105,65,55,51,68,7,117,110,105,65, + 55,51,69,7,117,110,105,65,55,51,70,7,117,110,105,65,55,52,48,7,117,110,105,65,55,52,49,7,117,110,105,65,55,52,54,7,117,110,105,65, + 55,52,55,7,117,110,105,65,55,52,56,7,117,110,105,65,55,52,57,7,117,110,105,65,55,52,65,7,117,110,105,65,55,52,66,7,117,110,105,65, + 55,52,69,7,117,110,105,65,55,52,70,7,117,110,105,65,55,53,48,7,117,110,105,65,55,53,49,7,117,110,105,65,55,53,50,7,117,110,105,65, + 55,53,51,7,117,110,105,65,55,53,54,7,117,110,105,65,55,53,55,7,117,110,105,65,55,54,52,7,117,110,105,65,55,54,53,7,117,110,105,65, + 55,54,54,7,117,110,105,65,55,54,55,7,117,110,105,65,55,56,48,7,117,110,105,65,55,56,49,7,117,110,105,65,55,56,50,7,117,110,105,65, + 55,56,51,7,117,110,105,65,55,56,57,7,117,110,105,65,55,56,65,7,117,110,105,65,55,56,66,7,117,110,105,65,55,56,67,7,117,110,105,65, + 55,56,68,7,117,110,105,65,55,56,69,7,117,110,105,65,55,57,48,7,117,110,105,65,55,57,49,7,117,110,105,65,55,65,48,7,117,110,105,65, + 55,65,49,7,117,110,105,65,55,65,50,7,117,110,105,65,55,65,51,7,117,110,105,65,55,65,52,7,117,110,105,65,55,65,53,7,117,110,105,65, + 55,65,54,7,117,110,105,65,55,65,55,7,117,110,105,65,55,65,56,7,117,110,105,65,55,65,57,7,117,110,105,65,55,65,65,7,117,110,105,65, + 55,70,65,7,117,110,105,65,55,70,66,7,117,110,105,65,55,70,67,7,117,110,105,65,55,70,68,7,117,110,105,65,55,70,69,7,117,110,105,65, + 55,70,70,9,117,110,105,48,50,69,53,46,53,9,117,110,105,48,50,69,54,46,53,9,117,110,105,48,50,69,55,46,53,9,117,110,105,48,50,69, + 56,46,53,9,117,110,105,48,50,69,57,46,53,9,117,110,105,48,50,69,53,46,52,9,117,110,105,48,50,69,54,46,52,9,117,110,105,48,50,69, + 55,46,52,9,117,110,105,48,50,69,56,46,52,9,117,110,105,48,50,69,57,46,52,9,117,110,105,48,50,69,53,46,51,9,117,110,105,48,50,69, + 54,46,51,9,117,110,105,48,50,69,55,46,51,9,117,110,105,48,50,69,56,46,51,9,117,110,105,48,50,69,57,46,51,9,117,110,105,48,50,69, + 53,46,50,9,117,110,105,48,50,69,54,46,50,9,117,110,105,48,50,69,55,46,50,9,117,110,105,48,50,69,56,46,50,9,117,110,105,48,50,69, + 57,46,50,9,117,110,105,48,50,69,53,46,49,9,117,110,105,48,50,69,54,46,49,9,117,110,105,48,50,69,55,46,49,9,117,110,105,48,50,69, + 56,46,49,9,117,110,105,48,50,69,57,46,49,4,115,116,101,109,7,117,110,105,70,48,48,48,7,117,110,105,70,48,48,49,7,117,110,105,70,48, + 48,50,7,117,110,105,70,48,48,51,7,117,110,105,70,52,48,48,7,117,110,105,70,52,48,49,7,117,110,105,70,52,48,50,7,117,110,105,70,52, + 48,51,7,117,110,105,70,52,48,52,7,117,110,105,70,52,48,53,7,117,110,105,70,52,48,54,7,117,110,105,70,52,48,55,7,117,110,105,70,52, + 48,56,7,117,110,105,70,52,48,57,7,117,110,105,70,52,48,65,7,117,110,105,70,52,48,66,7,117,110,105,70,52,48,67,7,117,110,105,70,52, + 48,68,7,117,110,105,70,52,48,69,7,117,110,105,70,52,48,70,7,117,110,105,70,52,49,48,7,117,110,105,70,52,49,49,7,117,110,105,70,52, + 49,50,7,117,110,105,70,52,49,51,7,117,110,105,70,52,49,52,7,117,110,105,70,52,49,53,7,117,110,105,70,52,49,54,7,117,110,105,70,52, + 49,55,7,117,110,105,70,52,49,56,7,117,110,105,70,52,49,57,7,117,110,105,70,52,49,65,7,117,110,105,70,52,49,66,7,117,110,105,70,52, + 49,67,7,117,110,105,70,52,49,68,7,117,110,105,70,52,49,69,7,117,110,105,70,52,49,70,7,117,110,105,70,52,50,48,7,117,110,105,70,52, + 50,49,7,117,110,105,70,52,50,50,7,117,110,105,70,52,50,51,7,117,110,105,70,52,50,52,7,117,110,105,70,52,50,53,7,117,110,105,70,52, + 50,54,7,117,110,105,70,52,50,56,7,117,110,105,70,52,50,57,7,117,110,105,70,52,50,65,7,117,110,105,70,52,50,66,7,117,110,105,70,52, + 50,67,7,117,110,105,70,52,50,68,7,117,110,105,70,52,50,69,7,117,110,105,70,52,50,70,7,117,110,105,70,52,51,48,7,117,110,105,70,52, + 51,49,7,117,110,105,70,52,51,50,7,117,110,105,70,52,51,51,7,117,110,105,70,52,51,52,7,117,110,105,70,52,51,53,7,117,110,105,70,52, + 51,54,7,117,110,105,70,52,51,55,7,117,110,105,70,52,51,56,7,117,110,105,70,52,51,57,7,117,110,105,70,52,51,65,7,117,110,105,70,52, + 51,66,7,117,110,105,70,52,51,67,7,117,110,105,70,52,51,68,7,117,110,105,70,52,51,69,7,117,110,105,70,52,51,70,7,117,110,105,70,52, + 52,48,7,117,110,105,70,52,52,49,7,117,110,105,70,54,67,53,7,117,110,105,70,66,48,48,7,117,110,105,70,66,48,51,7,117,110,105,70,66, + 48,52,7,117,110,105,70,66,48,53,7,117,110,105,70,66,48,54,7,117,110,105,70,66,49,51,7,117,110,105,70,66,49,52,7,117,110,105,70,66, + 49,53,7,117,110,105,70,66,49,54,7,117,110,105,70,66,49,55,7,117,110,105,70,66,49,68,7,117,110,105,70,66,49,69,7,117,110,105,70,66, + 49,70,7,117,110,105,70,66,50,48,7,117,110,105,70,66,50,49,7,117,110,105,70,66,50,50,7,117,110,105,70,66,50,51,7,117,110,105,70,66, + 50,52,7,117,110,105,70,66,50,53,7,117,110,105,70,66,50,54,7,117,110,105,70,66,50,55,7,117,110,105,70,66,50,56,7,117,110,105,70,66, + 50,57,7,117,110,105,70,66,50,65,7,117,110,105,70,66,50,66,7,117,110,105,70,66,50,67,7,117,110,105,70,66,50,68,7,117,110,105,70,66, + 50,69,7,117,110,105,70,66,50,70,7,117,110,105,70,66,51,48,7,117,110,105,70,66,51,49,7,117,110,105,70,66,51,50,7,117,110,105,70,66, + 51,51,7,117,110,105,70,66,51,52,7,117,110,105,70,66,51,53,7,117,110,105,70,66,51,54,7,117,110,105,70,66,51,56,7,117,110,105,70,66, + 51,57,7,117,110,105,70,66,51,65,7,117,110,105,70,66,51,66,7,117,110,105,70,66,51,67,7,117,110,105,70,66,51,69,7,117,110,105,70,66, + 52,48,7,117,110,105,70,66,52,49,7,117,110,105,70,66,52,51,7,117,110,105,70,66,52,52,7,117,110,105,70,66,52,54,7,117,110,105,70,66, + 52,55,7,117,110,105,70,66,52,56,7,117,110,105,70,66,52,57,7,117,110,105,70,66,52,65,7,117,110,105,70,66,52,66,7,117,110,105,70,66, + 52,67,7,117,110,105,70,66,52,68,7,117,110,105,70,66,52,69,7,117,110,105,70,66,52,70,7,117,110,105,70,66,53,50,7,117,110,105,70,66, + 53,51,7,117,110,105,70,66,53,52,7,117,110,105,70,66,53,53,7,117,110,105,70,66,53,54,7,117,110,105,70,66,53,55,7,117,110,105,70,66, + 53,56,7,117,110,105,70,66,53,57,7,117,110,105,70,66,53,65,7,117,110,105,70,66,53,66,7,117,110,105,70,66,53,67,7,117,110,105,70,66, + 53,68,7,117,110,105,70,66,53,69,7,117,110,105,70,66,53,70,7,117,110,105,70,66,54,48,7,117,110,105,70,66,54,49,7,117,110,105,70,66, + 54,50,7,117,110,105,70,66,54,51,7,117,110,105,70,66,54,52,7,117,110,105,70,66,54,53,7,117,110,105,70,66,54,54,7,117,110,105,70,66, + 54,55,7,117,110,105,70,66,54,56,7,117,110,105,70,66,54,57,7,117,110,105,70,66,54,65,7,117,110,105,70,66,54,66,7,117,110,105,70,66, + 54,67,7,117,110,105,70,66,54,68,7,117,110,105,70,66,54,69,7,117,110,105,70,66,54,70,7,117,110,105,70,66,55,48,7,117,110,105,70,66, + 55,49,7,117,110,105,70,66,55,50,7,117,110,105,70,66,55,51,7,117,110,105,70,66,55,52,7,117,110,105,70,66,55,53,7,117,110,105,70,66, + 55,54,7,117,110,105,70,66,55,55,7,117,110,105,70,66,55,56,7,117,110,105,70,66,55,57,7,117,110,105,70,66,55,65,7,117,110,105,70,66, + 55,66,7,117,110,105,70,66,55,67,7,117,110,105,70,66,55,68,7,117,110,105,70,66,55,69,7,117,110,105,70,66,55,70,7,117,110,105,70,66, + 56,48,7,117,110,105,70,66,56,49,7,117,110,105,70,66,56,50,7,117,110,105,70,66,56,51,7,117,110,105,70,66,56,52,7,117,110,105,70,66, + 56,53,7,117,110,105,70,66,56,54,7,117,110,105,70,66,56,55,7,117,110,105,70,66,56,56,7,117,110,105,70,66,56,57,7,117,110,105,70,66, + 56,65,7,117,110,105,70,66,56,66,7,117,110,105,70,66,56,67,7,117,110,105,70,66,56,68,7,117,110,105,70,66,56,69,7,117,110,105,70,66, + 56,70,7,117,110,105,70,66,57,48,7,117,110,105,70,66,57,49,7,117,110,105,70,66,57,50,7,117,110,105,70,66,57,51,7,117,110,105,70,66, + 57,52,7,117,110,105,70,66,57,53,7,117,110,105,70,66,57,54,7,117,110,105,70,66,57,55,7,117,110,105,70,66,57,56,7,117,110,105,70,66, + 57,57,7,117,110,105,70,66,57,65,7,117,110,105,70,66,57,66,7,117,110,105,70,66,57,67,7,117,110,105,70,66,57,68,7,117,110,105,70,66, + 57,69,7,117,110,105,70,66,57,70,7,117,110,105,70,66,65,48,7,117,110,105,70,66,65,49,7,117,110,105,70,66,65,50,7,117,110,105,70,66, + 65,51,7,117,110,105,70,66,65,65,7,117,110,105,70,66,65,66,7,117,110,105,70,66,65,67,7,117,110,105,70,66,65,68,7,117,110,105,70,66, + 68,51,7,117,110,105,70,66,68,52,7,117,110,105,70,66,68,53,7,117,110,105,70,66,68,54,7,117,110,105,70,66,68,57,7,117,110,105,70,66, + 68,65,7,117,110,105,70,66,69,56,7,117,110,105,70,66,69,57,7,117,110,105,70,66,70,67,7,117,110,105,70,66,70,68,7,117,110,105,70,66, + 70,69,7,117,110,105,70,66,70,70,7,117,110,105,70,69,48,48,7,117,110,105,70,69,48,49,7,117,110,105,70,69,48,50,7,117,110,105,70,69, + 48,51,7,117,110,105,70,69,48,52,7,117,110,105,70,69,48,53,7,117,110,105,70,69,48,54,7,117,110,105,70,69,48,55,7,117,110,105,70,69, + 48,56,7,117,110,105,70,69,48,57,7,117,110,105,70,69,48,65,7,117,110,105,70,69,48,66,7,117,110,105,70,69,48,67,7,117,110,105,70,69, + 48,68,7,117,110,105,70,69,48,69,7,117,110,105,70,69,48,70,7,117,110,105,70,69,50,48,7,117,110,105,70,69,50,49,7,117,110,105,70,69, + 50,50,7,117,110,105,70,69,50,51,7,117,110,105,70,69,55,48,7,117,110,105,70,69,55,49,7,117,110,105,70,69,55,50,7,117,110,105,70,69, + 55,51,7,117,110,105,70,69,55,52,7,117,110,105,70,69,55,54,7,117,110,105,70,69,55,55,7,117,110,105,70,69,55,56,7,117,110,105,70,69, + 55,57,7,117,110,105,70,69,55,65,7,117,110,105,70,69,55,66,7,117,110,105,70,69,55,67,7,117,110,105,70,69,55,68,7,117,110,105,70,69, + 55,69,7,117,110,105,70,69,55,70,7,117,110,105,70,69,56,48,7,117,110,105,70,69,56,49,7,117,110,105,70,69,56,50,7,117,110,105,70,69, + 56,51,7,117,110,105,70,69,56,52,7,117,110,105,70,69,56,53,7,117,110,105,70,69,56,54,7,117,110,105,70,69,56,55,7,117,110,105,70,69, + 56,56,7,117,110,105,70,69,56,57,7,117,110,105,70,69,56,65,7,117,110,105,70,69,56,66,7,117,110,105,70,69,56,67,7,117,110,105,70,69, + 56,68,7,117,110,105,70,69,56,69,7,117,110,105,70,69,56,70,7,117,110,105,70,69,57,48,7,117,110,105,70,69,57,49,7,117,110,105,70,69, + 57,50,7,117,110,105,70,69,57,51,7,117,110,105,70,69,57,52,7,117,110,105,70,69,57,53,7,117,110,105,70,69,57,54,7,117,110,105,70,69, + 57,55,7,117,110,105,70,69,57,56,7,117,110,105,70,69,57,57,7,117,110,105,70,69,57,65,7,117,110,105,70,69,57,66,7,117,110,105,70,69, + 57,67,7,117,110,105,70,69,57,68,7,117,110,105,70,69,57,69,7,117,110,105,70,69,57,70,7,117,110,105,70,69,65,48,7,117,110,105,70,69, + 65,49,7,117,110,105,70,69,65,50,7,117,110,105,70,69,65,51,7,117,110,105,70,69,65,52,7,117,110,105,70,69,65,53,7,117,110,105,70,69, + 65,54,7,117,110,105,70,69,65,55,7,117,110,105,70,69,65,56,7,117,110,105,70,69,65,57,7,117,110,105,70,69,65,65,7,117,110,105,70,69, + 65,66,7,117,110,105,70,69,65,67,7,117,110,105,70,69,65,68,7,117,110,105,70,69,65,69,7,117,110,105,70,69,65,70,7,117,110,105,70,69, + 66,48,7,117,110,105,70,69,66,49,7,117,110,105,70,69,66,50,7,117,110,105,70,69,66,51,7,117,110,105,70,69,66,52,7,117,110,105,70,69, + 66,53,7,117,110,105,70,69,66,54,7,117,110,105,70,69,66,55,7,117,110,105,70,69,66,56,7,117,110,105,70,69,66,57,7,117,110,105,70,69, + 66,65,7,117,110,105,70,69,66,66,7,117,110,105,70,69,66,67,7,117,110,105,70,69,66,68,7,117,110,105,70,69,66,69,7,117,110,105,70,69, + 66,70,7,117,110,105,70,69,67,48,7,117,110,105,70,69,67,49,7,117,110,105,70,69,67,50,7,117,110,105,70,69,67,51,7,117,110,105,70,69, + 67,52,7,117,110,105,70,69,67,53,7,117,110,105,70,69,67,54,7,117,110,105,70,69,67,55,7,117,110,105,70,69,67,56,7,117,110,105,70,69, + 67,57,7,117,110,105,70,69,67,65,7,117,110,105,70,69,67,66,7,117,110,105,70,69,67,67,7,117,110,105,70,69,67,68,7,117,110,105,70,69, + 67,69,7,117,110,105,70,69,67,70,7,117,110,105,70,69,68,48,7,117,110,105,70,69,68,49,7,117,110,105,70,69,68,50,7,117,110,105,70,69, + 68,51,7,117,110,105,70,69,68,52,7,117,110,105,70,69,68,53,7,117,110,105,70,69,68,54,7,117,110,105,70,69,68,55,7,117,110,105,70,69, + 68,56,7,117,110,105,70,69,68,57,7,117,110,105,70,69,68,65,7,117,110,105,70,69,68,66,7,117,110,105,70,69,68,67,7,117,110,105,70,69, + 68,68,7,117,110,105,70,69,68,69,7,117,110,105,70,69,68,70,7,117,110,105,70,69,69,48,7,117,110,105,70,69,69,49,7,117,110,105,70,69, + 69,50,7,117,110,105,70,69,69,51,7,117,110,105,70,69,69,52,7,117,110,105,70,69,69,53,7,117,110,105,70,69,69,54,7,117,110,105,70,69, + 69,55,7,117,110,105,70,69,69,56,7,117,110,105,70,69,69,57,7,117,110,105,70,69,69,65,7,117,110,105,70,69,69,66,7,117,110,105,70,69, + 69,67,7,117,110,105,70,69,69,68,7,117,110,105,70,69,69,69,7,117,110,105,70,69,69,70,7,117,110,105,70,69,70,48,7,117,110,105,70,69, + 70,49,7,117,110,105,70,69,70,50,7,117,110,105,70,69,70,51,7,117,110,105,70,69,70,52,7,117,110,105,70,69,70,53,7,117,110,105,70,69, + 70,54,7,117,110,105,70,69,70,55,7,117,110,105,70,69,70,56,7,117,110,105,70,69,70,57,7,117,110,105,70,69,70,65,7,117,110,105,70,69, + 70,66,7,117,110,105,70,69,70,67,7,117,110,105,70,69,70,70,7,117,110,105,70,70,70,57,7,117,110,105,70,70,70,65,7,117,110,105,70,70, + 70,66,7,117,110,105,70,70,70,67,7,117,110,105,70,70,70,68,6,117,49,48,51,48,48,6,117,49,48,51,48,49,6,117,49,48,51,48,50,6, + 117,49,48,51,48,51,6,117,49,48,51,48,52,6,117,49,48,51,48,53,6,117,49,48,51,48,54,6,117,49,48,51,48,55,6,117,49,48,51,48, + 56,6,117,49,48,51,48,57,6,117,49,48,51,48,65,6,117,49,48,51,48,66,6,117,49,48,51,48,67,6,117,49,48,51,48,68,6,117,49,48, + 51,48,69,6,117,49,48,51,48,70,6,117,49,48,51,49,48,6,117,49,48,51,49,49,6,117,49,48,51,49,50,6,117,49,48,51,49,51,6,117, + 49,48,51,49,52,6,117,49,48,51,49,53,6,117,49,48,51,49,54,6,117,49,48,51,49,55,6,117,49,48,51,49,56,6,117,49,48,51,49,57, + 6,117,49,48,51,49,65,6,117,49,48,51,49,66,6,117,49,48,51,49,67,6,117,49,48,51,49,68,6,117,49,48,51,49,69,6,117,49,48,51, + 50,48,6,117,49,48,51,50,49,6,117,49,48,51,50,50,6,117,49,48,51,50,51,6,117,49,68,51,48,48,6,117,49,68,51,48,49,6,117,49, + 68,51,48,50,6,117,49,68,51,48,51,6,117,49,68,51,48,52,6,117,49,68,51,48,53,6,117,49,68,51,48,54,6,117,49,68,51,48,55,6, + 117,49,68,51,48,56,6,117,49,68,51,48,57,6,117,49,68,51,48,65,6,117,49,68,51,48,66,6,117,49,68,51,48,67,6,117,49,68,51,48, + 68,6,117,49,68,51,48,69,6,117,49,68,51,48,70,6,117,49,68,51,49,48,6,117,49,68,51,49,49,6,117,49,68,51,49,50,6,117,49,68, + 51,49,51,6,117,49,68,51,49,52,6,117,49,68,51,49,53,6,117,49,68,51,49,54,6,117,49,68,51,49,55,6,117,49,68,51,49,56,6,117, + 49,68,51,49,57,6,117,49,68,51,49,65,6,117,49,68,51,49,66,6,117,49,68,51,49,67,6,117,49,68,51,49,68,6,117,49,68,51,49,69, + 6,117,49,68,51,49,70,6,117,49,68,51,50,48,6,117,49,68,51,50,49,6,117,49,68,51,50,50,6,117,49,68,51,50,51,6,117,49,68,51, + 50,52,6,117,49,68,51,50,53,6,117,49,68,51,50,54,6,117,49,68,51,50,55,6,117,49,68,51,50,56,6,117,49,68,51,50,57,6,117,49, + 68,51,50,65,6,117,49,68,51,50,66,6,117,49,68,51,50,67,6,117,49,68,51,50,68,6,117,49,68,51,50,69,6,117,49,68,51,50,70,6, + 117,49,68,51,51,48,6,117,49,68,51,51,49,6,117,49,68,51,51,50,6,117,49,68,51,51,51,6,117,49,68,51,51,52,6,117,49,68,51,51, + 53,6,117,49,68,51,51,54,6,117,49,68,51,51,55,6,117,49,68,51,51,56,6,117,49,68,51,51,57,6,117,49,68,51,51,65,6,117,49,68, + 51,51,66,6,117,49,68,51,51,67,6,117,49,68,51,51,68,6,117,49,68,51,51,69,6,117,49,68,51,51,70,6,117,49,68,51,52,48,6,117, + 49,68,51,52,49,6,117,49,68,51,52,50,6,117,49,68,51,52,51,6,117,49,68,51,52,52,6,117,49,68,51,52,53,6,117,49,68,51,52,54, + 6,117,49,68,51,52,55,6,117,49,68,51,52,56,6,117,49,68,51,52,57,6,117,49,68,51,52,65,6,117,49,68,51,52,66,6,117,49,68,51, + 52,67,6,117,49,68,51,52,68,6,117,49,68,51,52,69,6,117,49,68,51,52,70,6,117,49,68,51,53,48,6,117,49,68,51,53,49,6,117,49, + 68,51,53,50,6,117,49,68,51,53,51,6,117,49,68,51,53,52,6,117,49,68,51,53,53,6,117,49,68,51,53,54,6,117,49,68,53,51,56,6, + 117,49,68,53,51,57,6,117,49,68,53,51,66,6,117,49,68,53,51,67,6,117,49,68,53,51,68,6,117,49,68,53,51,69,6,117,49,68,53,52, + 48,6,117,49,68,53,52,49,6,117,49,68,53,52,50,6,117,49,68,53,52,51,6,117,49,68,53,52,52,6,117,49,68,53,52,54,6,117,49,68, + 53,52,65,6,117,49,68,53,52,66,6,117,49,68,53,52,67,6,117,49,68,53,52,68,6,117,49,68,53,52,69,6,117,49,68,53,52,70,6,117, + 49,68,53,53,48,6,117,49,68,53,53,50,6,117,49,68,53,53,51,6,117,49,68,53,53,52,6,117,49,68,53,53,53,6,117,49,68,53,53,54, + 6,117,49,68,53,53,55,6,117,49,68,53,53,56,6,117,49,68,53,53,57,6,117,49,68,53,53,65,6,117,49,68,53,53,66,6,117,49,68,53, + 53,67,6,117,49,68,53,53,68,6,117,49,68,53,53,69,6,117,49,68,53,53,70,6,117,49,68,53,54,48,6,117,49,68,53,54,49,6,117,49, + 68,53,54,50,6,117,49,68,53,54,51,6,117,49,68,53,54,52,6,117,49,68,53,54,53,6,117,49,68,53,54,54,6,117,49,68,53,54,55,6, + 117,49,68,53,54,56,6,117,49,68,53,54,57,6,117,49,68,53,54,65,6,117,49,68,53,54,66,6,117,49,68,53,65,48,6,117,49,68,53,65, + 49,6,117,49,68,53,65,50,6,117,49,68,53,65,51,6,117,49,68,53,65,52,6,117,49,68,53,65,53,6,117,49,68,53,65,54,6,117,49,68, + 53,65,55,6,117,49,68,53,65,56,6,117,49,68,53,65,57,6,117,49,68,53,65,65,6,117,49,68,53,65,66,6,117,49,68,53,65,67,6,117, + 49,68,53,65,68,6,117,49,68,53,65,69,6,117,49,68,53,65,70,6,117,49,68,53,66,48,6,117,49,68,53,66,49,6,117,49,68,53,66,50, + 6,117,49,68,53,66,51,6,117,49,68,53,66,52,6,117,49,68,53,66,53,6,117,49,68,53,66,54,6,117,49,68,53,66,55,6,117,49,68,53, + 66,56,6,117,49,68,53,66,57,6,117,49,68,53,66,65,6,117,49,68,53,66,66,6,117,49,68,53,66,67,6,117,49,68,53,66,68,6,117,49, + 68,53,66,69,6,117,49,68,53,66,70,6,117,49,68,53,67,48,6,117,49,68,53,67,49,6,117,49,68,53,67,50,6,117,49,68,53,67,51,6, + 117,49,68,53,67,52,6,117,49,68,53,67,53,6,117,49,68,53,67,54,6,117,49,68,53,67,55,6,117,49,68,53,67,56,6,117,49,68,53,67, + 57,6,117,49,68,53,67,65,6,117,49,68,53,67,66,6,117,49,68,53,67,67,6,117,49,68,53,67,68,6,117,49,68,53,67,69,6,117,49,68, + 53,67,70,6,117,49,68,53,68,48,6,117,49,68,53,68,49,6,117,49,68,53,68,50,6,117,49,68,53,68,51,6,117,49,68,55,68,56,6,117, + 49,68,55,68,57,6,117,49,68,55,68,65,6,117,49,68,55,68,66,6,117,49,68,55,68,67,6,117,49,68,55,68,68,6,117,49,68,55,68,69, + 6,117,49,68,55,68,70,6,117,49,68,55,69,48,6,117,49,68,55,69,49,6,117,49,68,55,69,50,6,117,49,68,55,69,51,6,117,49,68,55, + 69,52,6,117,49,68,55,69,53,6,117,49,68,55,69,54,6,117,49,68,55,69,55,6,117,49,68,55,69,56,6,117,49,68,55,69,57,6,117,49, + 68,55,69,65,6,117,49,68,55,69,66,6,117,49,70,48,51,48,6,117,49,70,48,51,49,6,117,49,70,48,51,50,6,117,49,70,48,51,51,6, + 117,49,70,48,51,52,6,117,49,70,48,51,53,6,117,49,70,48,51,54,6,117,49,70,48,51,55,6,117,49,70,48,51,56,6,117,49,70,48,51, + 57,6,117,49,70,48,51,65,6,117,49,70,48,51,66,6,117,49,70,48,51,67,6,117,49,70,48,51,68,6,117,49,70,48,51,69,6,117,49,70, + 48,51,70,6,117,49,70,48,52,48,6,117,49,70,48,52,49,6,117,49,70,48,52,50,6,117,49,70,48,52,51,6,117,49,70,48,52,52,6,117, + 49,70,48,52,53,6,117,49,70,48,52,54,6,117,49,70,48,52,55,6,117,49,70,48,52,56,6,117,49,70,48,52,57,6,117,49,70,48,52,65, + 6,117,49,70,48,52,66,6,117,49,70,48,52,67,6,117,49,70,48,52,68,6,117,49,70,48,52,69,6,117,49,70,48,52,70,6,117,49,70,48, + 53,48,6,117,49,70,48,53,49,6,117,49,70,48,53,50,6,117,49,70,48,53,51,6,117,49,70,48,53,52,6,117,49,70,48,53,53,6,117,49, + 70,48,53,54,6,117,49,70,48,53,55,6,117,49,70,48,53,56,6,117,49,70,48,53,57,6,117,49,70,48,53,65,6,117,49,70,48,53,66,6, + 117,49,70,48,53,67,6,117,49,70,48,53,68,6,117,49,70,48,53,69,6,117,49,70,48,53,70,6,117,49,70,48,54,48,6,117,49,70,48,54, + 49,6,117,49,70,48,54,50,6,117,49,70,48,54,51,6,117,49,70,48,54,52,6,117,49,70,48,54,53,6,117,49,70,48,54,54,6,117,49,70, + 48,54,55,6,117,49,70,48,54,56,6,117,49,70,48,54,57,6,117,49,70,48,54,65,6,117,49,70,48,54,66,6,117,49,70,48,54,67,6,117, + 49,70,48,54,68,6,117,49,70,48,54,69,6,117,49,70,48,54,70,6,117,49,70,48,55,48,6,117,49,70,48,55,49,6,117,49,70,48,55,50, + 6,117,49,70,48,55,51,6,117,49,70,48,55,52,6,117,49,70,48,55,53,6,117,49,70,48,55,54,6,117,49,70,48,55,55,6,117,49,70,48, + 55,56,6,117,49,70,48,55,57,6,117,49,70,48,55,65,6,117,49,70,48,55,66,6,117,49,70,48,55,67,6,117,49,70,48,55,68,6,117,49, + 70,48,55,69,6,117,49,70,48,55,70,6,117,49,70,48,56,48,6,117,49,70,48,56,49,6,117,49,70,48,56,50,6,117,49,70,48,56,51,6, + 117,49,70,48,56,52,6,117,49,70,48,56,53,6,117,49,70,48,56,54,6,117,49,70,48,56,55,6,117,49,70,48,56,56,6,117,49,70,48,56, + 57,6,117,49,70,48,56,65,6,117,49,70,48,56,66,6,117,49,70,48,56,67,6,117,49,70,48,56,68,6,117,49,70,48,56,69,6,117,49,70, + 48,56,70,6,117,49,70,48,57,48,6,117,49,70,48,57,49,6,117,49,70,48,57,50,6,117,49,70,48,57,51,6,117,49,70,48,65,48,6,117, + 49,70,48,65,49,6,117,49,70,48,65,50,6,117,49,70,48,65,51,6,117,49,70,48,65,52,6,117,49,70,48,65,53,6,117,49,70,48,65,54, + 6,117,49,70,48,65,55,6,117,49,70,48,65,56,6,117,49,70,48,65,57,6,117,49,70,48,65,65,6,117,49,70,48,65,66,6,117,49,70,48, + 65,67,6,117,49,70,48,65,68,6,117,49,70,48,65,69,6,117,49,70,48,66,49,6,117,49,70,48,66,50,6,117,49,70,48,66,51,6,117,49, + 70,48,66,52,6,117,49,70,48,66,53,6,117,49,70,48,66,54,6,117,49,70,48,66,55,6,117,49,70,48,66,56,6,117,49,70,48,66,57,6, + 117,49,70,48,66,65,6,117,49,70,48,66,66,6,117,49,70,48,66,67,6,117,49,70,48,66,68,6,117,49,70,48,66,69,6,117,49,70,48,67, + 49,6,117,49,70,48,67,50,6,117,49,70,48,67,51,6,117,49,70,48,67,52,6,117,49,70,48,67,53,6,117,49,70,48,67,54,6,117,49,70, + 48,67,55,6,117,49,70,48,67,56,6,117,49,70,48,67,57,6,117,49,70,48,67,65,6,117,49,70,48,67,66,6,117,49,70,48,67,67,6,117, + 49,70,48,67,68,6,117,49,70,48,67,69,6,117,49,70,48,67,70,6,117,49,70,48,68,49,6,117,49,70,48,68,50,6,117,49,70,48,68,51, + 6,117,49,70,48,68,52,6,117,49,70,48,68,53,6,117,49,70,48,68,54,6,117,49,70,48,68,55,6,117,49,70,48,68,56,6,117,49,70,48, + 68,57,6,117,49,70,48,68,65,6,117,49,70,48,68,66,6,117,49,70,48,68,67,6,117,49,70,48,68,68,6,117,49,70,48,68,69,6,117,49, + 70,48,68,70,6,117,49,70,52,50,68,6,117,49,70,52,50,69,6,117,49,70,52,51,49,6,117,49,70,52,51,53,6,117,49,70,54,48,48,6, + 117,49,70,54,48,49,6,117,49,70,54,48,50,6,117,49,70,54,48,51,6,117,49,70,54,48,52,6,117,49,70,54,48,53,6,117,49,70,54,48, + 54,6,117,49,70,54,48,55,6,117,49,70,54,48,56,6,117,49,70,54,48,57,6,117,49,70,54,48,65,6,117,49,70,54,48,66,6,117,49,70, + 54,48,67,6,117,49,70,54,48,68,6,117,49,70,54,48,69,6,117,49,70,54,48,70,6,117,49,70,54,49,48,6,117,49,70,54,49,49,6,117, + 49,70,54,49,50,6,117,49,70,54,49,51,6,117,49,70,54,49,52,6,117,49,70,54,49,53,6,117,49,70,54,49,54,6,117,49,70,54,49,55, + 6,117,49,70,54,49,56,6,117,49,70,54,49,57,6,117,49,70,54,49,65,6,117,49,70,54,49,66,6,117,49,70,54,49,67,6,117,49,70,54, + 49,68,6,117,49,70,54,49,69,6,117,49,70,54,49,70,6,117,49,70,54,50,48,6,117,49,70,54,50,49,6,117,49,70,54,50,50,6,117,49, + 70,54,50,51,6,117,49,70,54,50,53,6,117,49,70,54,50,54,6,117,49,70,54,50,55,6,117,49,70,54,50,56,6,117,49,70,54,50,57,6, + 117,49,70,54,50,65,6,117,49,70,54,50,66,6,117,49,70,54,50,68,6,117,49,70,54,50,69,6,117,49,70,54,50,70,6,117,49,70,54,51, + 48,6,117,49,70,54,51,49,6,117,49,70,54,51,50,6,117,49,70,54,51,51,6,117,49,70,54,51,52,6,117,49,70,54,51,53,6,117,49,70, + 54,51,54,6,117,49,70,54,51,55,6,117,49,70,54,51,56,6,117,49,70,54,51,57,6,117,49,70,54,51,65,6,117,49,70,54,51,66,6,117, + 49,70,54,51,67,6,117,49,70,54,51,68,6,117,49,70,54,51,69,6,117,49,70,54,51,70,6,117,49,70,54,52,48,9,100,108,76,116,99,97, + 114,111,110,8,68,105,101,114,101,115,105,115,5,65,99,117,116,101,5,84,105,108,100,101,5,71,114,97,118,101,10,67,105,114,99,117,109,102,108,101, + 120,5,67,97,114,111,110,12,117,110,105,48,51,49,49,46,99,97,115,101,5,66,114,101,118,101,9,68,111,116,97,99,99,101,110,116,12,72,117,110, + 103,97,114,117,109,108,97,117,116,11,68,111,117,98,108,101,103,114,97,118,101,10,97,114,97,98,105,99,95,100,111,116,12,97,114,97,98,105,99,95, + 50,100,111,116,115,12,97,114,97,98,105,99,95,51,100,111,116,115,14,97,114,97,98,105,99,95,51,100,111,116,115,95,97,14,97,114,97,98,105,99, + 95,50,100,111,116,115,95,97,12,97,114,97,98,105,99,95,52,100,111,116,115,12,117,110,105,48,54,54,69,46,102,105,110,97,12,117,110,105,48,54, + 54,69,46,105,110,105,116,12,117,110,105,48,54,54,69,46,109,101,100,105,12,117,110,105,48,54,65,49,46,102,105,110,97,12,117,110,105,48,54,65, + 49,46,105,110,105,116,12,117,110,105,48,54,65,49,46,109,101,100,105,12,117,110,105,48,54,54,70,46,102,105,110,97,12,117,110,105,48,54,54,70, + 46,105,110,105,116,12,117,110,105,48,54,54,70,46,109,101,100,105,12,117,110,105,48,54,66,65,46,105,110,105,116,12,117,110,105,48,54,66,65,46, + 109,101,100,105,11,97,114,97,98,105,99,95,114,105,110,103,12,117,110,105,48,54,55,67,46,102,105,110,97,12,117,110,105,48,54,55,67,46,105,110, + 105,116,12,117,110,105,48,54,55,67,46,109,101,100,105,12,117,110,105,48,54,55,68,46,102,105,110,97,12,117,110,105,48,54,55,68,46,105,110,105, + 116,12,117,110,105,48,54,55,68,46,109,101,100,105,12,117,110,105,48,54,56,49,46,102,105,110,97,12,117,110,105,48,54,56,49,46,105,110,105,116, + 12,117,110,105,48,54,56,49,46,109,101,100,105,12,117,110,105,48,54,56,50,46,102,105,110,97,12,117,110,105,48,54,56,50,46,105,110,105,116,12, + 117,110,105,48,54,56,50,46,109,101,100,105,12,117,110,105,48,54,56,53,46,102,105,110,97,12,117,110,105,48,54,56,53,46,105,110,105,116,12,117, + 110,105,48,54,56,53,46,109,101,100,105,12,117,110,105,48,54,66,70,46,102,105,110,97,12,117,110,105,48,54,66,70,46,105,110,105,116,12,117,110, + 105,48,54,66,70,46,109,101,100,105,14,97,114,97,98,105,99,95,103,97,102,95,98,97,114,7,69,110,103,46,97,108,116,15,117,110,105,48,50,54, + 56,46,100,111,116,108,101,115,115,15,117,110,105,48,50,57,68,46,100,111,116,108,101,115,115,11,117,110,105,48,51,48,56,48,51,48,52,11,117,110, + 105,48,51,48,52,48,51,48,56,11,117,110,105,48,51,48,55,48,51,48,52,11,117,110,105,48,51,48,56,48,51,48,49,11,117,110,105,48,51,48, + 56,48,51,48,48,11,117,110,105,48,51,48,52,48,51,48,49,11,117,110,105,48,51,48,52,48,51,48,48,11,117,110,105,48,51,48,51,48,51,48, + 52,11,117,110,105,48,51,48,56,48,51,48,67,11,117,110,105,48,51,48,51,48,51,48,56,11,117,110,105,48,51,48,67,48,51,48,55,11,117,110, + 105,48,51,48,51,48,51,48,49,11,117,110,105,48,51,48,50,48,51,48,49,11,117,110,105,48,51,48,50,48,51,48,48,11,117,110,105,48,51,48, + 50,48,51,48,51,11,117,110,105,48,51,48,54,48,51,48,51,11,117,110,105,48,51,48,54,48,51,48,49,11,117,110,105,48,51,48,54,48,51,48, + 48,11,117,110,105,48,51,48,54,48,51,48,57,11,117,110,105,48,51,48,50,48,51,48,57,11,117,110,105,48,51,48,49,48,51,48,55,10,98,114, + 97,105,108,108,101,100,111,116,5,74,46,97,108,116,12,117,110,105,48,54,57,53,46,102,105,110,97,22,117,110,105,70,69,65,69,46,102,105,110,97, + 46,108,111,110,103,115,116,97,114,116,12,117,110,105,48,54,66,53,46,102,105,110,97,12,117,110,105,48,54,66,53,46,105,110,105,116,12,117,110,105, + 48,54,66,53,46,109,101,100,105,12,117,110,105,48,54,67,69,46,102,105,110,97,12,117,110,105,48,54,67,69,46,105,110,105,116,12,117,110,105,48, + 54,67,69,46,109,101,100,105,12,117,110,105,48,54,57,50,46,102,105,110,97,5,108,46,97,108,116,12,117,110,105,48,54,68,53,46,102,105,110,97, + 17,117,110,105,48,52,55,56,46,109,111,110,111,103,114,97,112,104,17,117,110,105,48,52,55,57,46,109,111,110,111,103,114,97,112,104,15,105,111,103, + 111,110,101,107,46,100,111,116,108,101,115,115,15,117,110,105,50,49,52,56,46,100,111,116,108,101,115,115,15,117,110,105,50,49,52,57,46,100,111,116, + 108,101,115,115,15,117,110,105,49,69,50,68,46,100,111,116,108,101,115,115,15,117,110,105,49,69,67,66,46,100,111,116,108,101,115,115,3,100,99,111, + 5,73,46,97,108,116,10,97,114,114,111,119,46,98,97,115,101,11,117,110,105,48,54,53,49,48,54,52,66,11,117,110,105,48,54,53,49,48,54,52, + 67,11,117,110,105,48,54,52,66,48,54,53,49,11,117,110,105,48,54,53,49,48,54,52,69,11,117,110,105,48,54,53,49,48,54,52,70,11,117,110, + 105,48,54,52,69,48,54,53,49,11,117,110,105,48,54,53,52,48,54,52,69,11,117,110,105,48,54,53,52,48,54,52,70,12,117,110,105,48,55,67, + 65,46,102,105,110,97,12,117,110,105,48,55,67,65,46,109,101,100,105,12,117,110,105,48,55,67,65,46,105,110,105,116,12,117,110,105,48,55,67,66, + 46,102,105,110,97,12,117,110,105,48,55,67,66,46,109,101,100,105,12,117,110,105,48,55,67,66,46,105,110,105,116,12,117,110,105,48,55,67,67,46, + 102,105,110,97,12,117,110,105,48,55,67,67,46,109,101,100,105,12,117,110,105,48,55,67,67,46,105,110,105,116,12,117,110,105,48,55,67,68,46,102, + 105,110,97,12,117,110,105,48,55,67,68,46,109,101,100,105,12,117,110,105,48,55,67,68,46,105,110,105,116,12,117,110,105,48,55,67,69,46,102,105, + 110,97,12,117,110,105,48,55,67,69,46,109,101,100,105,12,117,110,105,48,55,67,69,46,105,110,105,116,12,117,110,105,48,55,67,70,46,102,105,110, + 97,12,117,110,105,48,55,67,70,46,109,101,100,105,12,117,110,105,48,55,67,70,46,105,110,105,116,12,117,110,105,48,55,68,48,46,102,105,110,97, + 12,117,110,105,48,55,68,48,46,109,101,100,105,12,117,110,105,48,55,68,48,46,105,110,105,116,12,117,110,105,48,55,68,49,46,102,105,110,97,12, + 117,110,105,48,55,68,49,46,109,101,100,105,12,117,110,105,48,55,68,49,46,105,110,105,116,12,117,110,105,48,55,68,50,46,102,105,110,97,12,117, + 110,105,48,55,68,50,46,109,101,100,105,12,117,110,105,48,55,68,50,46,105,110,105,116,12,117,110,105,48,55,68,51,46,102,105,110,97,12,117,110, + 105,48,55,68,51,46,109,101,100,105,12,117,110,105,48,55,68,51,46,105,110,105,116,12,117,110,105,48,55,68,52,46,102,105,110,97,12,117,110,105, + 48,55,68,52,46,109,101,100,105,12,117,110,105,48,55,68,52,46,105,110,105,116,12,117,110,105,48,55,68,53,46,102,105,110,97,12,117,110,105,48, + 55,68,53,46,109,101,100,105,12,117,110,105,48,55,68,53,46,105,110,105,116,12,117,110,105,48,55,68,54,46,102,105,110,97,12,117,110,105,48,55, + 68,54,46,109,101,100,105,12,117,110,105,48,55,68,54,46,105,110,105,116,12,117,110,105,48,55,68,55,46,102,105,110,97,12,117,110,105,48,55,68, + 55,46,109,101,100,105,12,117,110,105,48,55,68,55,46,105,110,105,116,12,117,110,105,48,55,68,56,46,102,105,110,97,12,117,110,105,48,55,68,56, + 46,109,101,100,105,12,117,110,105,48,55,68,56,46,105,110,105,116,12,117,110,105,48,55,68,57,46,102,105,110,97,12,117,110,105,48,55,68,57,46, + 109,101,100,105,12,117,110,105,48,55,68,57,46,105,110,105,116,12,117,110,105,48,55,68,65,46,102,105,110,97,12,117,110,105,48,55,68,65,46,109, + 101,100,105,12,117,110,105,48,55,68,65,46,105,110,105,116,12,117,110,105,48,55,68,66,46,102,105,110,97,12,117,110,105,48,55,68,66,46,109,101, + 100,105,12,117,110,105,48,55,68,66,46,105,110,105,116,12,117,110,105,48,55,68,67,46,102,105,110,97,12,117,110,105,48,55,68,67,46,109,101,100, + 105,12,117,110,105,48,55,68,67,46,105,110,105,116,12,117,110,105,48,55,68,68,46,102,105,110,97,12,117,110,105,48,55,68,68,46,109,101,100,105, + 12,117,110,105,48,55,68,68,46,105,110,105,116,12,117,110,105,48,55,68,69,46,102,105,110,97,12,117,110,105,48,55,68,69,46,109,101,100,105,12, + 117,110,105,48,55,68,69,46,105,110,105,116,12,117,110,105,48,55,68,70,46,102,105,110,97,12,117,110,105,48,55,68,70,46,109,101,100,105,12,117, + 110,105,48,55,68,70,46,105,110,105,116,12,117,110,105,48,55,69,48,46,102,105,110,97,12,117,110,105,48,55,69,48,46,109,101,100,105,12,117,110, + 105,48,55,69,48,46,105,110,105,116,12,117,110,105,48,55,69,49,46,102,105,110,97,12,117,110,105,48,55,69,49,46,109,101,100,105,12,117,110,105, + 48,55,69,49,46,105,110,105,116,12,117,110,105,48,55,69,50,46,102,105,110,97,12,117,110,105,48,55,69,50,46,109,101,100,105,12,117,110,105,48, + 55,69,50,46,105,110,105,116,12,117,110,105,48,55,69,51,46,102,105,110,97,12,117,110,105,48,55,69,51,46,109,101,100,105,12,117,110,105,48,55, + 69,51,46,105,110,105,116,12,117,110,105,48,55,69,52,46,102,105,110,97,12,117,110,105,48,55,69,52,46,109,101,100,105,12,117,110,105,48,55,69, + 52,46,105,110,105,116,12,117,110,105,48,55,69,53,46,102,105,110,97,12,117,110,105,48,55,69,53,46,109,101,100,105,12,117,110,105,48,55,69,53, + 46,105,110,105,116,12,117,110,105,48,55,69,54,46,102,105,110,97,12,117,110,105,48,55,69,54,46,109,101,100,105,12,117,110,105,48,55,69,54,46, + 105,110,105,116,12,117,110,105,48,55,69,55,46,102,105,110,97,12,117,110,105,48,55,69,55,46,109,101,100,105,12,117,110,105,48,55,69,55,46,105, + 110,105,116,9,82,105,110,103,97,98,111,118,101,11,117,110,105,50,54,51,48,46,97,108,116,11,117,110,105,50,54,51,49,46,97,108,116,11,117,110, + 105,50,54,51,50,46,97,108,116,11,117,110,105,50,54,51,51,46,97,108,116,11,117,110,105,50,54,51,52,46,97,108,116,11,117,110,105,50,54,51, + 53,46,97,108,116,11,117,110,105,50,54,51,54,46,97,108,116,11,117,110,105,50,54,51,55,46,97,108,116,12,117,110,105,48,52,55,69,46,100,105, + 97,99,17,117,110,105,48,52,56,65,46,98,114,101,118,101,108,101,115,115,17,117,110,105,48,52,56,66,46,98,114,101,118,101,108,101,115,115,5,121, + 46,97,108,116,12,117,110,105,48,54,56,57,46,102,105,110,97,12,117,110,105,48,54,56,65,46,102,105,110,97,12,117,110,105,48,54,56,66,46,102, + 105,110,97,12,117,110,105,48,54,56,70,46,102,105,110,97,12,117,110,105,48,54,57,48,46,102,105,110,97,12,117,110,105,48,54,57,51,46,102,105, + 110,97,12,117,110,105,48,54,57,52,46,102,105,110,97,12,117,110,105,48,54,57,54,46,102,105,110,97,12,117,110,105,48,54,57,55,46,102,105,110, + 97,12,117,110,105,48,54,57,57,46,102,105,110,97,12,117,110,105,48,54,57,65,46,102,105,110,97,12,117,110,105,48,54,57,65,46,105,110,105,116, + 12,117,110,105,48,54,57,65,46,109,101,100,105,12,117,110,105,48,54,57,66,46,102,105,110,97,12,117,110,105,48,54,57,66,46,105,110,105,116,12, + 117,110,105,48,54,57,66,46,109,101,100,105,12,117,110,105,48,54,57,67,46,102,105,110,97,12,117,110,105,48,54,57,67,46,105,110,105,116,12,117, + 110,105,48,54,57,67,46,109,101,100,105,12,117,110,105,48,54,57,68,46,102,105,110,97,12,117,110,105,48,54,57,68,46,105,110,105,116,12,117,110, + 105,48,54,57,68,46,109,101,100,105,12,117,110,105,48,54,57,69,46,102,105,110,97,12,117,110,105,48,54,57,69,46,105,110,105,116,12,117,110,105, + 48,54,57,69,46,109,101,100,105,12,117,110,105,48,54,57,70,46,102,105,110,97,12,117,110,105,48,54,57,70,46,105,110,105,116,12,117,110,105,48, + 54,57,70,46,109,101,100,105,12,117,110,105,48,54,65,48,46,102,105,110,97,12,117,110,105,48,54,65,48,46,105,110,105,116,12,117,110,105,48,54, + 65,48,46,109,101,100,105,12,117,110,105,48,54,65,50,46,102,105,110,97,12,117,110,105,48,54,65,50,46,105,110,105,116,12,117,110,105,48,54,65, + 50,46,109,101,100,105,12,117,110,105,48,54,65,51,46,102,105,110,97,12,117,110,105,48,54,65,51,46,105,110,105,116,12,117,110,105,48,54,65,51, + 46,109,101,100,105,12,117,110,105,48,54,65,53,46,102,105,110,97,12,117,110,105,48,54,65,53,46,105,110,105,116,12,117,110,105,48,54,65,53,46, + 109,101,100,105,12,117,110,105,48,54,65,55,46,102,105,110,97,12,117,110,105,48,54,65,55,46,105,110,105,116,12,117,110,105,48,54,65,55,46,109, + 101,100,105,12,117,110,105,48,54,65,56,46,102,105,110,97,12,117,110,105,48,54,65,56,46,105,110,105,116,12,117,110,105,48,54,65,56,46,109,101, + 100,105,12,117,110,105,48,54,65,65,46,102,105,110,97,12,117,110,105,48,54,65,65,46,105,110,105,116,12,117,110,105,48,54,65,65,46,109,101,100, + 105,12,117,110,105,48,54,65,66,46,102,105,110,97,12,117,110,105,48,54,65,66,46,105,110,105,116,12,117,110,105,48,54,65,66,46,109,101,100,105, + 12,117,110,105,48,54,65,67,46,102,105,110,97,12,117,110,105,48,54,65,67,46,105,110,105,116,12,117,110,105,48,54,65,67,46,109,101,100,105,12, + 117,110,105,48,54,65,69,46,102,105,110,97,12,117,110,105,48,54,65,69,46,105,110,105,116,12,117,110,105,48,54,65,69,46,109,101,100,105,12,117, + 110,105,48,54,66,48,46,102,105,110,97,12,117,110,105,48,54,66,48,46,105,110,105,116,12,117,110,105,48,54,66,48,46,109,101,100,105,12,117,110, + 105,48,54,66,50,46,102,105,110,97,12,117,110,105,48,54,66,50,46,105,110,105,116,12,117,110,105,48,54,66,50,46,109,101,100,105,12,117,110,105, + 48,54,66,52,46,102,105,110,97,12,117,110,105,48,54,66,52,46,105,110,105,116,12,117,110,105,48,54,66,52,46,109,101,100,105,12,117,110,105,48, + 54,66,54,46,102,105,110,97,12,117,110,105,48,54,66,54,46,105,110,105,116,12,117,110,105,48,54,66,54,46,109,101,100,105,12,117,110,105,48,54, + 66,55,46,102,105,110,97,12,117,110,105,48,54,66,55,46,105,110,105,116,12,117,110,105,48,54,66,55,46,109,101,100,105,12,117,110,105,48,54,66, + 56,46,102,105,110,97,12,117,110,105,48,54,66,56,46,105,110,105,116,12,117,110,105,48,54,66,56,46,109,101,100,105,12,117,110,105,48,54,66,57, + 46,102,105,110,97,12,117,110,105,48,54,66,57,46,105,110,105,116,12,117,110,105,48,54,66,57,46,109,101,100,105,12,117,110,105,48,54,66,67,46, + 102,105,110,97,12,117,110,105,48,54,66,67,46,105,110,105,116,12,117,110,105,48,54,66,67,46,109,101,100,105,12,117,110,105,48,54,66,68,46,102, + 105,110,97,12,117,110,105,48,54,66,68,46,105,110,105,116,12,117,110,105,48,54,66,68,46,109,101,100,105,0,0,0,184,2,128,64,255,251,254,3, + 250,20,3,249,37,3,248,50,3,247,150,3,246,14,3,245,254,3,244,254,3,243,37,3,242,14,3,241,150,3,240,37,3,239,138,65,5,239,254,3, + 238,150,3,237,150,3,236,250,3,235,250,3,234,254,3,233,58,3,232,66,3,231,254,3,230,50,3,229,228,83,5,229,150,3,228,138,65,5,228,83, + 3,227,226,47,5,227,250,3,226,47,3,225,254,3,224,254,3,223,50,3,222,20,3,221,150,3,220,254,3,219,18,3,218,125,3,217,187,3,216,254, + 3,214,138,65,5,214,125,3,213,212,71,5,213,125,3,212,71,3,211,210,27,5,211,254,3,210,27,3,209,254,3,208,254,3,207,254,3,206,254,3, + 205,150,3,204,203,30,5,204,254,3,203,30,3,202,50,3,201,254,3,198,133,17,5,198,28,3,197,22,3,196,254,3,195,254,3,194,254,3,193,254, + 3,192,254,3,191,254,3,190,254,3,189,254,3,188,254,3,187,254,3,186,17,3,185,134,37,5,185,254,3,184,183,187,5,184,254,3,183,182,93,5, + 183,187,3,183,128,4,182,181,37,5,182,93,64,255,3,182,64,4,181,37,3,180,254,3,179,150,3,178,254,3,177,254,3,176,254,3,175,254,3,174, + 100,3,173,14,3,172,171,37,5,172,100,3,171,170,18,5,171,37,3,170,18,3,169,138,65,5,169,250,3,168,254,3,167,254,3,166,254,3,165,18, + 3,164,254,3,163,162,14,5,163,50,3,162,14,3,161,100,3,160,138,65,5,160,150,3,159,254,3,158,157,12,5,158,254,3,157,12,3,156,155,25, + 5,156,100,3,155,154,16,5,155,25,3,154,16,3,153,10,3,152,254,3,151,150,13,5,151,254,3,150,13,3,149,138,65,5,149,150,3,148,147,14, + 5,148,40,3,147,14,3,146,250,3,145,144,187,5,145,254,3,144,143,93,5,144,187,3,144,128,4,143,142,37,5,143,93,3,143,64,4,142,37,3, + 141,254,3,140,139,46,5,140,254,3,139,46,3,138,134,37,5,138,65,3,137,136,11,5,137,20,3,136,11,3,135,134,37,5,135,100,3,134,133,17, + 5,134,37,3,133,17,3,132,254,3,131,130,17,5,131,254,3,130,17,3,129,254,3,128,254,3,127,254,3,64,255,126,125,125,5,126,254,3,125,125, + 3,124,100,3,123,84,21,5,123,37,3,122,254,3,121,254,3,120,14,3,119,12,3,118,10,3,117,254,3,116,250,3,115,250,3,114,250,3,113,250, + 3,112,254,3,111,254,3,110,254,3,108,33,3,107,254,3,106,17,66,5,106,83,3,105,254,3,104,125,3,103,17,66,5,102,254,3,101,254,3,100, + 254,3,99,254,3,98,254,3,97,58,3,96,250,3,94,12,3,93,254,3,91,254,3,90,254,3,89,88,10,5,89,250,3,88,10,3,87,22,25,5, + 87,50,3,86,254,3,85,84,21,5,85,66,3,84,21,3,83,1,16,5,83,24,3,82,20,3,81,74,19,5,81,254,3,80,11,3,79,254,3,78, + 77,16,5,78,254,3,77,16,3,76,254,3,75,74,19,5,75,254,3,74,73,16,5,74,19,3,73,29,13,5,73,16,3,72,13,3,71,254,3,70, + 150,3,69,150,3,68,254,3,67,2,45,5,67,250,3,66,187,3,65,75,3,64,254,3,63,254,3,62,61,18,5,62,20,3,61,60,15,5,61,18, + 3,60,59,13,5,60,64,255,15,3,59,13,3,58,254,3,57,254,3,56,55,20,5,56,250,3,55,54,16,5,55,20,3,54,53,11,5,54,16,3, + 53,11,3,52,30,3,51,13,3,50,49,11,5,50,254,3,49,11,3,48,47,11,5,48,13,3,47,11,3,46,45,9,5,46,16,3,45,9,3,44, + 50,3,43,42,37,5,43,100,3,42,41,18,5,42,37,3,41,18,3,40,39,37,5,40,65,3,39,37,3,38,37,11,5,38,15,3,37,11,3,36, + 254,3,35,254,3,34,15,3,33,1,16,5,33,18,3,32,100,3,31,250,3,30,29,13,5,30,100,3,29,13,3,28,17,66,5,28,254,3,27,250, + 3,26,66,3,25,17,66,5,25,254,3,24,100,3,23,22,25,5,23,254,3,22,1,16,5,22,25,3,21,254,3,20,254,3,19,254,3,18,17,66, + 5,18,254,3,17,2,45,5,17,66,3,16,125,3,15,100,3,14,254,3,13,12,22,5,13,254,3,12,1,16,5,12,22,3,11,254,3,10,16,3, + 9,254,3,8,2,45,5,8,254,3,7,20,3,6,100,3,4,1,16,5,4,254,3,64,21,3,2,45,5,3,254,3,2,1,16,5,2,45,3,1, + 16,3,0,254,3,1,184,1,100,133,141,1,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,0,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43, + 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,29,0,0}; +const char* dpf_resources::dejavusans_ttf = (const char*) temp1; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Resources.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Resources.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,12 @@ +/* (Auto-generated binary data file). */ + +#ifndef BINARY_DPF_RESOURCES_HPP_INCLUDED +#define BINARY_DPF_RESOURCES_HPP_INCLUDED + +namespace dpf_resources +{ + extern const char* dejavusans_ttf; + const unsigned int dejavusans_ttf_size = 741536; +}; + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/SubWidget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/SubWidget.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,198 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "SubWidgetPrivateData.hpp" +#include "WidgetPrivateData.hpp" +#include "../TopLevelWidget.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +SubWidget::SubWidget(Widget* const parentWidget) + : Widget(parentWidget), + pData(new PrivateData(this, parentWidget)) {} + +SubWidget::~SubWidget() +{ + delete pData; +} + +template +bool SubWidget::contains(const T x, const T y) const noexcept +{ + return Rectangle(0, 0, + static_cast(getWidth()), + static_cast(getHeight())).contains(x, y); +} + +template +bool SubWidget::contains(const Point& pos) const noexcept +{ + return contains(pos.getX(), pos.getY()); +} + +int SubWidget::getAbsoluteX() const noexcept +{ + return pData->absolutePos.getX(); +} + +int SubWidget::getAbsoluteY() const noexcept +{ + return pData->absolutePos.getY(); +} + +Point SubWidget::getAbsolutePos() const noexcept +{ + return pData->absolutePos; +} + +Rectangle SubWidget::getAbsoluteArea() const noexcept +{ + return Rectangle(getAbsolutePos(), getSize().toInt()); +} + +Rectangle SubWidget::getConstrainedAbsoluteArea() const noexcept +{ + const int x = getAbsoluteX(); + const int y = getAbsoluteY(); + + if (x >= 0 && y >= 0) + return Rectangle(x, y, getSize()); + + const int xOffset = std::min(0, x); + const int yOffset = std::min(0, y); + const int width = std::max(0, static_cast(getWidth()) + xOffset); + const int height = std::max(0, static_cast(getHeight()) + yOffset); + + return Rectangle(0, 0, static_cast(width), static_cast(height)); +} + +void SubWidget::setAbsoluteX(const int x) noexcept +{ + setAbsolutePos(Point(x, getAbsoluteY())); +} + +void SubWidget::setAbsoluteY(const int y) noexcept +{ + setAbsolutePos(Point(getAbsoluteX(), y)); +} + +void SubWidget::setAbsolutePos(const int x, const int y) noexcept +{ + setAbsolutePos(Point(x, y)); +} + +void SubWidget::setAbsolutePos(const Point& pos) noexcept +{ + if (pData->absolutePos == pos) + return; + + PositionChangedEvent ev; + ev.oldPos = pData->absolutePos; + ev.pos = pos; + + pData->absolutePos = pos; + onPositionChanged(ev); + + repaint(); +} + +Point SubWidget::getMargin() const noexcept +{ + return pData->margin; +} + +void SubWidget::setMargin(const int x, const int y) noexcept +{ + pData->margin = Point(x, y); +} + +void SubWidget::setMargin(const Point& offset) noexcept +{ + pData->margin = offset; +} + +Widget* SubWidget::getParentWidget() const noexcept +{ + return pData->parentWidget; +} + +void SubWidget::repaint() noexcept +{ + if (! isVisible()) + return; + + if (TopLevelWidget* const topw = getTopLevelWidget()) + { + if (pData->needsFullViewportForDrawing) + // repaint is virtual and we want precisely the top-level specific implementation, not any higher level + topw->TopLevelWidget::repaint(); + else + topw->repaint(getConstrainedAbsoluteArea()); + } +} + +void SubWidget::toBottom() +{ + std::list& subwidgets(pData->parentWidget->pData->subWidgets); + + subwidgets.remove(this); + subwidgets.insert(subwidgets.begin(), this); +} + +void SubWidget::toFront() +{ + std::list& subwidgets(pData->parentWidget->pData->subWidgets); + + subwidgets.remove(this); + subwidgets.push_back(this); +} + +void SubWidget::setNeedsFullViewportDrawing(const bool needsFullViewportForDrawing) +{ + pData->needsFullViewportForDrawing = needsFullViewportForDrawing; +} + +void SubWidget::setNeedsViewportScaling(const bool needsViewportScaling, const double autoScaleFactor) +{ + pData->needsViewportScaling = needsViewportScaling; + pData->viewportScaleFactor = autoScaleFactor; +} + +void SubWidget::setSkipDrawing(const bool skipDrawing) +{ + pData->skipDrawing = skipDrawing; +} + +void SubWidget::onPositionChanged(const PositionChangedEvent&) +{ +} + +// -------------------------------------------------------------------------------------------------------------------- +// Possible template data types + +template<> +bool SubWidget::contains(const Point& pos) const noexcept +{ + return contains(pos.getX(), pos.getY()); +} + +// float, int, uint, short, ushort + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/SubWidgetPrivateData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/SubWidgetPrivateData.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,45 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "SubWidgetPrivateData.hpp" +#include "WidgetPrivateData.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +SubWidget::PrivateData::PrivateData(SubWidget* const s, Widget* const pw) + : self(s), + selfw((Widget*)s), + parentWidget(pw), + absolutePos(), + margin(), + needsFullViewportForDrawing(false), + needsViewportScaling(false), + skipDrawing(false), + viewportScaleFactor(0.0) +{ + parentWidget->pData->subWidgets.push_back(self); +} + +SubWidget::PrivateData::~PrivateData() +{ + parentWidget->pData->subWidgets.remove(self); +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/SubWidgetPrivateData.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/SubWidgetPrivateData.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,50 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_SUBWIDGET_PRIVATE_DATA_HPP_INCLUDED +#define DGL_SUBWIDGET_PRIVATE_DATA_HPP_INCLUDED + +#include "../SubWidget.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +struct SubWidget::PrivateData { + SubWidget* const self; + Widget* const selfw; + Widget* const parentWidget; + Point absolutePos; + Point margin; + bool needsFullViewportForDrawing; // needed for widgets drawing out of bounds + bool needsViewportScaling; // needed for NanoVG + bool skipDrawing; // for context reuse in NanoVG based guis + double viewportScaleFactor; // auto-scaling for NanoVG + + explicit PrivateData(SubWidget* const s, Widget* const pw); + ~PrivateData(); + + // NOTE display function is different depending on build type, must call displaySubWidgets at the end + void display(uint width, uint height, double autoScaleFactor); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_SUBWIDGET_PRIVATE_DATA_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/TopLevelWidget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/TopLevelWidget.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,151 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "TopLevelWidgetPrivateData.hpp" +#include "../Window.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +TopLevelWidget::TopLevelWidget(Window& windowToMapTo) + : Widget(this), + pData(new PrivateData(this, windowToMapTo)) {} + +TopLevelWidget::~TopLevelWidget() +{ + delete pData; +} + +Application& TopLevelWidget::getApp() const noexcept +{ + return pData->window.getApp(); +} + +Window& TopLevelWidget::getWindow() const noexcept +{ + return pData->window; +} + +void TopLevelWidget::setWidth(const uint width) +{ + pData->window.setWidth(width); +} + +void TopLevelWidget::setHeight(const uint height) +{ + pData->window.setHeight(height); +} + +void TopLevelWidget::setSize(const uint width, const uint height) +{ + pData->window.setSize(width, height); +} + +void TopLevelWidget::setSize(const Size& size) +{ + pData->window.setSize(size); +} + +const void* TopLevelWidget::getClipboard(size_t& dataSize) +{ + return pData->window.getClipboard(dataSize); +} + +bool TopLevelWidget::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) +{ + return pData->window.setClipboard(mimeType, data, dataSize); +} + +bool TopLevelWidget::setCursor(const MouseCursor cursor) +{ + return pData->window.setCursor(cursor); +} + +bool TopLevelWidget::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) +{ + return pData->window.addIdleCallback(callback, timerFrequencyInMs); +} + +bool TopLevelWidget::removeIdleCallback(IdleCallback* const callback) +{ + return pData->window.removeIdleCallback(callback); +} + +double TopLevelWidget::getScaleFactor() const noexcept +{ + return pData->window.getScaleFactor(); +} + +void TopLevelWidget::repaint() noexcept +{ + pData->window.repaint(); +} + +void TopLevelWidget::repaint(const Rectangle& rect) noexcept +{ + pData->window.repaint(rect); +} + +void TopLevelWidget::setGeometryConstraints(const uint minimumWidth, + const uint minimumHeight, + const bool keepAspectRatio, + const bool automaticallyScale, + const bool resizeNowIfAutoScaling) +{ + pData->window.setGeometryConstraints(minimumWidth, + minimumHeight, + keepAspectRatio, + automaticallyScale, + resizeNowIfAutoScaling); +} + +// -------------------------------------------------------------------------------------------------------------------- + +bool TopLevelWidget::onKeyboard(const KeyboardEvent& ev) +{ + return pData->keyboardEvent(ev); +} + +bool TopLevelWidget::onCharacterInput(const CharacterInputEvent& ev) +{ + return pData->characterInputEvent(ev); +} + +bool TopLevelWidget::onMouse(const MouseEvent& ev) +{ + return pData->mouseEvent(ev); +} + +bool TopLevelWidget::onMotion(const MotionEvent& ev) +{ + return pData->motionEvent(ev); +} + +bool TopLevelWidget::onScroll(const ScrollEvent& ev) +{ + return pData->scrollEvent(ev); +} + +// -------------------------------------------------------------------------------------------------------------------- + +void TopLevelWidget::requestSizeChange(uint, uint) +{ +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/TopLevelWidgetPrivateData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/TopLevelWidgetPrivateData.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,145 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "TopLevelWidgetPrivateData.hpp" +#include "WidgetPrivateData.hpp" +#include "WindowPrivateData.hpp" +#include "pugl.hpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +TopLevelWidget::PrivateData::PrivateData(TopLevelWidget* const s, Window& w) + : self(s), + selfw(s), + window(w) +{ + /* if window already has a top-level-widget, make the new one match the first one in size + * this is needed because window creation and resize is a synchronous operation in some systems. + * as such, there's a chance the non-1st top-level-widgets would never get a valid size. + */ + if (!window.pData->topLevelWidgets.empty()) + { + TopLevelWidget* const first = window.pData->topLevelWidgets.front(); + + selfw->pData->size = first->getSize(); + } + + window.pData->topLevelWidgets.push_back(self); +} + +TopLevelWidget::PrivateData::~PrivateData() +{ + window.pData->topLevelWidgets.remove(self); +} + +bool TopLevelWidget::PrivateData::keyboardEvent(const KeyboardEvent& ev) +{ + // ignore event if we are not visible + if (! selfw->pData->visible) + return false; + + // propagate event to all subwidgets recursively + return selfw->pData->giveKeyboardEventForSubWidgets(ev); +} + +bool TopLevelWidget::PrivateData::characterInputEvent(const CharacterInputEvent& ev) +{ + // ignore event if we are not visible + if (! selfw->pData->visible) + return false; + + // propagate event to all subwidgets recursively + return selfw->pData->giveCharacterInputEventForSubWidgets(ev); +} + +bool TopLevelWidget::PrivateData::mouseEvent(const MouseEvent& ev) +{ + // ignore event if we are not visible + if (! selfw->pData->visible) + return false; + + MouseEvent rev = ev; + + if (window.pData->autoScaling) + { + const double autoScaleFactor = window.pData->autoScaleFactor; + + rev.pos.setX(ev.pos.getX() / autoScaleFactor); + rev.pos.setY(ev.pos.getY() / autoScaleFactor); + rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); + rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); + } + + // propagate event to all subwidgets recursively + return selfw->pData->giveMouseEventForSubWidgets(rev); +} + +bool TopLevelWidget::PrivateData::motionEvent(const MotionEvent& ev) +{ + // ignore event if we are not visible + if (! selfw->pData->visible) + return false; + + MotionEvent rev = ev; + + if (window.pData->autoScaling) + { + const double autoScaleFactor = window.pData->autoScaleFactor; + + rev.pos.setX(ev.pos.getX() / autoScaleFactor); + rev.pos.setY(ev.pos.getY() / autoScaleFactor); + rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); + rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); + } + + // propagate event to all subwidgets recursively + return selfw->pData->giveMotionEventForSubWidgets(rev); +} + +bool TopLevelWidget::PrivateData::scrollEvent(const ScrollEvent& ev) +{ + // ignore event if we are not visible + if (! selfw->pData->visible) + return false; + + ScrollEvent rev = ev; + + if (window.pData->autoScaling) + { + const double autoScaleFactor = window.pData->autoScaleFactor; + + rev.pos.setX(ev.pos.getX() / autoScaleFactor); + rev.pos.setY(ev.pos.getY() / autoScaleFactor); + rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); + rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); + rev.delta.setX(ev.delta.getX() / autoScaleFactor); + rev.delta.setY(ev.delta.getY() / autoScaleFactor); + } + + // propagate event to all subwidgets recursively + return selfw->pData->giveScrollEventForSubWidgets(rev); +} + +void TopLevelWidget::PrivateData::fallbackOnResize() +{ + puglFallbackOnResize(window.pData->view); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/TopLevelWidgetPrivateData.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/TopLevelWidgetPrivateData.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,50 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_TOP_LEVEL_WIDGET_PRIVATE_DATA_HPP_INCLUDED +#define DGL_TOP_LEVEL_WIDGET_PRIVATE_DATA_HPP_INCLUDED + +#include "../TopLevelWidget.hpp" + +#include + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +struct TopLevelWidget::PrivateData { + TopLevelWidget* const self; + Widget* const selfw; + Window& window; + + explicit PrivateData(TopLevelWidget* self, Window& window); + ~PrivateData(); + void display(); + bool keyboardEvent(const KeyboardEvent& ev); + bool characterInputEvent(const CharacterInputEvent& ev); + bool mouseEvent(const MouseEvent& ev); + bool motionEvent(const MotionEvent& ev); + bool scrollEvent(const ScrollEvent& ev); + void fallbackOnResize(); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_TOP_LEVEL_WIDGET_PRIVATE_DATA_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Vulkan.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Vulkan.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,250 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../Vulkan.hpp" +#include "../Color.hpp" + +#include "SubWidgetPrivateData.hpp" +#include "TopLevelWidgetPrivateData.hpp" +#include "WidgetPrivateData.hpp" +#include "WindowPrivateData.hpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +static void notImplemented(const char* const name) +{ + d_stderr2("vulkan function not implemented: %s", name); +} + +// ----------------------------------------------------------------------- +// Color + +void Color::setFor(const GraphicsContext&, bool) +{ + notImplemented("Color::setFor"); +} + +// ----------------------------------------------------------------------- +// Line + +template +void Line::draw(const GraphicsContext&, T) +{ + notImplemented("Line::draw"); +} + +template +void Line::draw() +{ + notImplemented("Line::draw"); +} + +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; +template class Line; + +// ----------------------------------------------------------------------- +// Circle + +template +void Circle::draw(const GraphicsContext&) +{ + notImplemented("Circle::draw"); +} + +template +void Circle::drawOutline(const GraphicsContext&, T) +{ + notImplemented("Circle::drawOutline"); +} + +template +void Circle::draw() +{ + notImplemented("Circle::draw"); +} + +template +void Circle::drawOutline() +{ + notImplemented("Circle::drawOutline"); +} + +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; +template class Circle; + +// ----------------------------------------------------------------------- +// Triangle + +template +void Triangle::draw(const GraphicsContext&) +{ + notImplemented("Triangle::draw"); +} + +template +void Triangle::drawOutline(const GraphicsContext&, T) +{ + notImplemented("Triangle::drawOutline"); +} + +template +void Triangle::draw() +{ + notImplemented("Triangle::draw"); +} + +template +void Triangle::drawOutline() +{ + notImplemented("Triangle::drawOutline"); +} + +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; +template class Triangle; + + +// ----------------------------------------------------------------------- +// Rectangle + +template +void Rectangle::draw(const GraphicsContext&) +{ + notImplemented("Rectangle::draw"); +} + +template +void Rectangle::drawOutline(const GraphicsContext&, T) +{ + notImplemented("Rectangle::drawOutline"); +} + +template +void Rectangle::draw() +{ + notImplemented("Rectangle::draw"); +} + +template +void Rectangle::drawOutline() +{ + notImplemented("Rectangle::drawOutline"); +} + +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; +template class Rectangle; + +// ----------------------------------------------------------------------- +// VulkanImage + +VulkanImage::VulkanImage() + : ImageBase() {} + +VulkanImage::VulkanImage(const char* const rdata, const uint w, const uint h, const ImageFormat fmt) + : ImageBase(rdata, w, h, fmt) {} + +VulkanImage::VulkanImage(const char* const rdata, const Size& s, const ImageFormat fmt) + : ImageBase(rdata, s, fmt) {} + +VulkanImage::VulkanImage(const VulkanImage& image) + : ImageBase(image.rawData, image.size, image.format) {} + +VulkanImage::~VulkanImage() {} + +void VulkanImage::loadFromMemory(const char* const rdata, const Size& s, const ImageFormat fmt) noexcept +{ + ImageBase::loadFromMemory(rdata, s, fmt); +} + +void VulkanImage::drawAt(const GraphicsContext&, const Point&) +{ +} + +VulkanImage& VulkanImage::operator=(const VulkanImage& image) noexcept +{ + rawData = image.rawData; + size = image.size; + format = image.format; + return *this; +} + +// ----------------------------------------------------------------------- + +void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) +{ + // TODO + + selfw->pData->displaySubWidgets(width, height, autoScaleFactor); +} + +// ----------------------------------------------------------------------- + +void TopLevelWidget::PrivateData::display() +{ + if (! selfw->pData->visible) + return; + + const Size size(window.getSize()); + const uint width = size.getWidth(); + const uint height = size.getHeight(); + + const double autoScaleFactor = window.pData->autoScaleFactor; + + // TODO + + // main widget drawing + self->onDisplay(); + + // now draw subwidgets if there are any + selfw->pData->displaySubWidgets(width, height, autoScaleFactor); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::renderToPicture(const char*, const GraphicsContext&, uint, uint) +{ + notImplemented("Window::PrivateData::renderToPicture"); +} + +// ----------------------------------------------------------------------- + +const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept +{ + return (const GraphicsContext&)graphicsContext; +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Widget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Widget.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,215 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "WidgetPrivateData.hpp" +#include "../TopLevelWidget.hpp" +#include "../Window.hpp" + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- +// Widget + +Widget::Widget(TopLevelWidget* const topLevelWidget) + : pData(new PrivateData(this, topLevelWidget)) {} + +Widget::Widget(Widget* const parentWidget) + : pData(new PrivateData(this, parentWidget)) {} + +Widget::~Widget() +{ + delete pData; +} + +bool Widget::isVisible() const noexcept +{ + return pData->visible; +} + +void Widget::setVisible(bool visible) +{ + if (pData->visible == visible) + return; + + pData->visible = visible; + repaint(); + + // FIXME check case of hiding a previously visible widget, does it trigger a repaint? +} + +void Widget::show() +{ + setVisible(true); +} + +void Widget::hide() +{ + setVisible(false); +} + +uint Widget::getWidth() const noexcept +{ + return pData->size.getWidth(); +} + +uint Widget::getHeight() const noexcept +{ + return pData->size.getHeight(); +} + +const Size Widget::getSize() const noexcept +{ + return pData->size; +} + +void Widget::setWidth(uint width) noexcept +{ + if (pData->size.getWidth() == width) + return; + + ResizeEvent ev; + ev.oldSize = pData->size; + ev.size = Size(width, pData->size.getHeight()); + + pData->size.setWidth(width); + onResize(ev); + + repaint(); +} + +void Widget::setHeight(uint height) noexcept +{ + if (pData->size.getHeight() == height) + return; + + ResizeEvent ev; + ev.oldSize = pData->size; + ev.size = Size(pData->size.getWidth(), height); + + pData->size.setHeight(height); + onResize(ev); + + repaint(); +} + +void Widget::setSize(uint width, uint height) noexcept +{ + setSize(Size(width, height)); +} + +void Widget::setSize(const Size& size) noexcept +{ + if (pData->size == size) + return; + + ResizeEvent ev; + ev.oldSize = pData->size; + ev.size = size; + + pData->size = size; + onResize(ev); + + repaint(); +} + +Application& Widget::getApp() const noexcept +{ + DISTRHO_SAFE_ASSERT(pData->topLevelWidget != nullptr); + return pData->topLevelWidget->getApp(); +} + +Window& Widget::getWindow() const noexcept +{ + DISTRHO_SAFE_ASSERT(pData->topLevelWidget != nullptr); + return pData->topLevelWidget->getWindow(); +} + +const GraphicsContext& Widget::getGraphicsContext() const noexcept +{ + DISTRHO_SAFE_ASSERT(pData->topLevelWidget != nullptr); + return pData->topLevelWidget->getWindow().getGraphicsContext(); +} + +TopLevelWidget* Widget::getTopLevelWidget() const noexcept +{ + return pData->topLevelWidget; +} + +std::list Widget::getChildren() const noexcept +{ + return pData->subWidgets; +} + +void Widget::repaint() noexcept +{ +} + +uint Widget::getId() const noexcept +{ + return pData->id; +} + +const char* Widget::getName() const noexcept +{ + return pData->name != nullptr ? pData->name : ""; +} + +void Widget::setId(uint id) noexcept +{ + pData->id = id; +} + +void Widget::setName(const char* const name) noexcept +{ + std::free(pData->name); + pData->name = strdup(name); +} + +bool Widget::onKeyboard(const KeyboardEvent& ev) +{ + return pData->giveKeyboardEventForSubWidgets(ev); +} + +bool Widget::onCharacterInput(const CharacterInputEvent& ev) +{ + return pData->giveCharacterInputEventForSubWidgets(ev); +} + +bool Widget::onMouse(const MouseEvent& ev) +{ + MouseEvent rev = ev; + return pData->giveMouseEventForSubWidgets(rev); +} + +bool Widget::onMotion(const MotionEvent& ev) +{ + MotionEvent rev = ev; + return pData->giveMotionEventForSubWidgets(rev); +} + +bool Widget::onScroll(const ScrollEvent& ev) +{ + ScrollEvent rev = ev; + return pData->giveScrollEventForSubWidgets(rev); +} + +void Widget::onResize(const ResizeEvent&) +{ +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/WidgetPrivateData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/WidgetPrivateData.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,232 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "WidgetPrivateData.hpp" +#include "SubWidgetPrivateData.hpp" +#include "../TopLevelWidget.hpp" + +START_NAMESPACE_DGL + +#define FOR_EACH_SUBWIDGET(it) \ + for (std::list::iterator it = subWidgets.begin(); it != subWidgets.end(); ++it) + +#define FOR_EACH_SUBWIDGET_INV(rit) \ + for (std::list::reverse_iterator rit = subWidgets.rbegin(); rit != subWidgets.rend(); ++rit) + +// ----------------------------------------------------------------------- + +Widget::PrivateData::PrivateData(Widget* const s, TopLevelWidget* const tlw) + : self(s), + topLevelWidget(tlw), + parentWidget(nullptr), + id(0), + name(nullptr), + needsScaling(false), + visible(true), + size(0, 0), + subWidgets() {} + +Widget::PrivateData::PrivateData(Widget* const s, Widget* const pw) + : self(s), + topLevelWidget(findTopLevelWidget(pw)), + parentWidget(pw), + id(0), + name(nullptr), + needsScaling(false), + visible(true), + size(0, 0), + subWidgets() {} + +Widget::PrivateData::~PrivateData() +{ + subWidgets.clear(); + std::free(name); +} + +void Widget::PrivateData::displaySubWidgets(const uint width, const uint height, const double autoScaleFactor) +{ + if (subWidgets.size() == 0) + return; + + for (std::list::iterator it = subWidgets.begin(); it != subWidgets.end(); ++it) + { + SubWidget* const subwidget(*it); + + if (subwidget->isVisible()) + subwidget->pData->display(width, height, autoScaleFactor); + } +} + +// ----------------------------------------------------------------------- + +bool Widget::PrivateData::giveKeyboardEventForSubWidgets(const KeyboardEvent& ev) +{ + if (! visible) + return false; + if (subWidgets.size() == 0) + return false; + + FOR_EACH_SUBWIDGET_INV(rit) + { + SubWidget* const widget(*rit); + + if (widget->isVisible() && widget->onKeyboard(ev)) + return true; + } + + return false; +} + +bool Widget::PrivateData::giveCharacterInputEventForSubWidgets(const CharacterInputEvent& ev) +{ + if (! visible) + return false; + if (subWidgets.size() == 0) + return false; + + FOR_EACH_SUBWIDGET_INV(rit) + { + SubWidget* const widget(*rit); + + if (widget->isVisible() && widget->onCharacterInput(ev)) + return true; + } + + return false; +} + +bool Widget::PrivateData::giveMouseEventForSubWidgets(MouseEvent& ev) +{ + if (! visible) + return false; + if (subWidgets.size() == 0) + return false; + + const double x = ev.absolutePos.getX(); + const double y = ev.absolutePos.getY(); + + if (SubWidget* const selfw = dynamic_cast(self)) + { + if (selfw->pData->needsViewportScaling) + { + ev.absolutePos.setX(x - selfw->getAbsoluteX() + selfw->getMargin().getX()); + ev.absolutePos.setY(y - selfw->getAbsoluteY() + selfw->getMargin().getY()); + } + } + + FOR_EACH_SUBWIDGET_INV(rit) + { + SubWidget* const widget(*rit); + + if (! widget->isVisible()) + continue; + + ev.pos = Point(x - widget->getAbsoluteX() + widget->getMargin().getX(), + y - widget->getAbsoluteY() + widget->getMargin().getY()); + + if (widget->onMouse(ev)) + return true; + } + + return false; +} + +bool Widget::PrivateData::giveMotionEventForSubWidgets(MotionEvent& ev) +{ + if (! visible) + return false; + if (subWidgets.size() == 0) + return false; + + const double x = ev.absolutePos.getX(); + const double y = ev.absolutePos.getY(); + + if (SubWidget* const selfw = dynamic_cast(self)) + { + if (selfw->pData->needsViewportScaling) + { + ev.absolutePos.setX(x - selfw->getAbsoluteX() + selfw->getMargin().getX()); + ev.absolutePos.setY(y - selfw->getAbsoluteY() + selfw->getMargin().getY()); + } + } + + FOR_EACH_SUBWIDGET_INV(rit) + { + SubWidget* const widget(*rit); + + if (! widget->isVisible()) + continue; + + ev.pos = Point(x - widget->getAbsoluteX() + widget->getMargin().getX(), + y - widget->getAbsoluteY() + widget->getMargin().getY()); + + if (widget->onMotion(ev)) + return true; + } + + return false; +} + +bool Widget::PrivateData::giveScrollEventForSubWidgets(ScrollEvent& ev) +{ + if (! visible) + return false; + if (subWidgets.size() == 0) + return false; + + const double x = ev.absolutePos.getX(); + const double y = ev.absolutePos.getY(); + + if (SubWidget* const selfw = dynamic_cast(self)) + { + if (selfw->pData->needsViewportScaling) + { + ev.absolutePos.setX(x - selfw->getAbsoluteX() + selfw->getMargin().getX()); + ev.absolutePos.setY(y - selfw->getAbsoluteY() + selfw->getMargin().getY()); + } + } + + FOR_EACH_SUBWIDGET_INV(rit) + { + SubWidget* const widget(*rit); + + if (! widget->isVisible()) + continue; + + ev.pos = Point(x - widget->getAbsoluteX() + widget->getMargin().getX(), + y - widget->getAbsoluteY() + widget->getMargin().getY()); + + if (widget->onScroll(ev)) + return true; + } + + return false; +} + +// ----------------------------------------------------------------------- + +TopLevelWidget* Widget::PrivateData::findTopLevelWidget(Widget* const pw) +{ + if (pw->pData->topLevelWidget != nullptr) + return pw->pData->topLevelWidget; + if (pw->pData->parentWidget != nullptr) + return findTopLevelWidget(pw->pData->parentWidget); + return nullptr; +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/WidgetPrivateData.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/WidgetPrivateData.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,62 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED +#define DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED + +#include "../Widget.hpp" + +#include + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +struct Widget::PrivateData { + Widget* const self; + TopLevelWidget* const topLevelWidget; + Widget* const parentWidget; + uint id; + char* name; + bool needsScaling; + bool visible; + Size size; + std::list subWidgets; + + // called via TopLevelWidget + explicit PrivateData(Widget* const s, TopLevelWidget* const tlw); + // called via SubWidget + explicit PrivateData(Widget* const s, Widget* const pw); + ~PrivateData(); + + void displaySubWidgets(uint width, uint height, double autoScaleFactor); + + bool giveKeyboardEventForSubWidgets(const KeyboardEvent& ev); + bool giveCharacterInputEventForSubWidgets(const CharacterInputEvent& ev); + bool giveMouseEventForSubWidgets(MouseEvent& ev); + bool giveMotionEventForSubWidgets(MotionEvent& ev); + bool giveScrollEventForSubWidgets(ScrollEvent& ev); + + static TopLevelWidget* findTopLevelWidget(Widget* const w); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/Window.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/Window.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,546 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "WindowPrivateData.hpp" +#include "../TopLevelWidget.hpp" + +#include "pugl.hpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- +// ScopedGraphicsContext + +Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win) + : window(win), + ppData(nullptr), + active(puglBackendEnter(window.pData->view)), + reenter(false) {} + +Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win, Window& transientWin) + : window(win), + ppData(transientWin.pData), + active(false), + reenter(true) +{ + puglBackendLeave(ppData->view); + active = puglBackendEnter(window.pData->view); +} + +Window::ScopedGraphicsContext::~ScopedGraphicsContext() +{ + done(); +} + +void Window::ScopedGraphicsContext::done() +{ + if (active) + { + puglBackendLeave(window.pData->view); + active = false; + } + + if (reenter) + { + reenter = false; + DISTRHO_SAFE_ASSERT_RETURN(ppData != nullptr,); + + puglBackendEnter(ppData->view); + } +} + +void Window::ScopedGraphicsContext::reinit() +{ + DISTRHO_SAFE_ASSERT_RETURN(!active,); + DISTRHO_SAFE_ASSERT_RETURN(!reenter,); + DISTRHO_SAFE_ASSERT_RETURN(ppData != nullptr,); + + reenter = true; + puglBackendLeave(ppData->view); + active = puglBackendEnter(window.pData->view); +} + +// ----------------------------------------------------------------------- +// Window + +Window::Window(Application& app) + : pData(new PrivateData(app, this)) +{ + pData->initPost(); +} + +Window::Window(Application& app, Window& transientParentWindow) + : pData(new PrivateData(app, this, transientParentWindow.pData)) +{ + pData->initPost(); +} + +Window::Window(Application& app, + const uintptr_t parentWindowHandle, + const double scaleFactor, + const bool resizable) + : pData(new PrivateData(app, this, parentWindowHandle, scaleFactor, resizable)) +{ + pData->initPost(); +} + +Window::Window(Application& app, + const uintptr_t parentWindowHandle, + const uint width, + const uint height, + const double scaleFactor, + const bool resizable) + : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, false)) +{ + pData->initPost(); +} + +Window::Window(Application& app, + const uintptr_t parentWindowHandle, + const uint width, + const uint height, + const double scaleFactor, + const bool resizable, + const bool isVST3, + const bool doPostInit) + : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, isVST3)) +{ + if (doPostInit) + pData->initPost(); +} + +Window::~Window() +{ + delete pData; +} + +bool Window::isEmbed() const noexcept +{ + return pData->isEmbed; +} + +bool Window::isVisible() const noexcept +{ + return pData->isVisible; +} + +void Window::setVisible(const bool visible) +{ + if (visible) + pData->show(); + else + pData->hide(); +} + +void Window::show() +{ + pData->show(); +} + +void Window::hide() +{ + pData->hide(); +} + +void Window::close() +{ + pData->close(); +} + +bool Window::isResizable() const noexcept +{ + return puglGetViewHint(pData->view, PUGL_RESIZABLE) == PUGL_TRUE; +} + +void Window::setResizable(const bool resizable) +{ + pData->setResizable(resizable); +} + +int Window::getOffsetX() const noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); + + return puglGetFrame(pData->view).x; +} + +int Window::getOffsetY() const noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); + + return puglGetFrame(pData->view).y; +} + +Point Window::getOffset() const noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Point()); + + const PuglRect rect = puglGetFrame(pData->view); + return Point(rect.x, rect.y); +} + +void Window::setOffsetX(const int x) +{ + setOffset(x, getOffsetY()); +} + +void Window::setOffsetY(const int y) +{ + setOffset(getOffsetX(), y); +} + +void Window::setOffset(const int x, const int y) +{ + puglSetPosition(pData->view, x, y); +} + +void Window::setOffset(const Point& offset) +{ + setOffset(offset.getX(), offset.getY()); +} + +uint Window::getWidth() const noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); + + const double width = puglGetFrame(pData->view).width; + DISTRHO_SAFE_ASSERT_RETURN(width >= 0.0, 0); + return static_cast(width + 0.5); +} + +uint Window::getHeight() const noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0); + + const double height = puglGetFrame(pData->view).height; + DISTRHO_SAFE_ASSERT_RETURN(height >= 0.0, 0); + return static_cast(height + 0.5); +} + +Size Window::getSize() const noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Size()); + + const PuglRect rect = puglGetFrame(pData->view); + DISTRHO_SAFE_ASSERT_RETURN(rect.width >= 0.0, Size()); + DISTRHO_SAFE_ASSERT_RETURN(rect.height >= 0.0, Size()); + return Size(static_cast(rect.width + 0.5), + static_cast(rect.height + 0.5)); +} + +void Window::setWidth(const uint width) +{ + setSize(width, getHeight()); +} + +void Window::setHeight(const uint height) +{ + setSize(getWidth(), height); +} + +void Window::setSize(uint width, uint height) +{ + DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,); + + if (pData->isEmbed) + { + const double scaleFactor = pData->scaleFactor; + uint minWidth = pData->minWidth; + uint minHeight = pData->minHeight; + + if (pData->autoScaling && scaleFactor != 1.0) + { + minWidth *= scaleFactor; + minHeight *= scaleFactor; + } + + // handle geometry constraints here + if (width < minWidth) + width = minWidth; + + if (height < minHeight) + height = minHeight; + + if (pData->keepAspectRatio) + { + const double ratio = static_cast(pData->minWidth) + / static_cast(pData->minHeight); + const double reqRatio = static_cast(width) + / static_cast(height); + + if (d_isNotEqual(ratio, reqRatio)) + { + // fix width + if (reqRatio > ratio) + width = static_cast(height * ratio + 0.5); + // fix height + else + height = static_cast(static_cast(width) / ratio + 0.5); + } + } + } + + if (pData->usesSizeRequest) + { + DISTRHO_SAFE_ASSERT_RETURN(pData->topLevelWidgets.size() != 0,); + + TopLevelWidget* const topLevelWidget = pData->topLevelWidgets.front(); + DISTRHO_SAFE_ASSERT_RETURN(topLevelWidget != nullptr,); + + topLevelWidget->requestSizeChange(width, height); + } + else + { + puglSetSizeAndDefault(pData->view, width, height); + } +} + +void Window::setSize(const Size& size) +{ + setSize(size.getWidth(), size.getHeight()); +} + +const char* Window::getTitle() const noexcept +{ + return puglGetWindowTitle(pData->view); +} + +void Window::setTitle(const char* const title) +{ + if (pData->view != nullptr) + puglSetWindowTitle(pData->view, title); +} + +bool Window::isIgnoringKeyRepeat() const noexcept +{ + return puglGetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT) == PUGL_TRUE; +} + +void Window::setIgnoringKeyRepeat(const bool ignore) noexcept +{ + puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore); +} + +const void* Window::getClipboard(size_t& dataSize) +{ + return pData->getClipboard(dataSize); +} + +bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize) +{ + return puglSetClipboard(pData->view, mimeType != nullptr ? mimeType : "text/plain", data, dataSize) == PUGL_SUCCESS; +} + +bool Window::setCursor(const MouseCursor cursor) +{ + return puglSetCursor(pData->view, static_cast(cursor)) == PUGL_SUCCESS; +} + +bool Window::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) +{ + DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false) + + return pData->addIdleCallback(callback, timerFrequencyInMs); +} + +bool Window::removeIdleCallback(IdleCallback* const callback) +{ + DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false) + + return pData->removeIdleCallback(callback); +} + +Application& Window::getApp() const noexcept +{ + return pData->app; +} + +#ifndef DPF_TEST_WINDOW_CPP +const GraphicsContext& Window::getGraphicsContext() const noexcept +{ + return pData->getGraphicsContext(); +} +#endif + +uintptr_t Window::getNativeWindowHandle() const noexcept +{ + return puglGetNativeView(pData->view); +} + +double Window::getScaleFactor() const noexcept +{ + return pData->scaleFactor; +} + +void Window::focus() +{ + pData->focus(); +} + +#ifndef DGL_FILE_BROWSER_DISABLED +bool Window::openFileBrowser(const FileBrowserOptions& options) +{ + return pData->openFileBrowser(options); +} +#endif + +void Window::repaint() noexcept +{ + if (pData->view == nullptr) + return; + + puglPostRedisplay(pData->view); +} + +void Window::repaint(const Rectangle& rect) noexcept +{ + if (pData->view == nullptr) + return; + + PuglRect prect = { + static_cast(rect.getX()), + static_cast(rect.getY()), + static_cast(rect.getWidth()), + static_cast(rect.getHeight()), + }; + if (pData->autoScaling) + { + const double autoScaleFactor = pData->autoScaleFactor; + + prect.x *= autoScaleFactor; + prect.y *= autoScaleFactor; + prect.width *= autoScaleFactor; + prect.height *= autoScaleFactor; + } + puglPostRedisplayRect(pData->view, prect); +} + +void Window::renderToPicture(const char* const filename) +{ + pData->filenameToRenderInto = strdup(filename); +} + +void Window::runAsModal(bool blockWait) +{ + pData->runAsModal(blockWait); +} + +Size Window::getGeometryConstraints(bool& keepAspectRatio) +{ + keepAspectRatio = pData->keepAspectRatio; + return Size(pData->minWidth, pData->minHeight); +} + +void Window::setGeometryConstraints(uint minimumWidth, + uint minimumHeight, + const bool keepAspectRatio, + const bool automaticallyScale, + const bool resizeNowIfAutoScaling) +{ + DISTRHO_SAFE_ASSERT_RETURN(minimumWidth > 0,); + DISTRHO_SAFE_ASSERT_RETURN(minimumHeight > 0,); + + pData->minWidth = minimumWidth; + pData->minHeight = minimumHeight; + pData->autoScaling = automaticallyScale; + pData->keepAspectRatio = keepAspectRatio; + + if (pData->view == nullptr) + return; + + const double scaleFactor = pData->scaleFactor; + + if (automaticallyScale && scaleFactor != 1.0) + { + minimumWidth *= scaleFactor; + minimumHeight *= scaleFactor; + } + + puglSetGeometryConstraints(pData->view, minimumWidth, minimumHeight, keepAspectRatio); + + if (scaleFactor != 1.0 && automaticallyScale && resizeNowIfAutoScaling) + { + const Size size(getSize()); + + setSize(static_cast(size.getWidth() * scaleFactor + 0.5), + static_cast(size.getHeight() * scaleFactor + 0.5)); + } +} + +void Window::setTransientParent(const uintptr_t transientParentWindowHandle) +{ + puglSetTransientParent(pData->view, transientParentWindowHandle); +} + +std::vector Window::getClipboardDataOfferTypes() +{ + std::vector offerTypes; + + if (const uint32_t numTypes = puglGetNumClipboardTypes(pData->view)) + { + offerTypes.reserve(numTypes); + + for (uint32_t i=0; iview, i) }; + offerTypes.push_back(offer); + } + } + + return offerTypes; +} + +uint32_t Window::onClipboardDataOffer() +{ + std::vector offers(getClipboardDataOfferTypes()); + + for (std::vector::iterator it=offers.begin(), end=offers.end(); it != end;++it) + { + const ClipboardDataOffer offer = *it; + if (std::strcmp(offer.type, "text/plain") == 0) + return offer.id; + } + + return 0; +} + +bool Window::onClose() +{ + return true; +} + +void Window::onFocus(bool, CrossingMode) +{ +} + +void Window::onReshape(uint, uint) +{ + puglFallbackOnResize(pData->view); +} + +void Window::onScaleFactorChanged(double) +{ +} + +#ifndef DGL_FILE_BROWSER_DISABLED +void Window::onFileSelected(const char*) +{ +} +#endif + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/WindowPrivateData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/WindowPrivateData.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1191 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "WindowPrivateData.hpp" +#include "TopLevelWidgetPrivateData.hpp" + +#include "pugl.hpp" + +// #define DGL_DEBUG_EVENTS + +#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) +# ifdef DISTRHO_PROPER_CPP11_SUPPORT +# include +# else +# include +# endif +#endif + +START_NAMESPACE_DGL + +#ifdef DGL_DEBUG_EVENTS +# define DGL_DBG(msg) std::fprintf(stderr, "%s", msg); +# define DGL_DBGp(...) std::fprintf(stderr, __VA_ARGS__); +# define DGL_DBGF std::fflush(stderr); +#else +# define DGL_DBG(msg) +# define DGL_DBGp(...) +# define DGL_DBGF +#endif + +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 + +#define FOR_EACH_TOP_LEVEL_WIDGET(it) \ + for (std::list::iterator it = topLevelWidgets.begin(); it != topLevelWidgets.end(); ++it) + +#define FOR_EACH_TOP_LEVEL_WIDGET_INV(rit) \ + for (std::list::reverse_iterator rit = topLevelWidgets.rbegin(); rit != topLevelWidgets.rend(); ++rit) + +// ----------------------------------------------------------------------- + +static double getScaleFactorFromParent(const PuglView* const view) +{ + // allow custom scale for testing + if (const char* const scale = getenv("DPF_SCALE_FACTOR")) + return std::max(1.0, std::atof(scale)); + + if (view != nullptr) + return puglGetScaleFactorFromParent(view); + + return 1.0; +} + +static PuglView* puglNewViewWithTransientParent(PuglWorld* const world, PuglView* const transientParentView) +{ + DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, nullptr); + + if (PuglView* const view = puglNewView(world)) + { + puglSetTransientParent(view, puglGetNativeView(transientParentView)); + return view; + } + + return nullptr; +} + +static PuglView* puglNewViewWithParentWindow(PuglWorld* const world, const uintptr_t parentWindowHandle) +{ + DISTRHO_SAFE_ASSERT_RETURN(world != nullptr, nullptr); + + if (PuglView* const view = puglNewView(world)) + { + puglSetParentWindow(view, parentWindowHandle); + return view; + } + + return nullptr; +} + +// ----------------------------------------------------------------------- + +Window::PrivateData::PrivateData(Application& a, Window* const s) + : app(a), + appData(a.pData), + self(s), + view(appData->world != nullptr ? puglNewView(appData->world) : nullptr), + topLevelWidgets(), + isClosed(true), + isVisible(false), + isEmbed(false), + usesSizeRequest(false), + scaleFactor(getScaleFactorFromParent(view)), + autoScaling(false), + autoScaleFactor(1.0), + minWidth(0), + minHeight(0), + keepAspectRatio(false), + ignoreIdleCallbacks(false), + waitingForClipboardData(false), + waitingForClipboardEvents(false), + clipboardTypeId(0), + filenameToRenderInto(nullptr), +#ifndef DGL_FILE_BROWSER_DISABLED + fileBrowserHandle(nullptr), +#endif + modal() +{ + initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); +} + +Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* const ppData) + : app(a), + appData(a.pData), + self(s), + view(puglNewViewWithTransientParent(appData->world, ppData->view)), + topLevelWidgets(), + isClosed(true), + isVisible(false), + isEmbed(false), + usesSizeRequest(false), + scaleFactor(ppData->scaleFactor), + autoScaling(false), + autoScaleFactor(1.0), + minWidth(0), + minHeight(0), + keepAspectRatio(false), + ignoreIdleCallbacks(false), + waitingForClipboardData(false), + waitingForClipboardEvents(false), + clipboardTypeId(0), + filenameToRenderInto(nullptr), +#ifndef DGL_FILE_BROWSER_DISABLED + fileBrowserHandle(nullptr), +#endif + modal(ppData) +{ + initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); +} + +Window::PrivateData::PrivateData(Application& a, Window* const s, + const uintptr_t parentWindowHandle, + const double scale, const bool resizable) + : app(a), + appData(a.pData), + self(s), + view(puglNewViewWithParentWindow(appData->world, parentWindowHandle)), + topLevelWidgets(), + isClosed(parentWindowHandle == 0), + isVisible(parentWindowHandle != 0), + isEmbed(parentWindowHandle != 0), + usesSizeRequest(false), + scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), + autoScaling(false), + autoScaleFactor(1.0), + minWidth(0), + minHeight(0), + keepAspectRatio(false), + ignoreIdleCallbacks(false), + waitingForClipboardData(false), + waitingForClipboardEvents(false), + clipboardTypeId(0), + filenameToRenderInto(nullptr), +#ifndef DGL_FILE_BROWSER_DISABLED + fileBrowserHandle(nullptr), +#endif + modal() +{ + initPre(DEFAULT_WIDTH, DEFAULT_HEIGHT, resizable); +} + +Window::PrivateData::PrivateData(Application& a, Window* const s, + const uintptr_t parentWindowHandle, + const uint width, const uint height, + const double scale, const bool resizable, const bool usesSizeRequest_) + : app(a), + appData(a.pData), + self(s), + view(puglNewViewWithParentWindow(appData->world, parentWindowHandle)), + topLevelWidgets(), + isClosed(parentWindowHandle == 0), + isVisible(parentWindowHandle != 0 && view != nullptr), + isEmbed(parentWindowHandle != 0), + usesSizeRequest(usesSizeRequest_), + scaleFactor(scale != 0.0 ? scale : getScaleFactorFromParent(view)), + autoScaling(false), + autoScaleFactor(1.0), + minWidth(0), + minHeight(0), + keepAspectRatio(false), + ignoreIdleCallbacks(false), + waitingForClipboardData(false), + waitingForClipboardEvents(false), + clipboardTypeId(0), + filenameToRenderInto(nullptr), +#ifndef DGL_FILE_BROWSER_DISABLED + fileBrowserHandle(nullptr), +#endif + modal() +{ + if (isEmbed) + puglSetParentWindow(view, parentWindowHandle); + + initPre(width != 0 ? width : DEFAULT_WIDTH, height != 0 ? height : DEFAULT_HEIGHT, resizable); +} + +Window::PrivateData::~PrivateData() +{ + appData->idleCallbacks.remove(this); + appData->windows.remove(self); + std::free(filenameToRenderInto); + + if (view == nullptr) + return; + + if (isEmbed) + { +#ifndef DGL_FILE_BROWSER_DISABLED + if (fileBrowserHandle != nullptr) + fileBrowserClose(fileBrowserHandle); +#endif + puglHide(view); + appData->oneWindowClosed(); + isClosed = true; + isVisible = false; + } + + puglFreeView(view); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::initPre(const uint width, const uint height, const bool resizable) +{ + appData->windows.push_back(self); + appData->idleCallbacks.push_back(this); + memset(graphicsContext, 0, sizeof(graphicsContext)); + + if (view == nullptr) + { + d_stderr2("Failed to create Pugl view, everything will fail!"); + return; + } + + puglSetMatchingBackendForCurrentBuild(view); + puglSetHandle(view, this); + + puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); + puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, PUGL_FALSE); +#if DGL_USE_RGBA + puglSetViewHint(view, PUGL_DEPTH_BITS, 24); +#else + puglSetViewHint(view, PUGL_DEPTH_BITS, 16); +#endif + puglSetViewHint(view, PUGL_STENCIL_BITS, 8); + + // PUGL_SAMPLES ?? + puglSetEventFunc(view, puglEventCallback); + + // setting default size triggers system-level calls, do it last + puglSetSizeHint(view, PUGL_DEFAULT_SIZE, width, height); +} + +bool Window::PrivateData::initPost() +{ + if (view == nullptr) + return false; + + // create view now, as a few methods we allow devs to use require it + if (puglRealize(view) != PUGL_SUCCESS) + { + view = nullptr; + d_stderr2("Failed to realize Pugl view, everything will fail!"); + return false; + } + + if (isEmbed) + { + appData->oneWindowShown(); + puglShow(view); + } + + return true; +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::close() +{ + DGL_DBG("Window close\n"); + // DGL_DBGp("Window close DBG %i %i %p\n", isEmbed, isClosed, appData); + + if (isEmbed || isClosed) + return; + + isClosed = true; + hide(); + appData->oneWindowClosed(); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::show() +{ + if (isVisible) + { + DGL_DBG("Window show matches current visible state, ignoring request\n"); + return; + } + if (isEmbed) + { + DGL_DBG("Window show cannot be called when embedded\n"); + return; + } + + DGL_DBG("Window show called\n"); + + if (view == nullptr) + return; + + if (isClosed) + { + isClosed = false; + appData->oneWindowShown(); + + // FIXME +// PuglRect rect = puglGetFrame(view); +// puglSetWindowSize(view, static_cast(rect.width), static_cast(rect.height)); + +#if defined(DISTRHO_OS_WINDOWS) + puglWin32ShowCentered(view); +#elif defined(DISTRHO_OS_MAC) + puglMacOSShowCentered(view); +#else + puglShow(view); +#endif + } + else + { +#ifdef DISTRHO_OS_WINDOWS + puglWin32RestoreWindow(view); +#else + puglShow(view); +#endif + } + + isVisible = true; +} + +void Window::PrivateData::hide() +{ + if (isEmbed) + { + DGL_DBG("Window hide cannot be called when embedded\n"); + return; + } + if (! isVisible) + { + DGL_DBG("Window hide matches current visible state, ignoring request\n"); + return; + } + + DGL_DBG("Window hide called\n"); + + if (modal.enabled) + stopModal(); + +#ifndef DGL_FILE_BROWSER_DISABLED + if (fileBrowserHandle != nullptr) + { + fileBrowserClose(fileBrowserHandle); + fileBrowserHandle = nullptr; + } +#endif + + puglHide(view); + + isVisible = false; +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::focus() +{ + if (view == nullptr) + return; + + if (! isEmbed) + puglRaiseWindow(view); + + puglGrabFocus(view); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::setResizable(const bool resizable) +{ + DISTRHO_SAFE_ASSERT_RETURN(! isEmbed,); + + DGL_DBG("Window setResizable called\n"); + + puglSetResizable(view, resizable); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::idleCallback() +{ +#ifndef DGL_FILE_BROWSER_DISABLED + if (fileBrowserHandle != nullptr && fileBrowserIdle(fileBrowserHandle)) + { + self->onFileSelected(fileBrowserGetPath(fileBrowserHandle)); + fileBrowserClose(fileBrowserHandle); + fileBrowserHandle = nullptr; + } +#endif +} + +// ----------------------------------------------------------------------- +// idle callback stuff + +bool Window::PrivateData::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs) +{ + if (ignoreIdleCallbacks) + return false; + + if (timerFrequencyInMs == 0) + { + appData->idleCallbacks.push_back(callback); + return true; + } + + return puglStartTimer(view, (uintptr_t)callback, static_cast(timerFrequencyInMs) / 1000.0) == PUGL_SUCCESS; +} + +bool Window::PrivateData::removeIdleCallback(IdleCallback* const callback) +{ + if (ignoreIdleCallbacks) + return false; + + if (std::find(appData->idleCallbacks.begin(), + appData->idleCallbacks.end(), callback) != appData->idleCallbacks.end()) + { + appData->idleCallbacks.remove(callback); + return true; + } + + return puglStopTimer(view, (uintptr_t)callback) == PUGL_SUCCESS; +} + +#ifndef DGL_FILE_BROWSER_DISABLED +// ----------------------------------------------------------------------- +// file handling + +bool Window::PrivateData::openFileBrowser(const FileBrowserOptions& options) +{ + if (fileBrowserHandle != nullptr) + fileBrowserClose(fileBrowserHandle); + + FileBrowserOptions options2 = options; + + if (options2.title == nullptr) + options2.title = puglGetWindowTitle(view); + + fileBrowserHandle = fileBrowserCreate(isEmbed, + puglGetNativeView(view), + autoScaling ? autoScaleFactor : scaleFactor, + options2); + + return fileBrowserHandle != nullptr; +} +#endif // ! DGL_FILE_BROWSER_DISABLED + +// ----------------------------------------------------------------------- +// modal handling + +void Window::PrivateData::startModal() +{ + DGL_DBG("Window modal loop starting..."); DGL_DBGF; + DISTRHO_SAFE_ASSERT_RETURN(modal.parent != nullptr, show()); + + // activate modal mode for this window + modal.enabled = true; + + // make parent give focus to us + modal.parent->modal.child = this; + + // make sure both parent and ourselves are visible + modal.parent->show(); + show(); + +#ifdef DISTRHO_OS_MAC + puglMacOSAddChildWindow(modal.parent->view, view); +#endif + + DGL_DBG("Ok\n"); +} + +void Window::PrivateData::stopModal() +{ + DGL_DBG("Window modal loop stopping..."); DGL_DBGF; + + // deactivate modal mode + modal.enabled = false; + + // safety checks, make sure we have a parent and we are currently active as the child to give focus to + if (modal.parent == nullptr) + return; + if (modal.parent->modal.child != this) + return; + +#ifdef DISTRHO_OS_MAC + puglMacOSRemoveChildWindow(modal.parent->view, view); +#endif + + // stop parent from giving focus to us, so it behaves like normal + modal.parent->modal.child = nullptr; + + // refocus main window after closing child + if (! modal.parent->isClosed) + { + const Widget::MotionEvent ev; + modal.parent->onPuglMotion(ev); + modal.parent->focus(); + } + + DGL_DBG("Ok\n"); +} + +void Window::PrivateData::runAsModal(const bool blockWait) +{ + DGL_DBGp("Window::PrivateData::runAsModal %i\n", blockWait); + startModal(); + + if (blockWait) + { + DISTRHO_SAFE_ASSERT_RETURN(appData->isStandalone,); + + while (isVisible && modal.enabled) + appData->idle(10); + + stopModal(); + } + else + { + appData->idle(0); + } +} + +// ----------------------------------------------------------------------- +// pugl events + +void Window::PrivateData::onPuglConfigure(const double width, const double height) +{ + DISTRHO_SAFE_ASSERT_INT2_RETURN(width > 1 && height > 1, width, height,); + + DGL_DBGp("PUGL: onReshape : %f %f\n", width, height); + + if (autoScaling) + { + const double scaleHorizontal = width / static_cast(minWidth); + const double scaleVertical = height / static_cast(minHeight); + autoScaleFactor = scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical; + } + + const uint uwidth = static_cast(width + 0.5); + const uint uheight = static_cast(height + 0.5); + + self->onReshape(uwidth, uheight); + +#ifndef DPF_TEST_WINDOW_CPP + FOR_EACH_TOP_LEVEL_WIDGET(it) + { + TopLevelWidget* const widget(*it); + + /* Some special care here, we call Widget::setSize instead of the TopLevelWidget one. + * This is because we want TopLevelWidget::setSize to handle both window and widget size, + * but we dont want to change window size here, because we are the window.. + * So we just call the Widget specific method manually. + * + * Alternatively, we could expose a resize function on the pData, like done with the display function. + * But there is nothing extra we need to do in there, so this works fine. + */ + ((Widget*)widget)->setSize(uwidth, uheight); + } +#endif + + // always repaint after a resize + puglPostRedisplay(view); +} + +void Window::PrivateData::onPuglExpose() +{ + // DGL_DBG("PUGL: onPuglExpose\n"); + + puglOnDisplayPrepare(view); + +#ifndef DPF_TEST_WINDOW_CPP + FOR_EACH_TOP_LEVEL_WIDGET(it) + { + TopLevelWidget* const widget(*it); + + if (widget->isVisible()) + widget->pData->display(); + } + + if (char* const filename = filenameToRenderInto) + { + const PuglRect rect = puglGetFrame(view); + filenameToRenderInto = nullptr; + renderToPicture(filename, getGraphicsContext(), static_cast(rect.width), static_cast(rect.height)); + std::free(filename); + } +#endif +} + +void Window::PrivateData::onPuglClose() +{ + DGL_DBG("PUGL: onClose\n"); + +#ifndef DISTRHO_OS_MAC + // if we are running as standalone we can prevent closing in certain conditions + if (appData->isStandalone) + { + // a child window is active, gives focus to it + if (modal.child != nullptr) + return modal.child->focus(); + + // ask window if we should close + if (! self->onClose()) + return; + } +#endif + + if (modal.enabled) + stopModal(); + + if (modal.child != nullptr) + { + modal.child->close(); + modal.child = nullptr; + } + + close(); +} + +void Window::PrivateData::onPuglFocus(const bool focus, const CrossingMode mode) +{ + DGL_DBGp("onPuglFocus : %i %i | %i\n", focus, mode, isClosed); + + if (isClosed) + return; + + if (modal.child != nullptr) + return modal.child->focus(); + + self->onFocus(focus, mode); +} + +void Window::PrivateData::onPuglKey(const Widget::KeyboardEvent& ev) +{ + DGL_DBGp("onPuglKey : %i %u %u\n", ev.press, ev.key, ev.keycode); + + if (modal.child != nullptr) + return modal.child->focus(); + +#ifndef DPF_TEST_WINDOW_CPP + FOR_EACH_TOP_LEVEL_WIDGET_INV(rit) + { + TopLevelWidget* const widget(*rit); + + if (widget->isVisible() && widget->onKeyboard(ev)) + break; + } +#endif +} + +void Window::PrivateData::onPuglText(const Widget::CharacterInputEvent& ev) +{ + DGL_DBGp("onPuglText : %u %u %s\n", ev.keycode, ev.character, ev.string); + + if (modal.child != nullptr) + return modal.child->focus(); + +#ifndef DPF_TEST_WINDOW_CPP + FOR_EACH_TOP_LEVEL_WIDGET_INV(rit) + { + TopLevelWidget* const widget(*rit); + + if (widget->isVisible() && widget->onCharacterInput(ev)) + break; + } +#endif +} + +void Window::PrivateData::onPuglMouse(const Widget::MouseEvent& ev) +{ + DGL_DBGp("onPuglMouse : %i %i %f %f\n", ev.button, ev.press, ev.pos.getX(), ev.pos.getY()); + + if (modal.child != nullptr) + return modal.child->focus(); + +#ifndef DPF_TEST_WINDOW_CPP + FOR_EACH_TOP_LEVEL_WIDGET_INV(rit) + { + TopLevelWidget* const widget(*rit); + + if (widget->isVisible() && widget->onMouse(ev)) + break; + } +#endif +} + +void Window::PrivateData::onPuglMotion(const Widget::MotionEvent& ev) +{ + DGL_DBGp("onPuglMotion : %f %f\n", ev.pos.getX(), ev.pos.getY()); + + if (modal.child != nullptr) + return modal.child->focus(); + +#ifndef DPF_TEST_WINDOW_CPP + FOR_EACH_TOP_LEVEL_WIDGET_INV(rit) + { + TopLevelWidget* const widget(*rit); + + if (widget->isVisible() && widget->onMotion(ev)) + break; + } +#endif +} + +void Window::PrivateData::onPuglScroll(const Widget::ScrollEvent& ev) +{ + DGL_DBGp("onPuglScroll : %f %f %f %f\n", ev.pos.getX(), ev.pos.getY(), ev.delta.getX(), ev.delta.getY()); + + if (modal.child != nullptr) + return modal.child->focus(); + +#ifndef DPF_TEST_WINDOW_CPP + FOR_EACH_TOP_LEVEL_WIDGET_INV(rit) + { + TopLevelWidget* const widget(*rit); + + if (widget->isVisible() && widget->onScroll(ev)) + break; + } +#endif +} + +const void* Window::PrivateData::getClipboard(size_t& dataSize) +{ + clipboardTypeId = 0; + waitingForClipboardData = true, + waitingForClipboardEvents = true; + + // begin clipboard dance here + if (puglPaste(view) != PUGL_SUCCESS) + { + dataSize = 0; + waitingForClipboardEvents = false; + return nullptr; + } + + #ifdef DGL_USING_X11 + // wait for type request, clipboardTypeId must be != 0 to be valid + int retry = static_cast(2 / 0.03); + while (clipboardTypeId == 0 && waitingForClipboardData && --retry >= 0) + { + if (puglX11UpdateWithoutExposures(appData->world) != PUGL_SUCCESS) + break; + } + #endif + + if (clipboardTypeId == 0) + { + dataSize = 0; + waitingForClipboardEvents = false; + return nullptr; + } + + #ifdef DGL_USING_X11 + // wait for actual data (assumes offer was accepted) + retry = static_cast(2 / 0.03); + while (waitingForClipboardData && --retry >= 0) + { + if (puglX11UpdateWithoutExposures(appData->world) != PUGL_SUCCESS) + break; + } + #endif + + if (clipboardTypeId == 0) + { + dataSize = 0; + waitingForClipboardEvents = false; + return nullptr; + } + + waitingForClipboardEvents = false; + return puglGetClipboard(view, clipboardTypeId - 1, &dataSize); +} + +uint32_t Window::PrivateData::onClipboardDataOffer() +{ + DGL_DBG("onClipboardDataOffer\n"); + + if ((clipboardTypeId = self->onClipboardDataOffer()) != 0) + return clipboardTypeId; + + // stop waiting for data, it was rejected + waitingForClipboardData = false; + return 0; +} + +void Window::PrivateData::onClipboardData(const uint32_t typeId) +{ + if (clipboardTypeId != typeId) + clipboardTypeId = 0; + + waitingForClipboardData = false; +} + +#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) +static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose); +#endif + +PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event) +{ + Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view); +#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) + if (event->type != PUGL_TIMER) { + printEvent(event, "pugl event: ", true); + } +#endif + + if (pData->waitingForClipboardEvents) + { + switch (event->type) + { + case PUGL_UPDATE: + case PUGL_EXPOSE: + case PUGL_FOCUS_IN: + case PUGL_FOCUS_OUT: + case PUGL_KEY_PRESS: + case PUGL_KEY_RELEASE: + case PUGL_TEXT: + case PUGL_POINTER_IN: + case PUGL_POINTER_OUT: + case PUGL_BUTTON_PRESS: + case PUGL_BUTTON_RELEASE: + case PUGL_MOTION: + case PUGL_SCROLL: + case PUGL_TIMER: + case PUGL_LOOP_ENTER: + case PUGL_LOOP_LEAVE: + return PUGL_SUCCESS; + case PUGL_DATA_OFFER: + case PUGL_DATA: + break; + default: + d_stdout("Got event %d while waitingForClipboardEvents", event->type); + break; + } + } + + switch (event->type) + { + ///< No event + case PUGL_NOTHING: + break; + + ///< View created, a #PuglEventCreate + case PUGL_CREATE: + #ifdef DGL_USING_X11 + if (! pData->isEmbed) + puglX11SetWindowTypeAndPID(view, pData->appData->isStandalone); + #endif + break; + + ///< View destroyed, a #PuglEventDestroy + case PUGL_DESTROY: + break; + + ///< View moved/resized, a #PuglEventConfigure + case PUGL_CONFIGURE: + // unused x, y (double) + pData->onPuglConfigure(event->configure.width, event->configure.height); + break; + + ///< View made visible, a #PuglEventMap + case PUGL_MAP: + break; + + ///< View made invisible, a #PuglEventUnmap + case PUGL_UNMAP: + break; + + ///< View ready to draw, a #PuglEventUpdate + case PUGL_UPDATE: + break; + + ///< View must be drawn, a #PuglEventExpose + case PUGL_EXPOSE: + // unused x, y, width, height (double) + pData->onPuglExpose(); + break; + + ///< View will be closed, a #PuglEventClose + case PUGL_CLOSE: + pData->onPuglClose(); + break; + + ///< Keyboard focus entered view, a #PuglEventFocus + case PUGL_FOCUS_IN: + ///< Keyboard focus left view, a #PuglEventFocus + case PUGL_FOCUS_OUT: + pData->onPuglFocus(event->type == PUGL_FOCUS_IN, + static_cast(event->focus.mode)); + break; + + ///< Key pressed, a #PuglEventKey + case PUGL_KEY_PRESS: + ///< Key released, a #PuglEventKey + case PUGL_KEY_RELEASE: + { + // unused x, y, xRoot, yRoot (double) + Widget::KeyboardEvent ev; + ev.mod = event->key.state; + ev.flags = event->key.flags; + ev.time = static_cast(event->key.time * 1000.0 + 0.5); + ev.press = event->type == PUGL_KEY_PRESS; + ev.key = event->key.key; + ev.keycode = event->key.keycode; + + // keyboard events must always be lowercase + if (ev.key >= 'A' && ev.key <= 'Z') + { + ev.key += 'a' - 'A'; // A-Z -> a-z + ev.mod |= kModifierShift; + } + + pData->onPuglKey(ev); + break; + } + + ///< Character entered, a #PuglEventText + case PUGL_TEXT: + { + // unused x, y, xRoot, yRoot (double) + Widget::CharacterInputEvent ev; + ev.mod = event->text.state; + ev.flags = event->text.flags; + ev.time = static_cast(event->text.time * 1000.0 + 0.5); + ev.keycode = event->text.keycode; + ev.character = event->text.character; + std::strncpy(ev.string, event->text.string, sizeof(ev.string)); + pData->onPuglText(ev); + break; + } + + ///< Pointer entered view, a #PuglEventCrossing + case PUGL_POINTER_IN: + break; + ///< Pointer left view, a #PuglEventCrossing + case PUGL_POINTER_OUT: + break; + + ///< Mouse button pressed, a #PuglEventButton + case PUGL_BUTTON_PRESS: + ///< Mouse button released, a #PuglEventButton + case PUGL_BUTTON_RELEASE: + { + Widget::MouseEvent ev; + ev.mod = event->button.state; + ev.flags = event->button.flags; + ev.time = static_cast(event->button.time * 1000.0 + 0.5); + ev.button = event->button.button + 1; + ev.press = event->type == PUGL_BUTTON_PRESS; + ev.pos = Point(event->button.x, event->button.y); + ev.absolutePos = ev.pos; + pData->onPuglMouse(ev); + break; + } + + ///< Pointer moved, a #PuglEventMotion + case PUGL_MOTION: + { + Widget::MotionEvent ev; + ev.mod = event->motion.state; + ev.flags = event->motion.flags; + ev.time = static_cast(event->motion.time * 1000.0 + 0.5); + ev.pos = Point(event->motion.x, event->motion.y); + ev.absolutePos = ev.pos; + pData->onPuglMotion(ev); + break; + } + + ///< Scrolled, a #PuglEventScroll + case PUGL_SCROLL: + { + Widget::ScrollEvent ev; + ev.mod = event->scroll.state; + ev.flags = event->scroll.flags; + ev.time = static_cast(event->scroll.time * 1000.0 + 0.5); + ev.pos = Point(event->scroll.x, event->scroll.y); + ev.delta = Point(event->scroll.dx, event->scroll.dy); + ev.direction = static_cast(event->scroll.direction); + ev.absolutePos = ev.pos; + pData->onPuglScroll(ev); + break; + } + + ///< Custom client message, a #PuglEventClient + case PUGL_CLIENT: + break; + + ///< Timer triggered, a #PuglEventTimer + case PUGL_TIMER: + if (IdleCallback* const idleCallback = reinterpret_cast(event->timer.id)) + idleCallback->idleCallback(); + break; + + ///< Recursive loop entered, a #PuglEventLoopEnter + case PUGL_LOOP_ENTER: + break; + + ///< Recursive loop left, a #PuglEventLoopLeave + case PUGL_LOOP_LEAVE: + break; + + ///< Data offered from clipboard, a #PuglDataOfferEvent + case PUGL_DATA_OFFER: + if (const uint32_t offerTypeId = pData->onClipboardDataOffer()) + puglAcceptOffer(view, &event->offer, offerTypeId - 1); + break; + + ///< Data available from clipboard, a #PuglDataEvent + case PUGL_DATA: + pData->onClipboardData(event->data.typeIndex + 1); + break; + } + + return PUGL_SUCCESS; +} + +// ----------------------------------------------------------------------- + +#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) +static int printModifiers(const uint32_t mods) +{ + return fprintf(stderr, "Modifiers:%s%s%s%s\n", + (mods & PUGL_MOD_SHIFT) ? " Shift" : "", + (mods & PUGL_MOD_CTRL) ? " Ctrl" : "", + (mods & PUGL_MOD_ALT) ? " Alt" : "", + (mods & PUGL_MOD_SUPER) ? " Super" : ""); +} + +static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose) +{ +#define FFMT "%6.1f" +#define PFMT FFMT " " FFMT +#define PRINT(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) + + switch (event->type) { + case PUGL_NOTHING: + return 0; + case PUGL_KEY_PRESS: + return PRINT("%sKey press code %3u key U+%04X\n", + prefix, + event->key.keycode, + event->key.key); + case PUGL_KEY_RELEASE: + return PRINT("%sKey release code %3u key U+%04X\n", + prefix, + event->key.keycode, + event->key.key); + case PUGL_TEXT: + return PRINT("%sText entry code %3u char U+%04X (%s)\n", + prefix, + event->text.keycode, + event->text.character, + event->text.string); + case PUGL_BUTTON_PRESS: + case PUGL_BUTTON_RELEASE: + return (PRINT("%sMouse %u %s at " PFMT " ", + prefix, + event->button.button, + (event->type == PUGL_BUTTON_PRESS) ? "down" : "up ", + event->button.x, + event->button.y) + + printModifiers(event->scroll.state)); + case PUGL_SCROLL: + return (PRINT("%sScroll %5.1f %5.1f at " PFMT " ", + prefix, + event->scroll.dx, + event->scroll.dy, + event->scroll.x, + event->scroll.y) + + printModifiers(event->scroll.state)); + case PUGL_POINTER_IN: + return PRINT("%sMouse enter at " PFMT "\n", + prefix, + event->crossing.x, + event->crossing.y); + case PUGL_POINTER_OUT: + return PRINT("%sMouse leave at " PFMT "\n", + prefix, + event->crossing.x, + event->crossing.y); + case PUGL_FOCUS_IN: + return PRINT("%sFocus in %i\n", + prefix, + event->focus.mode); + case PUGL_FOCUS_OUT: + return PRINT("%sFocus out %i\n", + prefix, + event->focus.mode); + case PUGL_CLIENT: + return PRINT("%sClient %" PRIXPTR " %" PRIXPTR "\n", + prefix, + event->client.data1, + event->client.data2); + case PUGL_TIMER: + return PRINT("%sTimer %" PRIuPTR "\n", prefix, event->timer.id); + default: + break; + } + + if (verbose) { + switch (event->type) { + case PUGL_CREATE: + return fprintf(stderr, "%sCreate\n", prefix); + case PUGL_DESTROY: + return fprintf(stderr, "%sDestroy\n", prefix); + case PUGL_MAP: + return fprintf(stderr, "%sMap\n", prefix); + case PUGL_UNMAP: + return fprintf(stderr, "%sUnmap\n", prefix); + case PUGL_UPDATE: + return 0; // fprintf(stderr, "%sUpdate\n", prefix); + case PUGL_CONFIGURE: + return PRINT("%sConfigure " PFMT " " PFMT "\n", + prefix, + event->configure.x, + event->configure.y, + event->configure.width, + event->configure.height); + case PUGL_EXPOSE: + return PRINT("%sExpose " PFMT " " PFMT "\n", + prefix, + event->expose.x, + event->expose.y, + event->expose.width, + event->expose.height); + case PUGL_CLOSE: + return PRINT("%sClose\n", prefix); + case PUGL_MOTION: + return PRINT("%sMouse motion at " PFMT "\n", + prefix, + event->motion.x, + event->motion.y); + default: + return PRINT("%sUnknown event type %d\n", prefix, (int)event->type); + } + } + +#undef PRINT +#undef PFMT +#undef FFMT + + return 0; +} +#endif + +#undef DGL_DBG +#undef DGL_DBGF + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/WindowPrivateData.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/WindowPrivateData.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,205 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED +#define DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED + +#include "../Window.hpp" +#include "../Widget.hpp" +#include "ApplicationPrivateData.hpp" + +#include "pugl.hpp" + +#include + +START_NAMESPACE_DGL + +class TopLevelWidget; + +// ----------------------------------------------------------------------- + +struct Window::PrivateData : IdleCallback { + /** Reference to the DGL Application class this (private data) window associates with. */ + Application& app; + + /** Direct access to the DGL Application private data where we registers ourselves in. */ + Application::PrivateData* const appData; + + /** Pointer to the the DGL Window class that this private data belongs to. */ + Window* const self; + + /** Pugl view instance. */ + PuglView* view; + + /** Reserved space for graphics context. */ + mutable uint8_t graphicsContext[sizeof(void*)]; + + /** The top-level widgets associated with this Window. */ + std::list topLevelWidgets; + + /** Whether this Window is closed (not visible or counted in the Application it is tied to). + Defaults to true unless embed (embed windows are never closed). */ + bool isClosed; + + /** Whether this Window is currently visible/mapped. Defaults to false. */ + bool isVisible; + + /** Whether this Window is embed into another (usually not DGL-controlled) Window. */ + const bool isEmbed; + + /** Whether to ignore resize requests and feed them into the host instead. used for VST3 */ + const bool usesSizeRequest; + + /** Scale factor to report to widgets on request, purely informational. */ + double scaleFactor; + + /** Automatic scaling to apply on widgets, implemented internally. */ + bool autoScaling; + double autoScaleFactor; + + /** Pugl geometry constraints access. */ + uint minWidth, minHeight; + bool keepAspectRatio; + + /** Whether to ignore idle callback requests, useful for temporary windows. */ + bool ignoreIdleCallbacks; + + /** Whether we are waiting to receive clipboard data, ignoring some events in the process. */ + bool waitingForClipboardData; + bool waitingForClipboardEvents; + + /** The type id returned by the last onClipboardDataOffer call. */ + uint32_t clipboardTypeId; + + /** Render to a picture file when non-null, automatically free+unset after saving. */ + char* filenameToRenderInto; + +#ifndef DGL_FILE_BROWSER_DISABLED + /** Handle for file browser dialog operations. */ + DGL_NAMESPACE::FileBrowserHandle fileBrowserHandle; +#endif + + /** Modal window setup. */ + struct Modal { + PrivateData* parent; // parent of this window (so we can become modal) + PrivateData* child; // child window to give focus to when modal mode is enabled + bool enabled; // wherever modal mode is enabled (only possible if parent != null) + + /** Constructor for a non-modal window. */ + Modal() noexcept + : parent(nullptr), + child(nullptr), + enabled(false) {} + + /** Constructor for a modal window (with a parent). */ + Modal(PrivateData* const p) noexcept + : parent(p), + child(nullptr), + enabled(false) {} + + /** Destructor. */ + ~Modal() noexcept + { + DISTRHO_SAFE_ASSERT(! enabled); + } + + DISTRHO_DECLARE_NON_COPYABLE(Modal) + DISTRHO_PREVENT_HEAP_ALLOCATION + } modal; + + /** Constructor for a regular, standalone window. */ + explicit PrivateData(Application& app, Window* self); + + /** Constructor for a modal window. */ + explicit PrivateData(Application& app, Window* self, PrivateData* ppData); + + /** Constructor for an embed Window, with a few extra hints from the host side. */ + explicit PrivateData(Application& app, Window* self, uintptr_t parentWindowHandle, double scaling, bool resizable); + + /** Constructor for an embed Window, with a few extra hints from the host side. */ + explicit PrivateData(Application& app, Window* self, uintptr_t parentWindowHandle, + uint width, uint height, double scaling, bool resizable, bool isVST3); + + /** Destructor. */ + ~PrivateData() override; + + /** Helper initialization function called at the end of all this class constructors. */ + void initPre(uint width, uint height, bool resizable); + /** Helper initialization function called on the Window constructor after we are done. */ + bool initPost(); + + /** Hide window and notify application of a window close event. + * Does nothing if window is embed (that is, not standalone). + * The application event-loop will stop when all windows have been closed. + * + * @note It is possible to hide the window while not stopping the event-loop. + * A closed window is always hidden, but the reverse is not always true. + */ + void close(); + + void show(); + void hide(); + + void focus(); + + void setResizable(bool resizable); + + const GraphicsContext& getGraphicsContext() const noexcept; + + // idle callback stuff + void idleCallback() override; + bool addIdleCallback(IdleCallback* callback, uint timerFrequencyInMs); + bool removeIdleCallback(IdleCallback* callback); + +#ifndef DGL_FILE_BROWSER_DISABLED + // file handling + bool openFileBrowser(const DGL_NAMESPACE::FileBrowserOptions& options); +#endif + + static void renderToPicture(const char* filename, const GraphicsContext& context, uint width, uint height); + + // modal handling + void startModal(); + void stopModal(); + void runAsModal(bool blockWait); + + // pugl events + void onPuglConfigure(double width, double height); + void onPuglExpose(); + void onPuglClose(); + void onPuglFocus(bool focus, CrossingMode mode); + void onPuglKey(const Widget::KeyboardEvent& ev); + void onPuglText(const Widget::CharacterInputEvent& ev); + void onPuglMouse(const Widget::MouseEvent& ev); + void onPuglMotion(const Widget::MotionEvent& ev); + void onPuglScroll(const Widget::ScrollEvent& ev); + + // clipboard related handling + const void* getClipboard(size_t& dataSize); + uint32_t onClipboardDataOffer(); + void onClipboardData(uint32_t typeId); + + // Pugl event handling entry point + static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/LICENSE.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,18 @@ +Copyright (c) 2013 Mikko Mononen memon@inside.org + +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. + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/fontstash.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/fontstash.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1816 @@ +// +// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org +// +// 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. +// + +#ifndef FONS_H +#define FONS_H + +#define FONS_INVALID -1 + +enum FONSflags { + FONS_ZERO_TOPLEFT = 1, + FONS_ZERO_BOTTOMLEFT = 2, +}; + +enum FONSalign { + // Horizontal align + FONS_ALIGN_LEFT = 1<<0, // Default + FONS_ALIGN_CENTER = 1<<1, + FONS_ALIGN_RIGHT = 1<<2, + // Vertical align + FONS_ALIGN_TOP = 1<<3, + FONS_ALIGN_MIDDLE = 1<<4, + FONS_ALIGN_BOTTOM = 1<<5, + FONS_ALIGN_BASELINE = 1<<6, // Default +}; + +enum FONSglyphBitmap { + FONS_GLYPH_BITMAP_OPTIONAL = 1, + FONS_GLYPH_BITMAP_REQUIRED = 2, +}; + +enum FONSerrorCode { + // Font atlas is full. + FONS_ATLAS_FULL = 1, + // Scratch memory used to render glyphs is full, requested size reported in 'val', you may need to bump up FONS_SCRATCH_BUF_SIZE. + FONS_SCRATCH_FULL = 2, + // Calls to fonsPushState has created too large stack, if you need deep state stack bump up FONS_MAX_STATES. + FONS_STATES_OVERFLOW = 3, + // Trying to pop too many states fonsPopState(). + FONS_STATES_UNDERFLOW = 4, +}; + +struct FONSparams { + int width, height; + unsigned char flags; + void* userPtr; + int (*renderCreate)(void* uptr, int width, int height); + int (*renderResize)(void* uptr, int width, int height); + void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data); + void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts); + void (*renderDelete)(void* uptr); +}; +typedef struct FONSparams FONSparams; + +struct FONSquad +{ + float x0,y0,s0,t0; + float x1,y1,s1,t1; +}; +typedef struct FONSquad FONSquad; + +struct FONStextIter { + float x, y, nextx, nexty, scale, spacing; + unsigned int codepoint; + short isize, iblur; + struct FONSfont* font; + int prevGlyphIndex; + const char* str; + const char* next; + const char* end; + unsigned int utf8state; + int bitmapOption; +}; +typedef struct FONStextIter FONStextIter; + +typedef struct FONScontext FONScontext; + +// Constructor and destructor. +FONScontext* fonsCreateInternal(FONSparams* params); +void fonsDeleteInternal(FONScontext* s); + +void fonsSetErrorCallback(FONScontext* s, void (*callback)(void* uptr, int error, int val), void* uptr); +// Returns current atlas size. +void fonsGetAtlasSize(FONScontext* s, int* width, int* height); +// Expands the atlas size. +int fonsExpandAtlas(FONScontext* s, int width, int height); +// Resets the whole stash. +int fonsResetAtlas(FONScontext* stash, int width, int height); + +// Add fonts +int fonsAddFont(FONScontext* s, const char* name, const char* path, int fontIndex); +int fonsAddFontMem(FONScontext* s, const char* name, unsigned char* data, int ndata, int freeData, int fontIndex); +int fonsGetFontByName(FONScontext* s, const char* name); + +// State handling +void fonsPushState(FONScontext* s); +void fonsPopState(FONScontext* s); +void fonsClearState(FONScontext* s); + +// State setting +void fonsSetSize(FONScontext* s, float size); +void fonsSetColor(FONScontext* s, unsigned int color); +void fonsSetSpacing(FONScontext* s, float spacing); +void fonsSetBlur(FONScontext* s, float blur); +void fonsSetAlign(FONScontext* s, int align); +void fonsSetFont(FONScontext* s, int font); + +// Draw text +float fonsDrawText(FONScontext* s, float x, float y, const char* string, const char* end); + +// Measure text +float fonsTextBounds(FONScontext* s, float x, float y, const char* string, const char* end, float* bounds); +void fonsLineBounds(FONScontext* s, float y, float* miny, float* maxy); +void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh); + +// Text iterator +int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end, int bitmapOption); +int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad); + +// Pull texture changes +const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height); +int fonsValidateTexture(FONScontext* s, int* dirty); + +// Draws the stash texture for debugging +void fonsDrawDebug(FONScontext* s, float x, float y); + +#endif // FONTSTASH_H + + +#ifdef FONTSTASH_IMPLEMENTATION + +#define FONS_NOTUSED(v) (void)sizeof(v) + +#ifdef FONS_USE_FREETYPE + +#include +#include FT_FREETYPE_H +#include FT_ADVANCES_H +#include + +struct FONSttFontImpl { + FT_Face font; +}; +typedef struct FONSttFontImpl FONSttFontImpl; + +#else + +#define STB_TRUETYPE_IMPLEMENTATION +static void* fons__tmpalloc(size_t size, void* up); +static void fons__tmpfree(void* ptr, void* up); +#define STBTT_malloc(x,u) fons__tmpalloc(x,u) +#define STBTT_free(x,u) fons__tmpfree(x,u) +#include "stb_truetype.h" + +struct FONSttFontImpl { + stbtt_fontinfo font; +}; +typedef struct FONSttFontImpl FONSttFontImpl; + +#endif + +#ifndef FONS_SCRATCH_BUF_SIZE +# define FONS_SCRATCH_BUF_SIZE 96000 +#endif +#ifndef FONS_HASH_LUT_SIZE +# define FONS_HASH_LUT_SIZE 256 +#endif +#ifndef FONS_INIT_FONTS +# define FONS_INIT_FONTS 4 +#endif +#ifndef FONS_INIT_GLYPHS +# define FONS_INIT_GLYPHS 256 +#endif +#ifndef FONS_INIT_ATLAS_NODES +# define FONS_INIT_ATLAS_NODES 256 +#endif +#ifndef FONS_VERTEX_COUNT +# define FONS_VERTEX_COUNT 1024 +#endif +#ifndef FONS_MAX_STATES +# define FONS_MAX_STATES 20 +#endif +#ifndef FONS_MAX_FALLBACKS +# define FONS_MAX_FALLBACKS 20 +#endif + +static unsigned int fons__hashint(unsigned int a) +{ + a += ~(a<<15); + a ^= (a>>10); + a += (a<<3); + a ^= (a>>6); + a += ~(a<<11); + a ^= (a>>16); + return a; +} + +static int fons__mini(int a, int b) +{ + return a < b ? a : b; +} + +static int fons__maxi(int a, int b) +{ + return a > b ? a : b; +} + +struct FONSglyph +{ + unsigned int codepoint; + int index; + int next; + short size, blur; + short x0,y0,x1,y1; + short xadv,xoff,yoff; +}; +typedef struct FONSglyph FONSglyph; + +struct FONSfont +{ + FONSttFontImpl font; + char name[64]; + unsigned char* data; + int dataSize; + unsigned char freeData; + float ascender; + float descender; + float lineh; + FONSglyph* glyphs; + int cglyphs; + int nglyphs; + int lut[FONS_HASH_LUT_SIZE]; + int fallbacks[FONS_MAX_FALLBACKS]; + int nfallbacks; +}; +typedef struct FONSfont FONSfont; + +struct FONSstate +{ + int font; + int align; + float size; + unsigned int color; + float blur; + float spacing; +}; +typedef struct FONSstate FONSstate; + +struct FONSatlasNode { + short x, y, width; +}; +typedef struct FONSatlasNode FONSatlasNode; + +struct FONSatlas +{ + int width, height; + FONSatlasNode* nodes; + int nnodes; + int cnodes; +}; +typedef struct FONSatlas FONSatlas; + +struct FONScontext +{ + FONSparams params; + float itw,ith; + unsigned char* texData; + int dirtyRect[4]; + FONSfont** fonts; + FONSatlas* atlas; + int cfonts; + int nfonts; + float verts[FONS_VERTEX_COUNT*2]; + float tcoords[FONS_VERTEX_COUNT*2]; + unsigned int colors[FONS_VERTEX_COUNT]; + int nverts; + unsigned char* scratch; + int nscratch; + FONSstate states[FONS_MAX_STATES]; + int nstates; + void (*handleError)(void* uptr, int error, int val); + void* errorUptr; +#ifdef FONS_USE_FREETYPE + FT_Library ftLibrary; +#endif +}; + +#ifdef FONS_USE_FREETYPE + +int fons__tt_init(FONScontext *context) +{ + FT_Error ftError; + ftError = FT_Init_FreeType(&context->ftLibrary); + return ftError == 0; +} + +int fons__tt_done(FONScontext *context) +{ + FT_Error ftError; + ftError = FT_Done_FreeType(context->ftLibrary); + return ftError == 0; +} + +int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize, int fontIndex) +{ + FT_Error ftError; + + //font->font.userdata = stash; + ftError = FT_New_Memory_Face(context->ftLibrary, (const FT_Byte*)data, dataSize, fontIndex, &font->font); + return ftError == 0; +} + +void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap) +{ + *ascent = font->font->ascender; + *descent = font->font->descender; + *lineGap = font->font->height - (*ascent - *descent); +} + +float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) +{ +#if 1 + // Note(DPF) maintain pixel-based units for compat after nanovg update + return size / (font->font->ascender - font->font->descender); +#else + return size / font->font->units_per_EM; +#endif +} + +int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) +{ + return FT_Get_Char_Index(font->font, codepoint); +} + +int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale, + int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1) +{ + FT_Error ftError; + FT_GlyphSlot ftGlyph; + FT_Fixed advFixed; + FONS_NOTUSED(scale); + +#if 1 + // Note(DPF) maintain pixel-based units for compat after nanovg update + ftError = FT_Set_Pixel_Sizes(font->font, 0, (FT_UInt)(size * (float)font->font->units_per_EM / (float)(font->font->ascender - font->font->descender))); +#else + ftError = FT_Set_Pixel_Sizes(font->font, 0, size); +#endif + if (ftError) return 0; +#if 1 + // Note(DPF) maintain pixel-based units for compat after nanovg update + ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER); +#else + ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT); +#endif + if (ftError) return 0; + ftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, &advFixed); + if (ftError) return 0; + ftGlyph = font->font->glyph; + *advance = (int)advFixed; + *lsb = (int)ftGlyph->metrics.horiBearingX; + *x0 = ftGlyph->bitmap_left; + *x1 = *x0 + ftGlyph->bitmap.width; + *y0 = -ftGlyph->bitmap_top; + *y1 = *y0 + ftGlyph->bitmap.rows; + return 1; +} + +void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, + float scaleX, float scaleY, int glyph) +{ + FT_GlyphSlot ftGlyph = font->font->glyph; + int ftGlyphOffset = 0; + unsigned int x, y; + FONS_NOTUSED(outWidth); + FONS_NOTUSED(outHeight); + FONS_NOTUSED(scaleX); + FONS_NOTUSED(scaleY); + FONS_NOTUSED(glyph); // glyph has already been loaded by fons__tt_buildGlyphBitmap + + for ( y = 0; y < ftGlyph->bitmap.rows; y++ ) { + for ( x = 0; x < ftGlyph->bitmap.width; x++ ) { + output[(y * outStride) + x] = ftGlyph->bitmap.buffer[ftGlyphOffset++]; + } + } +} + +int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2) +{ + FT_Vector ftKerning; + FT_Get_Kerning(font->font, glyph1, glyph2, FT_KERNING_DEFAULT, &ftKerning); + return (int)((ftKerning.x + 32) >> 6); // Round up and convert to integer +} + +#else + +int fons__tt_init(FONScontext *context) +{ + FONS_NOTUSED(context); + return 1; +} + +int fons__tt_done(FONScontext *context) +{ + FONS_NOTUSED(context); + return 1; +} + +int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize, int fontIndex) +{ + int offset, stbError; + FONS_NOTUSED(dataSize); + + font->font.userdata = context; + offset = stbtt_GetFontOffsetForIndex(data, fontIndex); + if (offset == -1) { + stbError = 0; + } else { + stbError = stbtt_InitFont(&font->font, data, offset); + } + return stbError; +} + +void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap) +{ + stbtt_GetFontVMetrics(&font->font, ascent, descent, lineGap); +} + +float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) +{ +#if 1 + // Note(DPF) maintain pixel-based units for compat after nanovg update + return stbtt_ScaleForPixelHeight(&font->font, size); +#else + return stbtt_ScaleForMappingEmToPixels(&font->font, size); +#endif +} + +int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) +{ + return stbtt_FindGlyphIndex(&font->font, codepoint); +} + +int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale, + int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1) +{ + FONS_NOTUSED(size); + stbtt_GetGlyphHMetrics(&font->font, glyph, advance, lsb); + stbtt_GetGlyphBitmapBox(&font->font, glyph, scale, scale, x0, y0, x1, y1); + return 1; +} + +void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, + float scaleX, float scaleY, int glyph) +{ + stbtt_MakeGlyphBitmap(&font->font, output, outWidth, outHeight, outStride, scaleX, scaleY, glyph); +} + +int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2) +{ + return stbtt_GetGlyphKernAdvance(&font->font, glyph1, glyph2); +} + +#endif + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +static void* fons__tmpalloc(size_t size, void* up) +{ + unsigned char* ptr; + FONScontext* stash = (FONScontext*)up; + + // 16-byte align the returned pointer + size = (size + 0xf) & ~0xf; + + if (stash->nscratch+(int)size > FONS_SCRATCH_BUF_SIZE) { + if (stash->handleError) + stash->handleError(stash->errorUptr, FONS_SCRATCH_FULL, stash->nscratch+(int)size); + return NULL; + } + ptr = stash->scratch + stash->nscratch; + stash->nscratch += (int)size; + return ptr; +} + +static void fons__tmpfree(void* ptr, void* up) +{ + (void)ptr; + (void)up; + // empty +} + +#endif // STB_TRUETYPE_IMPLEMENTATION + +// Copyright (c) 2008-2010 Bjoern Hoehrmann +// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + +#define FONS_UTF8_ACCEPT 0 +#define FONS_UTF8_REJECT 12 + +static unsigned int fons__decutf8(unsigned int* state, unsigned int* codep, unsigned int byte) +{ + static const unsigned char utf8d[] = { + // The first part of the table maps bytes to character classes that + // to reduce the size of the transition table and create bitmasks. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,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, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + // The second part is a transition table that maps a combination + // of a state of the automaton and a character class to a state. + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, + }; + + unsigned int type = utf8d[byte]; + + *codep = (*state != FONS_UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + +// Atlas based on Skyline Bin Packer by Jukka Jylänki + +static void fons__deleteAtlas(FONSatlas* atlas) +{ + if (atlas == NULL) return; + if (atlas->nodes != NULL) free(atlas->nodes); + free(atlas); +} + +static FONSatlas* fons__allocAtlas(int w, int h, int nnodes) +{ + FONSatlas* atlas = NULL; + + // Allocate memory for the font stash. + atlas = (FONSatlas*)malloc(sizeof(FONSatlas)); + if (atlas == NULL) goto error; + memset(atlas, 0, sizeof(FONSatlas)); + + atlas->width = w; + atlas->height = h; + + // Allocate space for skyline nodes + atlas->nodes = (FONSatlasNode*)malloc(sizeof(FONSatlasNode) * nnodes); + if (atlas->nodes == NULL) goto error; + memset(atlas->nodes, 0, sizeof(FONSatlasNode) * nnodes); + atlas->nnodes = 0; + atlas->cnodes = nnodes; + + // Init root node. + atlas->nodes[0].x = 0; + atlas->nodes[0].y = 0; + atlas->nodes[0].width = (short)w; + atlas->nnodes++; + + return atlas; + +error: + if (atlas) fons__deleteAtlas(atlas); + return NULL; +} + +static int fons__atlasInsertNode(FONSatlas* atlas, int idx, int x, int y, int w) +{ + int i; + // Insert node + if (atlas->nnodes+1 > atlas->cnodes) { + atlas->cnodes = atlas->cnodes == 0 ? 8 : atlas->cnodes * 2; + atlas->nodes = (FONSatlasNode*)realloc(atlas->nodes, sizeof(FONSatlasNode) * atlas->cnodes); + if (atlas->nodes == NULL) + return 0; + } + for (i = atlas->nnodes; i > idx; i--) + atlas->nodes[i] = atlas->nodes[i-1]; + atlas->nodes[idx].x = (short)x; + atlas->nodes[idx].y = (short)y; + atlas->nodes[idx].width = (short)w; + atlas->nnodes++; + + return 1; +} + +static void fons__atlasRemoveNode(FONSatlas* atlas, int idx) +{ + int i; + if (atlas->nnodes == 0) return; + for (i = idx; i < atlas->nnodes-1; i++) + atlas->nodes[i] = atlas->nodes[i+1]; + atlas->nnodes--; +} + +static void fons__atlasExpand(FONSatlas* atlas, int w, int h) +{ + // Insert node for empty space + if (w > atlas->width) + fons__atlasInsertNode(atlas, atlas->nnodes, atlas->width, 0, w - atlas->width); + atlas->width = w; + atlas->height = h; +} + +static void fons__atlasReset(FONSatlas* atlas, int w, int h) +{ + atlas->width = w; + atlas->height = h; + atlas->nnodes = 0; + + // Init root node. + atlas->nodes[0].x = 0; + atlas->nodes[0].y = 0; + atlas->nodes[0].width = (short)w; + atlas->nnodes++; +} + +static int fons__atlasAddSkylineLevel(FONSatlas* atlas, int idx, int x, int y, int w, int h) +{ + int i; + + // Insert new node + if (fons__atlasInsertNode(atlas, idx, x, y+h, w) == 0) + return 0; + + // Delete skyline segments that fall under the shadow of the new segment. + for (i = idx+1; i < atlas->nnodes; i++) { + if (atlas->nodes[i].x < atlas->nodes[i-1].x + atlas->nodes[i-1].width) { + int shrink = atlas->nodes[i-1].x + atlas->nodes[i-1].width - atlas->nodes[i].x; + atlas->nodes[i].x += (short)shrink; + atlas->nodes[i].width -= (short)shrink; + if (atlas->nodes[i].width <= 0) { + fons__atlasRemoveNode(atlas, i); + i--; + } else { + break; + } + } else { + break; + } + } + + // Merge same height skyline segments that are next to each other. + for (i = 0; i < atlas->nnodes-1; i++) { + if (atlas->nodes[i].y == atlas->nodes[i+1].y) { + atlas->nodes[i].width += atlas->nodes[i+1].width; + fons__atlasRemoveNode(atlas, i+1); + i--; + } + } + + return 1; +} + +static int fons__atlasRectFits(FONSatlas* atlas, int i, int w, int h) +{ + // Checks if there is enough space at the location of skyline span 'i', + // and return the max height of all skyline spans under that at that location, + // (think tetris block being dropped at that position). Or -1 if no space found. + int x = atlas->nodes[i].x; + int y = atlas->nodes[i].y; + int spaceLeft; + if (x + w > atlas->width) + return -1; + spaceLeft = w; + while (spaceLeft > 0) { + if (i == atlas->nnodes) return -1; + y = fons__maxi(y, atlas->nodes[i].y); + if (y + h > atlas->height) return -1; + spaceLeft -= atlas->nodes[i].width; + ++i; + } + return y; +} + +static int fons__atlasAddRect(FONSatlas* atlas, int rw, int rh, int* rx, int* ry) +{ + int besth = atlas->height, bestw = atlas->width, besti = -1; + int bestx = -1, besty = -1, i; + + // Bottom left fit heuristic. + for (i = 0; i < atlas->nnodes; i++) { + int y = fons__atlasRectFits(atlas, i, rw, rh); + if (y != -1) { + if (y + rh < besth || (y + rh == besth && atlas->nodes[i].width < bestw)) { + besti = i; + bestw = atlas->nodes[i].width; + besth = y + rh; + bestx = atlas->nodes[i].x; + besty = y; + } + } + } + + if (besti == -1) + return 0; + + // Perform the actual packing. + if (fons__atlasAddSkylineLevel(atlas, besti, bestx, besty, rw, rh) == 0) + return 0; + + *rx = bestx; + *ry = besty; + + return 1; +} + +static void fons__addWhiteRect(FONScontext* stash, int w, int h) +{ + int x, y, gx, gy; + unsigned char* dst; + if (fons__atlasAddRect(stash->atlas, w, h, &gx, &gy) == 0) + return; + + // Rasterize + dst = &stash->texData[gx + gy * stash->params.width]; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) + dst[x] = 0xff; + dst += stash->params.width; + } + + stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], gx); + stash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], gy); + stash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], gx+w); + stash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], gy+h); +} + +FONScontext* fonsCreateInternal(FONSparams* params) +{ + FONScontext* stash = NULL; + + // Allocate memory for the font stash. + stash = (FONScontext*)malloc(sizeof(FONScontext)); + if (stash == NULL) goto error; + memset(stash, 0, sizeof(FONScontext)); + + stash->params = *params; + + // Allocate scratch buffer. + stash->scratch = (unsigned char*)malloc(FONS_SCRATCH_BUF_SIZE); + if (stash->scratch == NULL) goto error; + + // Initialize implementation library + if (!fons__tt_init(stash)) goto error; + + if (stash->params.renderCreate != NULL) { + if (stash->params.renderCreate(stash->params.userPtr, stash->params.width, stash->params.height) == 0) + goto error; + } + + stash->atlas = fons__allocAtlas(stash->params.width, stash->params.height, FONS_INIT_ATLAS_NODES); + if (stash->atlas == NULL) goto error; + + // Allocate space for fonts. + stash->fonts = (FONSfont**)malloc(sizeof(FONSfont*) * FONS_INIT_FONTS); + if (stash->fonts == NULL) goto error; + memset(stash->fonts, 0, sizeof(FONSfont*) * FONS_INIT_FONTS); + stash->cfonts = FONS_INIT_FONTS; + stash->nfonts = 0; + + // Create texture for the cache. + stash->itw = 1.0f/stash->params.width; + stash->ith = 1.0f/stash->params.height; + stash->texData = (unsigned char*)malloc(stash->params.width * stash->params.height); + if (stash->texData == NULL) goto error; + memset(stash->texData, 0, stash->params.width * stash->params.height); + + stash->dirtyRect[0] = stash->params.width; + stash->dirtyRect[1] = stash->params.height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + + // Add white rect at 0,0 for debug drawing. + fons__addWhiteRect(stash, 2,2); + + fonsPushState(stash); + fonsClearState(stash); + + return stash; + +error: + fonsDeleteInternal(stash); + return NULL; +} + +static FONSstate* fons__getState(FONScontext* stash) +{ + return &stash->states[stash->nstates-1]; +} + +int fonsAddFallbackFont(FONScontext* stash, int base, int fallback) +{ + FONSfont* baseFont = stash->fonts[base]; + if (baseFont->nfallbacks < FONS_MAX_FALLBACKS) { + baseFont->fallbacks[baseFont->nfallbacks++] = fallback; + return 1; + } + return 0; +} + +void fonsResetFallbackFont(FONScontext* stash, int base) +{ + int i; + + FONSfont* baseFont = stash->fonts[base]; + baseFont->nfallbacks = 0; + baseFont->nglyphs = 0; + for (i = 0; i < FONS_HASH_LUT_SIZE; i++) + baseFont->lut[i] = -1; +} + +void fonsSetSize(FONScontext* stash, float size) +{ + fons__getState(stash)->size = size; +} + +void fonsSetColor(FONScontext* stash, unsigned int color) +{ + fons__getState(stash)->color = color; +} + +void fonsSetSpacing(FONScontext* stash, float spacing) +{ + fons__getState(stash)->spacing = spacing; +} + +void fonsSetBlur(FONScontext* stash, float blur) +{ + fons__getState(stash)->blur = blur; +} + +void fonsSetAlign(FONScontext* stash, int align) +{ + fons__getState(stash)->align = align; +} + +void fonsSetFont(FONScontext* stash, int font) +{ + fons__getState(stash)->font = font; +} + +void fonsPushState(FONScontext* stash) +{ + if (stash->nstates >= FONS_MAX_STATES) { + if (stash->handleError) + stash->handleError(stash->errorUptr, FONS_STATES_OVERFLOW, 0); + return; + } + if (stash->nstates > 0) + memcpy(&stash->states[stash->nstates], &stash->states[stash->nstates-1], sizeof(FONSstate)); + stash->nstates++; +} + +void fonsPopState(FONScontext* stash) +{ + if (stash->nstates <= 1) { + if (stash->handleError) + stash->handleError(stash->errorUptr, FONS_STATES_UNDERFLOW, 0); + return; + } + stash->nstates--; +} + +void fonsClearState(FONScontext* stash) +{ + FONSstate* state = fons__getState(stash); + state->size = 12.0f; + state->color = 0xffffffff; + state->font = 0; + state->blur = 0; + state->spacing = 0; + state->align = FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE; +} + +static void fons__freeFont(FONSfont* font) +{ + if (font == NULL) return; + if (font->glyphs) free(font->glyphs); + if (font->freeData && font->data) free(font->data); + free(font); +} + +static int fons__allocFont(FONScontext* stash) +{ + FONSfont* font = NULL; + if (stash->nfonts+1 > stash->cfonts) { + stash->cfonts = stash->cfonts == 0 ? 8 : stash->cfonts * 2; + stash->fonts = (FONSfont**)realloc(stash->fonts, sizeof(FONSfont*) * stash->cfonts); + if (stash->fonts == NULL) + return -1; + for (int i=stash->nfonts; icfonts; ++i) + stash->fonts[i] = NULL; + } + font = (FONSfont*)malloc(sizeof(FONSfont)); + if (font == NULL) goto error; + memset(font, 0, sizeof(FONSfont)); + + font->glyphs = (FONSglyph*)malloc(sizeof(FONSglyph) * FONS_INIT_GLYPHS); + if (font->glyphs == NULL) goto error; + font->cglyphs = FONS_INIT_GLYPHS; + font->nglyphs = 0; + + stash->fonts[stash->nfonts++] = font; + return stash->nfonts-1; + +error: + fons__freeFont(font); + + return FONS_INVALID; +} + +int fonsAddFont(FONScontext* stash, const char* name, const char* path, int fontIndex) +{ + FILE* fp = 0; + int dataSize = 0; + size_t readed; + unsigned char* data = NULL; + + // Read in the font data. + fp = fopen(path, "rb"); + if (fp == NULL) goto error; + fseek(fp,0,SEEK_END); + dataSize = (int)ftell(fp); + fseek(fp,0,SEEK_SET); + data = (unsigned char*)malloc(dataSize); + if (data == NULL) goto error; + readed = fread(data, 1, dataSize, fp); + fclose(fp); + fp = 0; + if (readed != (size_t)dataSize) goto error; + + return fonsAddFontMem(stash, name, data, dataSize, 1, fontIndex); + +error: + if (data) free(data); + if (fp) fclose(fp); + return FONS_INVALID; +} + +int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData, int fontIndex) +{ + int i, ascent, descent, fh, lineGap; + FONSfont* font; + + int idx = fons__allocFont(stash); + if (idx == FONS_INVALID) + { + if (freeData && data) free(data); + return FONS_INVALID; + } + + font = stash->fonts[idx]; + + strncpy(font->name, name, sizeof(font->name)); + font->name[sizeof(font->name)-1] = '\0'; + + // Init hash lookup. + for (i = 0; i < FONS_HASH_LUT_SIZE; ++i) + font->lut[i] = -1; + + // Read in the font data. + font->dataSize = dataSize; + font->data = data; + font->freeData = (unsigned char)freeData; + + // Init font + stash->nscratch = 0; + if (!fons__tt_loadFont(stash, &font->font, data, dataSize, fontIndex)) goto error; + + // Store normalized line height. The real line height is got + // by multiplying the lineh by font size. + fons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap); + ascent += lineGap; + fh = ascent - descent; + font->ascender = (float)ascent / (float)fh; + font->descender = (float)descent / (float)fh; + font->lineh = font->ascender - font->descender; + + return idx; + +error: + fons__freeFont(font); + stash->nfonts--; + return FONS_INVALID; +} + +int fonsGetFontByName(FONScontext* s, const char* name) +{ + int i; + for (i = 0; i < s->nfonts; i++) { + if (strcmp(s->fonts[i]->name, name) == 0) + return i; + } + return FONS_INVALID; +} + + +static FONSglyph* fons__allocGlyph(FONSfont* font) +{ + if (font->nglyphs+1 > font->cglyphs) { + font->cglyphs = font->cglyphs == 0 ? 8 : font->cglyphs * 2; + font->glyphs = (FONSglyph*)realloc(font->glyphs, sizeof(FONSglyph) * font->cglyphs); + if (font->glyphs == NULL) return NULL; + for (int i=font->nglyphs; icglyphs; ++i) + memset(&font->glyphs[i], 0, sizeof(*font->glyphs)); + } + font->nglyphs++; + return &font->glyphs[font->nglyphs-1]; +} + + +// Based on Exponential blur, Jani Huhtanen, 2006 + +#define APREC 16 +#define ZPREC 7 + +static void fons__blurCols(unsigned char* dst, int w, int h, int dstStride, int alpha) +{ + int x, y; + for (y = 0; y < h; y++) { + int z = 0; // force zero border + for (x = 1; x < w; x++) { + z += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC; + dst[x] = (unsigned char)(z >> ZPREC); + } + dst[w-1] = 0; // force zero border + z = 0; + for (x = w-2; x >= 0; x--) { + z += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC; + dst[x] = (unsigned char)(z >> ZPREC); + } + dst[0] = 0; // force zero border + dst += dstStride; + } +} + +static void fons__blurRows(unsigned char* dst, int w, int h, int dstStride, int alpha) +{ + int x, y; + for (x = 0; x < w; x++) { + int z = 0; // force zero border + for (y = dstStride; y < h*dstStride; y += dstStride) { + z += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC; + dst[y] = (unsigned char)(z >> ZPREC); + } + dst[(h-1)*dstStride] = 0; // force zero border + z = 0; + for (y = (h-2)*dstStride; y >= 0; y -= dstStride) { + z += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC; + dst[y] = (unsigned char)(z >> ZPREC); + } + dst[0] = 0; // force zero border + dst++; + } +} + + +static void fons__blur(FONScontext* stash, unsigned char* dst, int w, int h, int dstStride, int blur) +{ + int alpha; + float sigma; + (void)stash; + + if (blur < 1) + return; + // Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity) + sigma = (float)blur * 0.57735f; // 1 / sqrt(3) + alpha = (int)((1< 20) iblur = 20; + pad = iblur+2; + + // Reset allocator. + stash->nscratch = 0; + + // Find code point and size. + h = fons__hashint(codepoint) & (FONS_HASH_LUT_SIZE-1); + i = font->lut[h]; + while (i != -1) { + if (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur) { + glyph = &font->glyphs[i]; + if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL || (glyph->x0 >= 0 && glyph->y0 >= 0)) { + return glyph; + } + // At this point, glyph exists but the bitmap data is not yet created. + break; + } + i = font->glyphs[i].next; + } + + // Create a new glyph or rasterize bitmap data for a cached glyph. + g = fons__tt_getGlyphIndex(&font->font, codepoint); + // Try to find the glyph in fallback fonts. + if (g == 0) { + for (i = 0; i < font->nfallbacks; ++i) { + FONSfont* fallbackFont = stash->fonts[font->fallbacks[i]]; + int fallbackIndex = fons__tt_getGlyphIndex(&fallbackFont->font, codepoint); + if (fallbackIndex != 0) { + g = fallbackIndex; + renderFont = fallbackFont; + break; + } + } + // It is possible that we did not find a fallback glyph. + // In that case the glyph index 'g' is 0, and we'll proceed below and cache empty glyph. + } + scale = fons__tt_getPixelHeightScale(&renderFont->font, size); + fons__tt_buildGlyphBitmap(&renderFont->font, g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1); + gw = x1-x0 + pad*2; + gh = y1-y0 + pad*2; + + // Determines the spot to draw glyph in the atlas. + if (bitmapOption == FONS_GLYPH_BITMAP_REQUIRED) { + // Find free spot for the rect in the atlas + added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); + if (added == 0 && stash->handleError != NULL) { + // Atlas is full, let the user to resize the atlas (or not), and try again. + stash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0); + added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); + } + if (added == 0) return NULL; + } else { + // Negative coordinate indicates there is no bitmap data created. + gx = -1; + gy = -1; + } + + // Init glyph. + if (glyph == NULL) { + glyph = fons__allocGlyph(font); + glyph->codepoint = codepoint; + glyph->size = isize; + glyph->blur = iblur; + glyph->next = 0; + + // Insert char to hash lookup. + glyph->next = font->lut[h]; + font->lut[h] = font->nglyphs-1; + } + glyph->index = g; + glyph->x0 = (short)gx; + glyph->y0 = (short)gy; + glyph->x1 = (short)(glyph->x0+gw); + glyph->y1 = (short)(glyph->y0+gh); + glyph->xadv = (short)(scale * advance * 10.0f); + glyph->xoff = (short)(x0 - pad); + glyph->yoff = (short)(y0 - pad); + + if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL) { + return glyph; + } + + // Rasterize + dst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width]; + fons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale, scale, g); + + // Make sure there is one pixel empty border. + dst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; + for (y = 0; y < gh; y++) { + dst[y*stash->params.width] = 0; + dst[gw-1 + y*stash->params.width] = 0; + } + for (x = 0; x < gw; x++) { + dst[x] = 0; + dst[x + (gh-1)*stash->params.width] = 0; + } + + // Debug code to color the glyph background +/* unsigned char* fdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; + for (y = 0; y < gh; y++) { + for (x = 0; x < gw; x++) { + int a = (int)fdst[x+y*stash->params.width] + 20; + if (a > 255) a = 255; + fdst[x+y*stash->params.width] = a; + } + }*/ + + // Blur + if (iblur > 0) { + stash->nscratch = 0; + bdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; + fons__blur(stash, bdst, gw, gh, stash->params.width, iblur); + } + + stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], glyph->x0); + stash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], glyph->y0); + stash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], glyph->x1); + stash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], glyph->y1); + + return glyph; +} + +static void fons__getQuad(FONScontext* stash, FONSfont* font, + int prevGlyphIndex, FONSglyph* glyph, + float scale, float spacing, float* x, float* y, FONSquad* q) +{ + float rx,ry,xoff,yoff,x0,y0,x1,y1; + + if (prevGlyphIndex != -1) { + float adv = fons__tt_getGlyphKernAdvance(&font->font, prevGlyphIndex, glyph->index) * scale; + *x += (int)(adv + spacing + 0.5f); + } + + // Each glyph has 2px border to allow good interpolation, + // one pixel to prevent leaking, and one to allow good interpolation for rendering. + // Inset the texture region by one pixel for correct interpolation. + xoff = (short)(glyph->xoff+1); + yoff = (short)(glyph->yoff+1); + x0 = (float)(glyph->x0+1); + y0 = (float)(glyph->y0+1); + x1 = (float)(glyph->x1-1); + y1 = (float)(glyph->y1-1); + + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + rx = floorf(*x + xoff); + ry = floorf(*y + yoff); + + q->x0 = rx; + q->y0 = ry; + q->x1 = rx + x1 - x0; + q->y1 = ry + y1 - y0; + + q->s0 = x0 * stash->itw; + q->t0 = y0 * stash->ith; + q->s1 = x1 * stash->itw; + q->t1 = y1 * stash->ith; + } else { + rx = floorf(*x + xoff); + ry = floorf(*y - yoff); + + q->x0 = rx; + q->y0 = ry; + q->x1 = rx + x1 - x0; + q->y1 = ry - y1 + y0; + + q->s0 = x0 * stash->itw; + q->t0 = y0 * stash->ith; + q->s1 = x1 * stash->itw; + q->t1 = y1 * stash->ith; + } + + *x += (int)(glyph->xadv / 10.0f + 0.5f); +} + +static void fons__flush(FONScontext* stash) +{ + // Flush texture + if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) { + if (stash->params.renderUpdate != NULL) + stash->params.renderUpdate(stash->params.userPtr, stash->dirtyRect, stash->texData); + // Reset dirty rect + stash->dirtyRect[0] = stash->params.width; + stash->dirtyRect[1] = stash->params.height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + } + + // Flush triangles + if (stash->nverts > 0) { + if (stash->params.renderDraw != NULL) + stash->params.renderDraw(stash->params.userPtr, stash->verts, stash->tcoords, stash->colors, stash->nverts); + stash->nverts = 0; + } +} + +static __inline void fons__vertex(FONScontext* stash, float x, float y, float s, float t, unsigned int c) +{ + stash->verts[stash->nverts*2+0] = x; + stash->verts[stash->nverts*2+1] = y; + stash->tcoords[stash->nverts*2+0] = s; + stash->tcoords[stash->nverts*2+1] = t; + stash->colors[stash->nverts] = c; + stash->nverts++; +} + +static float fons__getVertAlign(FONScontext* stash, FONSfont* font, int align, short isize) +{ + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + if (align & FONS_ALIGN_TOP) { + return font->ascender * (float)isize/10.0f; + } else if (align & FONS_ALIGN_MIDDLE) { + return (font->ascender + font->descender) / 2.0f * (float)isize/10.0f; + } else if (align & FONS_ALIGN_BASELINE) { + return 0.0f; + } else if (align & FONS_ALIGN_BOTTOM) { + return font->descender * (float)isize/10.0f; + } + } else { + if (align & FONS_ALIGN_TOP) { + return -font->ascender * (float)isize/10.0f; + } else if (align & FONS_ALIGN_MIDDLE) { + return -(font->ascender + font->descender) / 2.0f * (float)isize/10.0f; + } else if (align & FONS_ALIGN_BASELINE) { + return 0.0f; + } else if (align & FONS_ALIGN_BOTTOM) { + return -font->descender * (float)isize/10.0f; + } + } + return 0.0; +} + +float fonsDrawText(FONScontext* stash, + float x, float y, + const char* str, const char* end) +{ + FONSstate* state = fons__getState(stash); + unsigned int codepoint; + unsigned int utf8state = 0; + FONSglyph* glyph = NULL; + FONSquad q; + int prevGlyphIndex = -1; + short isize = (short)(state->size*10.0f); + short iblur = (short)state->blur; + float scale; + FONSfont* font; + float width; + + if (stash == NULL) return x; + if (state->font < 0 || state->font >= stash->nfonts) return x; + font = stash->fonts[state->font]; + if (font->data == NULL) return x; + + scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f); + + if (end == NULL) + end = str + strlen(str); + + // Align horizontally + if (state->align & FONS_ALIGN_LEFT) { + // empty + } else if (state->align & FONS_ALIGN_RIGHT) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width; + } else if (state->align & FONS_ALIGN_CENTER) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width * 0.5f; + } + // Align vertically. + y += fons__getVertAlign(stash, font, state->align, isize); + + for (; str != end; ++str) { + if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) + continue; + glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_REQUIRED); + if (glyph != NULL) { + fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); + + if (stash->nverts+6 > FONS_VERTEX_COUNT) + fons__flush(stash); + + fons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color); + fons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color); + fons__vertex(stash, q.x1, q.y0, q.s1, q.t0, state->color); + + fons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color); + fons__vertex(stash, q.x0, q.y1, q.s0, q.t1, state->color); + fons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color); + } + prevGlyphIndex = glyph != NULL ? glyph->index : -1; + } + fons__flush(stash); + + return x; +} + +int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, + float x, float y, const char* str, const char* end, int bitmapOption) +{ + FONSstate* state = fons__getState(stash); + float width; + + memset(iter, 0, sizeof(*iter)); + + if (stash == NULL) return 0; + if (state->font < 0 || state->font >= stash->nfonts) return 0; + iter->font = stash->fonts[state->font]; + if (iter->font->data == NULL) return 0; + + iter->isize = (short)(state->size*10.0f); + iter->iblur = (short)state->blur; + iter->scale = fons__tt_getPixelHeightScale(&iter->font->font, (float)iter->isize/10.0f); + + // Align horizontally + if (state->align & FONS_ALIGN_LEFT) { + // empty + } else if (state->align & FONS_ALIGN_RIGHT) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width; + } else if (state->align & FONS_ALIGN_CENTER) { + width = fonsTextBounds(stash, x,y, str, end, NULL); + x -= width * 0.5f; + } + // Align vertically. + y += fons__getVertAlign(stash, iter->font, state->align, iter->isize); + + if (end == NULL) + end = str + strlen(str); + + iter->x = iter->nextx = x; + iter->y = iter->nexty = y; + iter->spacing = state->spacing; + iter->str = str; + iter->next = str; + iter->end = end; + iter->codepoint = 0; + iter->prevGlyphIndex = -1; + iter->bitmapOption = bitmapOption; + + return 1; +} + +int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad) +{ + FONSglyph* glyph = NULL; + const char* str = iter->next; + iter->str = iter->next; + + if (str == iter->end) + return 0; + + for (; str != iter->end; str++) { + if (fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str)) + continue; + str++; + // Get glyph and quad + iter->x = iter->nextx; + iter->y = iter->nexty; + glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur, iter->bitmapOption); + // If the iterator was initialized with FONS_GLYPH_BITMAP_OPTIONAL, then the UV coordinates of the quad will be invalid. + if (glyph != NULL) + fons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad); + iter->prevGlyphIndex = glyph != NULL ? glyph->index : -1; + break; + } + iter->next = str; + + return 1; +} + +void fonsDrawDebug(FONScontext* stash, float x, float y) +{ + int i; + int w = stash->params.width; + int h = stash->params.height; + float u = w == 0 ? 0 : (1.0f / w); + float v = h == 0 ? 0 : (1.0f / h); + + if (stash->nverts+6+6 > FONS_VERTEX_COUNT) + fons__flush(stash); + + // Draw background + fons__vertex(stash, x+0, y+0, u, v, 0x0fffffff); + fons__vertex(stash, x+w, y+h, u, v, 0x0fffffff); + fons__vertex(stash, x+w, y+0, u, v, 0x0fffffff); + + fons__vertex(stash, x+0, y+0, u, v, 0x0fffffff); + fons__vertex(stash, x+0, y+h, u, v, 0x0fffffff); + fons__vertex(stash, x+w, y+h, u, v, 0x0fffffff); + + // Draw texture + fons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff); + fons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff); + fons__vertex(stash, x+w, y+0, 1, 0, 0xffffffff); + + fons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff); + fons__vertex(stash, x+0, y+h, 0, 1, 0xffffffff); + fons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff); + + // Drawbug draw atlas + for (i = 0; i < stash->atlas->nnodes; i++) { + FONSatlasNode* n = &stash->atlas->nodes[i]; + + if (stash->nverts+6 > FONS_VERTEX_COUNT) + fons__flush(stash); + + fons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+n->width, y+n->y+0, u, v, 0xc00000ff); + + fons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+0, y+n->y+1, u, v, 0xc00000ff); + fons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff); + } + + fons__flush(stash); +} + +float fonsTextBounds(FONScontext* stash, + float x, float y, + const char* str, const char* end, + float* bounds) +{ + FONSstate* state = fons__getState(stash); + unsigned int codepoint; + unsigned int utf8state = 0; + FONSquad q; + FONSglyph* glyph = NULL; + int prevGlyphIndex = -1; + short isize = (short)(state->size*10.0f); + short iblur = (short)state->blur; + float scale; + FONSfont* font; + float startx, advance; + float minx, miny, maxx, maxy; + + if (stash == NULL) return 0; + if (state->font < 0 || state->font >= stash->nfonts) return 0; + font = stash->fonts[state->font]; + if (font->data == NULL) return 0; + + scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f); + + // Align vertically. + y += fons__getVertAlign(stash, font, state->align, isize); + + minx = maxx = x; + miny = maxy = y; + startx = x; + + if (end == NULL) + end = str + strlen(str); + + for (; str != end; ++str) { + if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) + continue; + glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_OPTIONAL); + if (glyph != NULL) { + fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); + if (q.x0 < minx) minx = q.x0; + if (q.x1 > maxx) maxx = q.x1; + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + if (q.y0 < miny) miny = q.y0; + if (q.y1 > maxy) maxy = q.y1; + } else { + if (q.y1 < miny) miny = q.y1; + if (q.y0 > maxy) maxy = q.y0; + } + } + prevGlyphIndex = glyph != NULL ? glyph->index : -1; + } + + advance = x - startx; + + // Align horizontally + if (state->align & FONS_ALIGN_LEFT) { + // empty + } else if (state->align & FONS_ALIGN_RIGHT) { + minx -= advance; + maxx -= advance; + } else if (state->align & FONS_ALIGN_CENTER) { + minx -= advance * 0.5f; + maxx -= advance * 0.5f; + } + + if (bounds) { + bounds[0] = minx; + bounds[1] = miny; + bounds[2] = maxx; + bounds[3] = maxy; + } + + return advance; +} + +void fonsVertMetrics(FONScontext* stash, + float* ascender, float* descender, float* lineh) +{ + FONSfont* font; + FONSstate* state = fons__getState(stash); + short isize; + + if (stash == NULL) return; + if (state->font < 0 || state->font >= stash->nfonts) return; + font = stash->fonts[state->font]; + isize = (short)(state->size*10.0f); + if (font->data == NULL) return; + + if (ascender) + *ascender = font->ascender*isize/10.0f; + if (descender) + *descender = font->descender*isize/10.0f; + if (lineh) + *lineh = font->lineh*isize/10.0f; +} + +void fonsLineBounds(FONScontext* stash, float y, float* miny, float* maxy) +{ + FONSfont* font; + FONSstate* state = fons__getState(stash); + short isize; + + if (stash == NULL) return; + if (state->font < 0 || state->font >= stash->nfonts) return; + font = stash->fonts[state->font]; + isize = (short)(state->size*10.0f); + if (font->data == NULL) return; + + y += fons__getVertAlign(stash, font, state->align, isize); + + if (stash->params.flags & FONS_ZERO_TOPLEFT) { + *miny = y - font->ascender * (float)isize/10.0f; + *maxy = *miny + font->lineh*isize/10.0f; + } else { + *maxy = y + font->descender * (float)isize/10.0f; + *miny = *maxy - font->lineh*isize/10.0f; + } +} + +const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height) +{ + if (width != NULL) + *width = stash->params.width; + if (height != NULL) + *height = stash->params.height; + return stash->texData; +} + +int fonsValidateTexture(FONScontext* stash, int* dirty) +{ + if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) { + dirty[0] = stash->dirtyRect[0]; + dirty[1] = stash->dirtyRect[1]; + dirty[2] = stash->dirtyRect[2]; + dirty[3] = stash->dirtyRect[3]; + // Reset dirty rect + stash->dirtyRect[0] = stash->params.width; + stash->dirtyRect[1] = stash->params.height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + return 1; + } + return 0; +} + +void fonsDeleteInternal(FONScontext* stash) +{ + int i; + if (stash == NULL) return; + + if (stash->params.renderDelete) + stash->params.renderDelete(stash->params.userPtr); + + for (i = 0; i < stash->nfonts; ++i) + fons__freeFont(stash->fonts[i]); + + if (stash->atlas) fons__deleteAtlas(stash->atlas); + if (stash->fonts) free(stash->fonts); + if (stash->texData) free(stash->texData); + if (stash->scratch) free(stash->scratch); + fons__tt_done(stash); + free(stash); +} + +void fonsSetErrorCallback(FONScontext* stash, void (*callback)(void* uptr, int error, int val), void* uptr) +{ + if (stash == NULL) return; + stash->handleError = callback; + stash->errorUptr = uptr; +} + +void fonsGetAtlasSize(FONScontext* stash, int* width, int* height) +{ + if (stash == NULL) return; + *width = stash->params.width; + *height = stash->params.height; +} + +int fonsExpandAtlas(FONScontext* stash, int width, int height) +{ + int i, maxy = 0; + unsigned char* data = NULL; + if (stash == NULL) return 0; + + width = fons__maxi(width, stash->params.width); + height = fons__maxi(height, stash->params.height); + + if (width == stash->params.width && height == stash->params.height) + return 1; + + // Flush pending glyphs. + fons__flush(stash); + + // Create new texture + if (stash->params.renderResize != NULL) { + if (stash->params.renderResize(stash->params.userPtr, width, height) == 0) + return 0; + } + // Copy old texture data over. + data = (unsigned char*)malloc(width * height); + if (data == NULL) + return 0; + for (i = 0; i < stash->params.height; i++) { + unsigned char* dst = &data[i*width]; + unsigned char* src = &stash->texData[i*stash->params.width]; + memcpy(dst, src, stash->params.width); + if (width > stash->params.width) + memset(dst+stash->params.width, 0, width - stash->params.width); + } + if (height > stash->params.height) + memset(&data[stash->params.height * width], 0, (height - stash->params.height) * width); + + free(stash->texData); + stash->texData = data; + + // Increase atlas size + fons__atlasExpand(stash->atlas, width, height); + + // Add existing data as dirty. + for (i = 0; i < stash->atlas->nnodes; i++) + maxy = fons__maxi(maxy, stash->atlas->nodes[i].y); + stash->dirtyRect[0] = 0; + stash->dirtyRect[1] = 0; + stash->dirtyRect[2] = stash->params.width; + stash->dirtyRect[3] = maxy; + + stash->params.width = width; + stash->params.height = height; + stash->itw = 1.0f/stash->params.width; + stash->ith = 1.0f/stash->params.height; + + return 1; +} + +int fonsResetAtlas(FONScontext* stash, int width, int height) +{ + int i, j; + if (stash == NULL) return 0; + + // Flush pending glyphs. + fons__flush(stash); + + // Create new texture + if (stash->params.renderResize != NULL) { + if (stash->params.renderResize(stash->params.userPtr, width, height) == 0) + return 0; + } + + // Reset atlas + fons__atlasReset(stash->atlas, width, height); + + // Clear texture data. + stash->texData = (unsigned char*)realloc(stash->texData, width * height); + if (stash->texData == NULL) return 0; + memset(stash->texData, 0, width * height); + + // Reset dirty rect + stash->dirtyRect[0] = width; + stash->dirtyRect[1] = height; + stash->dirtyRect[2] = 0; + stash->dirtyRect[3] = 0; + + // Reset cached glyphs + for (i = 0; i < stash->nfonts; i++) { + FONSfont* font = stash->fonts[i]; + font->nglyphs = 0; + for (j = 0; j < FONS_HASH_LUT_SIZE; j++) + font->lut[j] = -1; + } + + stash->params.width = width; + stash->params.height = height; + stash->itw = 1.0f/stash->params.width; + stash->ith = 1.0f/stash->params.height; + + // Add white rect at 0,0 for debug drawing. + fons__addWhiteRect(stash, 2,2); + + return 1; +} + + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3060 @@ +// +// Copyright (c) 2013 Mikko Mononen memon@inside.org +// +// 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. +// + +#include +#include +#include +#include + +#include "nanovg.h" +#define FONTSTASH_IMPLEMENTATION +#define stbtt_fontinfo dpf_nvg_stbtt_fontinfo +#define stbrp_context dpf_nvg_stbrp_context +#define stbrp_rect dpf_nvg_stbrp_rect +#define stbrp_node dpf_nvg_stbrp_node +#define stbrp_coord dpf_nvg_stbrp_coord +#include "fontstash.h" + +#ifndef NVG_NO_STB +#define STB_IMAGE_IMPLEMENTATION +#define stbi_convert_iphone_png_to_rgb dpf_stbi_convert_iphone_png_to_rgb +#define stbi_failure_reason dpf_stbi_failure_reason +#define stbi_hdr_to_ldr_gamma dpf_stbi_hdr_to_ldr_gamma +#define stbi_hdr_to_ldr_scale dpf_stbi_hdr_to_ldr_scale +#define stbi_image_free dpf_stbi_image_free +#define stbi_info dpf_stbi_info +#define stbi_info_from_callbacks dpf_stbi_info_from_callbacks +#define stbi_info_from_file dpf_stbi_info_from_file +#define stbi_info_from_memory dpf_stbi_info_from_memory +#define stbi_is_hdr dpf_stbi_is_hdr +#define stbi_is_hdr_from_callbacks dpf_stbi_is_hdr_from_callbacks +#define stbi_is_hdr_from_file dpf_stbi_is_hdr_from_file +#define stbi_is_hdr_from_memory dpf_stbi_is_hdr_from_memory +#define stbi_ldr_to_hdr_gamma dpf_stbi_ldr_to_hdr_gamma +#define stbi_ldr_to_hdr_scale dpf_stbi_ldr_to_hdr_scale +#define stbi_load dpf_stbi_load +#define stbi_load_from_callbacks dpf_stbi_load_from_callbacks +#define stbi_load_from_file dpf_stbi_load_from_file +#define stbi_load_from_memory dpf_stbi_load_from_memory +#define stbi_loadf dpf_stbi_loadf +#define stbi_loadf_from_callbacks dpf_stbi_loadf_from_callbacks +#define stbi_loadf_from_file dpf_stbi_loadf_from_file +#define stbi_loadf_from_memory dpf_stbi_loadf_from_memory +#define stbi_set_flip_vertically_on_load dpf_stbi_set_flip_vertically_on_load +#define stbi_set_unpremultiply_on_load dpf_stbi_set_unpremultiply_on_load +#define stbi_zlib_decode_buffer dpf_stbi_zlib_decode_buffer +#define stbi_zlib_decode_malloc dpf_stbi_zlib_decode_malloc +#define stbi_zlib_decode_malloc_guesssize dpf_stbi_zlib_decode_malloc_guesssize +#define stbi_zlib_decode_malloc_guesssize_headerflag dpf_stbi_zlib_decode_malloc_guesssize_headerflag +#define stbi_zlib_decode_noheader_buffer dpf_stbi_zlib_decode_noheader_buffer +#define stbi_zlib_decode_noheader_malloc dpf_stbi_zlib_decode_noheader_malloc +#include "stb_image.h" +#endif + +#ifdef NVG_DISABLE_SKIPPING_WHITESPACE +#define NVG_SKIPPED_CHAR NVG_SPACE +#else +#define NVG_SKIPPED_CHAR NVG_CHAR +#endif + +#ifndef NVG_FONT_TEXTURE_FLAGS +#define NVG_FONT_TEXTURE_FLAGS 0 +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4100) // unreferenced formal parameter +#pragma warning(disable: 4127) // conditional expression is constant +#pragma warning(disable: 4204) // nonstandard extension used : non-constant aggregate initializer +#pragma warning(disable: 4706) // assignment within conditional expression +#endif + +#define NVG_INIT_FONTIMAGE_SIZE 512 +#define NVG_MAX_FONTIMAGE_SIZE 2048 +#define NVG_MAX_FONTIMAGES 4 + +#define NVG_INIT_COMMANDS_SIZE 256 +#define NVG_INIT_POINTS_SIZE 128 +#define NVG_INIT_PATHS_SIZE 16 +#define NVG_INIT_VERTS_SIZE 256 +#define NVG_MAX_STATES 32 + +#define NVG_KAPPA90 0.5522847493f // Length proportional to radius of a cubic bezier handle for 90deg arcs. + +#define NVG_COUNTOF(arr) (sizeof(arr) / sizeof(0[arr])) + + +enum NVGcommands { + NVG_MOVETO = 0, + NVG_LINETO = 1, + NVG_BEZIERTO = 2, + NVG_CLOSE = 3, + NVG_WINDING = 4, +}; + +enum NVGpointFlags +{ + NVG_PT_CORNER = 0x01, + NVG_PT_LEFT = 0x02, + NVG_PT_BEVEL = 0x04, + NVG_PR_INNERBEVEL = 0x08, +}; + +struct NVGstate { + NVGcompositeOperationState compositeOperation; + int shapeAntiAlias; + NVGpaint fill; + NVGpaint stroke; + float strokeWidth; + float miterLimit; + int lineJoin; + int lineCap; + NVGcolor tint; + float xform[6]; + NVGscissor scissor; + float fontSize; + float letterSpacing; + float lineHeight; + float fontBlur; + int textAlign; + int fontId; +}; +typedef struct NVGstate NVGstate; + +struct NVGpoint { + float x,y; + float dx, dy; + float len; + float dmx, dmy; + unsigned char flags; +}; +typedef struct NVGpoint NVGpoint; + +struct NVGpathCache { + NVGpoint* points; + int npoints; + int cpoints; + NVGpath* paths; + int npaths; + int cpaths; + NVGvertex* verts; + int nverts; + int cverts; + float bounds[4]; +}; +typedef struct NVGpathCache NVGpathCache; + +struct NVGfontContext { // Fontstash context plus font images; shared between shared NanoVG contexts. + int refCount; + struct FONScontext* fs; + int fontImages[NVG_MAX_FONTIMAGES]; + int fontImageIdx; +}; +typedef struct NVGfontContext NVGfontContext; + +struct NVGcontext { + NVGparams params; + float* commands; + int ccommands; + int ncommands; + float commandx, commandy; + NVGstate states[NVG_MAX_STATES]; + int nstates; + NVGpathCache* cache; + float tessTol; + float distTol; + float fringeWidth; + float devicePxRatio; + NVGfontContext* fontContext; + int drawCallCount; + int fillTriCount; + int strokeTriCount; + int textTriCount; +}; + +static float nvg__sqrtf(float a) { return sqrtf(a); } +static float nvg__modf(float a, float b) { return fmodf(a, b); } +static float nvg__sinf(float a) { return sinf(a); } +static float nvg__cosf(float a) { return cosf(a); } +static float nvg__tanf(float a) { return tanf(a); } +static float nvg__atan2f(float a,float b) { return atan2f(a, b); } +static float nvg__acosf(float a) { return acosf(a); } + +static int nvg__mini(int a, int b) { return a < b ? a : b; } +static int nvg__maxi(int a, int b) { return a > b ? a : b; } +static int nvg__clampi(int a, int mn, int mx) { return a < mn ? mn : (a > mx ? mx : a); } +static float nvg__minf(float a, float b) { return a < b ? a : b; } +static float nvg__maxf(float a, float b) { return a > b ? a : b; } +static float nvg__absf(float a) { return a >= 0.0f ? a : -a; } +static float nvg__signf(float a) { return a >= 0.0f ? 1.0f : -1.0f; } +static float nvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } +static float nvg__cross(float dx0, float dy0, float dx1, float dy1) { return dx1*dy0 - dx0*dy1; } + +static float nvg__normalize(float *x, float* y) +{ + float d = nvg__sqrtf((*x)*(*x) + (*y)*(*y)); + if (d > 1e-6f) { + float id = 1.0f / d; + *x *= id; + *y *= id; + } + return d; +} + + +static void nvg__deletePathCache(NVGpathCache* c) +{ + if (c == NULL) return; + if (c->points != NULL) free(c->points); + if (c->paths != NULL) free(c->paths); + if (c->verts != NULL) free(c->verts); + free(c); +} + +static NVGpathCache* nvg__allocPathCache(void) +{ + NVGpathCache* c = (NVGpathCache*)malloc(sizeof(NVGpathCache)); + if (c == NULL) goto error; + memset(c, 0, sizeof(NVGpathCache)); + + c->points = (NVGpoint*)malloc(sizeof(NVGpoint)*NVG_INIT_POINTS_SIZE); + if (!c->points) goto error; + c->npoints = 0; + c->cpoints = NVG_INIT_POINTS_SIZE; + + c->paths = (NVGpath*)malloc(sizeof(NVGpath)*NVG_INIT_PATHS_SIZE); + if (!c->paths) goto error; + c->npaths = 0; + c->cpaths = NVG_INIT_PATHS_SIZE; + + c->verts = (NVGvertex*)malloc(sizeof(NVGvertex)*NVG_INIT_VERTS_SIZE); + if (!c->verts) goto error; + c->nverts = 0; + c->cverts = NVG_INIT_VERTS_SIZE; + + return c; +error: + nvg__deletePathCache(c); + return NULL; +} + +static void nvg__setDevicePixelRatio(NVGcontext* ctx, float ratio) +{ + ctx->tessTol = 0.25f / ratio; + ctx->distTol = 0.01f / ratio; + ctx->fringeWidth = 1.0f / ratio; + ctx->devicePxRatio = ratio; +} + +static NVGcompositeOperationState nvg__compositeOperationState(int op) +{ + int sfactor, dfactor; + + if (op == NVG_SOURCE_OVER) + { + sfactor = NVG_ONE; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else if (op == NVG_SOURCE_IN) + { + sfactor = NVG_DST_ALPHA; + dfactor = NVG_ZERO; + } + else if (op == NVG_SOURCE_OUT) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_ZERO; + } + else if (op == NVG_ATOP) + { + sfactor = NVG_DST_ALPHA; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else if (op == NVG_DESTINATION_OVER) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_ONE; + } + else if (op == NVG_DESTINATION_IN) + { + sfactor = NVG_ZERO; + dfactor = NVG_SRC_ALPHA; + } + else if (op == NVG_DESTINATION_OUT) + { + sfactor = NVG_ZERO; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else if (op == NVG_DESTINATION_ATOP) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_SRC_ALPHA; + } + else if (op == NVG_LIGHTER) + { + sfactor = NVG_ONE; + dfactor = NVG_ONE; + } + else if (op == NVG_COPY) + { + sfactor = NVG_ONE; + dfactor = NVG_ZERO; + } + else if (op == NVG_XOR) + { + sfactor = NVG_ONE_MINUS_DST_ALPHA; + dfactor = NVG_ONE_MINUS_SRC_ALPHA; + } + else + { + sfactor = NVG_ONE; + dfactor = NVG_ZERO; + } + + NVGcompositeOperationState state; + state.srcRGB = sfactor; + state.dstRGB = dfactor; + state.srcAlpha = sfactor; + state.dstAlpha = dfactor; + return state; +} + +static NVGstate* nvg__getState(NVGcontext* ctx) +{ + return &ctx->states[ctx->nstates-1]; +} + +NVGcontext* nvgCreateInternal(NVGparams* params, NVGcontext* other) // Share the fonts and images of 'other' if it's non-NULL. +{ + FONSparams fontParams; + NVGcontext* ctx = (NVGcontext*)malloc(sizeof(NVGcontext)); + int i; + if (ctx == NULL) goto error; + memset(ctx, 0, sizeof(NVGcontext)); + + ctx->params = *params; + if (other) { + ctx->fontContext = other->fontContext; + ctx->fontContext->refCount++; + } else { + ctx->fontContext = (NVGfontContext*)malloc(sizeof(NVGfontContext)); + if (ctx->fontContext == NULL) goto error; + for (i = 0; i < NVG_MAX_FONTIMAGES; i++) + ctx->fontContext->fontImages[i] = 0; + ctx->fontContext->refCount = 1; + } + + ctx->commands = (float*)malloc(sizeof(float)*NVG_INIT_COMMANDS_SIZE); + if (!ctx->commands) goto error; + ctx->ncommands = 0; + ctx->ccommands = NVG_INIT_COMMANDS_SIZE; + + ctx->cache = nvg__allocPathCache(); + if (ctx->cache == NULL) goto error; + + nvgSave(ctx); + nvgReset(ctx); + + nvg__setDevicePixelRatio(ctx, 1.0f); + + if (ctx->params.renderCreate(ctx->params.userPtr, other ? other->params.userPtr : NULL) == 0) goto error; + + // Init font rendering + if (!other) { + memset(&fontParams, 0, sizeof(fontParams)); + fontParams.width = NVG_INIT_FONTIMAGE_SIZE; + fontParams.height = NVG_INIT_FONTIMAGE_SIZE; + fontParams.flags = FONS_ZERO_TOPLEFT; + fontParams.renderCreate = NULL; + fontParams.renderUpdate = NULL; + fontParams.renderDraw = NULL; + fontParams.renderDelete = NULL; + fontParams.userPtr = NULL; + ctx->fontContext->fs = fonsCreateInternal(&fontParams); + if (ctx->fontContext->fs == NULL) goto error; + + // Create font texture + ctx->fontContext->fontImages[0] = ctx->params.renderCreateTexture(ctx->params.userPtr, + NVG_TEXTURE_ALPHA, + fontParams.width, + fontParams.height, + NVG_FONT_TEXTURE_FLAGS, + NULL); + if (ctx->fontContext->fontImages[0] == 0) goto error; + ctx->fontContext->fontImageIdx = 0; + } + + return ctx; + +error: + nvgDeleteInternal(ctx); + return 0; +} + +NVGparams* nvgInternalParams(NVGcontext* ctx) +{ + return &ctx->params; +} + +void nvgDeleteInternal(NVGcontext* ctx) +{ + int i; + if (ctx == NULL) return; + if (ctx->commands != NULL) free(ctx->commands); + if (ctx->cache != NULL) nvg__deletePathCache(ctx->cache); + + if (ctx->fontContext != NULL && --ctx->fontContext->refCount == 0) { + if (ctx->fontContext->fs) + fonsDeleteInternal(ctx->fontContext->fs); + + for (i = 0; i < NVG_MAX_FONTIMAGES; i++) { + if (ctx->fontContext->fontImages[i] != 0) { + nvgDeleteImage(ctx, ctx->fontContext->fontImages[i]); + ctx->fontContext->fontImages[i] = 0; + } + } + + free(ctx->fontContext); + } + + if (ctx->params.renderDelete != NULL) + ctx->params.renderDelete(ctx->params.userPtr); + + free(ctx); +} + +void nvgBeginFrame(NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio) +{ +/* printf("Tris: draws:%d fill:%d stroke:%d text:%d TOT:%d\n", + ctx->drawCallCount, ctx->fillTriCount, ctx->strokeTriCount, ctx->textTriCount, + ctx->fillTriCount+ctx->strokeTriCount+ctx->textTriCount);*/ + + ctx->nstates = 0; + nvgSave(ctx); + nvgReset(ctx); + + nvg__setDevicePixelRatio(ctx, devicePixelRatio); + + ctx->params.renderViewport(ctx->params.userPtr, windowWidth, windowHeight, devicePixelRatio); + + ctx->drawCallCount = 0; + ctx->fillTriCount = 0; + ctx->strokeTriCount = 0; + ctx->textTriCount = 0; +} + +void nvgCancelFrame(NVGcontext* ctx) +{ + ctx->params.renderCancel(ctx->params.userPtr); +} + +void nvgEndFrame(NVGcontext* ctx) +{ + ctx->params.renderFlush(ctx->params.userPtr); + if (ctx->fontContext->fontImageIdx != 0) { + int fontImage = ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx]; + int i, j, iw, ih; + // delete images that smaller than current one + if (fontImage == 0) + return; + nvgImageSize(ctx, fontImage, &iw, &ih); + for (i = j = 0; i < ctx->fontContext->fontImageIdx; i++) { + if (ctx->fontContext->fontImages[i] != 0) { + int nw, nh; + nvgImageSize(ctx, ctx->fontContext->fontImages[i], &nw, &nh); + if (nw < iw || nh < ih) + nvgDeleteImage(ctx, ctx->fontContext->fontImages[i]); + else + ctx->fontContext->fontImages[j++] = ctx->fontContext->fontImages[i]; + } + } + // make current font image to first + ctx->fontContext->fontImages[j++] = ctx->fontContext->fontImages[0]; + ctx->fontContext->fontImages[0] = fontImage; + ctx->fontContext->fontImageIdx = 0; + // clear all images after j + for (i = j; i < NVG_MAX_FONTIMAGES; i++) + ctx->fontContext->fontImages[i] = 0; + } +} + +NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b) +{ + return nvgRGBA(r,g,b,255); +} + +NVGcolor nvgRGBf(float r, float g, float b) +{ + return nvgRGBAf(r,g,b,1.0f); +} + +NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + NVGcolor color; + // Use longer initialization to suppress warning. + color.r = r / 255.0f; + color.g = g / 255.0f; + color.b = b / 255.0f; + color.a = a / 255.0f; + return color; +} + +NVGcolor nvgRGBAf(float r, float g, float b, float a) +{ + NVGcolor color; + // Use longer initialization to suppress warning. + color.r = r; + color.g = g; + color.b = b; + color.a = a; + return color; +} + +NVGcolor nvgTransRGBA(NVGcolor c, unsigned char a) +{ + c.a = a / 255.0f; + return c; +} + +NVGcolor nvgTransRGBAf(NVGcolor c, float a) +{ + c.a = a; + return c; +} + +NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u) +{ + int i; + float oneminu; + NVGcolor cint = {{{0}}}; + + u = nvg__clampf(u, 0.0f, 1.0f); + oneminu = 1.0f - u; + for( i = 0; i <4; i++ ) + { + cint.rgba[i] = c0.rgba[i] * oneminu + c1.rgba[i] * u; + } + + return cint; +} + +NVGcolor nvgHSL(float h, float s, float l) +{ + return nvgHSLA(h,s,l,255); +} + +static float nvg__hue(float h, float m1, float m2) +{ + if (h < 0) h += 1; + if (h > 1) h -= 1; + if (h < 1.0f/6.0f) + return m1 + (m2 - m1) * h * 6.0f; + else if (h < 3.0f/6.0f) + return m2; + else if (h < 4.0f/6.0f) + return m1 + (m2 - m1) * (2.0f/3.0f - h) * 6.0f; + return m1; +} + +NVGcolor nvgHSLA(float h, float s, float l, unsigned char a) +{ + float m1, m2; + NVGcolor col; + h = nvg__modf(h, 1.0f); + if (h < 0.0f) h += 1.0f; + s = nvg__clampf(s, 0.0f, 1.0f); + l = nvg__clampf(l, 0.0f, 1.0f); + m2 = l <= 0.5f ? (l * (1 + s)) : (l + s - l * s); + m1 = 2 * l - m2; + col.r = nvg__clampf(nvg__hue(h + 1.0f/3.0f, m1, m2), 0.0f, 1.0f); + col.g = nvg__clampf(nvg__hue(h, m1, m2), 0.0f, 1.0f); + col.b = nvg__clampf(nvg__hue(h - 1.0f/3.0f, m1, m2), 0.0f, 1.0f); + col.a = a/255.0f; + return col; +} + +void nvgTransformIdentity(float* t) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformTranslate(float* t, float tx, float ty) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = 0.0f; t[3] = 1.0f; + t[4] = tx; t[5] = ty; +} + +void nvgTransformScale(float* t, float sx, float sy) +{ + t[0] = sx; t[1] = 0.0f; + t[2] = 0.0f; t[3] = sy; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformRotate(float* t, float a) +{ + float cs = nvg__cosf(a), sn = nvg__sinf(a); + t[0] = cs; t[1] = sn; + t[2] = -sn; t[3] = cs; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformSkewX(float* t, float a) +{ + t[0] = 1.0f; t[1] = 0.0f; + t[2] = nvg__tanf(a); t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformSkewY(float* t, float a) +{ + t[0] = 1.0f; t[1] = nvg__tanf(a); + t[2] = 0.0f; t[3] = 1.0f; + t[4] = 0.0f; t[5] = 0.0f; +} + +void nvgTransformMultiply(float* t, const float* s) +{ + float t0 = t[0] * s[0] + t[1] * s[2]; + float t2 = t[2] * s[0] + t[3] * s[2]; + float t4 = t[4] * s[0] + t[5] * s[2] + s[4]; + t[1] = t[0] * s[1] + t[1] * s[3]; + t[3] = t[2] * s[1] + t[3] * s[3]; + t[5] = t[4] * s[1] + t[5] * s[3] + s[5]; + t[0] = t0; + t[2] = t2; + t[4] = t4; +} + +void nvgTransformPremultiply(float* t, const float* s) +{ + float s2[6]; + memcpy(s2, s, sizeof(float)*6); + nvgTransformMultiply(s2, t); + memcpy(t, s2, sizeof(float)*6); +} + +int nvgTransformInverse(float* inv, const float* t) +{ + double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1]; + if (det > -1e-6 && det < 1e-6) { + nvgTransformIdentity(inv); + return 0; + } + invdet = 1.0 / det; + inv[0] = (float)(t[3] * invdet); + inv[2] = (float)(-t[2] * invdet); + inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet); + inv[1] = (float)(-t[1] * invdet); + inv[3] = (float)(t[0] * invdet); + inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet); + return 1; +} + +void nvgTransformPoint(float* dx, float* dy, const float* t, float sx, float sy) +{ + *dx = sx*t[0] + sy*t[2] + t[4]; + *dy = sx*t[1] + sy*t[3] + t[5]; +} + +float nvgDegToRad(float deg) +{ + return deg / 180.0f * NVG_PI; +} + +float nvgRadToDeg(float rad) +{ + return rad / NVG_PI * 180.0f; +} + +static void nvg__setPaintColor(NVGpaint* p, NVGcolor color) +{ + memset(p, 0, sizeof(*p)); + nvgTransformIdentity(p->xform); + p->radius = 0.0f; + p->feather = 1.0f; + p->innerColor = color; + p->outerColor = color; +} + + +// State handling +void nvgSave(NVGcontext* ctx) +{ + if (ctx->nstates >= NVG_MAX_STATES) + return; + if (ctx->nstates > 0) + memcpy(&ctx->states[ctx->nstates], &ctx->states[ctx->nstates-1], sizeof(NVGstate)); + ctx->nstates++; +} + +void nvgRestore(NVGcontext* ctx) +{ + if (ctx->nstates <= 1) + return; + ctx->nstates--; +} + +void nvgReset(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + memset(state, 0, sizeof(*state)); + + nvg__setPaintColor(&state->fill, nvgRGBA(255,255,255,255)); + nvg__setPaintColor(&state->stroke, nvgRGBA(0,0,0,255)); + state->compositeOperation = nvg__compositeOperationState(NVG_SOURCE_OVER); + state->shapeAntiAlias = 1; + state->strokeWidth = 1.0f; + state->miterLimit = 10.0f; + state->lineCap = NVG_BUTT; + state->lineJoin = NVG_MITER; + state->tint = nvgRGBAf(1, 1, 1, 1); + nvgTransformIdentity(state->xform); + + state->scissor.extent[0] = -1.0f; + state->scissor.extent[1] = -1.0f; + + state->fontSize = 16.0f; + state->letterSpacing = 0.0f; + state->lineHeight = 1.0f; + state->fontBlur = 0.0f; + state->textAlign = NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE; + state->fontId = 0; +} + +// State setting +void nvgShapeAntiAlias(NVGcontext* ctx, int enabled) +{ + NVGstate* state = nvg__getState(ctx); + state->shapeAntiAlias = enabled; +} + +void nvgStrokeWidth(NVGcontext* ctx, float width) +{ + NVGstate* state = nvg__getState(ctx); + state->strokeWidth = width; +} + +void nvgMiterLimit(NVGcontext* ctx, float limit) +{ + NVGstate* state = nvg__getState(ctx); + state->miterLimit = limit; +} + +void nvgLineCap(NVGcontext* ctx, int cap) +{ + NVGstate* state = nvg__getState(ctx); + state->lineCap = cap; +} + +void nvgLineJoin(NVGcontext* ctx, int join) +{ + NVGstate* state = nvg__getState(ctx); + state->lineJoin = join; +} + +void nvgGlobalAlpha(NVGcontext* ctx, float alpha) +{ + NVGstate* state = nvg__getState(ctx); + state->tint.a = alpha; +} + +void nvgGlobalTint(NVGcontext* ctx, NVGcolor tint) +{ + NVGstate* state = nvg__getState(ctx); + state->tint = tint; +} + +NVGcolor nvgGetGlobalTint(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + return state->tint; +} + +void nvgAlpha(NVGcontext* ctx, float alpha) +{ + NVGstate* state = nvg__getState(ctx); + state->tint.a *= alpha; +} + +void nvgTint(NVGcontext* ctx, NVGcolor tint) +{ + NVGstate* state = nvg__getState(ctx); + int i; + for (i = 0; i < 4; i++) + state->tint.rgba[i] *= tint.rgba[i]; +} + +void nvgTransform(NVGcontext* ctx, float a, float b, float c, float d, float e, float f) +{ + NVGstate* state = nvg__getState(ctx); + float t[6] = { a, b, c, d, e, f }; + nvgTransformPremultiply(state->xform, t); +} + +void nvgResetTransform(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + nvgTransformIdentity(state->xform); +} + +void nvgTranslate(NVGcontext* ctx, float x, float y) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformTranslate(t, x,y); + nvgTransformPremultiply(state->xform, t); +} + +void nvgRotate(NVGcontext* ctx, float angle) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformRotate(t, angle); + nvgTransformPremultiply(state->xform, t); +} + +void nvgSkewX(NVGcontext* ctx, float angle) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformSkewX(t, angle); + nvgTransformPremultiply(state->xform, t); +} + +void nvgSkewY(NVGcontext* ctx, float angle) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformSkewY(t, angle); + nvgTransformPremultiply(state->xform, t); +} + +void nvgScale(NVGcontext* ctx, float x, float y) +{ + NVGstate* state = nvg__getState(ctx); + float t[6]; + nvgTransformScale(t, x,y); + nvgTransformPremultiply(state->xform, t); +} + +void nvgCurrentTransform(NVGcontext* ctx, float* xform) +{ + NVGstate* state = nvg__getState(ctx); + if (xform == NULL) return; + memcpy(xform, state->xform, sizeof(float)*6); +} + +void nvgStrokeColor(NVGcontext* ctx, NVGcolor color) +{ + NVGstate* state = nvg__getState(ctx); + nvg__setPaintColor(&state->stroke, color); +} + +void nvgStrokePaint(NVGcontext* ctx, NVGpaint paint) +{ + NVGstate* state = nvg__getState(ctx); + state->stroke = paint; + nvgTransformMultiply(state->stroke.xform, state->xform); +} + +void nvgFillColor(NVGcontext* ctx, NVGcolor color) +{ + NVGstate* state = nvg__getState(ctx); + nvg__setPaintColor(&state->fill, color); +} + +void nvgFillPaint(NVGcontext* ctx, NVGpaint paint) +{ + NVGstate* state = nvg__getState(ctx); + state->fill = paint; + nvgTransformMultiply(state->fill.xform, state->xform); +} + +#ifndef NVG_NO_STB +int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags) +{ + int w, h, n, image; + unsigned char* img; + stbi_set_unpremultiply_on_load(1); + stbi_convert_iphone_png_to_rgb(1); + img = stbi_load(filename, &w, &h, &n, 4); + if (img == NULL) { +// printf("Failed to load %s - %s\n", filename, stbi_failure_reason()); + return 0; + } + image = nvgCreateImageRGBA(ctx, w, h, imageFlags, img); + stbi_image_free(img); + return image; +} + +int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, const unsigned char* data, int ndata) +{ + int w, h, n, image; + unsigned char* img = stbi_load_from_memory(data, ndata, &w, &h, &n, 4); + if (img == NULL) { +// printf("Failed to load %s - %s\n", filename, stbi_failure_reason()); + return 0; + } + image = nvgCreateImageRGBA(ctx, w, h, imageFlags, img); + stbi_image_free(img); + return image; +} +#endif + +int nvgCreateImageRaw(NVGcontext* ctx, int w, int h, int imageFlags, NVGtexture format, const unsigned char* data) +{ + return ctx->params.renderCreateTexture(ctx->params.userPtr, format, w, h, imageFlags, data); +} + +int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data) +{ + return nvgCreateImageRaw(ctx, w, h, imageFlags, NVG_TEXTURE_RGBA, data); +} + +void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data) +{ + int w, h; + ctx->params.renderGetTextureSize(ctx->params.userPtr, image, &w, &h); + ctx->params.renderUpdateTexture(ctx->params.userPtr, image, 0,0, w,h, data); +} + +void nvgImageSize(NVGcontext* ctx, int image, int* w, int* h) +{ + ctx->params.renderGetTextureSize(ctx->params.userPtr, image, w, h); +} + +void nvgDeleteImage(NVGcontext* ctx, int image) +{ + ctx->params.renderDeleteTexture(ctx->params.userPtr, image); +} + +NVGpaint nvgLinearGradient(NVGcontext* ctx, + float sx, float sy, float ex, float ey, + NVGcolor icol, NVGcolor ocol) +{ + NVGpaint p; + float dx, dy, d; + const float large = 1e5; + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + // Calculate transform aligned to the line + dx = ex - sx; + dy = ey - sy; + d = sqrtf(dx*dx + dy*dy); + if (d > 0.0001f) { + dx /= d; + dy /= d; + } else { + dx = 0; + dy = 1; + } + + p.xform[0] = dy; p.xform[1] = -dx; + p.xform[2] = dx; p.xform[3] = dy; + p.xform[4] = sx - dx*large; p.xform[5] = sy - dy*large; + + p.extent[0] = large; + p.extent[1] = large + d*0.5f; + + p.radius = 0.0f; + + p.feather = nvg__maxf(1.0f, d); + + p.innerColor = icol; + p.outerColor = ocol; + + return p; +} + +NVGpaint nvgRadialGradient(NVGcontext* ctx, + float cx, float cy, float inr, float outr, + NVGcolor icol, NVGcolor ocol) +{ + NVGpaint p; + float r = (inr+outr)*0.5f; + float f = (outr-inr); + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + nvgTransformIdentity(p.xform); + p.xform[4] = cx; + p.xform[5] = cy; + + p.extent[0] = r; + p.extent[1] = r; + + p.radius = r; + + p.feather = nvg__maxf(1.0f, f); + + p.innerColor = icol; + p.outerColor = ocol; + + return p; +} + +NVGpaint nvgBoxGradient(NVGcontext* ctx, + float x, float y, float w, float h, float r, float f, + NVGcolor icol, NVGcolor ocol) +{ + NVGpaint p; + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + nvgTransformIdentity(p.xform); + p.xform[4] = x+w*0.5f; + p.xform[5] = y+h*0.5f; + + p.extent[0] = w*0.5f; + p.extent[1] = h*0.5f; + + p.radius = r; + + p.feather = nvg__maxf(1.0f, f); + + p.innerColor = icol; + p.outerColor = ocol; + + return p; +} + + +NVGpaint nvgImagePattern(NVGcontext* ctx, + float cx, float cy, float w, float h, float angle, + int image, float alpha) +{ + NVGpaint p; + NVG_NOTUSED(ctx); + memset(&p, 0, sizeof(p)); + + nvgTransformRotate(p.xform, angle); + p.xform[4] = cx; + p.xform[5] = cy; + + p.extent[0] = w; + p.extent[1] = h; + + p.image = image; + + p.innerColor = p.outerColor = nvgRGBAf(1,1,1,alpha); + + return p; +} + +// Scissoring +void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h) +{ + NVGstate* state = nvg__getState(ctx); + + w = nvg__maxf(0.0f, w); + h = nvg__maxf(0.0f, h); + + nvgTransformIdentity(state->scissor.xform); + state->scissor.xform[4] = x+w*0.5f; + state->scissor.xform[5] = y+h*0.5f; + nvgTransformMultiply(state->scissor.xform, state->xform); + + state->scissor.extent[0] = w*0.5f; + state->scissor.extent[1] = h*0.5f; +} + +static void nvg__isectRects(float* dst, + float ax, float ay, float aw, float ah, + float bx, float by, float bw, float bh) +{ + float minx = nvg__maxf(ax, bx); + float miny = nvg__maxf(ay, by); + float maxx = nvg__minf(ax+aw, bx+bw); + float maxy = nvg__minf(ay+ah, by+bh); + dst[0] = minx; + dst[1] = miny; + dst[2] = nvg__maxf(0.0f, maxx - minx); + dst[3] = nvg__maxf(0.0f, maxy - miny); +} + +void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h) +{ + NVGstate* state = nvg__getState(ctx); + float pxform[6], invxorm[6]; + float rect[4]; + float ex, ey, tex, tey; + + // If no previous scissor has been set, set the scissor as current scissor. + if (state->scissor.extent[0] < 0) { + nvgScissor(ctx, x, y, w, h); + return; + } + + // Transform the current scissor rect into current transform space. + // If there is difference in rotation, this will be approximation. + memcpy(pxform, state->scissor.xform, sizeof(float)*6); + ex = state->scissor.extent[0]; + ey = state->scissor.extent[1]; + nvgTransformInverse(invxorm, state->xform); + nvgTransformMultiply(pxform, invxorm); + tex = ex*nvg__absf(pxform[0]) + ey*nvg__absf(pxform[2]); + tey = ex*nvg__absf(pxform[1]) + ey*nvg__absf(pxform[3]); + + // Intersect rects. + nvg__isectRects(rect, pxform[4]-tex,pxform[5]-tey,tex*2,tey*2, x,y,w,h); + + nvgScissor(ctx, rect[0], rect[1], rect[2], rect[3]); +} + +void nvgResetScissor(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + memset(state->scissor.xform, 0, sizeof(state->scissor.xform)); + state->scissor.extent[0] = -1.0f; + state->scissor.extent[1] = -1.0f; +} + +// Global composite operation. +void nvgGlobalCompositeOperation(NVGcontext* ctx, int op) +{ + NVGstate* state = nvg__getState(ctx); + state->compositeOperation = nvg__compositeOperationState(op); +} + +void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor) +{ + nvgGlobalCompositeBlendFuncSeparate(ctx, sfactor, dfactor, sfactor, dfactor); +} + +void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) +{ + NVGcompositeOperationState op; + op.srcRGB = srcRGB; + op.dstRGB = dstRGB; + op.srcAlpha = srcAlpha; + op.dstAlpha = dstAlpha; + + NVGstate* state = nvg__getState(ctx); + state->compositeOperation = op; +} + +static int nvg__ptEquals(float x1, float y1, float x2, float y2, float tol) +{ + float dx = x2 - x1; + float dy = y2 - y1; + return dx*dx + dy*dy < tol*tol; +} + +static float nvg__distPtSeg(float x, float y, float px, float py, float qx, float qy) +{ + float pqx, pqy, dx, dy, d, t; + pqx = qx-px; + pqy = qy-py; + dx = x-px; + dy = y-py; + d = pqx*pqx + pqy*pqy; + t = pqx*dx + pqy*dy; + if (d > 0) t /= d; + if (t < 0) t = 0; + else if (t > 1) t = 1; + dx = px + t*pqx - x; + dy = py + t*pqy - y; + return dx*dx + dy*dy; +} + +static void nvg__appendCommands(NVGcontext* ctx, float* vals, int nvals) +{ + NVGstate* state = nvg__getState(ctx); + int i; + + if (ctx->ncommands+nvals > ctx->ccommands) { + float* commands; + int ccommands = ctx->ncommands+nvals + ctx->ccommands/2; + commands = (float*)realloc(ctx->commands, sizeof(float)*ccommands); + if (commands == NULL) return; + ctx->commands = commands; + ctx->ccommands = ccommands; + } + + if ((int)vals[0] != NVG_CLOSE && (int)vals[0] != NVG_WINDING) { + ctx->commandx = vals[nvals-2]; + ctx->commandy = vals[nvals-1]; + } + + // transform commands + i = 0; + while (i < nvals) { + int cmd = (int)vals[i]; + switch (cmd) { + case NVG_MOVETO: + nvgTransformPoint(&vals[i+1],&vals[i+2], state->xform, vals[i+1],vals[i+2]); + i += 3; + break; + case NVG_LINETO: + nvgTransformPoint(&vals[i+1],&vals[i+2], state->xform, vals[i+1],vals[i+2]); + i += 3; + break; + case NVG_BEZIERTO: + nvgTransformPoint(&vals[i+1],&vals[i+2], state->xform, vals[i+1],vals[i+2]); + nvgTransformPoint(&vals[i+3],&vals[i+4], state->xform, vals[i+3],vals[i+4]); + nvgTransformPoint(&vals[i+5],&vals[i+6], state->xform, vals[i+5],vals[i+6]); + i += 7; + break; + case NVG_CLOSE: + i++; + break; + case NVG_WINDING: + i += 2; + break; + default: + i++; + } + } + + memcpy(&ctx->commands[ctx->ncommands], vals, nvals*sizeof(float)); + + ctx->ncommands += nvals; +} + + +static void nvg__clearPathCache(NVGcontext* ctx) +{ + ctx->cache->npoints = 0; + ctx->cache->npaths = 0; +} + +static NVGpath* nvg__lastPath(NVGcontext* ctx) +{ + if (ctx->cache->npaths > 0) + return &ctx->cache->paths[ctx->cache->npaths-1]; + return NULL; +} + +static void nvg__addPath(NVGcontext* ctx) +{ + NVGpath* path; + if (ctx->cache->npaths+1 > ctx->cache->cpaths) { + NVGpath* paths; + int cpaths = ctx->cache->npaths+1 + ctx->cache->cpaths/2; + paths = (NVGpath*)realloc(ctx->cache->paths, sizeof(NVGpath)*cpaths); + if (paths == NULL) return; + ctx->cache->paths = paths; + ctx->cache->cpaths = cpaths; + } + path = &ctx->cache->paths[ctx->cache->npaths]; + memset(path, 0, sizeof(*path)); + path->first = ctx->cache->npoints; + path->winding = NVG_CCW; + + ctx->cache->npaths++; +} + +static NVGpoint* nvg__lastPoint(NVGcontext* ctx) +{ + if (ctx->cache->npoints > 0) + return &ctx->cache->points[ctx->cache->npoints-1]; + return NULL; +} + +static void nvg__addPoint(NVGcontext* ctx, float x, float y, int flags) +{ + NVGpath* path = nvg__lastPath(ctx); + NVGpoint* pt; + if (path == NULL) return; + + if (path->count > 0 && ctx->cache->npoints > 0) { + pt = nvg__lastPoint(ctx); + if (nvg__ptEquals(pt->x,pt->y, x,y, ctx->distTol)) { + pt->flags |= flags; + return; + } + } + + if (ctx->cache->npoints+1 > ctx->cache->cpoints) { + NVGpoint* points; + int cpoints = ctx->cache->npoints+1 + ctx->cache->cpoints/2; + points = (NVGpoint*)realloc(ctx->cache->points, sizeof(NVGpoint)*cpoints); + if (points == NULL) return; + ctx->cache->points = points; + ctx->cache->cpoints = cpoints; + } + + pt = &ctx->cache->points[ctx->cache->npoints]; + memset(pt, 0, sizeof(*pt)); + pt->x = x; + pt->y = y; + pt->flags = (unsigned char)flags; + + ctx->cache->npoints++; + path->count++; +} + +static void nvg__closePath(NVGcontext* ctx) +{ + NVGpath* path = nvg__lastPath(ctx); + if (path == NULL) return; + path->closed = 1; +} + +static void nvg__pathWinding(NVGcontext* ctx, int winding) +{ + NVGpath* path = nvg__lastPath(ctx); + if (path == NULL) return; + path->winding = winding; +} + +static float nvg__getAverageScale(float *t) +{ + float sx = sqrtf(t[0]*t[0] + t[2]*t[2]); + float sy = sqrtf(t[1]*t[1] + t[3]*t[3]); + return (sx + sy) * 0.5f; +} + +static NVGvertex* nvg__allocTempVerts(NVGcontext* ctx, int nverts) +{ + if (nverts > ctx->cache->cverts) { + NVGvertex* verts; + int cverts = (nverts + 0xff) & ~0xff; // Round up to prevent allocations when things change just slightly. + verts = (NVGvertex*)realloc(ctx->cache->verts, sizeof(NVGvertex)*cverts); + if (verts == NULL) return NULL; + ctx->cache->verts = verts; + ctx->cache->cverts = cverts; + } + + return ctx->cache->verts; +} + +static float nvg__triarea2(float ax, float ay, float bx, float by, float cx, float cy) +{ + float abx = bx - ax; + float aby = by - ay; + float acx = cx - ax; + float acy = cy - ay; + return acx*aby - abx*acy; +} + +static float nvg__polyArea(NVGpoint* pts, int npts) +{ + int i; + float area = 0; + for (i = 2; i < npts; i++) { + NVGpoint* a = &pts[0]; + NVGpoint* b = &pts[i-1]; + NVGpoint* c = &pts[i]; + area += nvg__triarea2(a->x,a->y, b->x,b->y, c->x,c->y); + } + return area * 0.5f; +} + +static void nvg__polyReverse(NVGpoint* pts, int npts) +{ + NVGpoint tmp; + int i = 0, j = npts-1; + while (i < j) { + tmp = pts[i]; + pts[i] = pts[j]; + pts[j] = tmp; + i++; + j--; + } +} + + +static void nvg__vset(NVGvertex* vtx, float x, float y, float u, float v) +{ + vtx->x = x; + vtx->y = y; + vtx->u = u; + vtx->v = v; +} + +static void nvg__tesselateBezier(NVGcontext* ctx, + float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4, + int level, int type) +{ + float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234; + float dx,dy,d2,d3; + + if (level > 10) return; + + x12 = (x1+x2)*0.5f; + y12 = (y1+y2)*0.5f; + x23 = (x2+x3)*0.5f; + y23 = (y2+y3)*0.5f; + x34 = (x3+x4)*0.5f; + y34 = (y3+y4)*0.5f; + x123 = (x12+x23)*0.5f; + y123 = (y12+y23)*0.5f; + + dx = x4 - x1; + dy = y4 - y1; + d2 = nvg__absf(((x2 - x4) * dy - (y2 - y4) * dx)); + d3 = nvg__absf(((x3 - x4) * dy - (y3 - y4) * dx)); + + if ((d2 + d3)*(d2 + d3) < ctx->tessTol * (dx*dx + dy*dy)) { + nvg__addPoint(ctx, x4, y4, type); + return; + } + +/* if (nvg__absf(x1+x3-x2-x2) + nvg__absf(y1+y3-y2-y2) + nvg__absf(x2+x4-x3-x3) + nvg__absf(y2+y4-y3-y3) < ctx->tessTol) { + nvg__addPoint(ctx, x4, y4, type); + return; + }*/ + + x234 = (x23+x34)*0.5f; + y234 = (y23+y34)*0.5f; + x1234 = (x123+x234)*0.5f; + y1234 = (y123+y234)*0.5f; + + nvg__tesselateBezier(ctx, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0); + nvg__tesselateBezier(ctx, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type); +} + +static void nvg__flattenPaths(NVGcontext* ctx) +{ + NVGpathCache* cache = ctx->cache; +// NVGstate* state = nvg__getState(ctx); + NVGpoint* last; + NVGpoint* p0; + NVGpoint* p1; + NVGpoint* pts; + NVGpath* path; + int i, j; + float* cp1; + float* cp2; + float* p; + float area; + + if (cache->npaths > 0) + return; + + // Flatten + i = 0; + while (i < ctx->ncommands) { + int cmd = (int)ctx->commands[i]; + switch (cmd) { + case NVG_MOVETO: + nvg__addPath(ctx); + p = &ctx->commands[i+1]; + nvg__addPoint(ctx, p[0], p[1], NVG_PT_CORNER); + i += 3; + break; + case NVG_LINETO: + p = &ctx->commands[i+1]; + nvg__addPoint(ctx, p[0], p[1], NVG_PT_CORNER); + i += 3; + break; + case NVG_BEZIERTO: + last = nvg__lastPoint(ctx); + if (last != NULL) { + cp1 = &ctx->commands[i+1]; + cp2 = &ctx->commands[i+3]; + p = &ctx->commands[i+5]; + nvg__tesselateBezier(ctx, last->x,last->y, cp1[0],cp1[1], cp2[0],cp2[1], p[0],p[1], 0, NVG_PT_CORNER); + } + i += 7; + break; + case NVG_CLOSE: + nvg__closePath(ctx); + i++; + break; + case NVG_WINDING: + nvg__pathWinding(ctx, (int)ctx->commands[i+1]); + i += 2; + break; + default: + i++; + } + } + + cache->bounds[0] = cache->bounds[1] = 1e6f; + cache->bounds[2] = cache->bounds[3] = -1e6f; + + // Calculate the direction and length of line segments. + for (j = 0; j < cache->npaths; j++) { + path = &cache->paths[j]; + pts = &cache->points[path->first]; + + // If the first and last points are the same, remove the last, mark as closed path. + p0 = &pts[path->count-1]; + p1 = &pts[0]; + if (nvg__ptEquals(p0->x,p0->y, p1->x,p1->y, ctx->distTol)) { + path->count--; + p0 = &pts[path->count-1]; + path->closed = 1; + } + + // Enforce winding. + if (path->count > 2) { + area = nvg__polyArea(pts, path->count); + if (path->winding == NVG_CCW && area < 0.0f) + nvg__polyReverse(pts, path->count); + if (path->winding == NVG_CW && area > 0.0f) + nvg__polyReverse(pts, path->count); + } + + for(i = 0; i < path->count; i++) { + // Calculate segment direction and length + p0->dx = p1->x - p0->x; + p0->dy = p1->y - p0->y; + p0->len = nvg__normalize(&p0->dx, &p0->dy); + // Update bounds + cache->bounds[0] = nvg__minf(cache->bounds[0], p0->x); + cache->bounds[1] = nvg__minf(cache->bounds[1], p0->y); + cache->bounds[2] = nvg__maxf(cache->bounds[2], p0->x); + cache->bounds[3] = nvg__maxf(cache->bounds[3], p0->y); + // Advance + p0 = p1++; + } + } +} + +static int nvg__curveDivs(float r, float arc, float tol) +{ + float da = acosf(r / (r + tol)) * 2.0f; + return nvg__maxi(2, (int)ceilf(arc / da)); +} + +static void nvg__chooseBevel(int bevel, NVGpoint* p0, NVGpoint* p1, float w, + float* x0, float* y0, float* x1, float* y1) +{ + if (bevel) { + *x0 = p1->x + p0->dy * w; + *y0 = p1->y - p0->dx * w; + *x1 = p1->x + p1->dy * w; + *y1 = p1->y - p1->dx * w; + } else { + *x0 = p1->x + p1->dmx * w; + *y0 = p1->y + p1->dmy * w; + *x1 = p1->x + p1->dmx * w; + *y1 = p1->y + p1->dmy * w; + } +} + +static NVGvertex* nvg__roundJoin(NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, + float lw, float rw, float lu, float ru, int ncap, + float fringe) +{ + int i, n; + float dlx0 = p0->dy; + float dly0 = -p0->dx; + float dlx1 = p1->dy; + float dly1 = -p1->dx; + NVG_NOTUSED(fringe); + + if (p1->flags & NVG_PT_LEFT) { + float lx0,ly0,lx1,ly1,a0,a1; + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, lw, &lx0,&ly0, &lx1,&ly1); + a0 = atan2f(-dly0, -dlx0); + a1 = atan2f(-dly1, -dlx1); + if (a1 > a0) a1 -= NVG_PI*2; + + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + n = nvg__clampi((int)ceilf(((a0 - a1) / NVG_PI) * ncap), 2, ncap); + for (i = 0; i < n; i++) { + float u = i/(float)(n-1); + float a = a0 + u*(a1-a0); + float rx = p1->x + cosf(a) * rw; + float ry = p1->y + sinf(a) * rw; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + nvg__vset(dst, rx, ry, ru,1); dst++; + } + + nvg__vset(dst, lx1, ly1, lu,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + + } else { + float rx0,ry0,rx1,ry1,a0,a1; + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, -rw, &rx0,&ry0, &rx1,&ry1); + a0 = atan2f(dly0, dlx0); + a1 = atan2f(dly1, dlx1); + if (a1 < a0) a1 += NVG_PI*2; + + nvg__vset(dst, p1->x + dlx0*rw, p1->y + dly0*rw, lu,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + n = nvg__clampi((int)ceilf(((a1 - a0) / NVG_PI) * ncap), 2, ncap); + for (i = 0; i < n; i++) { + float u = i/(float)(n-1); + float a = a0 + u*(a1-a0); + float lx = p1->x + cosf(a) * lw; + float ly = p1->y + sinf(a) * lw; + nvg__vset(dst, lx, ly, lu,1); dst++; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + } + + nvg__vset(dst, p1->x + dlx1*rw, p1->y + dly1*rw, lu,1); dst++; + nvg__vset(dst, rx1, ry1, ru,1); dst++; + + } + return dst; +} + +static NVGvertex* nvg__bevelJoin(NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, + float lw, float rw, float lu, float ru, float fringe) +{ + float rx0,ry0,rx1,ry1; + float lx0,ly0,lx1,ly1; + float dlx0 = p0->dy; + float dly0 = -p0->dx; + float dlx1 = p1->dy; + float dly1 = -p1->dx; + NVG_NOTUSED(fringe); + + if (p1->flags & NVG_PT_LEFT) { + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, lw, &lx0,&ly0, &lx1,&ly1); + + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + if (p1->flags & NVG_PT_BEVEL) { + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + nvg__vset(dst, lx1, ly1, lu,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + } else { + rx0 = p1->x - p1->dmx * rw; + ry0 = p1->y - p1->dmy * rw; + + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + nvg__vset(dst, p1->x - dlx0*rw, p1->y - dly0*rw, ru,1); dst++; + + nvg__vset(dst, rx0, ry0, ru,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + } + + nvg__vset(dst, lx1, ly1, lu,1); dst++; + nvg__vset(dst, p1->x - dlx1*rw, p1->y - dly1*rw, ru,1); dst++; + + } else { + nvg__chooseBevel(p1->flags & NVG_PR_INNERBEVEL, p0, p1, -rw, &rx0,&ry0, &rx1,&ry1); + + nvg__vset(dst, p1->x + dlx0*lw, p1->y + dly0*lw, lu,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + if (p1->flags & NVG_PT_BEVEL) { + nvg__vset(dst, p1->x + dlx0*lw, p1->y + dly0*lw, lu,1); dst++; + nvg__vset(dst, rx0, ry0, ru,1); dst++; + + nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++; + nvg__vset(dst, rx1, ry1, ru,1); dst++; + } else { + lx0 = p1->x + p1->dmx * lw; + ly0 = p1->y + p1->dmy * lw; + + nvg__vset(dst, p1->x + dlx0*lw, p1->y + dly0*lw, lu,1); dst++; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + + nvg__vset(dst, lx0, ly0, lu,1); dst++; + nvg__vset(dst, lx0, ly0, lu,1); dst++; + + nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++; + nvg__vset(dst, p1->x, p1->y, 0.5f,1); dst++; + } + + nvg__vset(dst, p1->x + dlx1*lw, p1->y + dly1*lw, lu,1); dst++; + nvg__vset(dst, rx1, ry1, ru,1); dst++; + } + + return dst; +} + +static NVGvertex* nvg__buttCapStart(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, float d, + float aa, float u0, float u1) +{ + float px = p->x - dx*d; + float py = p->y - dy*d; + float dlx = dy; + float dly = -dx; + nvg__vset(dst, px + dlx*w - dx*aa, py + dly*w - dy*aa, u0,0); dst++; + nvg__vset(dst, px - dlx*w - dx*aa, py - dly*w - dy*aa, u1,0); dst++; + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + return dst; +} + +static NVGvertex* nvg__buttCapEnd(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, float d, + float aa, float u0, float u1) +{ + float px = p->x + dx*d; + float py = p->y + dy*d; + float dlx = dy; + float dly = -dx; + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + nvg__vset(dst, px + dlx*w + dx*aa, py + dly*w + dy*aa, u0,0); dst++; + nvg__vset(dst, px - dlx*w + dx*aa, py - dly*w + dy*aa, u1,0); dst++; + return dst; +} + + +static NVGvertex* nvg__roundCapStart(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, int ncap, + float aa, float u0, float u1) +{ + int i; + float px = p->x; + float py = p->y; + float dlx = dy; + float dly = -dx; + NVG_NOTUSED(aa); + for (i = 0; i < ncap; i++) { + float a = i/(float)(ncap-1)*NVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + nvg__vset(dst, px - dlx*ax - dx*ay, py - dly*ax - dy*ay, u0,1); dst++; + nvg__vset(dst, px, py, 0.5f,1); dst++; + } + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + return dst; +} + +static NVGvertex* nvg__roundCapEnd(NVGvertex* dst, NVGpoint* p, + float dx, float dy, float w, int ncap, + float aa, float u0, float u1) +{ + int i; + float px = p->x; + float py = p->y; + float dlx = dy; + float dly = -dx; + NVG_NOTUSED(aa); + nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++; + nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++; + for (i = 0; i < ncap; i++) { + float a = i/(float)(ncap-1)*NVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + nvg__vset(dst, px, py, 0.5f,1); dst++; + nvg__vset(dst, px - dlx*ax + dx*ay, py - dly*ax + dy*ay, u0,1); dst++; + } + return dst; +} + + +static void nvg__calculateJoins(NVGcontext* ctx, float w, int lineJoin, float miterLimit) +{ + NVGpathCache* cache = ctx->cache; + int i, j; + float iw = 0.0f; + + if (w > 0.0f) iw = 1.0f / w; + + // Calculate which joins needs extra vertices to append, and gather vertex count. + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + NVGpoint* pts = &cache->points[path->first]; + NVGpoint* p0 = &pts[path->count-1]; + NVGpoint* p1 = &pts[0]; + int nleft = 0; + + path->nbevel = 0; + + for (j = 0; j < path->count; j++) { + float dlx0, dly0, dlx1, dly1, dmr2, cross, limit; + dlx0 = p0->dy; + dly0 = -p0->dx; + dlx1 = p1->dy; + dly1 = -p1->dx; + // Calculate extrusions + p1->dmx = (dlx0 + dlx1) * 0.5f; + p1->dmy = (dly0 + dly1) * 0.5f; + dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy; + if (dmr2 > 0.000001f) { + float scale = 1.0f / dmr2; + if (scale > 600.0f) { + scale = 600.0f; + } + p1->dmx *= scale; + p1->dmy *= scale; + } + + // Clear flags, but keep the corner. + p1->flags = (p1->flags & NVG_PT_CORNER) ? NVG_PT_CORNER : 0; + + // Keep track of left turns. + cross = p1->dx * p0->dy - p0->dx * p1->dy; + if (cross > 0.0f) { + nleft++; + p1->flags |= NVG_PT_LEFT; + } + + // Calculate if we should use bevel or miter for inner join. + limit = nvg__maxf(1.01f, nvg__minf(p0->len, p1->len) * iw); + if ((dmr2 * limit*limit) < 1.0f) + p1->flags |= NVG_PR_INNERBEVEL; + + // Check to see if the corner needs to be beveled. + if (p1->flags & NVG_PT_CORNER) { + if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NVG_BEVEL || lineJoin == NVG_ROUND) { + p1->flags |= NVG_PT_BEVEL; + } + } + + if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) + path->nbevel++; + + p0 = p1++; + } + + path->convex = (nleft == path->count) ? 1 : 0; + } +} + + +static int nvg__expandStroke(NVGcontext* ctx, float w, float fringe, int lineCap, int lineJoin, float miterLimit) +{ + NVGpathCache* cache = ctx->cache; + NVGvertex* verts; + NVGvertex* dst; + int cverts, i, j; + float aa = fringe;//ctx->fringeWidth; + float u0 = 0.0f, u1 = 1.0f; + int ncap = nvg__curveDivs(w, NVG_PI, ctx->tessTol); // Calculate divisions per half circle. + + w += aa * 0.5f; + + // Disable the gradient used for antialiasing when antialiasing is not used. + if (aa == 0.0f) { + u0 = 0.5f; + u1 = 0.5f; + } + + nvg__calculateJoins(ctx, w, lineJoin, miterLimit); + + // Calculate max vertex usage. + cverts = 0; + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + int loop = (path->closed == 0) ? 0 : 1; + if (lineJoin == NVG_ROUND) + cverts += (path->count + path->nbevel*(ncap+2) + 1) * 2; // plus one for loop + else + cverts += (path->count + path->nbevel*5 + 1) * 2; // plus one for loop + if (loop == 0) { + // space for caps + if (lineCap == NVG_ROUND) { + cverts += (ncap*2 + 2)*2; + } else { + cverts += (3+3)*2; + } + } + } + + verts = nvg__allocTempVerts(ctx, cverts); + if (verts == NULL) return 0; + + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + NVGpoint* pts = &cache->points[path->first]; + NVGpoint* p0; + NVGpoint* p1; + int s, e, loop; + float dx, dy; + + path->fill = 0; + path->nfill = 0; + + // Calculate fringe or stroke + loop = (path->closed == 0) ? 0 : 1; + dst = verts; + path->stroke = dst; + + if (loop) { + // Looping + p0 = &pts[path->count-1]; + p1 = &pts[0]; + s = 0; + e = path->count; + } else { + // Add cap + p0 = &pts[0]; + p1 = &pts[1]; + s = 1; + e = path->count-1; + } + + if (loop == 0) { + // Add cap + dx = p1->x - p0->x; + dy = p1->y - p0->y; + nvg__normalize(&dx, &dy); + if (lineCap == NVG_BUTT) + dst = nvg__buttCapStart(dst, p0, dx, dy, w, -aa*0.5f, aa, u0, u1); + else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE) + dst = nvg__buttCapStart(dst, p0, dx, dy, w, w-aa, aa, u0, u1); + else if (lineCap == NVG_ROUND) + dst = nvg__roundCapStart(dst, p0, dx, dy, w, ncap, aa, u0, u1); + } + + for (j = s; j < e; ++j) { + if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) { + if (lineJoin == NVG_ROUND) { + dst = nvg__roundJoin(dst, p0, p1, w, w, u0, u1, ncap, aa); + } else { + dst = nvg__bevelJoin(dst, p0, p1, w, w, u0, u1, aa); + } + } else { + nvg__vset(dst, p1->x + (p1->dmx * w), p1->y + (p1->dmy * w), u0,1); dst++; + nvg__vset(dst, p1->x - (p1->dmx * w), p1->y - (p1->dmy * w), u1,1); dst++; + } + p0 = p1++; + } + + if (loop) { + // Loop it + nvg__vset(dst, verts[0].x, verts[0].y, u0,1); dst++; + nvg__vset(dst, verts[1].x, verts[1].y, u1,1); dst++; + } else { + // Add cap + dx = p1->x - p0->x; + dy = p1->y - p0->y; + nvg__normalize(&dx, &dy); + if (lineCap == NVG_BUTT) + dst = nvg__buttCapEnd(dst, p1, dx, dy, w, -aa*0.5f, aa, u0, u1); + else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE) + dst = nvg__buttCapEnd(dst, p1, dx, dy, w, w-aa, aa, u0, u1); + else if (lineCap == NVG_ROUND) + dst = nvg__roundCapEnd(dst, p1, dx, dy, w, ncap, aa, u0, u1); + } + + path->nstroke = (int)(dst - verts); + + verts = dst; + } + + return 1; +} + +static int nvg__expandFill(NVGcontext* ctx, float w, int lineJoin, float miterLimit) +{ + NVGpathCache* cache = ctx->cache; + NVGvertex* verts; + NVGvertex* dst; + int cverts, convex, i, j; + float aa = ctx->fringeWidth; + int fringe = w > 0.0f; + + nvg__calculateJoins(ctx, w, lineJoin, miterLimit); + + // Calculate max vertex usage. + cverts = 0; + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + cverts += path->count + path->nbevel + 1; + if (fringe) + cverts += (path->count + path->nbevel*5 + 1) * 2; // plus one for loop + } + + verts = nvg__allocTempVerts(ctx, cverts); + if (verts == NULL) return 0; + + convex = cache->npaths == 1 && cache->paths[0].convex; + + for (i = 0; i < cache->npaths; i++) { + NVGpath* path = &cache->paths[i]; + NVGpoint* pts = &cache->points[path->first]; + NVGpoint* p0; + NVGpoint* p1; + float rw, lw, woff; + float ru, lu; + + // Calculate shape vertices. + woff = 0.5f*aa; + dst = verts; + path->fill = dst; + + if (fringe) { + // Looping + p0 = &pts[path->count-1]; + p1 = &pts[0]; + for (j = 0; j < path->count; ++j) { + if (p1->flags & NVG_PT_BEVEL) { + float dlx0 = p0->dy; + float dly0 = -p0->dx; + float dlx1 = p1->dy; + float dly1 = -p1->dx; + if (p1->flags & NVG_PT_LEFT) { + float lx = p1->x + p1->dmx * woff; + float ly = p1->y + p1->dmy * woff; + nvg__vset(dst, lx, ly, 0.5f,1); dst++; + } else { + float lx0 = p1->x + dlx0 * woff; + float ly0 = p1->y + dly0 * woff; + float lx1 = p1->x + dlx1 * woff; + float ly1 = p1->y + dly1 * woff; + nvg__vset(dst, lx0, ly0, 0.5f,1); dst++; + nvg__vset(dst, lx1, ly1, 0.5f,1); dst++; + } + } else { + nvg__vset(dst, p1->x + (p1->dmx * woff), p1->y + (p1->dmy * woff), 0.5f,1); dst++; + } + p0 = p1++; + } + } else { + for (j = 0; j < path->count; ++j) { + nvg__vset(dst, pts[j].x, pts[j].y, 0.5f,1); + dst++; + } + } + + path->nfill = (int)(dst - verts); + verts = dst; + + // Calculate fringe + if (fringe) { + lw = w + woff; + rw = w - woff; + lu = 0; + ru = 1; + dst = verts; + path->stroke = dst; + + // Create only half a fringe for convex shapes so that + // the shape can be rendered without stenciling. + if (convex) { + lw = woff; // This should generate the same vertex as fill inset above. + lu = 0.5f; // Set outline fade at middle. + } + + // Looping + p0 = &pts[path->count-1]; + p1 = &pts[0]; + + for (j = 0; j < path->count; ++j) { + if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) { + dst = nvg__bevelJoin(dst, p0, p1, lw, rw, lu, ru, ctx->fringeWidth); + } else { + nvg__vset(dst, p1->x + (p1->dmx * lw), p1->y + (p1->dmy * lw), lu,1); dst++; + nvg__vset(dst, p1->x - (p1->dmx * rw), p1->y - (p1->dmy * rw), ru,1); dst++; + } + p0 = p1++; + } + + // Loop it + nvg__vset(dst, verts[0].x, verts[0].y, lu,1); dst++; + nvg__vset(dst, verts[1].x, verts[1].y, ru,1); dst++; + + path->nstroke = (int)(dst - verts); + verts = dst; + } else { + path->stroke = NULL; + path->nstroke = 0; + } + } + + return 1; +} + + +// Draw +void nvgBeginPath(NVGcontext* ctx) +{ + ctx->ncommands = 0; + nvg__clearPathCache(ctx); +} + +void nvgMoveTo(NVGcontext* ctx, float x, float y) +{ + float vals[] = { NVG_MOVETO, x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgLineTo(NVGcontext* ctx, float x, float y) +{ + float vals[] = { NVG_LINETO, x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y) +{ + float vals[] = { NVG_BEZIERTO, c1x, c1y, c2x, c2y, x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y) +{ + float x0 = ctx->commandx; + float y0 = ctx->commandy; + float vals[] = { NVG_BEZIERTO, + x0 + 2.0f/3.0f*(cx - x0), y0 + 2.0f/3.0f*(cy - y0), + x + 2.0f/3.0f*(cx - x), y + 2.0f/3.0f*(cy - y), + x, y }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius) +{ + float x0 = ctx->commandx; + float y0 = ctx->commandy; + float dx0,dy0, dx1,dy1, a, d, cx,cy, a0,a1; + int dir; + + if (ctx->ncommands == 0) { + return; + } + + // Handle degenerate cases. + if (nvg__ptEquals(x0,y0, x1,y1, ctx->distTol) || + nvg__ptEquals(x1,y1, x2,y2, ctx->distTol) || + nvg__distPtSeg(x1,y1, x0,y0, x2,y2) < ctx->distTol*ctx->distTol || + radius < ctx->distTol) { + nvgLineTo(ctx, x1,y1); + return; + } + + // Calculate tangential circle to lines (x0,y0)-(x1,y1) and (x1,y1)-(x2,y2). + dx0 = x0-x1; + dy0 = y0-y1; + dx1 = x2-x1; + dy1 = y2-y1; + nvg__normalize(&dx0,&dy0); + nvg__normalize(&dx1,&dy1); + a = nvg__acosf(dx0*dx1 + dy0*dy1); + d = radius / nvg__tanf(a/2.0f); + +// printf("a=%f° d=%f\n", a/NVG_PI*180.0f, d); + + if (d > 10000.0f) { + nvgLineTo(ctx, x1,y1); + return; + } + + if (nvg__cross(dx0,dy0, dx1,dy1) > 0.0f) { + cx = x1 + dx0*d + dy0*radius; + cy = y1 + dy0*d + -dx0*radius; + a0 = nvg__atan2f(dx0, -dy0); + a1 = nvg__atan2f(-dx1, dy1); + dir = NVG_CW; +// printf("CW c=(%f, %f) a0=%f° a1=%f°\n", cx, cy, a0/NVG_PI*180.0f, a1/NVG_PI*180.0f); + } else { + cx = x1 + dx0*d + -dy0*radius; + cy = y1 + dy0*d + dx0*radius; + a0 = nvg__atan2f(-dx0, dy0); + a1 = nvg__atan2f(dx1, -dy1); + dir = NVG_CCW; +// printf("CCW c=(%f, %f) a0=%f° a1=%f°\n", cx, cy, a0/NVG_PI*180.0f, a1/NVG_PI*180.0f); + } + + nvgArc(ctx, cx, cy, radius, a0, a1, dir); +} + +void nvgClosePath(NVGcontext* ctx) +{ + float vals[] = { NVG_CLOSE }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgPathWinding(NVGcontext* ctx, int dir) +{ + float vals[] = { NVG_WINDING, (float)dir }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgArc(NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir) +{ + float a = 0, da = 0, hda = 0, kappa = 0; + float dx = 0, dy = 0, x = 0, y = 0, tanx = 0, tany = 0; + float px = 0, py = 0, ptanx = 0, ptany = 0; + float vals[3 + 5*7 + 100]; + int i, ndivs, nvals; + int move = ctx->ncommands > 0 ? NVG_LINETO : NVG_MOVETO; + + // Clamp angles + da = a1 - a0; + if (dir == NVG_CW) { + if (nvg__absf(da) >= NVG_PI*2) { + da = NVG_PI*2; + } else { + while (da < 0.0f) da += NVG_PI*2; + } + } else { + if (nvg__absf(da) >= NVG_PI*2) { + da = -NVG_PI*2; + } else { + while (da > 0.0f) da -= NVG_PI*2; + } + } + + // Split arc into max 90 degree segments. + ndivs = nvg__maxi(1, nvg__mini((int)(nvg__absf(da) / (NVG_PI*0.5f) + 0.5f), 5)); + hda = (da / (float)ndivs) / 2.0f; + kappa = nvg__absf(4.0f / 3.0f * (1.0f - nvg__cosf(hda)) / nvg__sinf(hda)); + + if (dir == NVG_CCW) + kappa = -kappa; + + nvals = 0; + for (i = 0; i <= ndivs; i++) { + a = a0 + da * (i/(float)ndivs); + dx = nvg__cosf(a); + dy = nvg__sinf(a); + x = cx + dx*r; + y = cy + dy*r; + tanx = -dy*r*kappa; + tany = dx*r*kappa; + + if (i == 0) { + vals[nvals++] = (float)move; + vals[nvals++] = x; + vals[nvals++] = y; + } else { + vals[nvals++] = NVG_BEZIERTO; + vals[nvals++] = px+ptanx; + vals[nvals++] = py+ptany; + vals[nvals++] = x-tanx; + vals[nvals++] = y-tany; + vals[nvals++] = x; + vals[nvals++] = y; + } + px = x; + py = y; + ptanx = tanx; + ptany = tany; + } + + nvg__appendCommands(ctx, vals, nvals); +} + +void nvgRect(NVGcontext* ctx, float x, float y, float w, float h) +{ + float vals[] = { + NVG_MOVETO, x,y, + NVG_LINETO, x,y+h, + NVG_LINETO, x+w,y+h, + NVG_LINETO, x+w,y, + NVG_CLOSE + }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r) +{ + nvgRoundedRectVarying(ctx, x, y, w, h, r, r, r, r); +} + +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft) +{ + if(radTopLeft < 0.1f && radTopRight < 0.1f && radBottomRight < 0.1f && radBottomLeft < 0.1f) { + nvgRect(ctx, x, y, w, h); + return; + } else { + float halfw = nvg__absf(w)*0.5f; + float halfh = nvg__absf(h)*0.5f; + float rxBL = nvg__minf(radBottomLeft, halfw) * nvg__signf(w), ryBL = nvg__minf(radBottomLeft, halfh) * nvg__signf(h); + float rxBR = nvg__minf(radBottomRight, halfw) * nvg__signf(w), ryBR = nvg__minf(radBottomRight, halfh) * nvg__signf(h); + float rxTR = nvg__minf(radTopRight, halfw) * nvg__signf(w), ryTR = nvg__minf(radTopRight, halfh) * nvg__signf(h); + float rxTL = nvg__minf(radTopLeft, halfw) * nvg__signf(w), ryTL = nvg__minf(radTopLeft, halfh) * nvg__signf(h); + float vals[] = { + NVG_MOVETO, x, y + ryTL, + NVG_LINETO, x, y + h - ryBL, + NVG_BEZIERTO, x, y + h - ryBL*(1 - NVG_KAPPA90), x + rxBL*(1 - NVG_KAPPA90), y + h, x + rxBL, y + h, + NVG_LINETO, x + w - rxBR, y + h, + NVG_BEZIERTO, x + w - rxBR*(1 - NVG_KAPPA90), y + h, x + w, y + h - ryBR*(1 - NVG_KAPPA90), x + w, y + h - ryBR, + NVG_LINETO, x + w, y + ryTR, + NVG_BEZIERTO, x + w, y + ryTR*(1 - NVG_KAPPA90), x + w - rxTR*(1 - NVG_KAPPA90), y, x + w - rxTR, y, + NVG_LINETO, x + rxTL, y, + NVG_BEZIERTO, x + rxTL*(1 - NVG_KAPPA90), y, x, y + ryTL*(1 - NVG_KAPPA90), x, y + ryTL, + NVG_CLOSE + }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); + } +} + +void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry) +{ + float vals[] = { + NVG_MOVETO, cx-rx, cy, + NVG_BEZIERTO, cx-rx, cy+ry*NVG_KAPPA90, cx-rx*NVG_KAPPA90, cy+ry, cx, cy+ry, + NVG_BEZIERTO, cx+rx*NVG_KAPPA90, cy+ry, cx+rx, cy+ry*NVG_KAPPA90, cx+rx, cy, + NVG_BEZIERTO, cx+rx, cy-ry*NVG_KAPPA90, cx+rx*NVG_KAPPA90, cy-ry, cx, cy-ry, + NVG_BEZIERTO, cx-rx*NVG_KAPPA90, cy-ry, cx-rx, cy-ry*NVG_KAPPA90, cx-rx, cy, + NVG_CLOSE + }; + nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); +} + +void nvgCircle(NVGcontext* ctx, float cx, float cy, float r) +{ + nvgEllipse(ctx, cx,cy, r,r); +} + +void nvgDebugDumpPathCache(NVGcontext* ctx) +{ + const NVGpath* path; + int i, j; + + printf("Dumping %d cached paths\n", ctx->cache->npaths); + for (i = 0; i < ctx->cache->npaths; i++) { + path = &ctx->cache->paths[i]; + printf(" - Path %d\n", i); + if (path->nfill) { + printf(" - fill: %d\n", path->nfill); + for (j = 0; j < path->nfill; j++) + printf("%f\t%f\n", path->fill[j].x, path->fill[j].y); + } + if (path->nstroke) { + printf(" - stroke: %d\n", path->nstroke); + for (j = 0; j < path->nstroke; j++) + printf("%f\t%f\n", path->stroke[j].x, path->stroke[j].y); + } + } +} + +void nvgFill(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + const NVGpath* path; + NVGpaint fillPaint = state->fill; + int i; + + nvg__flattenPaths(ctx); + if (ctx->params.edgeAntiAlias && state->shapeAntiAlias) + nvg__expandFill(ctx, ctx->fringeWidth, NVG_MITER, 2.4f); + else + nvg__expandFill(ctx, 0.0f, NVG_MITER, 2.4f); + + // Apply global tint + for (i = 0; i < 4; i++) { + fillPaint.innerColor.rgba[i] *= state->tint.rgba[i]; + fillPaint.outerColor.rgba[i] *= state->tint.rgba[i]; + } + + ctx->params.renderFill(ctx->params.userPtr, &fillPaint, state->compositeOperation, &state->scissor, ctx->fringeWidth, + ctx->cache->bounds, ctx->cache->paths, ctx->cache->npaths); + + // Count triangles + for (i = 0; i < ctx->cache->npaths; i++) { + path = &ctx->cache->paths[i]; + ctx->fillTriCount += path->nfill-2; + ctx->fillTriCount += path->nstroke-2; + ctx->drawCallCount += 2; + } +} + +void nvgStroke(NVGcontext* ctx) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getAverageScale(state->xform); + float strokeWidth = nvg__clampf(state->strokeWidth * scale, 0.0f, 200.0f); + NVGpaint strokePaint = state->stroke; + const NVGpath* path; + int i; + + + if (strokeWidth < ctx->fringeWidth) { + // If the stroke width is less than pixel size, use alpha to emulate coverage. + // Since coverage is area, scale by alpha*alpha. + float alpha = nvg__clampf(strokeWidth / ctx->fringeWidth, 0.0f, 1.0f); + strokePaint.innerColor.a *= alpha*alpha; + strokePaint.outerColor.a *= alpha*alpha; + strokeWidth = ctx->fringeWidth; + } + + // Apply global tint + for (i = 0; i < 4; i++) { + strokePaint.innerColor.rgba[i] *= state->tint.rgba[i]; + strokePaint.outerColor.rgba[i] *= state->tint.rgba[i]; + } + + nvg__flattenPaths(ctx); + + if (ctx->params.edgeAntiAlias && state->shapeAntiAlias) + nvg__expandStroke(ctx, strokeWidth*0.5f, ctx->fringeWidth, state->lineCap, state->lineJoin, state->miterLimit); + else + nvg__expandStroke(ctx, strokeWidth*0.5f, 0.0f, state->lineCap, state->lineJoin, state->miterLimit); + + ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, state->compositeOperation, &state->scissor, ctx->fringeWidth, + strokeWidth, ctx->cache->paths, ctx->cache->npaths); + + // Count triangles + for (i = 0; i < ctx->cache->npaths; i++) { + path = &ctx->cache->paths[i]; + ctx->strokeTriCount += path->nstroke-2; + ctx->drawCallCount++; + } +} + +// Add fonts +int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename) +{ + return fonsAddFont(ctx->fontContext->fs, name, filename, 0); +} + +int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex) +{ + return fonsAddFont(ctx->fontContext->fs, name, filename, fontIndex); +} + +int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData) +{ + return fonsAddFontMem(ctx->fontContext->fs, name, data, ndata, freeData, 0); +} + +int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex) +{ + return fonsAddFontMem(ctx->fontContext->fs, name, data, ndata, freeData, fontIndex); +} + +int nvgFindFont(NVGcontext* ctx, const char* name) +{ + if (name == NULL) return -1; + return fonsGetFontByName(ctx->fontContext->fs, name); +} + + +int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont) +{ + if(baseFont == -1 || fallbackFont == -1) return 0; + return fonsAddFallbackFont(ctx->fontContext->fs, baseFont, fallbackFont); +} + +int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont) +{ + return nvgAddFallbackFontId(ctx, nvgFindFont(ctx, baseFont), nvgFindFont(ctx, fallbackFont)); +} + +void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont) +{ + fonsResetFallbackFont(ctx->fontContext->fs, baseFont); +} + +void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont) +{ + nvgResetFallbackFontsId(ctx, nvgFindFont(ctx, baseFont)); +} + +// State setting +void nvgFontSize(NVGcontext* ctx, float size) +{ + NVGstate* state = nvg__getState(ctx); + state->fontSize = size; +} + +void nvgFontBlur(NVGcontext* ctx, float blur) +{ + NVGstate* state = nvg__getState(ctx); + state->fontBlur = blur; +} + +void nvgTextLetterSpacing(NVGcontext* ctx, float spacing) +{ + NVGstate* state = nvg__getState(ctx); + state->letterSpacing = spacing; +} + +void nvgTextLineHeight(NVGcontext* ctx, float lineHeight) +{ + NVGstate* state = nvg__getState(ctx); + state->lineHeight = lineHeight; +} + +void nvgTextAlign(NVGcontext* ctx, int align) +{ + NVGstate* state = nvg__getState(ctx); + state->textAlign = align; +} + +void nvgFontFaceId(NVGcontext* ctx, int font) +{ + NVGstate* state = nvg__getState(ctx); + state->fontId = font; +} + +void nvgFontFace(NVGcontext* ctx, const char* font) +{ + NVGstate* state = nvg__getState(ctx); + state->fontId = fonsGetFontByName(ctx->fontContext->fs, font); +} + +static float nvg__quantize(float a, float d) +{ + return ((int)(a / d + 0.5f)) * d; +} + +static float nvg__getFontScale(NVGstate* state) +{ + return nvg__minf(nvg__quantize(nvg__getAverageScale(state->xform), 0.01f), 4.0f); +} + +static void nvg__flushTextTexture(NVGcontext* ctx) +{ + int dirty[4]; + + if (fonsValidateTexture(ctx->fontContext->fs, dirty)) { + int fontImage = ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx]; + // Update texture + if (fontImage != 0) { + int iw, ih; + const unsigned char* data = fonsGetTextureData(ctx->fontContext->fs, &iw, &ih); + int x = dirty[0]; + int y = dirty[1]; + int w = dirty[2] - dirty[0]; + int h = dirty[3] - dirty[1]; + ctx->params.renderUpdateTexture(ctx->params.userPtr, fontImage, x,y, w,h, data); + } + } +} + +static int nvg__allocTextAtlas(NVGcontext* ctx) +{ + int iw, ih; + nvg__flushTextTexture(ctx); + if (ctx->fontContext->fontImageIdx >= NVG_MAX_FONTIMAGES-1) + return 0; + // if next fontImage already have a texture + if (ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1] != 0) + nvgImageSize(ctx, ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1], &iw, &ih); + else { // calculate the new font image size and create it. + nvgImageSize(ctx, ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx], &iw, &ih); + if (iw > ih) + ih *= 2; + else + iw *= 2; + if (iw > NVG_MAX_FONTIMAGE_SIZE || ih > NVG_MAX_FONTIMAGE_SIZE) + iw = ih = NVG_MAX_FONTIMAGE_SIZE; + ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx+1] + = ctx->params.renderCreateTexture(ctx->params.userPtr, + NVG_TEXTURE_ALPHA, iw, ih, NVG_FONT_TEXTURE_FLAGS, NULL); + } + ++ctx->fontContext->fontImageIdx; + fonsResetAtlas(ctx->fontContext->fs, iw, ih); + return 1; +} + +static void nvg__renderText(NVGcontext* ctx, NVGvertex* verts, int nverts) +{ + int i; + NVGstate* state = nvg__getState(ctx); + NVGpaint paint = state->fill; + + // Render triangles. + paint.image = ctx->fontContext->fontImages[ctx->fontContext->fontImageIdx]; + + // Apply global tint + for (i = 0; i < 4; i++) { + paint.innerColor.rgba[i] *= state->tint.rgba[i]; + paint.outerColor.rgba[i] *= state->tint.rgba[i]; + } + + ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts, ctx->fringeWidth); + + ctx->drawCallCount++; + ctx->textTriCount += nverts/3; +} + +static int nvg__isTransformFlipped(const float *xform) +{ + float det = xform[0] * xform[3] - xform[2] * xform[1]; + return( det < 0); +} + +float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end) +{ + NVGstate* state = nvg__getState(ctx); + FONStextIter iter, prevIter; + FONSquad q; + NVGvertex* verts; + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + int cverts = 0; + int nverts = 0; + int isFlipped = nvg__isTransformFlipped(state->xform); + + if (end == NULL) + end = string + strlen(string); + + if (state->fontId == FONS_INVALID) return x; + + fonsSetSize(ctx->fontContext->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fontContext->fs, state->textAlign); + fonsSetFont(ctx->fontContext->fs, state->fontId); + + cverts = nvg__maxi(2, (int)(end - string)) * 6; // conservative estimate. + verts = nvg__allocTempVerts(ctx, cverts); + if (verts == NULL) return x; + + fonsTextIterInit(ctx->fontContext->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_REQUIRED); + prevIter = iter; + while (fonsTextIterNext(ctx->fontContext->fs, &iter, &q)) { + float c[4*2]; + if (iter.prevGlyphIndex == -1) { // can not retrieve glyph? + if (nverts != 0) { + nvg__renderText(ctx, verts, nverts); + nverts = 0; + } + if (!nvg__allocTextAtlas(ctx)) + break; // no memory :( + iter = prevIter; + fonsTextIterNext(ctx->fontContext->fs, &iter, &q); // try again + if (iter.prevGlyphIndex == -1) // still can not find glyph? + break; + } + prevIter = iter; + if(isFlipped) { + float tmp; + + tmp = q.y0; q.y0 = q.y1; q.y1 = tmp; + tmp = q.t0; q.t0 = q.t1; q.t1 = tmp; + } + // Transform corners. + nvgTransformPoint(&c[0],&c[1], state->xform, q.x0*invscale, q.y0*invscale); + nvgTransformPoint(&c[2],&c[3], state->xform, q.x1*invscale, q.y0*invscale); + nvgTransformPoint(&c[4],&c[5], state->xform, q.x1*invscale, q.y1*invscale); + nvgTransformPoint(&c[6],&c[7], state->xform, q.x0*invscale, q.y1*invscale); + // Create triangles + if (nverts+6 <= cverts) { +#if NVG_FONT_TEXTURE_FLAGS + // align font kerning to integer pixel positions + for (int i = 0; i < 8; ++i) + c[i] = (int)(c[i] + 0.5f); +#endif + nvg__vset(&verts[nverts], c[0], c[1], q.s0, q.t0); nverts++; + nvg__vset(&verts[nverts], c[4], c[5], q.s1, q.t1); nverts++; + nvg__vset(&verts[nverts], c[2], c[3], q.s1, q.t0); nverts++; + nvg__vset(&verts[nverts], c[0], c[1], q.s0, q.t0); nverts++; + nvg__vset(&verts[nverts], c[6], c[7], q.s0, q.t1); nverts++; + nvg__vset(&verts[nverts], c[4], c[5], q.s1, q.t1); nverts++; + } + } + + // TODO: add back-end bit to do this just once per frame. + nvg__flushTextTexture(ctx); + + nvg__renderText(ctx, verts, nverts); + + return iter.nextx / scale; +} + +void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end) +{ + NVGstate* state = nvg__getState(ctx); + NVGtextRow rows[2]; + int nrows = 0, i; + int oldAlign = state->textAlign; + int haling = state->textAlign & (NVG_ALIGN_LEFT | NVG_ALIGN_CENTER | NVG_ALIGN_RIGHT); + int valign = state->textAlign & (NVG_ALIGN_TOP | NVG_ALIGN_MIDDLE | NVG_ALIGN_BOTTOM | NVG_ALIGN_BASELINE); + float lineh = 0; + + if (state->fontId == FONS_INVALID) return; + + nvgTextMetrics(ctx, NULL, NULL, &lineh); + + state->textAlign = NVG_ALIGN_LEFT | valign; + + while ((nrows = nvgTextBreakLines(ctx, string, end, breakRowWidth, rows, 2))) { + for (i = 0; i < nrows; i++) { + NVGtextRow* row = &rows[i]; + if (haling & NVG_ALIGN_LEFT) + nvgText(ctx, x, y, row->start, row->end); + else if (haling & NVG_ALIGN_CENTER) + nvgText(ctx, x + breakRowWidth*0.5f - row->width*0.5f, y, row->start, row->end); + else if (haling & NVG_ALIGN_RIGHT) + nvgText(ctx, x + breakRowWidth - row->width, y, row->start, row->end); + y += lineh * state->lineHeight; + } + string = rows[nrows-1].next; + } + + state->textAlign = oldAlign; +} + +int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + FONStextIter iter, prevIter; + FONSquad q; + int npos = 0; + + if (state->fontId == FONS_INVALID) return 0; + + if (end == NULL) + end = string + strlen(string); + + if (string == end) + return 0; + + fonsSetSize(ctx->fontContext->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fontContext->fs, state->textAlign); + fonsSetFont(ctx->fontContext->fs, state->fontId); + + fonsTextIterInit(ctx->fontContext->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_OPTIONAL); + prevIter = iter; + while (fonsTextIterNext(ctx->fontContext->fs, &iter, &q)) { + if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph? + iter = prevIter; + fonsTextIterNext(ctx->fontContext->fs, &iter, &q); // try again + } + prevIter = iter; + positions[npos].str = iter.str; + positions[npos].x = iter.x * invscale; + positions[npos].minx = nvg__minf(iter.x, q.x0) * invscale; + positions[npos].maxx = nvg__maxf(iter.nextx, q.x1) * invscale; + npos++; + if (npos >= maxPositions) + break; + } + + return npos; +} + +enum NVGcodepointType { + NVG_SPACE, + NVG_NEWLINE, + NVG_CHAR, + NVG_CJK_CHAR, +}; + +int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + FONStextIter iter, prevIter; + FONSquad q; + int nrows = 0; + float rowStartX = 0; + float rowWidth = 0; + float rowMinX = 0; + float rowMaxX = 0; + const char* rowStart = NULL; + const char* rowEnd = NULL; + const char* wordStart = NULL; + float wordStartX = 0; + float wordMinX = 0; + const char* breakEnd = NULL; + float breakWidth = 0; + float breakMaxX = 0; + int type = NVG_SPACE, ptype = NVG_SPACE; + unsigned int pcodepoint = 0; + + if (maxRows == 0) return 0; + if (state->fontId == FONS_INVALID) return 0; + + if (end == NULL) + end = string + strlen(string); + + if (string == end) return 0; + + fonsSetSize(ctx->fontContext->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fontContext->fs, state->textAlign); + fonsSetFont(ctx->fontContext->fs, state->fontId); + + breakRowWidth *= scale; + + fonsTextIterInit(ctx->fontContext->fs, &iter, 0, 0, string, end, FONS_GLYPH_BITMAP_OPTIONAL); + prevIter = iter; + while (fonsTextIterNext(ctx->fontContext->fs, &iter, &q)) { + if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph? + iter = prevIter; + fonsTextIterNext(ctx->fontContext->fs, &iter, &q); // try again + } + prevIter = iter; + switch (iter.codepoint) { + case 9: // \t + case 11: // \v + case 12: // \f + case 32: // space + case 0x00a0: // NBSP + type = NVG_SPACE; + break; + case 10: // \n + type = pcodepoint == 13 ? NVG_SPACE : NVG_NEWLINE; + break; + case 13: // \r + type = pcodepoint == 10 ? NVG_SPACE : NVG_NEWLINE; + break; + case 0x0085: // NEL + type = NVG_NEWLINE; + break; + default: + if ((iter.codepoint >= 0x4E00 && iter.codepoint <= 0x9FFF) || + (iter.codepoint >= 0x3000 && iter.codepoint <= 0x30FF) || + (iter.codepoint >= 0xFF00 && iter.codepoint <= 0xFFEF) || + (iter.codepoint >= 0x1100 && iter.codepoint <= 0x11FF) || + (iter.codepoint >= 0x3130 && iter.codepoint <= 0x318F) || + (iter.codepoint >= 0xAC00 && iter.codepoint <= 0xD7AF)) + type = NVG_CJK_CHAR; + else + type = NVG_CHAR; + break; + } + + if (type == NVG_NEWLINE) { + // Always handle new lines. + rows[nrows].start = rowStart != NULL ? rowStart : iter.str; + rows[nrows].end = rowEnd != NULL ? rowEnd : iter.str; + rows[nrows].width = rowWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = rowMaxX * invscale; + rows[nrows].next = iter.next; + nrows++; + if (nrows >= maxRows) + return nrows; + // Set null break point + breakEnd = rowStart; + breakWidth = 0.0; + breakMaxX = 0.0; + // Indicate to skip the white space at the beginning of the row. + rowStart = NULL; + rowEnd = NULL; + rowWidth = 0; + rowMinX = rowMaxX = 0; + } else { + if (rowStart == NULL) { + // Skip white space until the beginning of the line + if (type == NVG_CHAR || type == NVG_CJK_CHAR || type == NVG_SKIPPED_CHAR) { + // The current char is the row so far + rowStartX = iter.x; + rowStart = iter.str; + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMinX = q.x0 - rowStartX; + rowMaxX = q.x1 - rowStartX; + wordStart = iter.str; + wordStartX = iter.x; + wordMinX = q.x0 - rowStartX; + // Set null break point + breakEnd = rowStart; + breakWidth = 0.0; + breakMaxX = 0.0; + } + } else { + float nextWidth = iter.nextx - rowStartX; + + // track last non-white space character + if (type == NVG_CHAR || type == NVG_CJK_CHAR || type == NVG_SKIPPED_CHAR) { + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMaxX = q.x1 - rowStartX; + } + // track last end of a word + if (((ptype == NVG_CHAR || ptype == NVG_CJK_CHAR) && type == NVG_SPACE) || type == NVG_CJK_CHAR) { + breakEnd = iter.str; + breakWidth = rowWidth; + breakMaxX = rowMaxX; + } + // track last beginning of a word + if ((ptype == NVG_SPACE && (type == NVG_CHAR || type == NVG_CJK_CHAR)) || type == NVG_CJK_CHAR) { + wordStart = iter.str; + wordStartX = iter.x; + wordMinX = q.x0; + } + + // Break to new line when a character is beyond break width. + if ((type == NVG_CHAR || type == NVG_CJK_CHAR) && nextWidth > breakRowWidth) { + // The run length is too long, need to break to new line. + if (breakEnd == rowStart) { + // The current word is longer than the row length, just break it from here. + rows[nrows].start = rowStart; + rows[nrows].end = iter.str; + rows[nrows].width = rowWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = rowMaxX * invscale; + rows[nrows].next = iter.str; + nrows++; + if (nrows >= maxRows) + return nrows; + rowStartX = iter.x; + rowStart = iter.str; + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMinX = q.x0 - rowStartX; + rowMaxX = q.x1 - rowStartX; + wordStart = iter.str; + wordStartX = iter.x; + wordMinX = q.x0 - rowStartX; + } else { + // Break the line from the end of the last word, and start new line from the beginning of the new. + rows[nrows].start = rowStart; + rows[nrows].end = breakEnd; + rows[nrows].width = breakWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = breakMaxX * invscale; + rows[nrows].next = wordStart; + nrows++; + if (nrows >= maxRows) + return nrows; + // Update row + rowStartX = wordStartX; + rowStart = wordStart; + rowEnd = iter.next; + rowWidth = iter.nextx - rowStartX; + rowMinX = wordMinX - rowStartX; + rowMaxX = q.x1 - rowStartX; + } + // Set null break point + breakEnd = rowStart; + breakWidth = 0.0; + breakMaxX = 0.0; + } + } + } + + pcodepoint = iter.codepoint; + ptype = type; + } + + // Break the line from the end of the last word, and start new line from the beginning of the new. + if (rowStart != NULL) { + rows[nrows].start = rowStart; + rows[nrows].end = rowEnd; + rows[nrows].width = rowWidth * invscale; + rows[nrows].minx = rowMinX * invscale; + rows[nrows].maxx = rowMaxX * invscale; + rows[nrows].next = end; + nrows++; + } + + return nrows; +} + +float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + float width; + + if (state->fontId == FONS_INVALID) return 0; + + fonsSetSize(ctx->fontContext->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fontContext->fs, state->textAlign); + fonsSetFont(ctx->fontContext->fs, state->fontId); + + width = fonsTextBounds(ctx->fontContext->fs, x*scale, y*scale, string, end, bounds); + if (bounds != NULL) { + // Use line bounds for height. + fonsLineBounds(ctx->fontContext->fs, y*scale, &bounds[1], &bounds[3]); + bounds[0] *= invscale; + bounds[1] *= invscale; + bounds[2] *= invscale; + bounds[3] *= invscale; + } + return width * invscale; +} + +void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds) +{ + NVGstate* state = nvg__getState(ctx); + NVGtextRow rows[2]; + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + int nrows = 0, i; + int oldAlign = state->textAlign; + int haling = state->textAlign & (NVG_ALIGN_LEFT | NVG_ALIGN_CENTER | NVG_ALIGN_RIGHT); + int valign = state->textAlign & (NVG_ALIGN_TOP | NVG_ALIGN_MIDDLE | NVG_ALIGN_BOTTOM | NVG_ALIGN_BASELINE); + float lineh = 0, rminy = 0, rmaxy = 0; + float minx, miny, maxx, maxy; + + if (state->fontId == FONS_INVALID) { + if (bounds != NULL) + bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0f; + return; + } + + nvgTextMetrics(ctx, NULL, NULL, &lineh); + + state->textAlign = NVG_ALIGN_LEFT | valign; + + minx = maxx = x; + miny = maxy = y; + + fonsSetSize(ctx->fontContext->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fontContext->fs, state->textAlign); + fonsSetFont(ctx->fontContext->fs, state->fontId); + fonsLineBounds(ctx->fontContext->fs, 0, &rminy, &rmaxy); + rminy *= invscale; + rmaxy *= invscale; + + while ((nrows = nvgTextBreakLines(ctx, string, end, breakRowWidth, rows, 2))) { + for (i = 0; i < nrows; i++) { + NVGtextRow* row = &rows[i]; + float rminx, rmaxx, dx = 0; + // Horizontal bounds + if (haling & NVG_ALIGN_LEFT) + dx = 0; + else if (haling & NVG_ALIGN_CENTER) + dx = breakRowWidth*0.5f - row->width*0.5f; + else if (haling & NVG_ALIGN_RIGHT) + dx = breakRowWidth - row->width; + rminx = x + row->minx + dx; + rmaxx = x + row->maxx + dx; + minx = nvg__minf(minx, rminx); + maxx = nvg__maxf(maxx, rmaxx); + // Vertical bounds. + miny = nvg__minf(miny, y + rminy); + maxy = nvg__maxf(maxy, y + rmaxy); + + y += lineh * state->lineHeight; + } + string = rows[nrows-1].next; + } + + state->textAlign = oldAlign; + + if (bounds != NULL) { + bounds[0] = minx; + bounds[1] = miny; + bounds[2] = maxx; + bounds[3] = maxy; + } +} + +void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* lineh) +{ + NVGstate* state = nvg__getState(ctx); + float scale = nvg__getFontScale(state) * ctx->devicePxRatio; + float invscale = 1.0f / scale; + + if (state->fontId == FONS_INVALID) return; + + fonsSetSize(ctx->fontContext->fs, state->fontSize*scale); + fonsSetSpacing(ctx->fontContext->fs, state->letterSpacing*scale); + fonsSetBlur(ctx->fontContext->fs, state->fontBlur*scale); + fonsSetAlign(ctx->fontContext->fs, state->textAlign); + fonsSetFont(ctx->fontContext->fs, state->fontId); + + fonsVertMetrics(ctx->fontContext->fs, ascender, descender, lineh); + if (ascender != NULL) + *ascender *= invscale; + if (descender != NULL) + *descender *= invscale; + if (lineh != NULL) + *lineh *= invscale; +} +// vim: ft=c nu noet ts=4 diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,708 @@ +// +// Copyright (c) 2013 Mikko Mononen memon@inside.org +// +// 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. +// + +#ifndef NANOVG_H +#define NANOVG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define NVG_PI 3.14159265358979323846264338327f + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +#endif + +typedef struct NVGcontext NVGcontext; + +struct NVGcolor { + union { + float rgba[4]; + struct { + float r,g,b,a; + }; + }; +}; +typedef struct NVGcolor NVGcolor; + +struct NVGpaint { + float xform[6]; + float extent[2]; + float radius; + float feather; + NVGcolor innerColor; + NVGcolor outerColor; + int image; +}; +typedef struct NVGpaint NVGpaint; + +enum NVGwinding { + NVG_CCW = 1, // Winding for solid shapes + NVG_CW = 2, // Winding for holes +}; + +enum NVGsolidity { + NVG_SOLID = 1, // CCW + NVG_HOLE = 2, // CW +}; + +enum NVGlineCap { + NVG_BUTT, + NVG_ROUND, + NVG_SQUARE, + NVG_BEVEL, + NVG_MITER, +}; + +enum NVGalign { + // Horizontal align + NVG_ALIGN_LEFT = 1<<0, // Default, align text horizontally to left. + NVG_ALIGN_CENTER = 1<<1, // Align text horizontally to center. + NVG_ALIGN_RIGHT = 1<<2, // Align text horizontally to right. + // Vertical align + NVG_ALIGN_TOP = 1<<3, // Align text vertically to top. + NVG_ALIGN_MIDDLE = 1<<4, // Align text vertically to middle. + NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom. + NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline. +}; + +enum NVGblendFactor { + NVG_ZERO = 1<<0, + NVG_ONE = 1<<1, + NVG_SRC_COLOR = 1<<2, + NVG_ONE_MINUS_SRC_COLOR = 1<<3, + NVG_DST_COLOR = 1<<4, + NVG_ONE_MINUS_DST_COLOR = 1<<5, + NVG_SRC_ALPHA = 1<<6, + NVG_ONE_MINUS_SRC_ALPHA = 1<<7, + NVG_DST_ALPHA = 1<<8, + NVG_ONE_MINUS_DST_ALPHA = 1<<9, + NVG_SRC_ALPHA_SATURATE = 1<<10, +}; + +enum NVGcompositeOperation { + NVG_SOURCE_OVER, + NVG_SOURCE_IN, + NVG_SOURCE_OUT, + NVG_ATOP, + NVG_DESTINATION_OVER, + NVG_DESTINATION_IN, + NVG_DESTINATION_OUT, + NVG_DESTINATION_ATOP, + NVG_LIGHTER, + NVG_COPY, + NVG_XOR, +}; + +struct NVGcompositeOperationState { + int srcRGB; + int dstRGB; + int srcAlpha; + int dstAlpha; +}; +typedef struct NVGcompositeOperationState NVGcompositeOperationState; + +struct NVGglyphPosition { + const char* str; // Position of the glyph in the input string. + float x; // The x-coordinate of the logical glyph position. + float minx, maxx; // The bounds of the glyph shape. +}; +typedef struct NVGglyphPosition NVGglyphPosition; + +struct NVGtextRow { + const char* start; // Pointer to the input text where the row starts. + const char* end; // Pointer to the input text where the row ends (one past the last character). + const char* next; // Pointer to the beginning of the next row. + float width; // Logical width of the row. + float minx, maxx; // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending. +}; +typedef struct NVGtextRow NVGtextRow; + +enum NVGimageFlags { + NVG_IMAGE_GENERATE_MIPMAPS = 1<<0, // Generate mipmaps during creation of the image. + NVG_IMAGE_REPEATX = 1<<1, // Repeat image in X direction. + NVG_IMAGE_REPEATY = 1<<2, // Repeat image in Y direction. + NVG_IMAGE_FLIPY = 1<<3, // Flips (inverses) image in Y direction when rendered. + NVG_IMAGE_PREMULTIPLIED = 1<<4, // Image data has premultiplied alpha. + NVG_IMAGE_NEAREST = 1<<5, // Image interpolation is Nearest instead Linear +}; + +enum NVGtexture { + NVG_TEXTURE_ALPHA, + NVG_TEXTURE_BGR, + NVG_TEXTURE_BGRA, + NVG_TEXTURE_RGB, + NVG_TEXTURE_RGBA, +}; + +// Begin drawing a new frame +// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame() +// nvgBeginFrame() defines the size of the window to render to in relation currently +// set viewport (i.e. glViewport on GL backends). Device pixel ration allows to +// control the rendering on Hi-DPI devices. +// For example, GLFW returns two dimension for an opened window: window size and +// frame buffer size. In that case you would set windowWidth/Height to the window size +// devicePixelRatio to: frameBufferWidth / windowWidth. +void nvgBeginFrame(NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio); + +// Cancels drawing the current frame. +void nvgCancelFrame(NVGcontext* ctx); + +// Ends drawing flushing remaining render state. +void nvgEndFrame(NVGcontext* ctx); + +// +// Composite operation +// +// The composite operations in NanoVG are modeled after HTML Canvas API, and +// the blend func is based on OpenGL (see corresponding manuals for more info). +// The colors in the blending state have premultiplied alpha. + +// Sets the composite operation. The op parameter should be one of NVGcompositeOperation. +void nvgGlobalCompositeOperation(NVGcontext* ctx, int op); + +// Sets the composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor. +void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor); + +// Sets the composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor. +void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha); + +// +// Color utils +// +// Colors in NanoVG are stored as unsigned ints in ABGR format. + +// Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f). +NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b); + +// Returns a color value from red, green, blue values. Alpha will be set to 1.0f. +NVGcolor nvgRGBf(float r, float g, float b); + + +// Returns a color value from red, green, blue and alpha values. +NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +// Returns a color value from red, green, blue and alpha values. +NVGcolor nvgRGBAf(float r, float g, float b, float a); + + +// Linearly interpolates from color c0 to c1, and returns resulting color value. +NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u); + +// Sets transparency of a color value. +NVGcolor nvgTransRGBA(NVGcolor c0, unsigned char a); + +// Sets transparency of a color value. +NVGcolor nvgTransRGBAf(NVGcolor c0, float a); + +// Returns color value specified by hue, saturation and lightness. +// HSL values are all in range [0..1], alpha will be set to 255. +NVGcolor nvgHSL(float h, float s, float l); + +// Returns color value specified by hue, saturation and lightness and alpha. +// HSL values are all in range [0..1], alpha in range [0..255] +NVGcolor nvgHSLA(float h, float s, float l, unsigned char a); + +// +// State Handling +// +// NanoVG contains state which represents how paths will be rendered. +// The state contains transform, fill and stroke styles, text and font styles, +// and scissor clipping. + +// Pushes and saves the current render state into a state stack. +// A matching nvgRestore() must be used to restore the state. +void nvgSave(NVGcontext* ctx); + +// Pops and restores current render state. +void nvgRestore(NVGcontext* ctx); + +// Resets current render state to default values. Does not affect the render state stack. +void nvgReset(NVGcontext* ctx); + +// +// Render styles +// +// Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern. +// Solid color is simply defined as a color value, different kinds of paints can be created +// using nvgLinearGradient(), nvgBoxGradient(), nvgRadialGradient() and nvgImagePattern(). +// +// Current render style can be saved and restored using nvgSave() and nvgRestore(). + +// Sets whether to draw antialias for nvgStroke() and nvgFill(). It's enabled by default. +void nvgShapeAntiAlias(NVGcontext* ctx, int enabled); + +// Sets current stroke style to a solid color. +void nvgStrokeColor(NVGcontext* ctx, NVGcolor color); + +// Sets current stroke style to a paint, which can be a one of the gradients or a pattern. +void nvgStrokePaint(NVGcontext* ctx, NVGpaint paint); + +// Sets current fill style to a solid color. +void nvgFillColor(NVGcontext* ctx, NVGcolor color); + +// Sets current fill style to a paint, which can be a one of the gradients or a pattern. +void nvgFillPaint(NVGcontext* ctx, NVGpaint paint); + +// Sets the miter limit of the stroke style. +// Miter limit controls when a sharp corner is beveled. +void nvgMiterLimit(NVGcontext* ctx, float limit); + +// Sets the stroke width of the stroke style. +void nvgStrokeWidth(NVGcontext* ctx, float size); + +// Sets how the end of the line (cap) is drawn, +// Can be one of: NVG_BUTT (default), NVG_ROUND, NVG_SQUARE. +void nvgLineCap(NVGcontext* ctx, int cap); + +// Sets how sharp path corners are drawn. +// Can be one of NVG_MITER (default), NVG_ROUND, NVG_BEVEL. +void nvgLineJoin(NVGcontext* ctx, int join); + +// Sets the transparency applied to all rendered shapes. +// Already transparent paths will get proportionally more transparent as well. +void nvgGlobalAlpha(NVGcontext* ctx, float alpha); +void nvgGlobalTint(NVGcontext* ctx, NVGcolor tint); +NVGcolor nvgGetGlobalTint(NVGcontext* ctx); +void nvgAlpha(NVGcontext* ctx, float alpha); +void nvgTint(NVGcontext* ctx, NVGcolor tint); + +// +// Transforms +// +// The paths, gradients, patterns and scissor region are transformed by an transformation +// matrix at the time when they are passed to the API. +// The current transformation matrix is a affine matrix: +// [sx kx tx] +// [ky sy ty] +// [ 0 0 1] +// Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation. +// The last row is assumed to be 0,0,1 and is not stored. +// +// Apart from nvgResetTransform(), each transformation function first creates +// specific transformation matrix and pre-multiplies the current transformation by it. +// +// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore(). + +// Resets current transform to a identity matrix. +void nvgResetTransform(NVGcontext* ctx); + +// Premultiplies current coordinate system by specified matrix. +// The parameters are interpreted as matrix as follows: +// [a c e] +// [b d f] +// [0 0 1] +void nvgTransform(NVGcontext* ctx, float a, float b, float c, float d, float e, float f); + +// Translates current coordinate system. +void nvgTranslate(NVGcontext* ctx, float x, float y); + +// Rotates current coordinate system. Angle is specified in radians. +void nvgRotate(NVGcontext* ctx, float angle); + +// Skews the current coordinate system along X axis. Angle is specified in radians. +void nvgSkewX(NVGcontext* ctx, float angle); + +// Skews the current coordinate system along Y axis. Angle is specified in radians. +void nvgSkewY(NVGcontext* ctx, float angle); + +// Scales the current coordinate system. +void nvgScale(NVGcontext* ctx, float x, float y); + +// Stores the top part (a-f) of the current transformation matrix in to the specified buffer. +// [a c e] +// [b d f] +// [0 0 1] +// There should be space for 6 floats in the return buffer for the values a-f. +void nvgCurrentTransform(NVGcontext* ctx, float* xform); + + +// The following functions can be used to make calculations on 2x3 transformation matrices. +// A 2x3 matrix is represented as float[6]. + +// Sets the transform to identity matrix. +void nvgTransformIdentity(float* dst); + +// Sets the transform to translation matrix matrix. +void nvgTransformTranslate(float* dst, float tx, float ty); + +// Sets the transform to scale matrix. +void nvgTransformScale(float* dst, float sx, float sy); + +// Sets the transform to rotate matrix. Angle is specified in radians. +void nvgTransformRotate(float* dst, float a); + +// Sets the transform to skew-x matrix. Angle is specified in radians. +void nvgTransformSkewX(float* dst, float a); + +// Sets the transform to skew-y matrix. Angle is specified in radians. +void nvgTransformSkewY(float* dst, float a); + +// Sets the transform to the result of multiplication of two transforms, of A = A*B. +void nvgTransformMultiply(float* dst, const float* src); + +// Sets the transform to the result of multiplication of two transforms, of A = B*A. +void nvgTransformPremultiply(float* dst, const float* src); + +// Sets the destination to inverse of specified transform. +// Returns 1 if the inverse could be calculated, else 0. +int nvgTransformInverse(float* dst, const float* src); + +// Transform a point by given transform. +void nvgTransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy); + +// Converts degrees to radians and vice versa. +float nvgDegToRad(float deg); +float nvgRadToDeg(float rad); + +// +// Images +// +// NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering. +// In addition you can upload your own image. The image loading is provided by stb_image. +// The parameter imageFlags is combination of flags defined in NVGimageFlags. + +// Creates image by loading it from the disk from specified file name. +// Returns handle to the image. +int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags); + +// Creates image by loading it from the specified chunk of memory. +// Returns handle to the image. +int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, const unsigned char* data, int ndata); + +// Creates image from specified image data and texture format. +// Returns handle to the image. +int nvgCreateImageRaw(NVGcontext* ctx, int w, int h, int imageFlags, enum NVGtexture format, const unsigned char* data); + +// Creates image from specified image data. +// Returns handle to the image. +int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data); + +// Updates image data specified by image handle. +void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data); + +// Returns the dimensions of a created image. +void nvgImageSize(NVGcontext* ctx, int image, int* w, int* h); + +// Deletes created image. +void nvgDeleteImage(NVGcontext* ctx, int image); + +// +// Paints +// +// NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern. +// These can be used as paints for strokes and fills. + +// Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates +// of the linear gradient, icol specifies the start color and ocol the end color. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgLinearGradient(NVGcontext* ctx, float sx, float sy, float ex, float ey, + NVGcolor icol, NVGcolor ocol); + +// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering +// drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle, +// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry +// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgBoxGradient(NVGcontext* ctx, float x, float y, float w, float h, + float r, float f, NVGcolor icol, NVGcolor ocol); + +// Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify +// the inner and outer radius of the gradient, icol specifies the start color and ocol the end color. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr, + NVGcolor icol, NVGcolor ocol); + +// Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern, +// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render. +// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). +NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey, + float angle, int image, float alpha); + +// +// Scissoring +// +// Scissoring allows you to clip the rendering into a rectangle. This is useful for various +// user interface cases like rendering a text edit or a timeline. + +// Sets the current scissor rectangle. +// The scissor rectangle is transformed by the current transform. +void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h); + +// Intersects current scissor rectangle with the specified rectangle. +// The scissor rectangle is transformed by the current transform. +// Note: in case the rotation of previous scissor rect differs from +// the current one, the intersection will be done between the specified +// rectangle and the previous scissor rectangle transformed in the current +// transform space. The resulting shape is always rectangle. +void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h); + +// Reset and disables scissoring. +void nvgResetScissor(NVGcontext* ctx); + +// +// Paths +// +// Drawing a new shape starts with nvgBeginPath(), it clears all the currently defined paths. +// Then you define one or more paths and sub-paths which describe the shape. The are functions +// to draw common shapes like rectangles and circles, and lower level step-by-step functions, +// which allow to define a path curve by curve. +// +// NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise +// winding and holes should have counter clockwise order. To specify winding of a path you can +// call nvgPathWinding(). This is useful especially for the common shapes, which are drawn CCW. +// +// Finally you can fill the path using current fill style by calling nvgFill(), and stroke it +// with current stroke style by calling nvgStroke(). +// +// The curve segments and sub-paths are transformed by the current transform. + +// Clears the current path and sub-paths. +void nvgBeginPath(NVGcontext* ctx); + +// Starts new sub-path with specified point as first point. +void nvgMoveTo(NVGcontext* ctx, float x, float y); + +// Adds line segment from the last point in the path to the specified point. +void nvgLineTo(NVGcontext* ctx, float x, float y); + +// Adds cubic bezier segment from last point in the path via two control points to the specified point. +void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y); + +// Adds quadratic bezier segment from last point in the path via a control point to the specified point. +void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y); + +// Adds an arc segment at the corner defined by the last path point, and two specified points. +void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius); + +// Closes current sub-path with a line segment. +void nvgClosePath(NVGcontext* ctx); + +// Sets the current sub-path winding, see NVGwinding and NVGsolidity. +void nvgPathWinding(NVGcontext* ctx, int dir); + +// Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r, +// and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW, or NVG_CW). +// Angles are specified in radians. +void nvgArc(NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir); + +// Creates new rectangle shaped sub-path. +void nvgRect(NVGcontext* ctx, float x, float y, float w, float h); + +// Creates new rounded rectangle shaped sub-path. +void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r); + +// Creates new rounded rectangle shaped sub-path with varying radii for each corner. +void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft); + +// Creates new ellipse shaped sub-path. +void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry); + +// Creates new circle shaped sub-path. +void nvgCircle(NVGcontext* ctx, float cx, float cy, float r); + +// Fills the current path with current fill style. +void nvgFill(NVGcontext* ctx); + +// Fills the current path with current stroke style. +void nvgStroke(NVGcontext* ctx); + + +// +// Text +// +// NanoVG allows you to load .ttf files and use the font to render text. +// +// The appearance of the text can be defined by setting the current text style +// and by specifying the fill color. Common text and font settings such as +// font size, letter spacing and text align are supported. Font blur allows you +// to create simple text effects such as drop shadows. +// +// At render time the font face can be set based on the font handles or name. +// +// Font measure functions return values in local space, the calculations are +// carried in the same resolution as the final rendering. This is done because +// the text glyph positions are snapped to the nearest pixels sharp rendering. +// +// The local space means that values are not rotated or scale as per the current +// transformation. For example if you set font size to 12, which would mean that +// line height is 16, then regardless of the current scaling and rotation, the +// returned line height is always 16. Some measures may vary because of the scaling +// since aforementioned pixel snapping. +// +// While this may sound a little odd, the setup allows you to always render the +// same way regardless of scaling. I.e. following works regardless of scaling: +// +// const char* txt = "Text me up."; +// nvgTextBounds(vg, x,y, txt, NULL, bounds); +// nvgBeginPath(vg); +// nvgRoundedRect(vg, bounds[0],bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); +// nvgFill(vg); +// +// Note: currently only solid color fill is supported for text. + +// Creates font by loading it from the disk from specified file name. +// Returns handle to the font. +int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename); + +// fontIndex specifies which font face to load from a .ttf/.ttc file. +int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex); + +// Creates font by loading it from the specified memory chunk. +// Returns handle to the font. +int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData); + +// fontIndex specifies which font face to load from a .ttf/.ttc file. +int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex); + +// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found. +int nvgFindFont(NVGcontext* ctx, const char* name); + +// Adds a fallback font by handle. +int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont); + +// Adds a fallback font by name. +int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont); + +// Resets fallback fonts by handle. +void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont); + +// Resets fallback fonts by name. +void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont); + +// Sets the font size of current text style. +void nvgFontSize(NVGcontext* ctx, float size); + +// Sets the blur of current text style. +void nvgFontBlur(NVGcontext* ctx, float blur); + +// Sets the letter spacing of current text style. +void nvgTextLetterSpacing(NVGcontext* ctx, float spacing); + +// Sets the proportional line height of current text style. The line height is specified as multiple of font size. +void nvgTextLineHeight(NVGcontext* ctx, float lineHeight); + +// Sets the text align of current text style, see NVGalign for options. +void nvgTextAlign(NVGcontext* ctx, int align); + +// Sets the font face based on specified id of current text style. +void nvgFontFaceId(NVGcontext* ctx, int font); + +// Sets the font face based on specified name of current text style. +void nvgFontFace(NVGcontext* ctx, const char* font); + +// Draws text string at specified location. If end is specified only the sub-string up to the end is drawn. +float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end); + +// Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn. +// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered. +// Words longer than the max width are slit at nearest character (i.e. no hyphenation). +void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end); + +// Measures the specified text string. Parameter bounds should be a pointer to float[4], +// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax] +// Returns the horizontal advance of the measured text (i.e. where the next character should drawn). +// Measured values are returned in local coordinate space. +float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds); + +// Measures the specified multi-text string. Parameter bounds should be a pointer to float[4], +// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax] +// Measured values are returned in local coordinate space. +void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds); + +// Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used. +// Measured values are returned in local coordinate space. +int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions); + +// Returns the vertical metrics based on the current text style. +// Measured values are returned in local coordinate space. +void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* lineh); + +// Breaks the specified text into lines. If end is specified only the sub-string will be used. +// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered. +// Words longer than the max width are slit at nearest character (i.e. no hyphenation). +int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows); + +// +// Internal Render API +// +struct NVGscissor { + float xform[6]; + float extent[2]; +}; +typedef struct NVGscissor NVGscissor; + +struct NVGvertex { + float x,y,u,v; +}; +typedef struct NVGvertex NVGvertex; + +struct NVGpath { + int first; + int count; + unsigned char closed; + int nbevel; + NVGvertex* fill; + int nfill; + NVGvertex* stroke; + int nstroke; + int winding; + int convex; +}; +typedef struct NVGpath NVGpath; + +struct NVGparams { + void* userPtr; + int edgeAntiAlias; + int (*renderCreate)(void* uptr, void* otherUptr); + int (*renderCreateTexture)(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data); + int (*renderDeleteTexture)(void* uptr, int image); + int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data); + int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h); + void (*renderViewport)(void* uptr, float width, float height, float devicePixelRatio); + void (*renderCancel)(void* uptr); + void (*renderFlush)(void* uptr); + void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths); + void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths); + void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts, float fringe); + void (*renderDelete)(void* uptr); +}; +typedef struct NVGparams NVGparams; + +// Constructor and destructor, called by the render back-end. +NVGcontext* nvgCreateInternal(NVGparams* params, NVGcontext* other); +void nvgDeleteInternal(NVGcontext* ctx); + +NVGparams* nvgInternalParams(NVGcontext* ctx); + +// Debug function to dump cached path data. +void nvgDebugDumpPathCache(NVGcontext* ctx); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#define NVG_NOTUSED(v) for (;;) { (void)(1 ? (void)0 : ( (void)(v) ) ); break; } + +#ifdef __cplusplus +} +#endif + +#endif // NANOVG_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg_gl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg_gl.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1821 @@ +// +// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org +// +// 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. +// +#ifndef NANOVG_GL_H +#define NANOVG_GL_H + +#if defined NANOVG_GL2_FORCED +# undef NANOVG_GL3 +# undef NANOVG_GLES2 +# undef NANOVG_GLES3 +# define NANOVG_GL2 1 +#elif defined NANOVG_GL3_FORCED +# undef NANOVG_GL2 +# undef NANOVG_GLES2 +# undef NANOVG_GLES3 +# define NANOVG_GL3 1 +#elif defined NANOVG_GLES2_FORCED +# undef NANOVG_GL2 +# undef NANOVG_GL3 +# undef NANOVG_GLES3 +# define NANOVG_GLES2 1 +#elif defined NANOVG_GLES3_FORCED +# undef NANOVG_GL2 +# undef NANOVG_GL3 +# undef NANOVG_GLES2 +# define NANOVG_GLES3 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Create flags + +enum NVGcreateFlags { + // Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA). + NVG_ANTIALIAS = 1<<0, + // Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little + // slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once. + NVG_STENCIL_STROKES = 1<<1, + // Flag indicating that additional debug checks are done. + NVG_DEBUG = 1<<2, +}; + +#if defined NANOVG_GL2_IMPLEMENTATION +# define NANOVG_GL2 1 +# define NANOVG_GL_IMPLEMENTATION 1 +#elif defined NANOVG_GL3_IMPLEMENTATION +# define NANOVG_GL3 1 +# define NANOVG_GL_IMPLEMENTATION 1 +# define NANOVG_GL_USE_UNIFORMBUFFER 1 +#elif defined NANOVG_GLES2_IMPLEMENTATION +# define NANOVG_GLES2 1 +# define NANOVG_GL_IMPLEMENTATION 1 +#elif defined NANOVG_GLES3_IMPLEMENTATION +# define NANOVG_GLES3 1 +# define NANOVG_GL_IMPLEMENTATION 1 +#endif + +#define NANOVG_GL_USE_STATE_FILTER (1) + +// Creates NanoVG contexts for different OpenGL (ES) versions. +// Flags should be combination of the create flags above. + +#if defined NANOVG_GL2 + +NVGcontext* nvgCreateGL2(int flags); +NVGcontext* nvgCreateSharedGL2(NVGcontext* other, int flags); +void nvgDeleteGL2(NVGcontext* ctx); + +int nvglCreateImageFromHandleGL2(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGL2(NVGcontext* ctx, int image); + +#endif + +#if defined NANOVG_GL3 + +NVGcontext* nvgCreateGL3(int flags); +NVGcontext* nvgCreateSharedGL3(NVGcontext* other, int flags); +void nvgDeleteGL3(NVGcontext* ctx); + +int nvglCreateImageFromHandleGL3(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGL3(NVGcontext* ctx, int image); + +#endif + +#if defined NANOVG_GLES2 + +NVGcontext* nvgCreateGLES2(int flags); +NVGcontext* nvgCreateSharedGLES2(NVGcontext* other, int flags); +void nvgDeleteGLES2(NVGcontext* ctx); + +int nvglCreateImageFromHandleGLES2(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGLES2(NVGcontext* ctx, int image); + +#endif + +#if defined NANOVG_GLES3 + +NVGcontext* nvgCreateGLES3(int flags); +NVGcontext* nvgCreateSharedGLES3(NVGcontext* other, int flags); +void nvgDeleteGLES3(NVGcontext* ctx); + +int nvglCreateImageFromHandleGLES3(NVGcontext* ctx, GLuint textureId, int w, int h, int flags); +GLuint nvglImageHandleGLES3(NVGcontext* ctx, int image); + +#endif + +// These are additional flags on top of NVGimageFlags. +enum NVGimageFlagsGL { + NVG_IMAGE_NODELETE = 1<<16, // Do not delete GL texture handle. +}; + +#ifdef __cplusplus +} +#endif + +#endif /* NANOVG_GL_H */ + +#ifdef NANOVG_GL_IMPLEMENTATION + +#include +#include +#include +#include +#include "nanovg.h" + +enum GLNVGuniformLoc { + GLNVG_LOC_VIEWSIZE, + GLNVG_LOC_TEX, + GLNVG_LOC_FRAG, + GLNVG_MAX_LOCS +}; + +enum GLNVGshaderType { + NSVG_SHADER_FILLGRAD, + NSVG_SHADER_FILLIMG, + NSVG_SHADER_SIMPLE, + NSVG_SHADER_IMG +}; + +#if NANOVG_GL_USE_UNIFORMBUFFER +enum GLNVGuniformBindings { + GLNVG_FRAG_BINDING = 0, +}; +#endif + +struct GLNVGshader { + GLuint prog; + GLuint frag; + GLuint vert; + GLint loc[GLNVG_MAX_LOCS]; +}; +typedef struct GLNVGshader GLNVGshader; + +struct GLNVGtexture { + int id; + GLuint tex; + int width, height; + int type; + int flags; +#if defined NANOVG_GLES2 + unsigned char* data; +#endif +}; +typedef struct GLNVGtexture GLNVGtexture; + +struct GLNVGblend +{ + GLenum srcRGB; + GLenum dstRGB; + GLenum srcAlpha; + GLenum dstAlpha; +}; +typedef struct GLNVGblend GLNVGblend; + +enum GLNVGcallType { + GLNVG_NONE = 0, + GLNVG_FILL, + GLNVG_CONVEXFILL, + GLNVG_STROKE, + GLNVG_TRIANGLES, +}; + +struct GLNVGcall { + int type; + int image; + int pathOffset; + int pathCount; + int triangleOffset; + int triangleCount; + int uniformOffset; + GLNVGblend blendFunc; +}; +typedef struct GLNVGcall GLNVGcall; + +struct GLNVGpath { + int fillOffset; + int fillCount; + int strokeOffset; + int strokeCount; +}; +typedef struct GLNVGpath GLNVGpath; + +struct GLNVGfragUniforms { + #if NANOVG_GL_USE_UNIFORMBUFFER + float scissorMat[12]; // matrices are actually 3 vec4s + float paintMat[12]; + struct NVGcolor innerCol; + struct NVGcolor outerCol; + float scissorExt[2]; + float scissorScale[2]; + float extent[2]; + float radius; + float feather; + float strokeMult; + float strokeThr; + int texType; + int type; + #else + // note: after modifying layout or size of uniform array, + // don't forget to also update the fragment shader source! + #define NANOVG_GL_UNIFORMARRAY_SIZE 11 + union { + struct { + float scissorMat[12]; // matrices are actually 3 vec4s + float paintMat[12]; + struct NVGcolor innerCol; + struct NVGcolor outerCol; + float scissorExt[2]; + float scissorScale[2]; + float extent[2]; + float radius; + float feather; + float strokeMult; + float strokeThr; + float texType; + float type; + }; + float uniformArray[NANOVG_GL_UNIFORMARRAY_SIZE][4]; + }; + #endif +}; +typedef struct GLNVGfragUniforms GLNVGfragUniforms; + +struct GLNVGtextureContext { // Textures; shared between shared NanoVG contexts. + int refCount; + GLNVGtexture* textures; + int ntextures; + int ctextures; + int textureId; +}; +typedef struct GLNVGtextureContext GLNVGtextureContext; + +struct GLNVGcontext { + GLNVGshader shader; + GLNVGtextureContext* textureContext; + float view[2]; + GLuint vertBuf; +#if defined NANOVG_GL3 + GLuint vertArr; +#endif +#if NANOVG_GL_USE_UNIFORMBUFFER + GLuint fragBuf; +#endif + int fragSize; + int flags; + + // Per frame buffers + GLNVGcall* calls; + int ccalls; + int ncalls; + GLNVGpath* paths; + int cpaths; + int npaths; + struct NVGvertex* verts; + int cverts; + int nverts; + unsigned char* uniforms; + int cuniforms; + int nuniforms; + + // cached state + #if NANOVG_GL_USE_STATE_FILTER + GLuint boundTexture; + GLuint stencilMask; + GLenum stencilFunc; + GLint stencilFuncRef; + GLuint stencilFuncMask; + GLNVGblend blendFunc; + #endif + + int dummyTex; +}; +typedef struct GLNVGcontext GLNVGcontext; + +static int glnvg__maxi(int a, int b) { return a > b ? a : b; } + +#ifdef NANOVG_GLES2 +static unsigned int glnvg__nearestPow2(unsigned int num) +{ + unsigned n = num > 0 ? num - 1 : 0; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + return n; +} +#endif + +static void glnvg__bindTexture(GLNVGcontext* gl, GLuint tex) +{ +#if NANOVG_GL_USE_STATE_FILTER + if (gl->boundTexture != tex) { + gl->boundTexture = tex; + glBindTexture(GL_TEXTURE_2D, tex); + } +#else + glBindTexture(GL_TEXTURE_2D, tex); +#endif +} + +static void glnvg__stencilMask(GLNVGcontext* gl, GLuint mask) +{ +#if NANOVG_GL_USE_STATE_FILTER + if (gl->stencilMask != mask) { + gl->stencilMask = mask; + glStencilMask(mask); + } +#else + glStencilMask(mask); +#endif +} + +static void glnvg__stencilFunc(GLNVGcontext* gl, GLenum func, GLint ref, GLuint mask) +{ +#if NANOVG_GL_USE_STATE_FILTER + if ((gl->stencilFunc != func) || + (gl->stencilFuncRef != ref) || + (gl->stencilFuncMask != mask)) { + + gl->stencilFunc = func; + gl->stencilFuncRef = ref; + gl->stencilFuncMask = mask; + glStencilFunc(func, ref, mask); + } +#else + glStencilFunc(func, ref, mask); +#endif +} +static void glnvg__blendFuncSeparate(GLNVGcontext* gl, const GLNVGblend* blend) +{ +#if NANOVG_GL_USE_STATE_FILTER + if ((gl->blendFunc.srcRGB != blend->srcRGB) || + (gl->blendFunc.dstRGB != blend->dstRGB) || + (gl->blendFunc.srcAlpha != blend->srcAlpha) || + (gl->blendFunc.dstAlpha != blend->dstAlpha)) { + + gl->blendFunc = *blend; + glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha); + } +#else + glBlendFuncSeparate(blend->srcRGB, blend->dstRGB, blend->srcAlpha,blend->dstAlpha); +#endif +} + +static GLNVGtexture* glnvg__allocTexture(GLNVGcontext* gl) +{ + GLNVGtexture* tex = NULL; + int i; + + for (i = 0; i < gl->textureContext->ntextures; i++) { + if (gl->textureContext->textures[i].id == 0) { + tex = &gl->textureContext->textures[i]; + break; + } + } + if (tex == NULL) { + if (gl->textureContext->ntextures+1 > gl->textureContext->ctextures) { + GLNVGtexture* textures; + int ctextures = glnvg__maxi(gl->textureContext->ntextures+1, 4) + gl->textureContext->ctextures/2; // 1.5x Overallocate + textures = (GLNVGtexture*)realloc(gl->textureContext->textures, sizeof(GLNVGtexture)*ctextures); + if (textures == NULL) return NULL; + gl->textureContext->textures = textures; + gl->textureContext->ctextures = ctextures; + } + tex = &gl->textureContext->textures[gl->textureContext->ntextures++]; + } + + memset(tex, 0, sizeof(*tex)); + tex->id = ++gl->textureContext->textureId; + + return tex; +} + +static GLNVGtexture* glnvg__findTexture(GLNVGcontext* gl, int id) +{ + int i; + for (i = 0; i < gl->textureContext->ntextures; i++) + if (gl->textureContext->textures[i].id == id) + return &gl->textureContext->textures[i]; + return NULL; +} + +static int glnvg__deleteTexture(GLNVGcontext* gl, int id) +{ + int i; + for (i = 0; i < gl->textureContext->ntextures; i++) { + if (gl->textureContext->textures[i].id == id) { + if (gl->textureContext->textures[i].tex != 0 && (gl->textureContext->textures[i].flags & NVG_IMAGE_NODELETE) == 0) + { + glDeleteTextures(1, &gl->textureContext->textures[i].tex); +#if defined NANOVG_GLES2 + free(gl->textureContext->textures[i].data); +#endif + } + memset(&gl->textureContext->textures[i], 0, sizeof(gl->textureContext->textures[i])); + return 1; + } + } + return 0; +} + +static void glnvg__dumpShaderError(GLuint shader, const char* name, const char* type) +{ + GLchar str[512+1]; + GLsizei len = 0; + glGetShaderInfoLog(shader, 512, &len, str); + if (len > 512) len = 512; + str[len] = '\0'; + printf("Shader %s/%s error:\n%s\n", name, type, str); +} + +static void glnvg__dumpProgramError(GLuint prog, const char* name) +{ + GLchar str[512+1]; + GLsizei len = 0; + glGetProgramInfoLog(prog, 512, &len, str); + if (len > 512) len = 512; + str[len] = '\0'; + printf("Program %s error:\n%s\n", name, str); +} + +static void glnvg__checkError(GLNVGcontext* gl, const char* str) +{ + GLenum err; + if ((gl->flags & NVG_DEBUG) == 0) return; + err = glGetError(); + if (err != GL_NO_ERROR) { + printf("Error %08x after %s\n", err, str); + return; + } +} + +static int glnvg__createShader(GLNVGshader* shader, const char* name, const char* header, const char* opts, const char* vshader, const char* fshader) +{ + GLint status; + GLuint prog, vert, frag; + const char* str[3]; + str[0] = header; + str[1] = opts != NULL ? opts : ""; + + memset(shader, 0, sizeof(*shader)); + + prog = glCreateProgram(); + vert = glCreateShader(GL_VERTEX_SHADER); + frag = glCreateShader(GL_FRAGMENT_SHADER); + str[2] = vshader; + glShaderSource(vert, 3, str, 0); + str[2] = fshader; + glShaderSource(frag, 3, str, 0); + + glCompileShader(vert); + glGetShaderiv(vert, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + glnvg__dumpShaderError(vert, name, "vert"); + return 0; + } + + glCompileShader(frag); + glGetShaderiv(frag, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + glnvg__dumpShaderError(frag, name, "frag"); + return 0; + } + + glAttachShader(prog, vert); + glAttachShader(prog, frag); + + glBindAttribLocation(prog, 0, "vertex"); + glBindAttribLocation(prog, 1, "tcoord"); + + glLinkProgram(prog); + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status != GL_TRUE) { + glnvg__dumpProgramError(prog, name); + return 0; + } + + shader->prog = prog; + shader->vert = vert; + shader->frag = frag; + + return 1; +} + +static void glnvg__deleteShader(GLNVGshader* shader) +{ + if (shader->prog != 0) + glDeleteProgram(shader->prog); + if (shader->vert != 0) + glDeleteShader(shader->vert); + if (shader->frag != 0) + glDeleteShader(shader->frag); +} + +static void glnvg__getUniforms(GLNVGshader* shader) +{ + shader->loc[GLNVG_LOC_VIEWSIZE] = glGetUniformLocation(shader->prog, "viewSize"); + shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex"); + +#if NANOVG_GL_USE_UNIFORMBUFFER + shader->loc[GLNVG_LOC_FRAG] = glGetUniformBlockIndex(shader->prog, "frag"); +#else + shader->loc[GLNVG_LOC_FRAG] = glGetUniformLocation(shader->prog, "frag"); +#endif +} + +static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data); + +static int glnvg__renderCreate(void* uptr, void* otherUptr) // Share the textures of GLNVGcontext 'otherUptr' if it's non-NULL. +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + + if (otherUptr) { + GLNVGcontext* other = (GLNVGcontext*)otherUptr; + gl->textureContext = other->textureContext; + gl->textureContext->refCount++; + } else { + gl->textureContext = (GLNVGtextureContext*)malloc(sizeof(GLNVGtextureContext)); + memset(gl->textureContext, 0, sizeof(GLNVGtextureContext)); + gl->textureContext->refCount = 1; + } + + int align = 4; + + // TODO: mediump float may not be enough for GLES2 in iOS. + // see the following discussion: https://github.com/memononen/nanovg/issues/46 + static const char* shaderHeader = +#if defined NANOVG_GL2 + "#define NANOVG_GL2 1\n" +#elif defined NANOVG_GL3 + "#version 150 core\n" + "#define NANOVG_GL3 1\n" +#elif defined NANOVG_GLES2 + "#version 100\n" + "#define NANOVG_GL2 1\n" +#elif defined NANOVG_GLES3 + "#version 300 es\n" + "#define NANOVG_GL3 1\n" +#endif + +#if NANOVG_GL_USE_UNIFORMBUFFER + "#define USE_UNIFORMBUFFER 1\n" +#else + "#define UNIFORMARRAY_SIZE 11\n" +#endif + "\n"; + + static const char* fillVertShader = + "#ifdef NANOVG_GL3\n" + " uniform vec2 viewSize;\n" + " in vec2 vertex;\n" + " in vec2 tcoord;\n" + " out vec2 ftcoord;\n" + " out vec2 fpos;\n" + "#else\n" + " uniform vec2 viewSize;\n" + " attribute vec2 vertex;\n" + " attribute vec2 tcoord;\n" + " varying vec2 ftcoord;\n" + " varying vec2 fpos;\n" + "#endif\n" + "void main(void) {\n" + " ftcoord = tcoord;\n" + " fpos = vertex;\n" + " gl_Position = vec4(2.0*vertex.x/viewSize.x - 1.0, 1.0 - 2.0*vertex.y/viewSize.y, 0, 1);\n" + "}\n"; + + static const char* fillFragShader = + "#ifdef GL_ES\n" + "#if defined(GL_FRAGMENT_PRECISION_HIGH) || defined(NANOVG_GL3)\n" + " precision highp float;\n" + "#else\n" + " precision mediump float;\n" + "#endif\n" + "#endif\n" + "#ifdef NANOVG_GL3\n" + "#ifdef USE_UNIFORMBUFFER\n" + " layout(std140) uniform frag {\n" + " mat3 scissorMat;\n" + " mat3 paintMat;\n" + " vec4 innerCol;\n" + " vec4 outerCol;\n" + " vec2 scissorExt;\n" + " vec2 scissorScale;\n" + " vec2 extent;\n" + " float radius;\n" + " float feather;\n" + " float strokeMult;\n" + " float strokeThr;\n" + " int texType;\n" + " int type;\n" + " };\n" + "#else\n" // NANOVG_GL3 && !USE_UNIFORMBUFFER + " uniform vec4 frag[UNIFORMARRAY_SIZE];\n" + "#endif\n" + " uniform sampler2D tex;\n" + " in vec2 ftcoord;\n" + " in vec2 fpos;\n" + " out vec4 outColor;\n" + "#else\n" // !NANOVG_GL3 + " uniform vec4 frag[UNIFORMARRAY_SIZE];\n" + " uniform sampler2D tex;\n" + " varying vec2 ftcoord;\n" + " varying vec2 fpos;\n" + "#endif\n" + "#ifndef USE_UNIFORMBUFFER\n" + " #define scissorMat mat3(frag[0].xyz, frag[1].xyz, frag[2].xyz)\n" + " #define paintMat mat3(frag[3].xyz, frag[4].xyz, frag[5].xyz)\n" + " #define innerCol frag[6]\n" + " #define outerCol frag[7]\n" + " #define scissorExt frag[8].xy\n" + " #define scissorScale frag[8].zw\n" + " #define extent frag[9].xy\n" + " #define radius frag[9].z\n" + " #define feather frag[9].w\n" + " #define strokeMult frag[10].x\n" + " #define strokeThr frag[10].y\n" + " #define texType int(frag[10].z)\n" + " #define type int(frag[10].w)\n" + "#endif\n" + "\n" + "float sdroundrect(vec2 pt, vec2 ext, float rad) {\n" + " vec2 ext2 = ext - vec2(rad,rad);\n" + " vec2 d = abs(pt) - ext2;\n" + " return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n" + "}\n" + "\n" + "// Scissoring\n" + "float scissorMask(vec2 p) {\n" + " vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);\n" + " sc = vec2(0.5,0.5) - sc * scissorScale;\n" + " return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n" + "}\n" + "#ifdef EDGE_AA\n" + "// Stroke - from [0..1] to clipped pyramid, where the slope is 1px.\n" + "float strokeMask() {\n" + " return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * min(1.0, ftcoord.y);\n" + "}\n" + "#endif\n" + "\n" + "void main(void) {\n" + " vec4 result;\n" + " float scissor = scissorMask(fpos);\n" + "#ifdef EDGE_AA\n" + " float strokeAlpha = strokeMask();\n" + " if (strokeAlpha < strokeThr) discard;\n" + "#else\n" + " float strokeAlpha = 1.0;\n" + "#endif\n" + " if (type == 0) { // Gradient\n" + " // Calculate gradient color using box gradient\n" + " vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n" + " float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n" + " vec4 color = mix(innerCol,outerCol,d);\n" + " // Combine alpha\n" + " color *= strokeAlpha * scissor;\n" + " result = color;\n" + " } else if (type == 1) { // Image\n" + " // Calculate color fron texture\n" + " vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;\n" + "#ifdef NANOVG_GL3\n" + " vec4 color = texture(tex, pt);\n" + "#else\n" + " vec4 color = texture2D(tex, pt);\n" + "#endif\n" + " if (texType == 1) color = vec4(color.xyz*color.w,color.w);" + " if (texType == 2) color = vec4(color.x);" + " // Apply color tint and alpha.\n" + " color *= innerCol;\n" + " // Combine alpha\n" + " color *= strokeAlpha * scissor;\n" + " result = color;\n" + " } else if (type == 2) { // Stencil fill\n" + " result = vec4(1,1,1,1);\n" + " } else if (type == 3) { // Textured tris\n" + "#ifdef NANOVG_GL3\n" + " vec4 color = texture(tex, ftcoord);\n" + "#else\n" + " vec4 color = texture2D(tex, ftcoord);\n" + "#endif\n" + " if (texType == 1) color = vec4(color.xyz*color.w,color.w);" + " if (texType == 2) color = vec4(color.x);" + " color *= scissor;\n" + " result = color * innerCol;\n" + " }\n" + "#ifdef NANOVG_GL3\n" + " outColor = result;\n" + "#else\n" + " gl_FragColor = result;\n" + "#endif\n" + "}\n"; + + glnvg__checkError(gl, "init"); + + if (gl->flags & NVG_ANTIALIAS) { + if (glnvg__createShader(&gl->shader, "shader", shaderHeader, "#define EDGE_AA 1\n", fillVertShader, fillFragShader) == 0) + return 0; + } else { + if (glnvg__createShader(&gl->shader, "shader", shaderHeader, NULL, fillVertShader, fillFragShader) == 0) + return 0; + } + + glnvg__checkError(gl, "uniform locations"); + glnvg__getUniforms(&gl->shader); + + // Create dynamic vertex array +#if defined NANOVG_GL3 + glGenVertexArrays(1, &gl->vertArr); +#endif + glGenBuffers(1, &gl->vertBuf); + +#if NANOVG_GL_USE_UNIFORMBUFFER + // Create UBOs + glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_FRAG], GLNVG_FRAG_BINDING); + glGenBuffers(1, &gl->fragBuf); + glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &align); +#endif + gl->fragSize = sizeof(GLNVGfragUniforms) + align - sizeof(GLNVGfragUniforms) % align; + + // Some platforms does not allow to have samples to unset textures. + // Create empty one which is bound when there's no texture specified. + gl->dummyTex = glnvg__renderCreateTexture(gl, NVG_TEXTURE_ALPHA, 1, 1, 0, NULL); + + glnvg__checkError(gl, "create done"); + + glFinish(); + + return 1; +} + +static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGtexture* tex = glnvg__allocTexture(gl); + + if (tex == NULL) return 0; + +#ifdef NANOVG_GLES2 + // Check for non-power of 2. + if (glnvg__nearestPow2(w) != (unsigned int)w || glnvg__nearestPow2(h) != (unsigned int)h) { + // No repeat + if ((imageFlags & NVG_IMAGE_REPEATX) != 0 || (imageFlags & NVG_IMAGE_REPEATY) != 0) { + printf("Repeat X/Y is not supported for non power-of-two textures (%d x %d)\n", w, h); + imageFlags &= ~(NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); + } + // No mips. + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + printf("Mip-maps is not supported for non power-of-two textures (%d x %d)\n", w, h); + imageFlags &= ~NVG_IMAGE_GENERATE_MIPMAPS; + } + } +#endif + + glGenTextures(1, &tex->tex); + tex->width = w; + tex->height = h; + tex->type = type; + tex->flags = imageFlags; + glnvg__bindTexture(gl, tex->tex); + + glPixelStorei(GL_UNPACK_ALIGNMENT,1); +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); +#endif + +#if defined (NANOVG_GL2) + // GL 1.4 and later has support for generating mipmaps using a tex parameter. + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + } +#endif + + switch (type) + { + case NVG_TEXTURE_BGR: +#if NANOVG_GLES2 + // GLES2 cannot handle GL_BGR, do local conversion to GL_RGB + tex->data = (uint8_t*)malloc(sizeof(uint8_t) * 3 * w * h); + for (uint32_t i=0; idata[i*3+0] = data[i*3+2]; + tex->data[i*3+1] = data[i*3+1]; + tex->data[i*3+2] = data[i*3+0]; + } + data = tex->data; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, data); +#endif + break; + case NVG_TEXTURE_BGRA: +#if NANOVG_GLES2 + // GLES2 cannot handle GL_BGRA, do local conversion to GL_RGBA + tex->data = (uint8_t*)malloc(sizeof(uint8_t) * 4 * w * h); + for (uint32_t i=0; idata[i*3+0] = data[i*3+3]; + tex->data[i*3+1] = data[i*3+2]; + tex->data[i*3+2] = data[i*3+1]; + tex->data[i*3+3] = data[i*3+0]; + } + data = tex->data; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); +#endif + break; + case NVG_TEXTURE_RGB: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_RGBA: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + break; + default: +#if defined(NANOVG_GLES2) || defined (NANOVG_GL2) + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); +#elif defined(NANOVG_GLES3) + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); +#else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); +#endif + break; + } + + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + if (imageFlags & NVG_IMAGE_NEAREST) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + } else { + if (imageFlags & NVG_IMAGE_NEAREST) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + } + + if (imageFlags & NVG_IMAGE_NEAREST) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (imageFlags & NVG_IMAGE_REPEATX) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + if (imageFlags & NVG_IMAGE_REPEATY) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); +#endif + + // The new way to build mipmaps on GLES and GL3 +#if !defined(NANOVG_GL2) + if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { + glGenerateMipmap(GL_TEXTURE_2D); + } +#endif + + glnvg__checkError(gl, "create tex"); + glnvg__bindTexture(gl, 0); + + return tex->id; +} + + +static int glnvg__renderDeleteTexture(void* uptr, int image) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + return glnvg__deleteTexture(gl, image); +} + +static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGtexture* tex = glnvg__findTexture(gl, image); + + if (tex == NULL) return 0; + glnvg__bindTexture(gl, tex->tex); + + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); + glPixelStorei(GL_UNPACK_SKIP_ROWS, y); +#else + // No support for all of skip, need to update a whole row at a time. + switch (tex->type) + { + case NVG_TEXTURE_BGR: + data += y*tex->width*3; + break; + case NVG_TEXTURE_BGRA: + data += y*tex->width*4; + break; + case NVG_TEXTURE_RGB: + data += y*tex->width*3; + break; + case NVG_TEXTURE_RGBA: + data += y*tex->width*4; + break; + default: + data += y*tex->width; + break; + } + x = 0; + w = tex->width; +#endif + + switch (tex->type) + { + case NVG_TEXTURE_BGR: + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_BGR, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_BGRA: + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_BGRA, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_RGB: + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGB, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_RGBA: + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data); + break; + default: +#if defined(NANOVG_GLES2) || defined(NANOVG_GL2) + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); +#else + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data); +#endif + break; + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); +#ifndef NANOVG_GLES2 + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); +#endif + + glnvg__bindTexture(gl, 0); + + return 1; +} + +static int glnvg__renderGetTextureSize(void* uptr, int image, int* w, int* h) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGtexture* tex = glnvg__findTexture(gl, image); + if (tex == NULL) return 0; + *w = tex->width; + *h = tex->height; + return 1; +} + +static void glnvg__xformToMat3x4(float* m3, float* t) +{ + m3[0] = t[0]; + m3[1] = t[1]; + m3[2] = 0.0f; + m3[3] = 0.0f; + m3[4] = t[2]; + m3[5] = t[3]; + m3[6] = 0.0f; + m3[7] = 0.0f; + m3[8] = t[4]; + m3[9] = t[5]; + m3[10] = 1.0f; + m3[11] = 0.0f; +} + +static NVGcolor glnvg__premulColor(NVGcolor c) +{ + c.r *= c.a; + c.g *= c.a; + c.b *= c.a; + return c; +} + +static int glnvg__convertPaint(GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGpaint* paint, + NVGscissor* scissor, float width, float fringe, float strokeThr) +{ + GLNVGtexture* tex = NULL; + float invxform[6]; + + memset(frag, 0, sizeof(*frag)); + + frag->innerCol = glnvg__premulColor(paint->innerColor); + frag->outerCol = glnvg__premulColor(paint->outerColor); + + if (scissor->extent[0] < -0.5f || scissor->extent[1] < -0.5f) { + memset(frag->scissorMat, 0, sizeof(frag->scissorMat)); + frag->scissorExt[0] = 1.0f; + frag->scissorExt[1] = 1.0f; + frag->scissorScale[0] = 1.0f; + frag->scissorScale[1] = 1.0f; + } else { + nvgTransformInverse(invxform, scissor->xform); + glnvg__xformToMat3x4(frag->scissorMat, invxform); + frag->scissorExt[0] = scissor->extent[0]; + frag->scissorExt[1] = scissor->extent[1]; + frag->scissorScale[0] = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]) / fringe; + frag->scissorScale[1] = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]) / fringe; + } + + memcpy(frag->extent, paint->extent, sizeof(frag->extent)); + frag->strokeMult = (width*0.5f + fringe*0.5f) / fringe; + frag->strokeThr = strokeThr; + + if (paint->image != 0) { + tex = glnvg__findTexture(gl, paint->image); + if (tex == NULL) return 0; + if ((tex->flags & NVG_IMAGE_FLIPY) != 0) { + float m1[6], m2[6]; + nvgTransformTranslate(m1, 0.0f, frag->extent[1] * 0.5f); + nvgTransformMultiply(m1, paint->xform); + nvgTransformScale(m2, 1.0f, -1.0f); + nvgTransformMultiply(m2, m1); + nvgTransformTranslate(m1, 0.0f, -frag->extent[1] * 0.5f); + nvgTransformMultiply(m1, m2); + nvgTransformInverse(invxform, m1); + } else { + nvgTransformInverse(invxform, paint->xform); + } + frag->type = NSVG_SHADER_FILLIMG; + + #if NANOVG_GL_USE_UNIFORMBUFFER + switch (tex->type) + { + case NVG_TEXTURE_BGR: + case NVG_TEXTURE_BGRA: + case NVG_TEXTURE_RGB: + case NVG_TEXTURE_RGBA: + frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1; + break; + default: + frag->texType = 2; + break; + } + #else + switch (tex->type) + { + case NVG_TEXTURE_BGR: + case NVG_TEXTURE_BGRA: + case NVG_TEXTURE_RGB: + case NVG_TEXTURE_RGBA: + frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0.0f : 1.0f; + break; + default: + frag->texType = 2.0f; + break; + } + #endif +// printf("frag->texType = %d\n", frag->texType); + } else { + frag->type = NSVG_SHADER_FILLGRAD; + frag->radius = paint->radius; + frag->feather = paint->feather; + nvgTransformInverse(invxform, paint->xform); + } + + glnvg__xformToMat3x4(frag->paintMat, invxform); + + return 1; +} + +static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i); + +static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image) +{ + GLNVGtexture* tex = NULL; +#if NANOVG_GL_USE_UNIFORMBUFFER + glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_FRAG_BINDING, gl->fragBuf, uniformOffset, sizeof(GLNVGfragUniforms)); +#else + GLNVGfragUniforms* frag = nvg__fragUniformPtr(gl, uniformOffset); + glUniform4fv(gl->shader.loc[GLNVG_LOC_FRAG], NANOVG_GL_UNIFORMARRAY_SIZE, &(frag->uniformArray[0][0])); +#endif + + if (image != 0) { + tex = glnvg__findTexture(gl, image); + } + // If no image is set, use empty texture + if (tex == NULL) { + tex = glnvg__findTexture(gl, gl->dummyTex); + } + glnvg__bindTexture(gl, tex != NULL ? tex->tex : 0); + glnvg__checkError(gl, "tex paint tex"); +} + +static void glnvg__renderViewport(void* uptr, float width, float height, float devicePixelRatio) +{ + NVG_NOTUSED(devicePixelRatio); + GLNVGcontext* gl = (GLNVGcontext*)uptr; + gl->view[0] = width; + gl->view[1] = height; +} + +static void glnvg__fill(GLNVGcontext* gl, GLNVGcall* call) +{ + GLNVGpath* paths = &gl->paths[call->pathOffset]; + int i, npaths = call->pathCount; + + // Draw shapes + glEnable(GL_STENCIL_TEST); + glnvg__stencilMask(gl, 0xff); + glnvg__stencilFunc(gl, GL_ALWAYS, 0, 0xff); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + // set bindpoint for solid loc + glnvg__setUniforms(gl, call->uniformOffset, 0); + glnvg__checkError(gl, "fill simple"); + + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP); + glDisable(GL_CULL_FACE); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); + glEnable(GL_CULL_FACE); + + // Draw anti-aliased pixels + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image); + glnvg__checkError(gl, "fill fill"); + + if (gl->flags & NVG_ANTIALIAS) { + glnvg__stencilFunc(gl, GL_EQUAL, 0x00, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + // Draw fringes + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + } + + // Draw fill + glnvg__stencilFunc(gl, GL_NOTEQUAL, 0x0, 0xff); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + glDrawArrays(GL_TRIANGLE_STRIP, call->triangleOffset, call->triangleCount); + + glDisable(GL_STENCIL_TEST); +} + +static void glnvg__convexFill(GLNVGcontext* gl, GLNVGcall* call) +{ + GLNVGpath* paths = &gl->paths[call->pathOffset]; + int i, npaths = call->pathCount; + + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__checkError(gl, "convex fill"); + + for (i = 0; i < npaths; i++) { + glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); + // Draw fringes + if (paths[i].strokeCount > 0) { + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + } + } +} + +static void glnvg__stroke(GLNVGcontext* gl, GLNVGcall* call) +{ + GLNVGpath* paths = &gl->paths[call->pathOffset]; + int npaths = call->pathCount, i; + + if (gl->flags & NVG_STENCIL_STROKES) { + + glEnable(GL_STENCIL_TEST); + glnvg__stencilMask(gl, 0xff); + + // Fill the stroke base without overlap + glnvg__stencilFunc(gl, GL_EQUAL, 0x0, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + glnvg__setUniforms(gl, call->uniformOffset + gl->fragSize, call->image); + glnvg__checkError(gl, "stroke fill 0"); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + + // Draw anti-aliased pixels. + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__stencilFunc(gl, GL_EQUAL, 0x00, 0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + + // Clear stencil buffer. + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glnvg__stencilFunc(gl, GL_ALWAYS, 0x0, 0xff); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + glnvg__checkError(gl, "stroke fill 1"); + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glDisable(GL_STENCIL_TEST); + +// glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, strokeWidth, fringe, 1.0f - 0.5f/255.0f); + + } else { + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__checkError(gl, "stroke fill"); + // Draw Strokes + for (i = 0; i < npaths; i++) + glDrawArrays(GL_TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount); + } +} + +static void glnvg__triangles(GLNVGcontext* gl, GLNVGcall* call) +{ + glnvg__setUniforms(gl, call->uniformOffset, call->image); + glnvg__checkError(gl, "triangles fill"); + + glDrawArrays(GL_TRIANGLES, call->triangleOffset, call->triangleCount); +} + +static void glnvg__renderCancel(void* uptr) { + GLNVGcontext* gl = (GLNVGcontext*)uptr; + gl->nverts = 0; + gl->npaths = 0; + gl->ncalls = 0; + gl->nuniforms = 0; +} + +static GLenum glnvg_convertBlendFuncFactor(int factor) +{ + if (factor == NVG_ZERO) + return GL_ZERO; + if (factor == NVG_ONE) + return GL_ONE; + if (factor == NVG_SRC_COLOR) + return GL_SRC_COLOR; + if (factor == NVG_ONE_MINUS_SRC_COLOR) + return GL_ONE_MINUS_SRC_COLOR; + if (factor == NVG_DST_COLOR) + return GL_DST_COLOR; + if (factor == NVG_ONE_MINUS_DST_COLOR) + return GL_ONE_MINUS_DST_COLOR; + if (factor == NVG_SRC_ALPHA) + return GL_SRC_ALPHA; + if (factor == NVG_ONE_MINUS_SRC_ALPHA) + return GL_ONE_MINUS_SRC_ALPHA; + if (factor == NVG_DST_ALPHA) + return GL_DST_ALPHA; + if (factor == NVG_ONE_MINUS_DST_ALPHA) + return GL_ONE_MINUS_DST_ALPHA; + if (factor == NVG_SRC_ALPHA_SATURATE) + return GL_SRC_ALPHA_SATURATE; + return GL_INVALID_ENUM; +} + +static GLNVGblend glnvg__blendCompositeOperation(NVGcompositeOperationState op) +{ + GLNVGblend blend; + blend.srcRGB = glnvg_convertBlendFuncFactor(op.srcRGB); + blend.dstRGB = glnvg_convertBlendFuncFactor(op.dstRGB); + blend.srcAlpha = glnvg_convertBlendFuncFactor(op.srcAlpha); + blend.dstAlpha = glnvg_convertBlendFuncFactor(op.dstAlpha); + if (blend.srcRGB == GL_INVALID_ENUM || blend.dstRGB == GL_INVALID_ENUM || blend.srcAlpha == GL_INVALID_ENUM || blend.dstAlpha == GL_INVALID_ENUM) + { + blend.srcRGB = GL_ONE; + blend.dstRGB = GL_ONE_MINUS_SRC_ALPHA; + blend.srcAlpha = GL_ONE; + blend.dstAlpha = GL_ONE_MINUS_SRC_ALPHA; + } + return blend; +} + +static void glnvg__renderFlush(void* uptr) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + int i; + + if (gl->ncalls > 0) { + + // Setup require GL state. + glUseProgram(gl->shader.prog); + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glStencilMask(0xffffffff); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_ALWAYS, 0, 0xffffffff); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + #if NANOVG_GL_USE_STATE_FILTER + gl->boundTexture = 0; + gl->stencilMask = 0xffffffff; + gl->stencilFunc = GL_ALWAYS; + gl->stencilFuncRef = 0; + gl->stencilFuncMask = 0xffffffff; + gl->blendFunc.srcRGB = GL_INVALID_ENUM; + gl->blendFunc.srcAlpha = GL_INVALID_ENUM; + gl->blendFunc.dstRGB = GL_INVALID_ENUM; + gl->blendFunc.dstAlpha = GL_INVALID_ENUM; + #endif + +#if NANOVG_GL_USE_UNIFORMBUFFER + // Upload ubo for frag shaders + glBindBuffer(GL_UNIFORM_BUFFER, gl->fragBuf); + glBufferData(GL_UNIFORM_BUFFER, gl->nuniforms * gl->fragSize, gl->uniforms, GL_STREAM_DRAW); +#endif + + // Upload vertex data +#if defined NANOVG_GL3 + glBindVertexArray(gl->vertArr); +#endif + glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf); + glBufferData(GL_ARRAY_BUFFER, gl->nverts * sizeof(NVGvertex), gl->verts, GL_STREAM_DRAW); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(NVGvertex), (const GLvoid*)(size_t)0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(NVGvertex), (const GLvoid*)(0 + 2*sizeof(float))); + + // Set view and texture just once per frame. + glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0); + glUniform2fv(gl->shader.loc[GLNVG_LOC_VIEWSIZE], 1, gl->view); + +#if NANOVG_GL_USE_UNIFORMBUFFER + glBindBuffer(GL_UNIFORM_BUFFER, gl->fragBuf); +#endif + + for (i = 0; i < gl->ncalls; i++) { + GLNVGcall* call = &gl->calls[i]; + glnvg__blendFuncSeparate(gl,&call->blendFunc); + if (call->type == GLNVG_FILL) + glnvg__fill(gl, call); + else if (call->type == GLNVG_CONVEXFILL) + glnvg__convexFill(gl, call); + else if (call->type == GLNVG_STROKE) + glnvg__stroke(gl, call); + else if (call->type == GLNVG_TRIANGLES) + glnvg__triangles(gl, call); + } + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); +#if defined NANOVG_GL3 + glBindVertexArray(0); +#endif + glDisable(GL_CULL_FACE); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glUseProgram(0); + glnvg__bindTexture(gl, 0); + } + + // Reset calls + gl->nverts = 0; + gl->npaths = 0; + gl->ncalls = 0; + gl->nuniforms = 0; +} + +static int glnvg__maxVertCount(const NVGpath* paths, int npaths) +{ + int i, count = 0; + for (i = 0; i < npaths; i++) { + count += paths[i].nfill; + count += paths[i].nstroke; + } + return count; +} + +static GLNVGcall* glnvg__allocCall(GLNVGcontext* gl) +{ + GLNVGcall* ret = NULL; + if (gl->ncalls+1 > gl->ccalls) { + GLNVGcall* calls; + int ccalls = glnvg__maxi(gl->ncalls+1, 128) + gl->ccalls/2; // 1.5x Overallocate + calls = (GLNVGcall*)realloc(gl->calls, sizeof(GLNVGcall) * ccalls); + if (calls == NULL) return NULL; + gl->calls = calls; + gl->ccalls = ccalls; + } + ret = &gl->calls[gl->ncalls++]; + memset(ret, 0, sizeof(GLNVGcall)); + return ret; +} + +static int glnvg__allocPaths(GLNVGcontext* gl, int n) +{ + int ret = 0; + if (gl->npaths+n > gl->cpaths) { + GLNVGpath* paths; + int cpaths = glnvg__maxi(gl->npaths + n, 128) + gl->cpaths/2; // 1.5x Overallocate + paths = (GLNVGpath*)realloc(gl->paths, sizeof(GLNVGpath) * cpaths); + if (paths == NULL) return -1; + gl->paths = paths; + gl->cpaths = cpaths; + } + ret = gl->npaths; + gl->npaths += n; + return ret; +} + +static int glnvg__allocVerts(GLNVGcontext* gl, int n) +{ + int ret = 0; + if (gl->nverts+n > gl->cverts) { + NVGvertex* verts; + int cverts = glnvg__maxi(gl->nverts + n, 4096) + gl->cverts/2; // 1.5x Overallocate + verts = (NVGvertex*)realloc(gl->verts, sizeof(NVGvertex) * cverts); + if (verts == NULL) return -1; + gl->verts = verts; + gl->cverts = cverts; + } + ret = gl->nverts; + gl->nverts += n; + return ret; +} + +static int glnvg__allocFragUniforms(GLNVGcontext* gl, int n) +{ + int ret = 0, structSize = gl->fragSize; + if (gl->nuniforms+n > gl->cuniforms) { + unsigned char* uniforms; + int cuniforms = glnvg__maxi(gl->nuniforms+n, 128) + gl->cuniforms/2; // 1.5x Overallocate + uniforms = (unsigned char*)realloc(gl->uniforms, structSize * cuniforms); + if (uniforms == NULL) return -1; + gl->uniforms = uniforms; + gl->cuniforms = cuniforms; + } + ret = gl->nuniforms * structSize; + gl->nuniforms += n; + return ret; +} + +static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i) +{ + return (GLNVGfragUniforms*)&gl->uniforms[i]; +} + +static void glnvg__vset(NVGvertex* vtx, float x, float y, float u, float v) +{ + vtx->x = x; + vtx->y = y; + vtx->u = u; + vtx->v = v; +} + +static void glnvg__renderFill(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, + const float* bounds, const NVGpath* paths, int npaths) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGcall* call = glnvg__allocCall(gl); + NVGvertex* quad; + GLNVGfragUniforms* frag; + int i, maxverts, offset; + + if (call == NULL) return; + + call->type = GLNVG_FILL; + call->triangleCount = 4; + call->pathOffset = glnvg__allocPaths(gl, npaths); + if (call->pathOffset == -1) goto error; + call->pathCount = npaths; + call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); + + if (npaths == 1 && paths[0].convex) + { + call->type = GLNVG_CONVEXFILL; + call->triangleCount = 0; // Bounding box fill quad not needed for convex fill + } + + // Allocate vertices for all the paths. + maxverts = glnvg__maxVertCount(paths, npaths) + call->triangleCount; + offset = glnvg__allocVerts(gl, maxverts); + if (offset == -1) goto error; + + for (i = 0; i < npaths; i++) { + GLNVGpath* copy = &gl->paths[call->pathOffset + i]; + const NVGpath* path = &paths[i]; + memset(copy, 0, sizeof(GLNVGpath)); + if (path->nfill > 0) { + copy->fillOffset = offset; + copy->fillCount = path->nfill; + memcpy(&gl->verts[offset], path->fill, sizeof(NVGvertex) * path->nfill); + offset += path->nfill; + } + if (path->nstroke > 0) { + copy->strokeOffset = offset; + copy->strokeCount = path->nstroke; + memcpy(&gl->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke); + offset += path->nstroke; + } + } + + // Setup uniforms for draw calls + if (call->type == GLNVG_FILL) { + // Quad + call->triangleOffset = offset; + quad = &gl->verts[call->triangleOffset]; + glnvg__vset(&quad[0], bounds[2], bounds[3], 0.5f, 1.0f); + glnvg__vset(&quad[1], bounds[2], bounds[1], 0.5f, 1.0f); + glnvg__vset(&quad[2], bounds[0], bounds[3], 0.5f, 1.0f); + glnvg__vset(&quad[3], bounds[0], bounds[1], 0.5f, 1.0f); + + call->uniformOffset = glnvg__allocFragUniforms(gl, 2); + if (call->uniformOffset == -1) goto error; + // Simple shader for stencil + frag = nvg__fragUniformPtr(gl, call->uniformOffset); + memset(frag, 0, sizeof(*frag)); + frag->strokeThr = -1.0f; + frag->type = NSVG_SHADER_SIMPLE; + // Fill shader + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, fringe, fringe, -1.0f); + } else { + call->uniformOffset = glnvg__allocFragUniforms(gl, 1); + if (call->uniformOffset == -1) goto error; + // Fill shader + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, fringe, fringe, -1.0f); + } + + return; + +error: + // We get here if call alloc was ok, but something else is not. + // Roll back the last call to prevent drawing it. + if (gl->ncalls > 0) gl->ncalls--; +} + +static void glnvg__renderStroke(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, + float strokeWidth, const NVGpath* paths, int npaths) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGcall* call = glnvg__allocCall(gl); + int i, maxverts, offset; + + if (call == NULL) return; + + call->type = GLNVG_STROKE; + call->pathOffset = glnvg__allocPaths(gl, npaths); + if (call->pathOffset == -1) goto error; + call->pathCount = npaths; + call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); + + // Allocate vertices for all the paths. + maxverts = glnvg__maxVertCount(paths, npaths); + offset = glnvg__allocVerts(gl, maxverts); + if (offset == -1) goto error; + + for (i = 0; i < npaths; i++) { + GLNVGpath* copy = &gl->paths[call->pathOffset + i]; + const NVGpath* path = &paths[i]; + memset(copy, 0, sizeof(GLNVGpath)); + if (path->nstroke) { + copy->strokeOffset = offset; + copy->strokeCount = path->nstroke; + memcpy(&gl->verts[offset], path->stroke, sizeof(NVGvertex) * path->nstroke); + offset += path->nstroke; + } + } + + if (gl->flags & NVG_STENCIL_STROKES) { + // Fill shader + call->uniformOffset = glnvg__allocFragUniforms(gl, 2); + if (call->uniformOffset == -1) goto error; + + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f); + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset + gl->fragSize), paint, scissor, strokeWidth, fringe, 1.0f - 0.5f/255.0f); + + } else { + // Fill shader + call->uniformOffset = glnvg__allocFragUniforms(gl, 1); + if (call->uniformOffset == -1) goto error; + glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call->uniformOffset), paint, scissor, strokeWidth, fringe, -1.0f); + } + + return; + +error: + // We get here if call alloc was ok, but something else is not. + // Roll back the last call to prevent drawing it. + if (gl->ncalls > 0) gl->ncalls--; +} + +static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, + const NVGvertex* verts, int nverts, float fringe) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + GLNVGcall* call = glnvg__allocCall(gl); + GLNVGfragUniforms* frag; + + if (call == NULL) return; + + call->type = GLNVG_TRIANGLES; + call->image = paint->image; + call->blendFunc = glnvg__blendCompositeOperation(compositeOperation); + + // Allocate vertices for all the paths. + call->triangleOffset = glnvg__allocVerts(gl, nverts); + if (call->triangleOffset == -1) goto error; + call->triangleCount = nverts; + + memcpy(&gl->verts[call->triangleOffset], verts, sizeof(NVGvertex) * nverts); + + // Fill shader + call->uniformOffset = glnvg__allocFragUniforms(gl, 1); + if (call->uniformOffset == -1) goto error; + frag = nvg__fragUniformPtr(gl, call->uniformOffset); + glnvg__convertPaint(gl, frag, paint, scissor, 1.0f, fringe, -1.0f); + frag->type = NSVG_SHADER_IMG; + + return; + +error: + // We get here if call alloc was ok, but something else is not. + // Roll back the last call to prevent drawing it. + if (gl->ncalls > 0) gl->ncalls--; +} + +static void glnvg__renderDelete(void* uptr) +{ + GLNVGcontext* gl = (GLNVGcontext*)uptr; + int i; + if (gl == NULL) return; + + glnvg__deleteShader(&gl->shader); + +#if NANOVG_GL3 +#if NANOVG_GL_USE_UNIFORMBUFFER + if (gl->fragBuf != 0) + glDeleteBuffers(1, &gl->fragBuf); +#endif + if (gl->vertArr != 0) + glDeleteVertexArrays(1, &gl->vertArr); +#endif + if (gl->vertBuf != 0) + glDeleteBuffers(1, &gl->vertBuf); + + if (gl->textureContext != NULL && --gl->textureContext->refCount == 0) { + for (i = 0; i < gl->textureContext->ntextures; i++) { + if (gl->textureContext->textures[i].tex != 0 && (gl->textureContext->textures[i].flags & NVG_IMAGE_NODELETE) == 0) + glDeleteTextures(1, &gl->textureContext->textures[i].tex); + } + free(gl->textureContext->textures); + free(gl->textureContext); + } + + free(gl->paths); + free(gl->verts); + free(gl->uniforms); + free(gl->calls); + + free(gl); +} + + +#if defined NANOVG_GL2 +NVGcontext* nvgCreateGL2(int flags) +#elif defined NANOVG_GL3 +NVGcontext* nvgCreateGL3(int flags) +#elif defined NANOVG_GLES2 +NVGcontext* nvgCreateGLES2(int flags) +#elif defined NANOVG_GLES3 +NVGcontext* nvgCreateGLES3(int flags) +#endif +{ +#if defined NANOVG_GL2 + return nvgCreateSharedGL2(NULL, flags); +#elif defined NANOVG_GL3 + return nvgCreateSharedGL3(NULL, flags); +#elif defined NANOVG_GLES2 + return nvgCreateSharedGLES2(NULL, flags); +#elif defined NANOVG_GLES3 + return nvgCreateSharedGLES3(NULL, flags); +#endif +} + +// Share the fonts and textures of 'other' if it's non-NULL. +#if defined NANOVG_GL2 +NVGcontext* nvgCreateSharedGL2(NVGcontext* other, int flags) +#elif defined NANOVG_GL3 +NVGcontext* nvgCreateSharedGL3(NVGcontext* other, int flags) +#elif defined NANOVG_GLES2 +NVGcontext* nvgCreateSharedGLES2(NVGcontext* other, int flags) +#elif defined NANOVG_GLES3 +NVGcontext* nvgCreateSharedGLES3(NVGcontext* other, int flags) +#endif +{ + NVGparams params; + NVGcontext* ctx = NULL; + GLNVGcontext* gl = (GLNVGcontext*)malloc(sizeof(GLNVGcontext)); + if (gl == NULL) goto error; + memset(gl, 0, sizeof(GLNVGcontext)); + + memset(¶ms, 0, sizeof(params)); + params.renderCreate = glnvg__renderCreate; + params.renderCreateTexture = glnvg__renderCreateTexture; + params.renderDeleteTexture = glnvg__renderDeleteTexture; + params.renderUpdateTexture = glnvg__renderUpdateTexture; + params.renderGetTextureSize = glnvg__renderGetTextureSize; + params.renderViewport = glnvg__renderViewport; + params.renderCancel = glnvg__renderCancel; + params.renderFlush = glnvg__renderFlush; + params.renderFill = glnvg__renderFill; + params.renderStroke = glnvg__renderStroke; + params.renderTriangles = glnvg__renderTriangles; + params.renderDelete = glnvg__renderDelete; + params.userPtr = gl; + params.edgeAntiAlias = flags & NVG_ANTIALIAS ? 1 : 0; + + gl->flags = flags; + + ctx = nvgCreateInternal(¶ms, other); + if (ctx == NULL) goto error; + + return ctx; + +error: + // 'gl' is freed by nvgDeleteInternal. + if (ctx != NULL) nvgDeleteInternal(ctx); + return NULL; +} + +#if defined NANOVG_GL2 +void nvgDeleteGL2(NVGcontext* ctx) +#elif defined NANOVG_GL3 +void nvgDeleteGL3(NVGcontext* ctx) +#elif defined NANOVG_GLES2 +void nvgDeleteGLES2(NVGcontext* ctx) +#elif defined NANOVG_GLES3 +void nvgDeleteGLES3(NVGcontext* ctx) +#endif +{ + nvgDeleteInternal(ctx); +} + +#if defined NANOVG_GL2 +int nvglCreateImageFromHandleGL2(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#elif defined NANOVG_GL3 +int nvglCreateImageFromHandleGL3(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#elif defined NANOVG_GLES2 +int nvglCreateImageFromHandleGLES2(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#elif defined NANOVG_GLES3 +int nvglCreateImageFromHandleGLES3(NVGcontext* ctx, GLuint textureId, int w, int h, int imageFlags) +#endif +{ + GLNVGcontext* gl = (GLNVGcontext*)nvgInternalParams(ctx)->userPtr; + GLNVGtexture* tex = glnvg__allocTexture(gl); + + if (tex == NULL) return 0; + + tex->type = NVG_TEXTURE_RGBA; + tex->tex = textureId; + tex->flags = imageFlags; + tex->width = w; + tex->height = h; + + return tex->id; +} + +#if defined NANOVG_GL2 +GLuint nvglImageHandleGL2(NVGcontext* ctx, int image) +#elif defined NANOVG_GL3 +GLuint nvglImageHandleGL3(NVGcontext* ctx, int image) +#elif defined NANOVG_GLES2 +GLuint nvglImageHandleGLES2(NVGcontext* ctx, int image) +#elif defined NANOVG_GLES3 +GLuint nvglImageHandleGLES3(NVGcontext* ctx, int image) +#endif +{ + GLNVGcontext* gl = (GLNVGcontext*)nvgInternalParams(ctx)->userPtr; + GLNVGtexture* tex = glnvg__findTexture(gl, image); + return tex->tex; +} + +#endif /* NANOVG_GL_IMPLEMENTATION */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg_gl_utils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/nanovg_gl_utils.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,154 @@ +// +// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org +// +// 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. +// +#ifndef NANOVG_GL_UTILS_H +#define NANOVG_GL_UTILS_H + +struct NVGLUframebuffer { + NVGcontext* ctx; + GLuint fbo; + GLuint rbo; + GLuint texture; + int image; +}; +typedef struct NVGLUframebuffer NVGLUframebuffer; + +// Helper function to create GL frame buffer to render to. +void nvgluBindFramebuffer(NVGLUframebuffer* fb); +NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags); +void nvgluDeleteFramebuffer(NVGLUframebuffer* fb); + +#endif // NANOVG_GL_UTILS_H + +#ifdef NANOVG_GL_IMPLEMENTATION + +#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3) +// FBO is core in OpenGL 3>. +# define NANOVG_FBO_VALID 1 +#elif defined(NANOVG_GL2) +// On OS X including glext defines FBO on GL2 too. +# ifdef __APPLE__ +# include +# define NANOVG_FBO_VALID 1 +# endif +#endif + +static GLint defaultFBO = -1; + +NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags) +{ +#ifdef NANOVG_FBO_VALID + GLint defaultFBO; + GLint defaultRBO; + NVGLUframebuffer* fb = NULL; + + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); + glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO); + + fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer)); + if (fb == NULL) goto error; + memset(fb, 0, sizeof(NVGLUframebuffer)); + + fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL); + +#if defined NANOVG_GL2 + fb->texture = nvglImageHandleGL2(ctx, fb->image); +#elif defined NANOVG_GL3 + fb->texture = nvglImageHandleGL3(ctx, fb->image); +#elif defined NANOVG_GLES2 + fb->texture = nvglImageHandleGLES2(ctx, fb->image); +#elif defined NANOVG_GLES3 + fb->texture = nvglImageHandleGLES3(ctx, fb->image); +#endif + + fb->ctx = ctx; + + // frame buffer object + glGenFramebuffers(1, &fb->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); + + // render buffer object + glGenRenderbuffers(1, &fb->rbo); + glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h); + + // combine all + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { +#ifdef GL_DEPTH24_STENCIL8 + // If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback. + // Some graphics cards require a depth buffer along with a stencil. + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) +#endif // GL_DEPTH24_STENCIL8 + goto error; + } + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); + return fb; +error: + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); + nvgluDeleteFramebuffer(fb); + return NULL; +#else + NVG_NOTUSED(ctx); + NVG_NOTUSED(w); + NVG_NOTUSED(h); + NVG_NOTUSED(imageFlags); + return NULL; +#endif +} + +void nvgluBindFramebuffer(NVGLUframebuffer* fb) +{ +#ifdef NANOVG_FBO_VALID + if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); + glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO); +#else + NVG_NOTUSED(fb); +#endif +} + +void nvgluDeleteFramebuffer(NVGLUframebuffer* fb) +{ +#ifdef NANOVG_FBO_VALID + if (fb == NULL) return; + if (fb->fbo != 0) + glDeleteFramebuffers(1, &fb->fbo); + if (fb->rbo != 0) + glDeleteRenderbuffers(1, &fb->rbo); + if (fb->image >= 0) + nvgDeleteImage(fb->ctx, fb->image); + fb->ctx = NULL; + fb->fbo = 0; + fb->rbo = 0; + fb->texture = 0; + fb->image = -1; + free(fb); +#else + NVG_NOTUSED(fb); +#endif +} + +#endif // NANOVG_GL_IMPLEMENTATION diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/stb_image.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/stb_image.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,6614 @@ +/* stb_image - v2.10 - public domain image loader - http://nothings.org/stb_image.h + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8-bit-per-channel (16 bpc not supported) + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + + Revision 2.00 release notes: + + - Progressive JPEG is now supported. + + - PPM and PGM binary formats are now supported, thanks to Ken Miller. + + - x86 platforms now make use of SSE2 SIMD instructions for + JPEG decoding, and ARM platforms can use NEON SIMD if requested. + This work was done by Fabian "ryg" Giesen. SSE2 is used by + default, but NEON must be enabled explicitly; see docs. + + With other JPEG optimizations included in this version, we see + 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup + on a JPEG on an ARM machine, relative to previous versions of this + library. The same results will not obtain for all JPGs and for all + x86/ARM machines. (Note that progressive JPEGs are significantly + slower to decode than regular JPEGs.) This doesn't mean that this + is the fastest JPEG decoder in the land; rather, it brings it + closer to parity with standard libraries. If you want the fastest + decode, look elsewhere. (See "Philosophy" section of docs below.) + + See final bullet items below for more info on SIMD. + + - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing + the memory allocator. Unlike other STBI libraries, these macros don't + support a context parameter, so if you need to pass a context in to + the allocator, you'll have to store it in a global or a thread-local + variable. + + - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and + STBI_NO_LINEAR. + STBI_NO_HDR: suppress implementation of .hdr reader format + STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API + + - You can suppress implementation of any of the decoders to reduce + your code footprint by #defining one or more of the following + symbols before creating the implementation. + + STBI_NO_JPEG + STBI_NO_PNG + STBI_NO_BMP + STBI_NO_PSD + STBI_NO_TGA + STBI_NO_GIF + STBI_NO_HDR + STBI_NO_PIC + STBI_NO_PNM (.ppm and .pgm) + + - You can request *only* certain decoders and suppress all other ones + (this will be more forward-compatible, as addition of new decoders + doesn't require you to disable them explicitly): + + STBI_ONLY_JPEG + STBI_ONLY_PNG + STBI_ONLY_BMP + STBI_ONLY_PSD + STBI_ONLY_TGA + STBI_ONLY_GIF + STBI_ONLY_HDR + STBI_ONLY_PIC + STBI_ONLY_PNM (.ppm and .pgm) + + Note that you can define multiples of these, and you will get all + of them ("only x" and "only y" is interpreted to mean "only x&y"). + + - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still + want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB + + - Compilation of all SIMD code can be suppressed with + #define STBI_NO_SIMD + It should not be necessary to disable SIMD unless you have issues + compiling (e.g. using an x86 compiler which doesn't support SSE + intrinsics or that doesn't support the method used to detect + SSE2 support at run-time), and even those can be reported as + bugs so I can refine the built-in compile-time checking to be + smarter. + + - The old STBI_SIMD system which allowed installing a user-defined + IDCT etc. has been removed. If you need this, don't upgrade. My + assumption is that almost nobody was doing this, and those who + were will find the built-in SIMD more satisfactory anyway. + + - RGB values computed for JPEG images are slightly different from + previous versions of stb_image. (This is due to using less + integer precision in SIMD.) The C code has been adjusted so + that the same RGB values will be computed regardless of whether + SIMD support is available, so your app should always produce + consistent results. But these results are slightly different from + previous versions. (Specifically, about 3% of available YCbCr values + will compute different RGB results from pre-1.49 versions by +-1; + most of the deviating values are one smaller in the G channel.) + + - If you must produce consistent results with previous versions of + stb_image, #define STBI_JPEG_OLD and you will get the same results + you used to; however, you will not get the SIMD speedups for + the YCbCr-to-RGB conversion step (although you should still see + significant JPEG speedup from the other changes). + + Please note that STBI_JPEG_OLD is a temporary feature; it will be + removed in future versions of the library. It is only intended for + near-term back-compatibility use. + + + Latest revision history: + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) partial animated GIF support + limited 16-bit PSD support + minor bugs, code cleanup, and compiler warnings + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) additional corruption checking + stbi_set_flip_vertically_on_load + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD + progressive JPEG + PGM/PPM support + STBI_MALLOC,STBI_REALLOC,STBI_FREE + STBI_NO_*, STBI_ONLY_* + GIF bugfix + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted) + optimize PNG + fix bug in interlaced PNG with user-specified channel count + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + urraka@github (animated gif) Junggon Kim (PNM comments) + Daniel Gibson (16-bit TGA) + + Optimizations & bugfixes + Fabian "ryg" Giesen + Arseny Kapoulkine + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson + Dave Moore Roy Eltham Hayaki Saito Phil Jordan + Won Chun Luke Graham Johan Duparc Nathan Reed + the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis + Janez Zemva John Bartholomew Michal Cichon svdijk@github + Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson + Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github + Aruelien Pocheville Thibault Reuille Cass Everitt + Ryamond Barbiero Paul Du Bois Engin Manap + Blazej Dariusz Roszkowski + Michaelangel007@github + + +LICENSE + +This software is in the public domain. Where that dedication is not +recognized, you are granted a perpetual, irrevocable license to copy, +distribute, and modify this file as you see fit. + +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 16-bit-per-channel PNG +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - no 1-bit BMP +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *comp -- outputs # of image components in image file +// int req_comp -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. +// If req_comp is non-zero, *comp has the number of components that _would_ +// have been output otherwise. E.g. if you set req_comp to 4, you will always +// get RGBA output, but you can check *comp to see if it's trivially opaque +// because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() +// can be queried for an extremely brief, end-user unfriendly explanation +// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid +// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy to use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// make more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// The output of the JPEG decoder is slightly different from versions where +// SIMD support was introduced (that is, for versions before 1.49). The +// difference is only +-1 in the 8-bit RGB channels, and only on a small +// fraction of pixels. You can force the pre-1.49 behavior by defining +// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path +// and hence cost some performance. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for req_comp + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); + +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// NOTE: not clear do we actually need this for the 64-bit path? +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; +// this is just broken and gcc are jerks for not fixing it properly +// http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +static int stbi__sse2_available() +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +static int stbi__sse2_available() +{ +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later + // GCC 4.8+ has a nice way to do this + return __builtin_cpu_supports("sse2"); +#else + // portable way to do this, preferably without using GCC inline ASM? + // just bail for now. + return 0; +#endif +} +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result = stbi__load_main(s, x, y, comp, req_comp); + + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + int row,col,z; + stbi_uc temp; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } + + return result; +} + +#ifndef STBI_NO_HDR +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + int row,col,z; + float temp; + + // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once + for (row = 0; row < (h>>1); row++) { + for (col = 0; col < w; col++) { + for (z = 0; z < depth; z++) { + temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } +} +#endif + +#ifndef STBI_NO_STDIO + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_flip(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} +#endif //!STBI_NO_STDIO + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_flip(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_flip(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_flip(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_file(&s,f); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc(req_comp * x * y); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: STBI_ASSERT(0); + } + #undef CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi_uc dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (-1 << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi_uc *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + stbi__skip(z->s, stbi__get16be(z->s)-2); + return 1; + } + return 0; +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) { + z->img_comp[i].id = stbi__get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! + return stbi__err("bad component ID","Corrupt JPEG"); + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + } + return stbi__err("outofmem", "Out of memory"); + } + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + if (z->progressive) { + z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; + z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; + z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } else { + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } else if (x != 0) { + return stbi__err("junk before marker", "Corrupt JPEG"); + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#ifdef STBI_JPEG_OLD +// this is the same YCbCr-to-RGB calculation that stb_image has used +// historically before the algorithm changes in 1.49 +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#else +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* float2fixed(1.40200f); + g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* float2fixed(1.40200f); + g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + #ifndef STBI_JPEG_OLD + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + #endif + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + #ifndef STBI_JPEG_OLD + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + #endif + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + int i; + for (i=0; i < j->s->img_n; ++i) { + if (j->img_comp[i].raw_data) { + STBI_FREE(j->img_comp[i].raw_data); + j->img_comp[i].raw_data = NULL; + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].raw_coeff) { + STBI_FREE(j->img_comp[i].raw_coeff); + j->img_comp[i].raw_coeff = 0; + j->img_comp[i].coeff = 0; + } + if (j->img_comp[i].linebuf) { + STBI_FREE(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n; + + if (z->s->img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4]; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n; // report original components, not output + return output; + } +} + +static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__jpeg j; + j.s = s; + stbi__setup_jpeg(&j); + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg j; + j.s = s; + stbi__setup_jpeg(&j); + r = stbi__decode_jpeg_header(&j, STBI__SCAN_type); + stbi__rewind(s); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__jpeg j; + j.s = s; + return stbi__jpeg_info_raw(&j, x, y, comp); +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int stbi__zlength_base[31] = { + 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 int stbi__zlength_extra[31]= +{ 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,0,0 }; + +static int stbi__zdist_base[32] = { 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 int stbi__zdist_extra[32] = +{ 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}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else if (c == 16) { + c = stbi__zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncomperssed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; +static void stbi__init_zdefaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncomperssed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + if (s->img_x == x && s->img_y == y) { + if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } else { // interlaced: + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior = cur - stride; + int filter = *raw++; + int filter_bytes = img_n; + int width = x; + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*img_n; + #define CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; + } + #undef CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(STBI__F_none) cur[k] = raw[k]; break; + CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break; + CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break; + CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break; + CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break; + } + #undef CASE + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, + a->out + (j*x+i)*out_n, out_n); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + p[0] = p[2] * 255 / a; + p[1] = p[1] * 255 / a; + p[2] = t * 255 / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, depth=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + for (k=0; k < s->img_n; ++k) + tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0; + if (has_trans) + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_out_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int stbi__shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + info->mr = info->mg = info->mb = 0; + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if(is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // else: fall-through + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fall-through + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (r * 255)/31; + out[1] = (g * 255)/31; + out[2] = (b * 255)/31; + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4]; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp ); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int bitdepth; + int w,h; + stbi_uc *out; + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) stbi__malloc(4 * w*h); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out + channel; + if (channel >= channelCount) { + // Fill this channel with default data. + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } else { + // Read the data. + if (bitdepth == 16) { + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + + if (req_comp && req_comp != 4) { + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp) +{ + stbi_uc *result; + int i, x,y; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc(x*y*4); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out, *old_out; // output buffer (always 4 components) + int flags, bgindex, ratio, transparent, eflags, delay; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[4096]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif g; + if (!stbi__gif_header(s, &g, comp, 1)) { + stbi__rewind( s ); + return 0; + } + if (x) *x = g.w; + if (y) *y = g.h; + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + p = &g->out[g->cur_x + g->cur_y]; + c = &g->color_table[g->codes[code].suffix * 4]; + + if (c[3] >= 128) { + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1) +{ + int x, y; + stbi_uc *c = g->pal[g->bgindex]; + for (y = y0; y < y1; y += 4 * g->w) { + for (x = x0; x < x1; x += 4) { + stbi_uc *p = &g->out[y + x]; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = 0; + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) +{ + int i; + stbi_uc *prev_out = 0; + + if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) + return 0; // stbi__g_failure_reason set by stbi__gif_header + + prev_out = g->out; + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + switch ((g->eflags & 0x1C) >> 2) { + case 0: // unspecified (also always used on 1st frame) + stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h); + break; + case 1: // do not dispose + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + g->old_out = prev_out; + break; + case 2: // dispose to background + if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); + stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y); + break; + case 3: // dispose to previous + if (g->old_out) { + for (i = g->start_y; i < g->max_y; i += 4 * g->w) + memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x); + } + break; + } + + for (;;) { + switch (stbi__get8(s)) { + case 0x2C: /* Image Descriptor */ + { + int prev_trans = -1; + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + if (g->transparent >= 0 && (g->eflags & 0x01)) { + prev_trans = g->pal[g->transparent][3]; + g->pal[g->transparent][3] = 0; + } + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (o == NULL) return NULL; + + if (prev_trans != -1) + g->pal[g->transparent][3] = (stbi_uc) prev_trans; + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = stbi__get16le(s); + g->transparent = stbi__get8(s); + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) + stbi__skip(s, len); + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } + + STBI_NOTUSED(req_comp); +} + +static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + + u = stbi__gif_load_next(s, &g, comp, req_comp); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } + else if (g.out) + STBI_FREE(g.out); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s); + stbi__rewind(s); + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + *x = s->img_x; + *y = s->img_y; + *comp = info.ma ? 4 : 3; + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + if (stbi__get16be(s) != 8) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained; + stbi__pic_packet packets[10]; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi_uc *out; + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + *x = s->img_x; + *y = s->img_y; + *comp = s->img_n; + + out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv; + char c, p, t; + + stbi__rewind( s ); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/stb_truetype.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/nanovg/stb_truetype.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,5011 @@ +// stb_truetype.h - v1.24 - public domain +// authored from 2009-2020 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning +// +// Misc other: +// Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) +// +// VERSION HISTORY +// +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// +// Full history can be found at the end of this file. +// +// LICENSE +// +// See end of file for license information. +// +// USAGE +// +// Include this file in whatever places need to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// To make the implementation private to the file that generates the implementation, +// #define STBTT_STATIC +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// Improved 3D API (more shippable): +// #include "stb_rect_pack.h" -- optional, but you really want it +// stbtt_PackBegin() +// stbtt_PackSetOversampling() -- for improved quality on small fonts +// stbtt_PackFontRanges() -- pack and renders +// stbtt_PackEnd() +// stbtt_GetPackedQuad() +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() +// stbtt_GetCodepointKernAdvance() +// +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=2; // leave a little padding in case the character extends left + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + #ifndef STBTT_sqrt + #include + #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) + #endif + + #ifndef STBTT_fabs + #include + #define STBTT_fabs(x) fabs(x) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) ((void)(u),malloc(x)) + #define STBTT_free(x,u) ((void)(u),free(x)) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef STBTT_STATIC +#define STBTT_DEF static +#else +#define STBTT_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + + +////////////////////////////////////////////////////////////////////////////// +// +// NEW TEXTURE BAKING API +// +// This provides options for packing multiple fonts into one atlas, not +// perfectly but better than nothing. + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; + float xoff2,yoff2; +} stbtt_packedchar; + +typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); +// Initializes a packing context stored in the passed-in stbtt_pack_context. +// Future calls using this context will pack characters into the bitmap passed +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is +// the distance from one row to the next (or 0 to mean they are packed tightly +// together). "padding" is the amount of padding to leave between each +// character (normally you want '1' for bitmaps you'll use as textures with +// bilinear filtering). +// +// Returns 0 on failure, 1 on success. + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); +// Cleans up the packing context and frees all memory. + +#define STBTT_POINT_SIZE(x) (-(x)) + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); +// Creates character bitmaps from the font_index'th font found in fontdata (use +// font_index=0 if you don't know what that is). It creates num_chars_in_range +// bitmaps for characters with unicode values starting at first_unicode_char_in_range +// and increasing. Data for how to render them is stored in chardata_for_range; +// pass these to stbtt_GetPackedQuad to get back renderable quads. +// +// font_size is the full height of the character from ascender to descender, +// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed +// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() +// and pass that result as 'font_size': +// ..., 20 , ... // font max minus min y is 20 pixels tall +// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall + +typedef struct +{ + float font_size; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; + stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally +} stbtt_pack_range; + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +// Creates character bitmaps from multiple ranges of characters stored in +// ranges. This will usually create a better-packed bitmap than multiple +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); +// Oversampling a font increases the quality by allowing higher-quality subpixel +// positioning, and is especially valuable at smaller text sizes. +// +// This function sets the amount of oversampling for all following calls to +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is +// h_oversample*v_oversample larger than the default; for example, 2x2 +// oversampling requires 4x the storage of 1x1. For best results, render +// oversampled textures with bilinear filtering. Look at the readme in +// stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int align_to_integer); + +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + +// this is an opaque structure that you shouldn't mess with which holds +// all the context needed from PackBegin to PackEnd. +struct stbtt_pack_context { + void *user_allocator_context; + void *pack_info; + int width; + int height; + int stride_in_bytes; + int padding; + int skip_missing; + unsigned int h_oversample, v_oversample; + unsigned char *pixels; + void *nodes; +}; + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. + +// The following structure is defined publicly so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve, + STBTT_vcubic + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy,cx1,cy1; + unsigned char type,padding; + } stbtt_vertex; +#endif + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates +// +// The shape is a series of contours. Each one starts with +// a STBTT_moveto, then consists of a series of mixed +// STBTT_lineto and STBTT_curveto segments. A lineto +// draws a line from previous endpoint to its x,y; a curveto +// draws a quadratic bezier from previous endpoint to +// its x,y, using cx,cy as the bezier control point. + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC + +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +#ifndef STBTT_MAX_OVERSAMPLE +#define STBTT_MAX_OVERSAMPLE 8 +#endif + +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + +typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; + +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*4); + } + } + return -1; +} + +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) +{ + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) + return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + info->svg = -1; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + case STBTT_PLATFORM_ID_UNICODE: + // Mac/iOS has these + // all the encodingIDs are unicode, so we don't bother to check it + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + stbtt_uint16 end; + searchRange >>= 1; + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + { + stbtt_uint16 offset, start; + stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); + + STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + if (unicode_codepoint < start) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + STBTT_assert(!info->cff.size); + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } + return 1; +} + +STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours < 0) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // fallthrough + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + +STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch(coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + } break; + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch(classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + + classDefTable = classDef1ValueArray + 2 * glyphCount; + } break; + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + + classDefTable = classRangeRecords + 6 * classRangeCount; + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } break; + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + STBTT_assert(glyph1class < class1Count); + STBTT_assert(glyph2class < class2Count); + + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { + stbtt_uint8 *class1Records = table + 16; + stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); + stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + break; + }; + } + } + break; + }; + + default: + // TODO: Implement other stuff. + break; + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + +STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + +STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { + // e.g. space character + if (ix0) *ix0 = 0; + if (iy0) *iy0 = 0; + if (ix1) *ix1 = 0; + if (iy1) *iy1 = 0; + } else { + // move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); + if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); + if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); + } +} + +STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + + +typedef struct stbtt__active_edge +{ + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 + int x,dx; + float ey; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif +} stbtt__active_edge; + +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) + +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + if (!z) return z; + + // round dx down to avoid overshooting + if (dxdy < 0) + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); + else + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + + z->ey = e->y1; + z->next = 0; + z->direction = e->invert ? 1 : -1; + return z; +} +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#if STBTT_RASTERIZER_VERSION == 1 +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->direction; + } else { + int x1 = e->x; w += e->direction; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +#elif STBTT_RASTERIZER_VERSION == 2 + +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = sy1 - sy0; + STBTT_assert(x >= 0 && x < len); + scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; + scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = (x1+1 - x0) * dy + y_top; + + sign = e->direction; + // area of the rectangle covered from y0..y_crossing + area = sign * (y_crossing-sy0); + // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) + scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); + + step = sign * dy; + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; + area += step; + } + y_crossing += dy * (x2 - (x1+1)); + + STBTT_assert(STBTT_fabs(area) <= 1.01f); + + scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); + + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clearly-defined pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) STBTT_fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 + int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + +// returns number of contours +static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) { + STBTT_free(vertices, info->userdata); + return NULL; + } + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + f.userdata = NULL; + if (!stbtt_InitFont(&f, data, offset)) + return -1; + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 1; + if (y+gh+1 > bottom_y) + bottom_y = y+gh+1; + } + return bottom_y; +} + +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// rectangle packing replacement routines if you don't have stb_rect_pack.h +// + +#ifndef STB_RECT_PACK_VERSION + +typedef int stbrp_coord; + +//////////////////////////////////////////////////////////////////////////////////// +// // +// // +// COMPILER WARNING ?!?!? // +// // +// // +// if you get a compile warning due to these symbols being defined more than // +// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // +// // +//////////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int width,height; + int x,y,bottom_y; +} stbrp_context; + +typedef struct +{ + unsigned char x; +} stbrp_node; + +struct stbrp_rect +{ + stbrp_coord x,y; + int id,w,h,was_packed; +}; + +static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) +{ + con->width = pw; + con->height = ph; + con->x = 0; + con->y = 0; + con->bottom_y = 0; + STBTT__NOTUSED(nodes); + STBTT__NOTUSED(num_nodes); +} + +static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) +{ + int i; + for (i=0; i < num_rects; ++i) { + if (con->x + rects[i].w > con->width) { + con->x = 0; + con->y = con->bottom_y; + } + if (con->y + rects[i].h > con->height) + break; + rects[i].x = con->x; + rects[i].y = con->y; + rects[i].was_packed = 1; + con->x += rects[i].w; + if (con->y + rects[i].h > con->bottom_y) + con->bottom_y = con->y + rects[i].h; + } + for ( ; i < num_rects; ++i) + rects[i].was_packed = 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If +// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. + +STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) +{ + stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); + int num_nodes = pw - padding; + stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); + + if (context == NULL || nodes == NULL) { + if (context != NULL) STBTT_free(context, alloc_context); + if (nodes != NULL) STBTT_free(nodes , alloc_context); + return 0; + } + + spc->user_allocator_context = alloc_context; + spc->width = pw; + spc->height = ph; + spc->pixels = pixels; + spc->pack_info = context; + spc->nodes = nodes; + spc->padding = padding; + spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; + spc->h_oversample = 1; + spc->v_oversample = 1; + spc->skip_missing = 0; + + stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); + + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + + return 1; +} + +STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) +{ + STBTT_free(spc->nodes , spc->user_allocator_context); + STBTT_free(spc->pack_info, spc->user_allocator_context); +} + +STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) +{ + STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); + STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); + if (h_oversample <= STBTT_MAX_OVERSAMPLE) + spc->h_oversample = h_oversample; + if (v_oversample <= STBTT_MAX_OVERSAMPLE) + spc->v_oversample = v_oversample; +} + +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + +#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) + +static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_w = w - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < h; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < w; ++i) { + STBTT_assert(pixels[i] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i] = (unsigned char) (total / kernel_width); + } + + pixels += stride_in_bytes; + } +} + +static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) +{ + unsigned char buffer[STBTT_MAX_OVERSAMPLE]; + int safe_h = h - kernel_width; + int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze + for (j=0; j < w; ++j) { + int i; + unsigned int total; + STBTT_memset(buffer, 0, kernel_width); + + total = 0; + + // make kernel_width a constant in common cases so compiler can optimize out the divide + switch (kernel_width) { + case 2: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 2); + } + break; + case 3: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 3); + } + break; + case 4: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 4); + } + break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; + default: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + break; + } + + for (; i < h; ++i) { + STBTT_assert(pixels[i*stride_in_bytes] == 0); + total -= buffer[i & STBTT__OVER_MASK]; + pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); + } + + pixels += 1; + } +} + +static float stbtt__oversample_shift(int oversample) +{ + if (!oversample) + return 0.0f; + + // The prefilter is a box filter of width "oversample", + // which shifts phase by (oversample - 1)/2 pixels in + // oversampled space. We want to shift in the opposite + // direction to counter this. + return (float)-(oversample - 1) / (2.0f * (float)oversample); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k; + int missing_glyph_added = 0; + + k=0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { + int x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } + ++k; + } + } + + return k; +} + +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, missing_glyph = -1, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; + + k = 0; + for (i=0; i < num_ranges; ++i) { + float fh = ranges[i].font_size; + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { + stbrp_rect *r = &rects[k]; + if (r->was_packed && r->w != 0 && r->h != 0) { + stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; + int advance, lsb, x0,y0,x1,y1; + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbrp_coord pad = (stbrp_coord) spc->padding; + + // pad on left and top + r->x += pad; + r->y += pad; + r->w -= pad; + r->h -= pad; + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + &x0,&y0,&x1,&y1); + stbtt_MakeGlyphBitmapSubpixel(info, + spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w - spc->h_oversample+1, + r->h - spc->v_oversample+1, + spc->stride_in_bytes, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + glyph); + + if (spc->h_oversample > 1) + stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->h_oversample); + + if (spc->v_oversample > 1) + stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, + r->w, r->h, spc->stride_in_bytes, + spc->v_oversample); + + bc->x0 = (stbtt_int16) r->x; + bc->y0 = (stbtt_int16) r->y; + bc->x1 = (stbtt_int16) (r->x + r->w); + bc->y1 = (stbtt_int16) (r->y + r->h); + bc->xadvance = scale * advance; + bc->xoff = (float) x0 * recip_h + sub_x; + bc->yoff = (float) y0 * recip_v + sub_y; + bc->xoff2 = (x0 + r->w) * recip_h + sub_x; + bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; + } else { + return_value = 0; // if any fail, report failure + } + + ++k; + } + } + + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + info.userdata = spc->user_allocator_context; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + + STBTT_free(rects, spc->user_allocator_context); + return return_value; +} + +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) +{ + stbtt_pack_range range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; + range.chardata_for_range = chardata_for_range; + range.font_size = font_size; + return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); +} + +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +{ + float ipw = 1.0f / pw, iph = 1.0f / ph; + const stbtt_packedchar *b = chardata + char_index; + + if (align_to_integer) { + float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); + float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); + q->x0 = x; + q->y0 = y; + q->x1 = x + b->xoff2 - b->xoff; + q->y1 = y + b->yoff2 - b->yoff; + } else { + q->x0 = *xpos + b->xoff; + q->y0 = *ypos + b->yoff; + q->x1 = *xpos + b->xoff2; + q->y1 = *ypos + b->yoff2; + } + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + orig[0] = x; + orig[1] = y; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + c*x^2 + b*x + a = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve + float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (verts[i].type == STBTT_vline) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3],px,py,t,it; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8); + stbtt_int32 off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + slen = ttUSHORT(fc+loc+12+8); + off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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 -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,402 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "haiku.h" + +#include "../pugl-upstream/src/internal.h" + +class PuglHaikuView : public BView +{ + PuglView* const view; + +public: + PuglHaikuView(PuglView* const v) + : BView(NULL, B_FULL_UPDATE_ON_RESIZE|B_FRAME_EVENTS|B_NAVIGABLE|B_INPUT_METHOD_AWARE), + view(v) {} + +protected: + void GetPreferredSize(float* width, float* height) override + { + d_stdout("%s %i", __func__, __LINE__); + if (width != nullptr) + *width = view->frame.width; + if (height != nullptr) + *height = view->frame.height; + d_stdout("%s %i", __func__, __LINE__); + } +}; + +class PuglHaikuWindow : public BWindow +{ + PuglView* const view; + +public: + PuglHaikuWindow(PuglView* const v) + : BWindow(BRect(1.0f), "DPF-Window", B_TITLED_WINDOW, 0x0), + view(v) {} + +// protected: +// bool QuitRequested() override +// { +// d_stdout("%s %i", __func__, __LINE__); +// if (puglView->closeFunc) { +// puglView->closeFunc(puglView); +// puglView->redisplay = false; +// } +// needsQuit = false; +// d_stdout("%s %i", __func__, __LINE__); +// return true; +// } +}; + +BApplication* s_app = NULL; + +PuglWorldInternals* +puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags) +{ + if (!s_app) { + status_t status; + s_app = new BApplication("application/x-vnd.pugl-application", &status); + + if (status != B_OK) { + delete s_app; + return NULL; + } + } + + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); + + impl->app = s_app; + return impl; +} + +void* +puglGetNativeWorld(PuglWorld* const world) +{ + return world->impl->app; +} + +PuglInternals* +puglInitViewInternals(PuglWorld* const world) +{ + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + + return impl; +} + +PuglStatus +puglRealize(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + PuglStatus st = PUGL_SUCCESS; + + // Ensure that we're unrealized and that a reasonable backend has been set + if (impl->view) { + return PUGL_FAILURE; + } + if (!view->backend || !view->backend->configure) { + return PUGL_BAD_BACKEND; + } + + // Set the size to the default if it has not already been set + if (view->frame.width <= 0.0 || view->frame.height <= 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { + return PUGL_BAD_CONFIGURATION; + } + + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + } + + // Center top-level windows if a position has not been set + if (!view->parent && !view->frame.x && !view->frame.y) { + // TODO + } + + if (!view->parent) { + impl->window = new PuglHaikuWindow(view); + impl->window->Lock(); + } + + impl->view = new PuglHaikuView(view); + + if (view->parent) { + BView* const pview = (BView*)view->parent; + pview->AddChild(impl->view); + } else { + impl->window->AddChild(impl->view); + } + + // Configure and create the backend + if ((st = view->backend->configure(view)) || (st = view->backend->create(view))) { + view->backend->destroy(view); + return st; + } + + if (view->title) { + puglSetWindowTitle(view, view->title); + } + + if (view->transientParent) { + puglSetTransientParent(view, view->transientParent); + } + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + if (impl->window) { + impl->window->Unlock(); + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglShow(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + if (impl->window) { + impl->window->Show(); + } else { + impl->view->Show(); + } + return PUGL_SUCCESS; +} + +PuglStatus +puglHide(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + if (impl->window) { + impl->window->Hide(); + } else { + impl->view->Hide(); + } + return PUGL_SUCCESS; +} + +void +puglFreeViewInternals(PuglView* const view) +{ + if (view && view->impl) { + PuglInternals* const impl = view->impl; + if (view->backend) { + view->backend->destroy(view); + } + if (impl->view) { + if (impl->window) { + impl->window->RemoveChild(impl->view); + } + delete impl->view; + delete impl->window; + } + free(impl); + } +} + +void +puglFreeWorldInternals(PuglWorld* const world) +{ +// if (world->impl->app != nullptr && world->impl->app->CountWindows() == 0) { +// delete world->impl->app; +// s_app = NULL; +// } + free(world->impl); +} + +PuglStatus +puglGrabFocus(PuglView*) +{ + return PUGL_UNSUPPORTED; +} + +double +puglGetScaleFactor(const PuglView* const view) +{ + return 1.0; +} + +double +puglGetTime(const PuglWorld* const world) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) - + world->startTime; +} + +PuglStatus +puglUpdate(PuglWorld* const world, const double timeout) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglPostRedisplay(PuglView* const view) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglPostRedisplayRect(PuglView* const view, const PuglRect rect) +{ + return PUGL_UNSUPPORTED; +} + +PuglNativeView +puglGetNativeView(PuglView* const view) +{ + return 0; +} + +PuglStatus +puglSetWindowTitle(PuglView* const view, const char* const title) +{ + puglSetString(&view->title, title); + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) +{ + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; + return PUGL_SUCCESS; +} + +PuglStatus +puglStartTimer(PuglView* const view, const uintptr_t id, const double timeout) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglStopTimer(PuglView* const view, const uintptr_t id) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglPaste(PuglView* const view) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglAcceptOffer(PuglView* const view, + const PuglDataOfferEvent* const offer, + const uint32_t typeIndex) +{ + return PUGL_UNSUPPORTED; +} + +uint32_t +puglGetNumClipboardTypes(const PuglView* const view) +{ + return 0u; +} + +const char* +puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex) +{ + return NULL; +} + +const void* +puglGetClipboard(PuglView* const view, + const uint32_t typeIndex, + size_t* const len) +{ + return NULL; +} + +PuglStatus +puglSetClipboard(PuglView* const view, + const char* const type, + const void* const data, + const size_t len) +{ + return PUGL_FAILURE; +} + +PuglStatus +puglSetCursor(PuglView* const view, const PuglCursor cursor) +{ + return PUGL_FAILURE; +} + +PuglStatus +puglSetTransientParent(PuglView* const view, const PuglNativeView parent) +{ + return PUGL_FAILURE; +} + +PuglStatus +puglSetPosition(PuglView* const view, const int x, const int y) +{ + return PUGL_FAILURE; +} + +#if 0 +PuglStatus +puglGrabFocus(PuglView* view) +{ + view->impl->bView->MakeFocus(true); + return PUGL_SUCCESS; +} + +// extras follow + +void +puglRaiseWindow(PuglView* view) +{ +} + +void +puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height) +{ + bView->ResizeTo(width, height); + + if (bWindow != nullptr && bWindow->LockLooper()) + { + bWindow->MoveTo(50, 50); + bWindow->ResizeTo(width, height); + + if (! forced) + bWindow->Flush(); + + bWindow->UnlockLooper(); + } + // TODO resizable +} + +void setVisible(const bool yesNo) +{ + if (bWindow != nullptr) + { + if (bWindow->LockLooper()) + { + if (yesNo) + bWindow->Show(); + else + bWindow->Hide(); + + // TODO use flush? + bWindow->Sync(); + bWindow->UnlockLooper(); + } + } + else + { + if (yesNo) + bView->Show(); + else + bView->Hide(); + } +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,25 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_HAIKU_H +#define PUGL_SRC_HAIKU_H + +#include "../pugl-upstream/src/types.h" + +#include "pugl/pugl.h" + +#include +#include + +struct PuglWorldInternalsImpl { + BApplication* app; +}; + +struct PuglInternalsImpl { + PuglSurface* surface; + BView* view; + BWindow* window; +}; + +#endif // PUGL_SRC_HAIKU_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku_gl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku_gl.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,87 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "../pugl-upstream/src/stub.h" +#include "haiku.h" + +#include "pugl/pugl.h" + +#include +#include + +#include +#include + +typedef struct { + BGLView* view; +} PuglHaikuGlSurface; + +static PuglStatus +puglHaikuGlConfigure(PuglView* view) +{ + PuglInternals* const impl = view->impl; + + PuglHaikuGlSurface* const surface = + (PuglHaikuGlSurface*)calloc(1, sizeof(PuglHaikuGlSurface)); + impl->surface = surface; + + return PUGL_SUCCESS; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglHaikuGlEnter(PuglView* const view, const PuglExposeEvent* PUGL_UNUSED(expose)) +{ + PuglHaikuGlSurface* const surface = (PuglHaikuGlSurface*)view->impl->surface; + if (!surface || !surface->view) { + return PUGL_FAILURE; + } + + surface->view->LockGL(); + return PUGL_SUCCESS; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglHaikuGlLeave(PuglView* const view, const PuglExposeEvent* const expose) +{ + PuglHaikuGlSurface* const surface = (PuglHaikuGlSurface*)view->impl->surface; + if (!surface || !surface->view) { + return PUGL_FAILURE; + } + + if (expose) + surface->view->SwapBuffers(); + + surface->view->UnlockGL(); + return PUGL_SUCCESS; +} + +static PuglStatus +puglHaikuGlCreate(PuglView* view) +{ + return PUGL_SUCCESS; +} + +static void +puglHaikuGlDestroy(PuglView* view) +{ + PuglHaikuGlSurface* surface = (PuglHaikuGlSurface*)view->impl->surface; + if (surface) { + free(surface); + view->impl->surface = NULL; + } +} + +const PuglBackend* +puglGlBackend(void) +{ + static const PuglBackend backend = {puglHaikuGlConfigure, + puglHaikuGlCreate, + puglHaikuGlDestroy, + puglHaikuGlEnter, + puglHaikuGlLeave, + puglStubGetContext}; + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku_stub.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/haiku_stub.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,24 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "pugl/stub.h" + +#include "../pugl-upstream/src/stub.h" + +#include "pugl/pugl.h" + +const PuglBackend* +puglStubBackend(void) +{ + static const PuglBackend backend = { + puglStubConfigure, + puglStubCreate, + puglStubDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext, + }; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1141 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "wasm.h" + +#include "../pugl-upstream/src/internal.h" + +#include + +#include + +#ifdef __cplusplus +# define PUGL_INIT_STRUCT \ + {} +#else +# define PUGL_INIT_STRUCT \ + { \ + 0 \ + } +#endif + +#ifdef __MOD_DEVICES__ +# define MOD_SCALE_FACTOR_MULT 1 +#endif + +// #define PUGL_WASM_AUTO_POINTER_LOCK +// #define PUGL_WASM_NO_KEYBOARD_INPUT +// #define PUGL_WASM_NO_MOUSEWHEEL_INPUT + +PuglWorldInternals* +puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags) +{ + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); + + impl->scaleFactor = emscripten_get_device_pixel_ratio(); +#ifdef __MOD_DEVICES__ + impl->scaleFactor *= MOD_SCALE_FACTOR_MULT; +#endif + + printf("DONE: %s %d | -> %f\n", __func__, __LINE__, impl->scaleFactor); + + return impl; +} + +void* +puglGetNativeWorld(PuglWorld*) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + return NULL; +} + +PuglInternals* +puglInitViewInternals(PuglWorld* const world) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + + impl->buttonPressTimeout = -1; + impl->supportsTouch = PUGL_DONT_CARE; // not yet known + +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + impl->supportsClipboardRead = (PuglViewHintValue)EM_ASM_INT({ + if (typeof(navigator.clipboard) !== 'undefined' && typeof(navigator.clipboard.readText) === 'function' && window.isSecureContext) { + return 1; // PUGL_TRUE + } + return 0; // PUGL_FALSE + }); + + impl->supportsClipboardWrite = (PuglViewHintValue)EM_ASM_INT({ + if (typeof(navigator.clipboard) !== 'undefined' && typeof(navigator.clipboard.writeText) === 'function' && window.isSecureContext) { + return 1; // PUGL_TRUE + } + if (typeof(document.queryCommandSupported) !== 'undefined' && document.queryCommandSupported("copy")) { + return 1; // PUGL_TRUE + } + return 0; // PUGL_FALSE + }); +#endif + + return impl; +} + +static PuglStatus +puglDispatchEventWithContext(PuglView* const view, const PuglEvent* event) +{ + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + + if (!(st0 = view->backend->enter(view, NULL))) { + st0 = view->eventFunc(view, event); + st1 = view->backend->leave(view, NULL); + } + + return st0 ? st0 : st1; +} + +static PuglMods +translateModifiers(const EM_BOOL ctrlKey, + const EM_BOOL shiftKey, + const EM_BOOL altKey, + const EM_BOOL metaKey) +{ + return (ctrlKey ? PUGL_MOD_CTRL : 0u) | + (shiftKey ? PUGL_MOD_SHIFT : 0u) | + (altKey ? PUGL_MOD_ALT : 0u) | + (metaKey ? PUGL_MOD_SUPER : 0u); +} + +#ifndef PUGL_WASM_NO_KEYBOARD_INPUT +static PuglKey +keyCodeToSpecial(const unsigned long code, const unsigned long location) +{ + switch (code) { + case 0x08: return PUGL_KEY_BACKSPACE; + case 0x1B: return PUGL_KEY_ESCAPE; + case 0x2E: return PUGL_KEY_DELETE; + case 0x70: return PUGL_KEY_F1; + case 0x71: return PUGL_KEY_F2; + case 0x72: return PUGL_KEY_F3; + case 0x73: return PUGL_KEY_F4; + case 0x74: return PUGL_KEY_F5; + case 0x75: return PUGL_KEY_F6; + case 0x76: return PUGL_KEY_F7; + case 0x77: return PUGL_KEY_F8; + case 0x78: return PUGL_KEY_F9; + case 0x79: return PUGL_KEY_F10; + case 0x7A: return PUGL_KEY_F11; + case 0x7B: return PUGL_KEY_F12; + case 0x25: return PUGL_KEY_LEFT; + case 0x26: return PUGL_KEY_UP; + case 0x27: return PUGL_KEY_RIGHT; + case 0x28: return PUGL_KEY_DOWN; + case 0x21: return PUGL_KEY_PAGE_UP; + case 0x22: return PUGL_KEY_PAGE_DOWN; + case 0x24: return PUGL_KEY_HOME; + case 0x23: return PUGL_KEY_END; + case 0x2D: return PUGL_KEY_INSERT; + case 0x10: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_SHIFT_R : PUGL_KEY_SHIFT_L; + case 0x11: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_CTRL_R : PUGL_KEY_CTRL_L; + case 0x12: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_ALT_R : PUGL_KEY_ALT_L; + case 0xE0: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_SUPER_R : PUGL_KEY_SUPER_L; + case 0x5D: return PUGL_KEY_MENU; + case 0x14: return PUGL_KEY_CAPS_LOCK; + case 0x91: return PUGL_KEY_SCROLL_LOCK; + case 0x90: return PUGL_KEY_NUM_LOCK; + case 0x2C: return PUGL_KEY_PRINT_SCREEN; + case 0x13: return PUGL_KEY_PAUSE; + case '\r': return (PuglKey)'\r'; + default: break; + } + + return (PuglKey)0; +} + +static bool +decodeCharacterString(const unsigned long keyCode, + const EM_UTF8 key[EM_HTML5_SHORT_STRING_LEN_BYTES], + char str[8]) +{ + if (key[1] == 0) + { + str[0] = key[0]; + return true; + } + + return false; +} + +static EM_BOOL +puglKeyCallback(const int eventType, const EmscriptenKeyboardEvent* const keyEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + if (keyEvent->repeat && view->hints[PUGL_IGNORE_KEY_REPEAT]) + return EM_TRUE; + + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + + const uint state = translateModifiers(keyEvent->ctrlKey, + keyEvent->shiftKey, + keyEvent->altKey, + keyEvent->metaKey); + + const PuglKey special = keyCodeToSpecial(keyEvent->keyCode, keyEvent->location); + + uint key = keyEvent->key[0] >= ' ' && keyEvent->key[0] <= '~' && keyEvent->key[1] == '\0' + ? keyEvent->key[0] + : keyEvent->keyCode; + + if (key >= 'A' && key <= 'Z' && !keyEvent->shiftKey) + key += 'a' - 'A'; + + PuglEvent event = {{PUGL_NOTHING, 0}}; + event.key.type = eventType == EMSCRIPTEN_EVENT_KEYDOWN ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; + event.key.time = keyEvent->timestamp / 1e3; + // event.key.x = xevent.xkey.x; + // event.key.y = xevent.xkey.y; + // event.key.xRoot = xevent.xkey.x_root; + // event.key.yRoot = xevent.xkey.y_root; + event.key.key = special ? special : key; + event.key.keycode = keyEvent->keyCode; + event.key.state = state; + st0 = puglDispatchEventWithContext(view, &event); + + d_debug("key event \n" + "\tdown: %d\n" + "\trepeat: %d\n" + "\tlocation: %d\n" + "\tstate: 0x%x\n" + "\tkey[]: '%s'\n" + "\tcode[]: '%s'\n" + "\tlocale[]: '%s'\n" + "\tkeyCode: 0x%lx:'%c' [deprecated, use key]\n" + "\twhich: 0x%lx:'%c' [deprecated, use key, same as keycode?]\n" + "\tspecial: 0x%x", + eventType == EMSCRIPTEN_EVENT_KEYDOWN, + keyEvent->repeat, + keyEvent->location, + state, + keyEvent->key, + keyEvent->code, + keyEvent->locale, + keyEvent->keyCode, keyEvent->keyCode >= ' ' && keyEvent->keyCode <= '~' ? keyEvent->keyCode : 0, + keyEvent->which, keyEvent->which >= ' ' && keyEvent->which <= '~' ? keyEvent->which : 0, + special); + + if (event.type == PUGL_KEY_PRESS && !special && !(keyEvent->ctrlKey|keyEvent->altKey|keyEvent->metaKey)) { + char str[8] = PUGL_INIT_STRUCT; + + if (decodeCharacterString(keyEvent->keyCode, keyEvent->key, str)) { + d_debug("resulting string is '%s'", str); + + event.text.type = PUGL_TEXT; + event.text.character = event.key.key; + memcpy(event.text.string, str, sizeof(event.text.string)); + st1 = puglDispatchEventWithContext(view, &event); + } + } + + return (st0 ? st0 : st1) == PUGL_SUCCESS ? EM_TRUE : EM_FALSE; +} +#endif + +static EM_BOOL +puglMouseCallback(const int eventType, const EmscriptenMouseEvent* const mouseEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + PuglEvent event = {{PUGL_NOTHING, 0}}; + + const double time = mouseEvent->timestamp / 1e3; + const PuglMods state = translateModifiers(mouseEvent->ctrlKey, + mouseEvent->shiftKey, + mouseEvent->altKey, + mouseEvent->metaKey); + + double scaleFactor = view->world->impl->scaleFactor; +#ifdef __MOD_DEVICES__ + if (!view->impl->isFullscreen) { + scaleFactor /= EM_ASM_DOUBLE({ + return parseFloat( + RegExp('^scale\\\((.*)\\\)$') + .exec(document.getElementById("pedalboard-dashboard").style.transform)[1] + ); + }) * MOD_SCALE_FACTOR_MULT; + } +#endif + + // workaround missing pointer lock callback, see https://github.com/emscripten-core/emscripten/issues/9681 + EmscriptenPointerlockChangeEvent e; + if (emscripten_get_pointerlock_status(&e) == EMSCRIPTEN_RESULT_SUCCESS) + view->impl->pointerLocked = e.isActive; + +#ifdef __MOD_DEVICES__ + const long canvasX = mouseEvent->canvasX; + const long canvasY = mouseEvent->canvasY; +#else + const char* const className = view->world->className; + const double canvasX = mouseEvent->clientX - EM_ASM_DOUBLE({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.getBoundingClientRect().x; + }, className); + const double canvasY = mouseEvent->clientY - EM_ASM_DOUBLE({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.getBoundingClientRect().y; + }, className); +#endif + + switch (eventType) { + case EMSCRIPTEN_EVENT_MOUSEDOWN: + case EMSCRIPTEN_EVENT_MOUSEUP: + event.button.type = eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? PUGL_BUTTON_PRESS : PUGL_BUTTON_RELEASE; + event.button.time = time; + event.button.x = canvasX * scaleFactor; + event.button.y = canvasY * scaleFactor; + event.button.xRoot = mouseEvent->screenX * scaleFactor; + event.button.yRoot = mouseEvent->screenY * scaleFactor; + event.button.state = state; + switch (mouseEvent->button) { + case 1: + event.button.button = 2; + break; + case 2: + event.button.button = 1; + break; + default: + event.button.button = mouseEvent->button; + break; + } + break; + case EMSCRIPTEN_EVENT_MOUSEMOVE: + event.motion.type = PUGL_MOTION; + event.motion.time = time; + if (view->impl->pointerLocked) { + // adjust local values for delta + const double movementX = mouseEvent->movementX * scaleFactor; + const double movementY = mouseEvent->movementY * scaleFactor; + view->impl->lastMotion.x += movementX; + view->impl->lastMotion.y += movementY; + view->impl->lastMotion.xRoot += movementX; + view->impl->lastMotion.yRoot += movementY; + // now set x, y, xRoot and yRoot + event.motion.x = view->impl->lastMotion.x; + event.motion.y = view->impl->lastMotion.y; + event.motion.xRoot = view->impl->lastMotion.xRoot; + event.motion.yRoot = view->impl->lastMotion.yRoot; + } else { + // cache values for possible pointer lock movement later + view->impl->lastMotion.x = event.motion.x = canvasX * scaleFactor; + view->impl->lastMotion.y = event.motion.y = canvasY * scaleFactor; + view->impl->lastMotion.xRoot = event.motion.xRoot = mouseEvent->screenX * scaleFactor; + view->impl->lastMotion.yRoot = event.motion.yRoot = mouseEvent->screenY * scaleFactor; + } + event.motion.state = state; + break; + case EMSCRIPTEN_EVENT_MOUSEENTER: + case EMSCRIPTEN_EVENT_MOUSELEAVE: + event.crossing.type = eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? PUGL_POINTER_IN : PUGL_POINTER_OUT; + event.crossing.time = time; + event.crossing.x = canvasX * scaleFactor; + event.crossing.y = canvasY * scaleFactor; + event.crossing.xRoot = mouseEvent->screenX * scaleFactor; + event.crossing.yRoot = mouseEvent->screenY * scaleFactor; + event.crossing.state = state; + event.crossing.mode = PUGL_CROSSING_NORMAL; + break; + } + + if (event.type == PUGL_NOTHING) + return EM_FALSE; + + puglDispatchEventWithContext(view, &event); + +#ifdef PUGL_WASM_AUTO_POINTER_LOCK + switch (eventType) { + case EMSCRIPTEN_EVENT_MOUSEDOWN: + emscripten_request_pointerlock(view->world->className, false); + break; + case EMSCRIPTEN_EVENT_MOUSEUP: + emscripten_exit_pointerlock(); + break; + } +#endif + + // note: we must always return false, otherwise canvas never gets keyboard input + return EM_FALSE; +} + +static void +puglTouchStartDelay(void* const userData) +{ + PuglView* const view = (PuglView*)userData; + PuglInternals* const impl = view->impl; + + impl->buttonPressTimeout = -1; + impl->nextButtonEvent.button.time += 2000; + puglDispatchEventWithContext(view, &impl->nextButtonEvent); +} + +static EM_BOOL +puglTouchCallback(const int eventType, const EmscriptenTouchEvent* const touchEvent, void* const userData) +{ + if (touchEvent->numTouches <= 0) { + return EM_FALSE; + } + + PuglView* const view = (PuglView*)userData; + PuglInternals* const impl = view->impl; + const char* const className = view->world->className; + + if (impl->supportsTouch == PUGL_DONT_CARE) { + impl->supportsTouch = PUGL_TRUE; + + // stop using mouse press events which conflict with touch + emscripten_set_mousedown_callback(className, view, false, NULL); + emscripten_set_mouseup_callback(className, view, false, NULL); + } + + if (!view->visible) { + return EM_FALSE; + } + + PuglEvent event = {{PUGL_NOTHING, 0}}; + + const double time = touchEvent->timestamp / 1e3; + const PuglMods state = translateModifiers(touchEvent->ctrlKey, + touchEvent->shiftKey, + touchEvent->altKey, + touchEvent->metaKey); + + double scaleFactor = view->world->impl->scaleFactor; +#ifdef __MOD_DEVICES__ + if (!view->impl->isFullscreen) { + scaleFactor /= EM_ASM_DOUBLE({ + return parseFloat( + RegExp('^scale\\\((.*)\\\)$') + .exec(document.getElementById("pedalboard-dashboard").style.transform)[1] + ); + }) * MOD_SCALE_FACTOR_MULT; + } +#endif + + d_debug("touch %d|%s %d || %ld", + eventType, + eventType == EMSCRIPTEN_EVENT_TOUCHSTART ? "start" : + eventType == EMSCRIPTEN_EVENT_TOUCHEND ? "end" : "cancel", + touchEvent->numTouches, + impl->buttonPressTimeout); + + const EmscriptenTouchPoint* point = &touchEvent->touches[0]; + + if (impl->buttonPressTimeout != -1 || eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL) { + // if we received an event while touch is active, trigger initial click now + if (impl->buttonPressTimeout != -1) { + emscripten_clear_timeout(impl->buttonPressTimeout); + impl->buttonPressTimeout = -1; + if (eventType != EMSCRIPTEN_EVENT_TOUCHCANCEL) { + impl->nextButtonEvent.button.button = 0; + } + } + impl->nextButtonEvent.button.time = time; + puglDispatchEventWithContext(view, &impl->nextButtonEvent); + } + +#ifdef __MOD_DEVICES__ + const long canvasX = point->canvasX; + const long canvasY = point->canvasY; +#else + const double canvasX = point->clientX - EM_ASM_DOUBLE({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.getBoundingClientRect().x; + }, className); + const double canvasY = point->clientY - EM_ASM_DOUBLE({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.getBoundingClientRect().y; + }, className); +#endif + + switch (eventType) { + case EMSCRIPTEN_EVENT_TOUCHEND: + case EMSCRIPTEN_EVENT_TOUCHCANCEL: + event.button.type = PUGL_BUTTON_RELEASE; + event.button.time = time; + event.button.button = eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL ? 1 : 0; + event.button.x = canvasX * scaleFactor; + event.button.y = canvasY * scaleFactor; + event.button.xRoot = point->screenX * scaleFactor; + event.button.yRoot = point->screenY * scaleFactor; + event.button.state = state; + break; + + case EMSCRIPTEN_EVENT_TOUCHSTART: + // this event can be used for a couple of things, store it until we know more + event.button.type = PUGL_BUTTON_PRESS; + event.button.time = time; + event.button.button = 1; // if no other event occurs soon, treat it as right-click + event.button.x = canvasX * scaleFactor; + event.button.y = canvasY * scaleFactor; + event.button.xRoot = point->screenX * scaleFactor; + event.button.yRoot = point->screenY * scaleFactor; + event.button.state = state; + memcpy(&impl->nextButtonEvent, &event, sizeof(PuglEvent)); + impl->buttonPressTimeout = emscripten_set_timeout(puglTouchStartDelay, 2000, view); + // fall through, moving "mouse" to touch position + + case EMSCRIPTEN_EVENT_TOUCHMOVE: + event.motion.type = PUGL_MOTION; + event.motion.time = time; + event.motion.x = canvasX * scaleFactor; + event.motion.y = canvasY * scaleFactor; + event.motion.xRoot = point->screenX * scaleFactor; + event.motion.yRoot = point->screenY * scaleFactor; + event.motion.state = state; + break; + } + + if (event.type == PUGL_NOTHING) + return EM_FALSE; + + puglDispatchEventWithContext(view, &event); + + // FIXME we must always return false?? + return EM_FALSE; +} + +static EM_BOOL +puglFocusCallback(const int eventType, const EmscriptenFocusEvent* /*const focusEvent*/, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + d_debug("focus %d|%s", eventType, eventType == EMSCRIPTEN_EVENT_FOCUSIN ? "focus-in" : "focus-out"); + + PuglEvent event = {{eventType == EMSCRIPTEN_EVENT_FOCUSIN ? PUGL_FOCUS_IN : PUGL_FOCUS_OUT, 0}}; + event.focus.mode = PUGL_CROSSING_NORMAL; + + puglDispatchEventWithContext(view, &event); + + // note: we must always return false, otherwise canvas never gets proper focus + return EM_FALSE; +} + +static EM_BOOL +puglPointerLockChangeCallback(const int eventType, const EmscriptenPointerlockChangeEvent* event, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + view->impl->pointerLocked = event->isActive; + return EM_TRUE; +} + +#ifndef PUGL_WASM_NO_MOUSEWHEEL_INPUT +static EM_BOOL +puglWheelCallback(const int eventType, const EmscriptenWheelEvent* const wheelEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + double scaleFactor = view->world->impl->scaleFactor; +#ifdef __MOD_DEVICES__ + if (!view->impl->isFullscreen) { + scaleFactor /= EM_ASM_DOUBLE({ + return parseFloat( + RegExp('^scale\\\((.*)\\\)$') + .exec(document.getElementById("pedalboard-dashboard").style.transform)[1] + ); + }) * MOD_SCALE_FACTOR_MULT; + } +#endif + +#ifdef __MOD_DEVICES__ + const long canvasX = wheelEvent->mouse.canvasX; + const long canvasY = wheelEvent->mouse.canvasY; +#else + const char* const className = view->world->className; + const double canvasX = wheelEvent->mouse.canvasX - EM_ASM_INT({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.getBoundingClientRect().x; + }, className); + const double canvasY = wheelEvent->mouse.canvasY - EM_ASM_INT({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.getBoundingClientRect().y; + }, className); +#endif + + PuglEvent event = {{PUGL_SCROLL, 0}}; + event.scroll.time = wheelEvent->mouse.timestamp / 1e3; + event.scroll.x = canvasX; + event.scroll.y = canvasY; + event.scroll.xRoot = wheelEvent->mouse.screenX; + event.scroll.yRoot = wheelEvent->mouse.screenY; + event.scroll.state = translateModifiers(wheelEvent->mouse.ctrlKey, + wheelEvent->mouse.shiftKey, + wheelEvent->mouse.altKey, + wheelEvent->mouse.metaKey); + event.scroll.direction = PUGL_SCROLL_SMOOTH; + // FIXME handle wheelEvent->deltaMode + event.scroll.dx = wheelEvent->deltaX * 0.01 * scaleFactor; + event.scroll.dy = -wheelEvent->deltaY * 0.01 * scaleFactor; + + return puglDispatchEventWithContext(view, &event) == PUGL_SUCCESS ? EM_TRUE : EM_FALSE; +} +#endif + +static EM_BOOL +puglUiCallback(const int eventType, const EmscriptenUiEvent* const uiEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + const char* const className = view->world->className; + + // FIXME + const int width = EM_ASM_INT({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + canvasWrapper.style.setProperty("--device-pixel-ratio", window.devicePixelRatio); + return canvasWrapper.clientWidth; + }, className); + + const int height = EM_ASM_INT({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.clientHeight; + }, className); + + if (!width || !height) + return EM_FALSE; + + double scaleFactor = emscripten_get_device_pixel_ratio(); +#ifdef __MOD_DEVICES__ + scaleFactor *= MOD_SCALE_FACTOR_MULT; +#endif + view->world->impl->scaleFactor = scaleFactor; + + PuglEvent event = {{PUGL_CONFIGURE, 0}}; + event.configure.x = view->frame.x; + event.configure.y = view->frame.y; + event.configure.width = width * scaleFactor; + event.configure.height = height * scaleFactor; + puglDispatchEvent(view, &event); + + emscripten_set_canvas_element_size(view->world->className, width * scaleFactor, height * scaleFactor); + return EM_TRUE; +} + +static EM_BOOL +puglFullscreenChangeCallback(const int eventType, const EmscriptenFullscreenChangeEvent* const fscEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + view->impl->isFullscreen = fscEvent->isFullscreen; + + double scaleFactor = emscripten_get_device_pixel_ratio(); +#ifdef __MOD_DEVICES__ + scaleFactor *= MOD_SCALE_FACTOR_MULT; +#endif + view->world->impl->scaleFactor = scaleFactor; + + if (fscEvent->isFullscreen) { + PuglEvent event = {{PUGL_CONFIGURE, 0}}; + event.configure.x = 0; + event.configure.y = 0; + event.configure.width = fscEvent->elementWidth * scaleFactor; + event.configure.height = fscEvent->elementHeight * scaleFactor; + puglDispatchEvent(view, &event); + + emscripten_set_canvas_element_size(view->world->className, + fscEvent->elementWidth * scaleFactor, + fscEvent->elementHeight * scaleFactor); + +#ifdef __MOD_DEVICES__ + EM_ASM({ + document.getElementById("pedalboard-dashboard").style.transform = "scale(1.0)"; + }); +#endif + return EM_TRUE; + } + + return puglUiCallback(0, NULL, userData); +} + +static EM_BOOL +puglVisibilityChangeCallback(const int eventType, const EmscriptenVisibilityChangeEvent* const visibilityChangeEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + view->visible = visibilityChangeEvent->hidden == EM_FALSE; + PuglEvent event = {{ view->visible ? PUGL_MAP : PUGL_UNMAP, 0}}; + puglDispatchEvent(view, &event); + return EM_FALSE; +} + +PuglStatus +puglRealize(PuglView* const view) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + PuglStatus st = PUGL_SUCCESS; + + // Ensure that we do not have a parent + if (view->parent) { + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_FAILURE; + } + + if (!view->backend || !view->backend->configure) { + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_BAD_BACKEND; + } + + const char* const className = view->world->className; + d_stdout("className is %s", className); + + // Set the size to the default if it has not already been set + if (view->frame.width <= 0.0 && view->frame.height <= 0.0) { + PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { + return PUGL_BAD_CONFIGURATION; + } + + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + } + + // Configure and create the backend + if ((st = view->backend->configure(view)) || (st = view->backend->create(view))) { + view->backend->destroy(view); + return st; + } + + if (view->title) { + puglSetWindowTitle(view, view->title); + } + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + PuglEvent event = {{PUGL_CONFIGURE, 0}}; + event.configure.x = view->frame.x; + event.configure.y = view->frame.y; + event.configure.width = view->frame.width; + event.configure.height = view->frame.height; + puglDispatchEvent(view, &event); + + EM_ASM({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + canvasWrapper.style.setProperty("--device-pixel-ratio", window.devicePixelRatio); + }, className); + + emscripten_set_canvas_element_size(className, view->frame.width, view->frame.height); +#ifndef PUGL_WASM_NO_KEYBOARD_INPUT +// emscripten_set_keypress_callback(className, view, false, puglKeyCallback); + emscripten_set_keydown_callback(className, view, false, puglKeyCallback); + emscripten_set_keyup_callback(className, view, false, puglKeyCallback); +#endif + emscripten_set_touchstart_callback(className, view, false, puglTouchCallback); + emscripten_set_touchend_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglTouchCallback); + emscripten_set_touchmove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglTouchCallback); + emscripten_set_touchcancel_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglTouchCallback); + emscripten_set_mousedown_callback(className, view, false, puglMouseCallback); + emscripten_set_mouseup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglMouseCallback); + emscripten_set_mousemove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglMouseCallback); + emscripten_set_mouseenter_callback(className, view, false, puglMouseCallback); + emscripten_set_mouseleave_callback(className, view, false, puglMouseCallback); + emscripten_set_focusin_callback(className, view, false, puglFocusCallback); + emscripten_set_focusout_callback(className, view, false, puglFocusCallback); +#ifndef PUGL_WASM_NO_MOUSEWHEEL_INPUT + emscripten_set_wheel_callback(className, view, false, puglWheelCallback); +#endif + emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglPointerLockChangeCallback); + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglUiCallback); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglFullscreenChangeCallback); + emscripten_set_visibilitychange_callback(view, false, puglVisibilityChangeCallback); + + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_SUCCESS; +} + +PuglStatus +puglShow(PuglView* const view) +{ + view->visible = true; + view->impl->needsRepaint = true; + return puglPostRedisplay(view); +} + +PuglStatus +puglHide(PuglView* const view) +{ + view->visible = false; + return PUGL_FAILURE; +} + +void +puglFreeViewInternals(PuglView* const view) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + if (view && view->impl) { + if (view->backend) { + // unregister the window events, to make sure no callbacks to old views are triggered + emscripten_set_touchend_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_touchmove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_touchcancel_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_mouseup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_mousemove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, NULL); + emscripten_set_visibilitychange_callback(NULL, false, NULL); + view->backend->destroy(view); + } + free(view->impl->clipboardData); + free(view->impl->timers); + free(view->impl); + } +} + +void +puglFreeWorldInternals(PuglWorld* const world) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + free(world->impl); +} + +PuglStatus +puglGrabFocus(PuglView*) +{ + return PUGL_FAILURE; +} + +double +puglGetScaleFactor(const PuglView* const view) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + return view->world->impl->scaleFactor; +} + +double +puglGetTime(const PuglWorld*) +{ + return emscripten_get_now() / 1e3; +} + +PuglStatus +puglUpdate(PuglWorld* const world, const double timeout) +{ + for (size_t i = 0; i < world->numViews; ++i) { + PuglView* const view = world->views[i]; + + if (!view->visible) { + continue; + } + + puglDispatchSimpleEvent(view, PUGL_UPDATE); + + if (!view->impl->needsRepaint) { + continue; + } + + view->impl->needsRepaint = false; + + PuglEvent event = {{PUGL_EXPOSE, 0}}; + event.expose.x = view->frame.x; + event.expose.y = view->frame.y; + event.expose.width = view->frame.width; + event.expose.height = view->frame.height; + puglDispatchEvent(view, &event); + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglPostRedisplay(PuglView* const view) +{ + view->impl->needsRepaint = true; + return PUGL_SUCCESS; +} + +PuglStatus +puglPostRedisplayRect(PuglView* const view, const PuglRect rect) +{ + view->impl->needsRepaint = true; + return PUGL_FAILURE; +} + +PuglNativeView +puglGetNativeView(PuglView* const view) +{ + return 0; +} + +PuglStatus +puglSetWindowTitle(PuglView* const view, const char* const title) +{ + puglSetString(&view->title, title); + emscripten_set_window_title(title); + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) +{ + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; + return PUGL_SUCCESS; +} + +static EM_BOOL +puglTimerLoopCallback(double timeout, void* const arg) +{ + PuglTimer* const timer = (PuglTimer*)arg; + PuglInternals* const impl = timer->view->impl; + + // only handle active timers + for (uint32_t i=0; inumTimers; ++i) + { + if (impl->timers[i].id == timer->id) + { + PuglEvent event = {{PUGL_TIMER, 0}}; + event.timer.id = timer->id; + puglDispatchEventWithContext(timer->view, &event); + return EM_TRUE; + } + } + + return EM_FALSE; + + // unused + (void)timeout; +} + +PuglStatus +puglStartTimer(PuglView* const view, const uintptr_t id, const double timeout) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + PuglInternals* const impl = view->impl; + const uint32_t timerIndex = impl->numTimers++; + + if (impl->timers == NULL) + impl->timers = (PuglTimer*)malloc(sizeof(PuglTimer)); + else + impl->timers = (PuglTimer*)realloc(impl->timers, sizeof(PuglTimer) * timerIndex); + + PuglTimer* const timer = &impl->timers[timerIndex]; + timer->view = view; + timer->id = id; + + emscripten_set_timeout_loop(puglTimerLoopCallback, timeout * 1e3, timer); + return PUGL_SUCCESS; +} + +PuglStatus +puglStopTimer(PuglView* const view, const uintptr_t id) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + PuglInternals* const impl = view->impl; + + if (impl->timers == NULL || impl->numTimers == 0) + return PUGL_FAILURE; + + for (uint32_t i=0; inumTimers; ++i) + { + if (impl->timers[i].id == id) + { + memmove(impl->timers + i, impl->timers + (i + 1), sizeof(PuglTimer) * (impl->numTimers - 1)); + --impl->numTimers; + return PUGL_SUCCESS; + } + } + + return PUGL_FAILURE; +} + +#ifdef PUGL_WASM_ASYNC_CLIPBOARD +EM_JS(char*, puglGetAsyncClipboardData, (), { + var text = Asyncify.handleSleep(function(wakeUp) { + navigator.clipboard.readText() + .then(function(text) { + wakeUp(text); + }) + .catch(function() { + wakeUp(""); + }); + }); + if (!text.length) { + return null; + } + var length = lengthBytesUTF8(text) + 1; + var str = _malloc(length); + stringToUTF8(text, str, length); + return str; +}); +#endif + +PuglStatus +puglPaste(PuglView* const view) +{ +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + // abort early if we already know it is not supported + if (view->impl->supportsClipboardRead == PUGL_FALSE) { + return PUGL_UNSUPPORTED; + } + + free(view->impl->clipboardData); + view->impl->clipboardData = puglGetAsyncClipboardData(); +#endif + + if (view->impl->clipboardData == NULL) { + return PUGL_FAILURE; + } + + const PuglDataOfferEvent offer = { + PUGL_DATA_OFFER, + 0, + emscripten_get_now() / 1e3, + }; + + PuglEvent offerEvent; + offerEvent.offer = offer; + puglDispatchEvent(view, &offerEvent); + return PUGL_SUCCESS; +} + +PuglStatus +puglAcceptOffer(PuglView* const view, + const PuglDataOfferEvent* const offer, + const uint32_t typeIndex) +{ + if (typeIndex != 0) { + return PUGL_UNSUPPORTED; + } + + const PuglDataEvent data = { + PUGL_DATA, + 0, + emscripten_get_now() / 1e3, + 0, + }; + + PuglEvent dataEvent; + dataEvent.data = data; + puglDispatchEvent(view, &dataEvent); + return PUGL_SUCCESS; +} + +uint32_t +puglGetNumClipboardTypes(const PuglView* const view) +{ + return view->impl->clipboardData != NULL ? 1u : 0u; +} + +const char* +puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex) +{ + return (typeIndex == 0 && view->impl->clipboardData != NULL) + ? "text/plain" + : NULL; +} + +const void* +puglGetClipboard(PuglView* const view, + const uint32_t typeIndex, + size_t* const len) +{ + return view->impl->clipboardData; +} + +PuglStatus +puglSetClipboard(PuglView* const view, + const char* const type, + const void* const data, + const size_t len) +{ + // only utf8 text supported for now + if (type != NULL && strcmp(type, "text/plain") != 0) { + return PUGL_UNSUPPORTED; + } + + const char* const className = view->world->className; + const char* const text = (const char*)data; + +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + // abort early if we already know it is not supported + if (view->impl->supportsClipboardWrite == PUGL_FALSE) { + return PUGL_UNSUPPORTED; + } +#else + puglSetString(&view->impl->clipboardData, text); +#endif + + EM_ASM({ + if (typeof(navigator.clipboard) !== 'undefined' && typeof(navigator.clipboard.writeText) === 'function' && window.isSecureContext) { + navigator.clipboard.writeText(UTF8ToString($1)); + } else { + var canvasClipboardObjName = UTF8ToString($0) + "_clipboard"; + var canvasClipboardElem = document.getElementById(canvasClipboardObjName); + + if (!canvasClipboardElem) { + canvasClipboardElem = document.createElement('textarea'); + canvasClipboardElem.id = canvasClipboardObjName; + canvasClipboardElem.style.position = 'fixed'; + canvasClipboardElem.style.whiteSpace = 'pre'; + canvasClipboardElem.style.zIndex = '-1'; + canvasClipboardElem.setAttribute('readonly', true); + document.body.appendChild(canvasClipboardElem); + } + + canvasClipboardElem.textContent = UTF8ToString($1); + canvasClipboardElem.select(); + document.execCommand("copy"); + } + }, className, text); + + // FIXME proper return status + return PUGL_SUCCESS; +} + +PuglStatus +puglSetCursor(PuglView* const view, const PuglCursor cursor) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_FAILURE; +} + +PuglStatus +puglSetTransientParent(PuglView* const view, const PuglNativeView parent) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + view->transientParent = parent; + return PUGL_FAILURE; +} + +PuglStatus +puglSetPosition(PuglView* const view, const int x, const int y) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + + if (x > INT16_MAX || y > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + view->frame.x = (PuglCoord)x; + view->frame.y = (PuglCoord)y; + return PUGL_FAILURE; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,45 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_WASM_H +#define PUGL_SRC_WASM_H + +#include "../pugl-upstream/src/types.h" + +#include "pugl/pugl.h" + +// #define PUGL_WASM_ASYNC_CLIPBOARD + +struct PuglTimer { + PuglView* view; + uintptr_t id; +}; + +struct PuglWorldInternalsImpl { + double scaleFactor; +}; + +struct LastMotionValues { + double x, y, xRoot, yRoot; +}; + +struct PuglInternalsImpl { + PuglSurface* surface; + bool isFullscreen; + bool needsRepaint; + bool pointerLocked; + uint32_t numTimers; + LastMotionValues lastMotion; + long buttonPressTimeout; + PuglEvent nextButtonEvent; +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + PuglViewHintValue supportsClipboardRead; + PuglViewHintValue supportsClipboardWrite; +#endif + PuglViewHintValue supportsTouch; + char* clipboardData; + struct PuglTimer* timers; +}; + +#endif // PUGL_SRC_WASM_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm_gl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm_gl.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,228 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "../pugl-upstream/src/stub.h" +#include "wasm.h" + +#include "pugl/pugl.h" + +#include +#include + +#include + +// for performance reasons we can keep a single EGL context always active +#define PUGL_WASM_SINGLE_EGL_CONTEXT + +typedef struct { + EGLDisplay display; + EGLConfig config; + EGLContext context; + EGLSurface surface; +} PuglWasmGlSurface; + +static EGLint +puglWasmGlHintValue(const int value) +{ + return value == PUGL_DONT_CARE ? EGL_DONT_CARE : value; +} + +static int +puglWasmGlGetAttrib(const EGLDisplay display, + const EGLConfig config, + const EGLint attrib) +{ + EGLint value = 0; + eglGetConfigAttrib(display, config, attrib, &value); + return value; +} + +static PuglStatus +puglWasmGlConfigure(PuglView* view) +{ + PuglInternals* const impl = view->impl; + + const EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + if (display == EGL_NO_DISPLAY) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + int major, minor; + if (eglInitialize(display, &major, &minor) != EGL_TRUE) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + EGLConfig config; + int numConfigs; + + if (eglGetConfigs(display, &config, 1, &numConfigs) != EGL_TRUE || numConfigs != 1) { + eglTerminate(display); + return PUGL_CREATE_CONTEXT_FAILED; + } + + // clang-format off + const EGLint attrs[] = { + /* + GLX_X_RENDERABLE, True, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + EGL_SAMPLE_BUFFERS, view->hints[PUGL_MULTI_SAMPLE] ? 1 : 0, + */ + EGL_SAMPLES, puglWasmGlHintValue(view->hints[PUGL_SAMPLES]), + EGL_RED_SIZE, puglWasmGlHintValue(view->hints[PUGL_RED_BITS]), + EGL_GREEN_SIZE, puglWasmGlHintValue(view->hints[PUGL_GREEN_BITS]), + EGL_BLUE_SIZE, puglWasmGlHintValue(view->hints[PUGL_BLUE_BITS]), + EGL_ALPHA_SIZE, puglWasmGlHintValue(view->hints[PUGL_ALPHA_BITS]), + EGL_DEPTH_SIZE, puglWasmGlHintValue(view->hints[PUGL_DEPTH_BITS]), + EGL_STENCIL_SIZE, puglWasmGlHintValue(view->hints[PUGL_STENCIL_BITS]), + EGL_NONE + }; + // clang-format on + + if (eglChooseConfig(display, attrs, &config, 1, &numConfigs) != EGL_TRUE || numConfigs != 1) { + eglTerminate(display); + return PUGL_CREATE_CONTEXT_FAILED; + } + + PuglWasmGlSurface* const surface = + (PuglWasmGlSurface*)calloc(1, sizeof(PuglWasmGlSurface)); + impl->surface = surface; + + surface->display = display; + surface->config = config; + surface->context = EGL_NO_SURFACE; + surface->surface = EGL_NO_CONTEXT; + + view->hints[PUGL_RED_BITS] = + puglWasmGlGetAttrib(display, config, EGL_RED_SIZE); + view->hints[PUGL_GREEN_BITS] = + puglWasmGlGetAttrib(display, config, EGL_GREEN_SIZE); + view->hints[PUGL_BLUE_BITS] = + puglWasmGlGetAttrib(display, config, EGL_BLUE_SIZE); + view->hints[PUGL_ALPHA_BITS] = + puglWasmGlGetAttrib(display, config, EGL_ALPHA_SIZE); + view->hints[PUGL_DEPTH_BITS] = + puglWasmGlGetAttrib(display, config, EGL_DEPTH_SIZE); + view->hints[PUGL_STENCIL_BITS] = + puglWasmGlGetAttrib(display, config, EGL_STENCIL_SIZE); + view->hints[PUGL_SAMPLES] = + puglWasmGlGetAttrib(display, config, EGL_SAMPLES); + + // double-buffering is always enabled for EGL + view->hints[PUGL_DOUBLE_BUFFER] = 1; + + return PUGL_SUCCESS; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglWasmGlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) +{ + PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; + if (!surface || !surface->context || !surface->surface) { + return PUGL_FAILURE; + } + +#ifndef PUGL_WASM_SINGLE_EGL_CONTEXT + return eglMakeCurrent(surface->display, surface->surface, surface->surface, surface->context) ? PUGL_SUCCESS : PUGL_FAILURE; +#else + return PUGL_SUCCESS; +#endif +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglWasmGlLeave(PuglView* view, const PuglExposeEvent* expose) +{ + PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; + + if (expose) { // note: swap buffers always enabled for EGL + eglSwapBuffers(surface->display, surface->surface); + } + +#ifndef PUGL_WASM_SINGLE_EGL_CONTEXT + return eglMakeCurrent(surface->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) ? PUGL_SUCCESS : PUGL_FAILURE; +#else + return PUGL_SUCCESS; +#endif +} + +static PuglStatus +puglWasmGlCreate(PuglView* view) +{ + PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; + const EGLDisplay display = surface->display; + const EGLConfig config = surface->config; + + const EGLint attrs[] = { + EGL_CONTEXT_CLIENT_VERSION, + view->hints[PUGL_CONTEXT_VERSION_MAJOR], + + EGL_CONTEXT_MAJOR_VERSION, + view->hints[PUGL_CONTEXT_VERSION_MAJOR], + + /* + EGL_CONTEXT_MINOR_VERSION, + view->hints[PUGL_CONTEXT_VERSION_MINOR], + + EGL_CONTEXT_OPENGL_DEBUG, + (view->hints[PUGL_USE_DEBUG_CONTEXT] ? EGL_TRUE : EGL_FALSE), + + EGL_CONTEXT_OPENGL_PROFILE_MASK, + (view->hints[PUGL_USE_COMPAT_PROFILE] + ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT + : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT), + */ + + EGL_NONE + }; + + surface->context = eglCreateContext(display, config, EGL_NO_CONTEXT, attrs); + + if (surface->context == EGL_NO_CONTEXT) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + surface->surface = eglCreateWindowSurface(display, config, 0, NULL); + + if (surface->surface == EGL_NO_SURFACE) { + return PUGL_CREATE_CONTEXT_FAILED; + } + +#ifdef PUGL_WASM_SINGLE_EGL_CONTEXT + eglMakeCurrent(surface->display, surface->surface, surface->surface, surface->context); +#endif + + return PUGL_SUCCESS; +} + +static void +puglWasmGlDestroy(PuglView* view) +{ + PuglWasmGlSurface* surface = (PuglWasmGlSurface*)view->impl->surface; + if (surface) { + const EGLDisplay display = surface->display; + if (surface->surface != EGL_NO_SURFACE) + eglDestroySurface(display, surface->surface); + if (surface->context != EGL_NO_CONTEXT) + eglDestroyContext(display, surface->context); + eglTerminate(display); + free(surface); + view->impl->surface = NULL; + } +} + +const PuglBackend* +puglGlBackend(void) +{ + static const PuglBackend backend = {puglWasmGlConfigure, + puglWasmGlCreate, + puglWasmGlDestroy, + puglWasmGlEnter, + puglWasmGlLeave, + puglStubGetContext}; + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-extra/wasm_stub.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,24 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "pugl/stub.h" + +#include "../pugl-upstream/src/stub.h" + +#include "pugl/pugl.h" + +const PuglBackend* +puglStubBackend(void) +{ + static const PuglBackend backend = { + puglStubConfigure, + puglStubCreate, + puglStubDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext, + }; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.clang-format --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.clang-format Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,29 @@ +--- +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlinesLeft: true +BasedOnStyle: Mozilla +BraceWrapping: + AfterNamespace: false + AfterClass: true + AfterEnum: false + AfterExternBlock: false + AfterFunction: true + AfterStruct: false + SplitEmptyFunction: false + SplitEmptyRecord: false +BreakBeforeBraces: Custom +Cpp11BracedListStyle: true +IndentCaseLabels: false +IndentPPDirectives: AfterHash +KeepEmptyLinesAtTheStartOfBlocks: false +SpacesInContainerLiterals: false +StatementMacros: + - PUGL_API + - PUGL_CONST_API + - PUGL_CONST_FUNC + - PUGL_DEPRECATED_BY + - PUGL_UNUSED + - PUGL_WARN_UNUSED_RESULT + - _Pragma +... diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.clant.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.clant.json Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,13 @@ +{ + "version": "1.0.0", + "include_dirs": [ + "bindings/cpp/include", + "include" + ], + "exclude_patterns": [ + "glad\\.c" + ], + "mapping_files": [ + ".includes.imp" + ] +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.editorconfig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.editorconfig Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,19 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{c,h,m,cpp,hpp,mm,glsl,frag,vert}] +indent_style = space +indent_size = 2 + +[*.py] +indent_style = space +indent_size = 4 + +[doc/**.{html,xml,css}] +indent_style = space +indent_size = 2 diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.gitignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.gitignore Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3 @@ +build/ +__pycache__ +*.pyc diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.gitlab-ci.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.gitlab-ci.yml Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,153 @@ +stages: + - build + - deploy + +.build_template: &build_definition + stage: build + +arm32_dbg: + <<: *build_definition + image: lv2plugin/debian-arm32 + script: + - meson setup build --cross-file=/usr/share/meson/cross/arm-linux-gnueabihf.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + +arm32_rel: + <<: *build_definition + image: lv2plugin/debian-arm32 + script: + - meson setup build --cross-file=/usr/share/meson/cross/arm-linux-gnueabihf.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + + +arm64_dbg: + <<: *build_definition + image: lv2plugin/debian-arm64 + script: + - meson setup build --cross-file=/usr/share/meson/cross/aarch64-linux-gnu.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + +arm64_rel: + <<: *build_definition + image: lv2plugin/debian-arm64 + script: + - meson setup build --cross-file=/usr/share/meson/cross/aarch64-linux-gnu.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + + +x64_dbg: + <<: *build_definition + image: lv2plugin/debian-x64 + script: + - meson setup build -Dbuildtype=debug -Ddocs=enabled -Dstrict=true -Dwerror=true + - ninja -C build + artifacts: + paths: + - build/doc + +x64_rel: + <<: *build_definition + image: lv2plugin/debian-x64 + script: + - meson setup build -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + + +x64_static: + <<: *build_definition + image: lv2plugin/debian-x64 + script: + - meson setup build -Ddefault_library=static -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + + +x64_sanitize: + <<: *build_definition + image: lv2plugin/debian-x64-clang + script: + - meson setup build -Db_lundef=false -Dbuildtype=plain -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + variables: + CC: "clang" + CXX: "clang++" + CFLAGS: "-fno-sanitize-recover=all -fsanitize=address -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability" + CXXFLAGS: "-fno-sanitize-recover=all -fsanitize=address -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability" + LDFLAGS: "-fno-sanitize-recover=all -fsanitize=address -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=unsigned-integer-overflow -fsanitize=implicit-conversion -fsanitize=local-bounds -fsanitize=nullability" + + +mingw32_dbg: + <<: *build_definition + image: lv2plugin/debian-mingw32 + script: + - meson setup build --cross-file=/usr/share/meson/cross/i686-w64-mingw32.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + +mingw32_rel: + <<: *build_definition + image: lv2plugin/debian-mingw32 + script: + - meson setup build --cross-file=/usr/share/meson/cross/i686-w64-mingw32.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + + +mingw64_dbg: + <<: *build_definition + image: lv2plugin/debian-mingw64 + script: + - meson setup build --cross-file=/usr/share/meson/cross/x86_64-w64-mingw32.ini -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + +mingw64_rel: + <<: *build_definition + image: lv2plugin/debian-mingw64 + script: + - meson setup build --cross-file=/usr/share/meson/cross/x86_64-w64-mingw32.ini -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + + +mac_dbg: + <<: *build_definition + tags: [macos] + script: + - meson setup build -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + +mac_rel: + <<: *build_definition + tags: [macos] + script: + - meson setup build -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + + +win_dbg: + <<: *build_definition + tags: [windows,meson] + script: + - meson setup build -Dbuildtype=debug -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + +win_rel: + <<: *build_definition + tags: [windows,meson] + script: + - meson setup build -Dbuildtype=release -Ddocs=disabled -Dstrict=true -Dwerror=true + - ninja -C build + +pages: + stage: deploy + script: + - mkdir public + - mkdir public/c + - mkdir public/cpp + - mv build/doc/c/singlehtml/ public/c/singlehtml/ + - mv build/doc/cpp/singlehtml/ public/cpp/singlehtml/ + - mv build/doc/c/html/ public/c/html/ + - mv build/doc/cpp/html/ public/cpp/html/ + dependencies: + - x64_dbg + artifacts: + paths: + - public + only: + - master diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.includes.imp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.includes.imp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,7 @@ +[ + { "include": [ "", "private", "", "public", ] }, + { "include": [ "", "private", "", "public", ] }, + { "symbol": [ "std::uintptr_t", "private", "", "public" ] }, + { "symbol": [ "timespec", "private", "", "public" ] }, + { "symbol": [ "timeval", "private", "", "public" ] } +] diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.reuse/dep5 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/.reuse/dep5 Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,16 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: pugl +Upstream-Contact: David Robillard +Source: https://gitlab.com/lv2/pugl + +Files: **/meson.build *.md */.clang* .clang* .clant.json .editorconfig .git* .includes.imp AUTHORS doc/*.in meson_options.txt resources/Info.plist.in +Copyright: 2021 David Robillard +License: CC0-1.0 OR ISC + +Files: doc/*.rst examples/glad/glad.c examples/glad/glad.h resources/pugl.ipe resources/pugl.png resources/pugl.svg +Copyright: 2021 David Robillard +License: ISC + +Files: examples/glad/khrplatform.h +Copyright: 2008-2018 The Khronos Group Inc. +License: MIT diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/AUTHORS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/AUTHORS Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,13 @@ +Pugl is primarily written and maintained by David Robillard +with contributions from (in increasing chronological order): + +Ben Loftis +Robin Gareus +Erik Ã…ldstedt Sund +Hanspeter Portner +Stefan Westerfeld +Jordan Halase +Oliver Schmidt +Zoë Sparks +Jean Pierre Cimalando +Thomas Brand diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/COPYING Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,13 @@ +Copyright 2011-2021 David Robillard + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/LICENSES/CC0-1.0.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/LICENSES/CC0-1.0.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/LICENSES/ISC.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/LICENSES/ISC.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,11 @@ +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/LICENSES/MIT.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/LICENSES/MIT.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,17 @@ +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 -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/README.md Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,72 @@ +Pugl +==== + +Pugl (PlUgin Graphics Library) is a minimal portability layer for GUIs which is +suitable for use in plugins. It works on X11, MacOS, and Windows, and includes +optional support for drawing with Vulkan, OpenGL, and Cairo. + +Pugl is vaguely similar to libraries like GLUT and GLFW, but has different +goals and priorities: + + * Minimal in scope, providing only a thin interface to isolate + platform-specific details from applications. + + * Zero dependencies, aside from standard system libraries. + + * Support for embedding in native windows, for example as a plugin or + component within a larger application that is not based on Pugl. + + * Explicit context and no static data, so that several instances can be used + within a single program at once. + + * Consistent event-based API that makes dispatching in application or toolkit + code easy with minimal boilerplate. + + * Suitable for both continuously rendering applications like games, and + event-driven applications that only draw when necessary. + + * Small, liberally licensed implementation that is suitable for vendoring + and/or static linking. Pugl can be installed as a library, or used by + simply copying the implementation into a project. + +Stability +--------- + +Pugl is currently being developed towards a long-term stable API. For the time +being, however, the API may break occasionally. Please report any relevant +feedback, or file feature requests, so that we can ensure that the released API +is stable for as long as possible. + +When the API changes, backwards compatibility is maintained where possible. +These compatibility shims will be removed before release, so users are +encouraged to build with `PUGL_DISABLE_DEPRECATED` defined. + +Documentation +------------- + +Pugl is a C library that includes C++ bindings. +Each API is documented separately: + + * [C Documentation (single page)](https://lv2.gitlab.io/pugl/c/singlehtml/) + * [C Documentation (paginated)](https://lv2.gitlab.io/pugl/c/html/) + * [C++ Documentation (single page)](https://lv2.gitlab.io/pugl/cpp/singlehtml/) + * [C++ Documentation (paginated)](https://lv2.gitlab.io/pugl/cpp/html/) + +The documentation will also be built from the source if the `docs` +configuration option is enabled, and both Doxygen and Sphinx are available. + +Testing +------- + +Some unit tests are included, but unfortunately manual testing is still +required. The tests and example programs are built by default. You can run +all the tests at once via ninja: + + meson setup build + cd build + ninja test + +The [examples](examples) directory contains several demonstration programs that +can be used for manual testing. + + -- David Robillard diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/.clang-tidy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/.clang-tidy Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,10 @@ +Checks: > + *, + -*-magic-numbers, + -*-uppercase-literal-suffix, + -altera*, + -clang-diagnostic-unused-function, + -clang-diagnostic-unused-macros, + -llvmlibc-*, +FormatStyle: file +HeaderFilterRegex: 'pugl/.*' diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/meson.build --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/meson.build Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,15 @@ +# Copyright 2021 David Robillard +# SPDX-License-Identifier: CC0-1.0 OR ISC + +c_headers = [ + 'pugl/pugl.h', + + 'pugl/cairo.h', + 'pugl/gl.h', + 'pugl/stub.h', + 'pugl/vulkan.h', +] + +c_header_files = files(c_headers) + +install_headers(c_headers, subdir: versioned_name / 'pugl') diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/cairo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/cairo.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,33 @@ +// Copyright 2012-2020 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_CAIRO_H +#define PUGL_CAIRO_H + +#include "pugl/pugl.h" + +PUGL_BEGIN_DECLS + +/** + @defgroup cairo Cairo + Cairo graphics support. + @ingroup pugl + @{ +*/ + +/** + Cairo graphics backend accessor. + + Pass the returned value to puglSetBackend() to draw to a view with Cairo. +*/ +PUGL_CONST_API +const PuglBackend* +puglCairoBackend(void); + +/** + @} +*/ + +PUGL_END_DECLS + +#endif // PUGL_CAIRO_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/gl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/gl.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,94 @@ +// Copyright 2012-2020 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_GL_H +#define PUGL_GL_H + +#include "pugl/pugl.h" + +// IWYU pragma: begin_exports + +/* Unfortunately, GL includes vary across platforms, so include them here to + enable pure portable programs. */ + +#ifndef PUGL_NO_INCLUDE_GL_H +# ifdef __APPLE__ +# include +# else +# ifdef _WIN32 +# include +# endif +# include +# endif +#endif + +#ifndef PUGL_NO_INCLUDE_GLU_H +# ifdef __APPLE__ +# include +# else +# ifdef _WIN32 +# include +# endif +# include +# endif +#endif + +// IWYU pragma: end_exports + +PUGL_BEGIN_DECLS + +/** + @defgroup gl OpenGL + OpenGL graphics support. + @ingroup pugl + @{ +*/ + +/** + OpenGL extension function. +*/ +typedef void (*PuglGlFunc)(void); + +/** + Return the address of an OpenGL extension function. +*/ +PUGL_API +PuglGlFunc +puglGetProcAddress(const char* name); + +/** + Enter the OpenGL context. + + This can be used to enter the graphics context in unusual situations, for + doing things like loading textures. Note that this must not be used for + drawing, which may only be done while processing an expose event. +*/ +PUGL_API +PuglStatus +puglEnterContext(PuglView* view); + +/** + Leave the OpenGL context. + + This must only be called after puglEnterContext(). +*/ +PUGL_API +PuglStatus +puglLeaveContext(PuglView* view); + +/** + OpenGL graphics backend. + + Pass the returned value to puglSetBackend() to draw to a view with OpenGL. +*/ +PUGL_CONST_API +const PuglBackend* +puglGlBackend(void); + +PUGL_END_DECLS + +/** + @} +*/ + +#endif // PUGL_GL_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/pugl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/pugl.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1932 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_PUGL_H +#define PUGL_PUGL_H + +#include +#include + +#ifndef __cplusplus +# include +#endif + +#ifndef PUGL_API +# if defined(_WIN32) && !defined(PUGL_STATIC) && defined(PUGL_INTERNAL) +# define PUGL_API __declspec(dllexport) +# elif defined(_WIN32) && !defined(PUGL_STATIC) +# define PUGL_API __declspec(dllimport) +# elif defined(__GNUC__) +# define PUGL_API __attribute__((visibility("default"))) +# else +# define PUGL_API +# endif +#endif + +#ifndef PUGL_DISABLE_DEPRECATED +# if defined(__clang__) +# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("", rep))) +# elif defined(__GNUC__) +# define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("Use " rep))) +# else +# define PUGL_DEPRECATED_BY(rep) +# endif +#endif + +#if defined(__GNUC__) +# define PUGL_CONST_FUNC __attribute__((const)) +#else +# define PUGL_CONST_FUNC +#endif + +#define PUGL_CONST_API \ + PUGL_API \ + PUGL_CONST_FUNC + +#define PUGL_BEGIN_DECLS +#define PUGL_END_DECLS + +PUGL_BEGIN_DECLS + +/** + @defgroup pugl Pugl C API + Pugl C API. + @{ +*/ + +/** + A pixel coordinate within/of a view. + + This is relative to the top left corner of the view's parent, or to the top + left corner of the view itself, depending on the context. + + There are platform-imposed limits on window positions. For portability, + applications should keep coordinates between -16000 and 16000. Note that + negative frame coordinates are possible, for example with multiple screens. +*/ +typedef int16_t PuglCoord; + +/** + A pixel span (width or height) within/of a view. + + Due to platform limits, the span of a view in either dimension should be + between 1 and 10000. +*/ +typedef uint16_t PuglSpan; + +/** + A rectangle in a view or on the screen. + + This type is used to describe two things: the position and size of a view + (for configuring), or a rectangle within a view (for exposing). + + The coordinate (0, 0) represents the top-left pixel of the parent window (or + display if there isn't one), or the top-left pixel of the view, + respectively. +*/ +typedef struct { + PuglCoord x; + PuglCoord y; + PuglSpan width; + PuglSpan height; +} PuglRect; + +/** + @defgroup events Events + + All updates to the view happen via events, which are dispatched to the + view's event function. Most events map directly to one from the underlying + window system, but some are constructed by Pugl itself so there is not + necessarily a direct correspondence. + + @{ +*/ + +/// Keyboard modifier flags +typedef enum { + PUGL_MOD_SHIFT = 1u << 0u, ///< Shift key + PUGL_MOD_CTRL = 1u << 1u, ///< Control key + PUGL_MOD_ALT = 1u << 2u, ///< Alt/Option key + PUGL_MOD_SUPER = 1u << 3u ///< Mod4/Command/Windows key +} PuglMod; + +/// Bitwise OR of #PuglMod values +typedef uint32_t PuglMods; + +/** + Keyboard key codepoints. + + All keys are identified by a Unicode code point in PuglKeyEvent::key. This + enumeration defines constants for special keys that do not have a standard + code point, and some convenience constants for control characters. Note + that all keys are handled in the same way, this enumeration is just for + convenience when writing hard-coded key bindings. + + Keys that do not have a standard code point use values in the Private Use + Area in the Basic Multilingual Plane (`U+E000` to `U+F8FF`). Applications + must take care to not interpret these values beyond key detection, the + mapping used here is arbitrary and specific to Pugl. +*/ +typedef enum { + // ASCII control codes + PUGL_KEY_BACKSPACE = 0x08, + PUGL_KEY_ESCAPE = 0x1B, + PUGL_KEY_DELETE = 0x7F, + + // Unicode Private Use Area + PUGL_KEY_F1 = 0xE000, + PUGL_KEY_F2, + PUGL_KEY_F3, + PUGL_KEY_F4, + PUGL_KEY_F5, + PUGL_KEY_F6, + PUGL_KEY_F7, + PUGL_KEY_F8, + PUGL_KEY_F9, + PUGL_KEY_F10, + PUGL_KEY_F11, + PUGL_KEY_F12, + PUGL_KEY_LEFT, + PUGL_KEY_UP, + PUGL_KEY_RIGHT, + PUGL_KEY_DOWN, + PUGL_KEY_PAGE_UP, + PUGL_KEY_PAGE_DOWN, + PUGL_KEY_HOME, + PUGL_KEY_END, + PUGL_KEY_INSERT, + PUGL_KEY_SHIFT, + PUGL_KEY_SHIFT_L = PUGL_KEY_SHIFT, + PUGL_KEY_SHIFT_R, + PUGL_KEY_CTRL, + PUGL_KEY_CTRL_L = PUGL_KEY_CTRL, + PUGL_KEY_CTRL_R, + PUGL_KEY_ALT, + PUGL_KEY_ALT_L = PUGL_KEY_ALT, + PUGL_KEY_ALT_R, + PUGL_KEY_SUPER, + PUGL_KEY_SUPER_L = PUGL_KEY_SUPER, + PUGL_KEY_SUPER_R, + PUGL_KEY_MENU, + PUGL_KEY_CAPS_LOCK, + PUGL_KEY_SCROLL_LOCK, + PUGL_KEY_NUM_LOCK, + PUGL_KEY_PRINT_SCREEN, + PUGL_KEY_PAUSE +} PuglKey; + +/// The type of a PuglEvent +typedef enum { + PUGL_NOTHING, ///< No event + PUGL_CREATE, ///< View created, a #PuglCreateEvent + PUGL_DESTROY, ///< View destroyed, a #PuglDestroyEvent + PUGL_CONFIGURE, ///< View moved/resized, a #PuglConfigureEvent + PUGL_MAP, ///< View made visible, a #PuglMapEvent + PUGL_UNMAP, ///< View made invisible, a #PuglUnmapEvent + PUGL_UPDATE, ///< View ready to draw, a #PuglUpdateEvent + PUGL_EXPOSE, ///< View must be drawn, a #PuglExposeEvent + PUGL_CLOSE, ///< View will be closed, a #PuglCloseEvent + PUGL_FOCUS_IN, ///< Keyboard focus entered view, a #PuglFocusEvent + PUGL_FOCUS_OUT, ///< Keyboard focus left view, a #PuglFocusEvent + PUGL_KEY_PRESS, ///< Key pressed, a #PuglKeyEvent + PUGL_KEY_RELEASE, ///< Key released, a #PuglKeyEvent + PUGL_TEXT, ///< Character entered, a #PuglTextEvent + PUGL_POINTER_IN, ///< Pointer entered view, a #PuglCrossingEvent + PUGL_POINTER_OUT, ///< Pointer left view, a #PuglCrossingEvent + PUGL_BUTTON_PRESS, ///< Mouse button pressed, a #PuglButtonEvent + PUGL_BUTTON_RELEASE, ///< Mouse button released, a #PuglButtonEvent + PUGL_MOTION, ///< Pointer moved, a #PuglMotionEvent + PUGL_SCROLL, ///< Scrolled, a #PuglScrollEvent + PUGL_CLIENT, ///< Custom client message, a #PuglClientEvent + PUGL_TIMER, ///< Timer triggered, a #PuglTimerEvent + PUGL_LOOP_ENTER, ///< Recursive loop entered, a #PuglLoopEnterEvent + PUGL_LOOP_LEAVE, ///< Recursive loop left, a #PuglLoopLeaveEvent + PUGL_DATA_OFFER, ///< Data offered from clipboard, a #PuglDataOfferEvent + PUGL_DATA, ///< Data available from clipboard, a #PuglDataEvent +} PuglEventType; + +/// Common flags for all event types +typedef enum { + PUGL_IS_SEND_EVENT = 1, ///< Event is synthetic + PUGL_IS_HINT = 2 ///< Event is a hint (not direct user input) +} PuglEventFlag; + +/// Bitwise OR of #PuglEventFlag values +typedef uint32_t PuglEventFlags; + +/// Reason for a PuglCrossingEvent +typedef enum { + PUGL_CROSSING_NORMAL, ///< Crossing due to pointer motion + PUGL_CROSSING_GRAB, ///< Crossing due to a grab + PUGL_CROSSING_UNGRAB ///< Crossing due to a grab release +} PuglCrossingMode; + +/** + Scroll direction. + + Describes the direction of a #PuglScrollEvent along with whether the scroll + is a "smooth" scroll. The discrete directions are for devices like mouse + wheels with constrained axes, while a smooth scroll is for those with + arbitrary scroll direction freedom, like some touchpads. +*/ +typedef enum { + PUGL_SCROLL_UP, ///< Scroll up + PUGL_SCROLL_DOWN, ///< Scroll down + PUGL_SCROLL_LEFT, ///< Scroll left + PUGL_SCROLL_RIGHT, ///< Scroll right + PUGL_SCROLL_SMOOTH ///< Smooth scroll in any direction +} PuglScrollDirection; + +/// Common header for all event structs +typedef struct { + PuglEventType type; ///< Event type + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values +} PuglAnyEvent; + +/** + View create event. + + This event is sent when a view is realized before it is first displayed, + with the graphics context entered. This is typically used for setting up + the graphics system, for example by loading OpenGL extensions. + + This event type has no extra fields. +*/ +typedef PuglAnyEvent PuglCreateEvent; + +/** + View destroy event. + + This event is the counterpart to #PuglCreateEvent, and it is sent when the + view is being destroyed. This is typically used for tearing down the + graphics system, or otherwise freeing any resources allocated when the + create event was handled. + + This is the last event sent to any view, and immediately after it is + processed, the view is destroyed and may no longer be used. + + This event type has no extra fields. +*/ +typedef PuglAnyEvent PuglDestroyEvent; + +/** + View resize or move event. + + A configure event is sent whenever the view is resized or moved. When a + configure event is received, the graphics context is active but not set up + for drawing. For example, it is valid to adjust the OpenGL viewport or + otherwise configure the context, but not to draw anything. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_CONFIGURE + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + PuglCoord x; ///< Parent-relative X coordinate of view + PuglCoord y; ///< Parent-relative Y coordinate of view + PuglSpan width; ///< Width of view + PuglSpan height; ///< Height of view +} PuglConfigureEvent; + +/** + View show event. + + This event is sent when a view is mapped to the screen and made visible. + + This event type has no extra fields. +*/ +typedef PuglAnyEvent PuglMapEvent; + +/** + View hide event. + + This event is sent when a view is unmapped from the screen and made + invisible. + + This event type has no extra fields. +*/ +typedef PuglAnyEvent PuglUnmapEvent; + +/** + View update event. + + This event is sent to every view near the end of a main loop iteration when + any pending exposures are about to be redrawn. It is typically used to mark + regions to expose with puglPostRedisplay() or puglPostRedisplayRect(). For + example, to continuously animate, a view calls puglPostRedisplay() when an + update event is received, and it will then shortly receive an expose event. +*/ +typedef PuglAnyEvent PuglUpdateEvent; + +/** + Expose event for when a region must be redrawn. + + When an expose event is received, the graphics context is active, and the + view must draw the entire specified region. The contents of the region are + undefined, there is no preservation of anything drawn previously. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_EXPOSE + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + PuglCoord x; ///< View-relative top-left X coordinate of region + PuglCoord y; ///< View-relative top-left Y coordinate of region + PuglSpan width; ///< Width of exposed region + PuglSpan height; ///< Height of exposed region +} PuglExposeEvent; + +/** + View close event. + + This event is sent when the view is to be closed, for example when the user + clicks the close button. + + This event type has no extra fields. +*/ +typedef PuglAnyEvent PuglCloseEvent; + +/** + Keyboard focus event. + + This event is sent whenever the view gains or loses the keyboard focus. The + view with the keyboard focus will receive any key press or release events. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_FOCUS_IN or #PUGL_FOCUS_OUT + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + PuglCrossingMode mode; ///< Reason for focus change +} PuglFocusEvent; + +/** + Key press or release event. + + This event represents low-level key presses and releases. This can be used + for "direct" keyboard handing like key bindings, but must not be interpreted + as text input. + + Keys are represented portably as Unicode code points, using the "natural" + code point for the key where possible (see #PuglKey for details). The `key` + field is the code for the pressed key, without any modifiers applied. For + example, a press or release of the 'A' key will have `key` 97 ('a') + regardless of whether shift or control are being held. + + Alternatively, the raw `keycode` can be used to work directly with physical + keys, but note that this value is not portable and differs between platforms + and hardware. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_KEY_PRESS or #PUGL_KEY_RELEASE + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds + double x; ///< View-relative X coordinate + double y; ///< View-relative Y coordinate + double xRoot; ///< Root-relative X coordinate + double yRoot; ///< Root-relative Y coordinate + PuglMods state; ///< Bitwise OR of #PuglMod flags + uint32_t keycode; ///< Raw key code + uint32_t key; ///< Unshifted Unicode character code, or 0 +} PuglKeyEvent; + +/** + Character input event. + + This event represents text input, usually as the result of a key press. The + text is given both as a Unicode character code and a UTF-8 string. + + Note that this event is generated by the platform's input system, so there + is not necessarily a direct correspondence between text events and physical + key presses. For example, with some input methods a sequence of several key + presses will generate a single character. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_TEXT + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds + double x; ///< View-relative X coordinate + double y; ///< View-relative Y coordinate + double xRoot; ///< Root-relative X coordinate + double yRoot; ///< Root-relative Y coordinate + PuglMods state; ///< Bitwise OR of #PuglMod flags + uint32_t keycode; ///< Raw key code + uint32_t character; ///< Unicode character code + char string[8]; ///< UTF-8 string +} PuglTextEvent; + +/** + Pointer enter or leave event. + + This event is sent when the pointer enters or leaves the view. This can + happen for several reasons (not just the user dragging the pointer over the + window edge), as described by the `mode` field. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_POINTER_IN or #PUGL_POINTER_OUT + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds + double x; ///< View-relative X coordinate + double y; ///< View-relative Y coordinate + double xRoot; ///< Root-relative X coordinate + double yRoot; ///< Root-relative Y coordinate + PuglMods state; ///< Bitwise OR of #PuglMod flags + PuglCrossingMode mode; ///< Reason for crossing +} PuglCrossingEvent; + +/** + Button press or release event. + + Button numbers start from 0, and are ordered: primary, secondary, middle. + So, on a typical right-handed mouse, the button numbers are: + + Left: 0 + Right: 1 + Middle (often a wheel): 2 + + Higher button numbers are reported in the same order they are represented on + the system. There is no universal standard here, but buttons 3 and 4 are + typically a pair of buttons or a rocker, which are usually bound to "back" + and "forward" operations. + + Note that these numbers may differ from those used on the underlying + platform, since they are manipulated to provide a consistent portable API. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_BUTTON_PRESS or #PUGL_BUTTON_RELEASE + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds + double x; ///< View-relative X coordinate + double y; ///< View-relative Y coordinate + double xRoot; ///< Root-relative X coordinate + double yRoot; ///< Root-relative Y coordinate + PuglMods state; ///< Bitwise OR of #PuglMod flags + uint32_t button; ///< Button number starting from 0 +} PuglButtonEvent; + +/** + Pointer motion event. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_MOTION + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds + double x; ///< View-relative X coordinate + double y; ///< View-relative Y coordinate + double xRoot; ///< Root-relative X coordinate + double yRoot; ///< Root-relative Y coordinate + PuglMods state; ///< Bitwise OR of #PuglMod flags +} PuglMotionEvent; + +/** + Scroll event. + + The scroll distance is expressed in "lines", an arbitrary unit that + corresponds to a single tick of a detented mouse wheel. For example, `dy` = + 1.0 scrolls 1 line up. Some systems and devices support finer resolution + and/or higher values for fast scrolls, so programs should handle any value + gracefully. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_SCROLL + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds + double x; ///< View-relative X coordinate + double y; ///< View-relative Y coordinate + double xRoot; ///< Root-relative X coordinate + double yRoot; ///< Root-relative Y coordinate + PuglMods state; ///< Bitwise OR of #PuglMod flags + PuglScrollDirection direction; ///< Scroll direction + double dx; ///< Scroll X distance in lines + double dy; ///< Scroll Y distance in lines +} PuglScrollEvent; + +/** + Custom client message event. + + This can be used to send a custom message to a view, which is delivered via + the window system and processed in the event loop as usual. Among other + things, this makes it possible to wake up the event loop for any reason. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_CLIENT + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + uintptr_t data1; ///< Client-specific data + uintptr_t data2; ///< Client-specific data +} PuglClientEvent; + +/** + Timer event. + + This event is sent at the regular interval specified in the call to + puglStartTimer() that activated it. + + The `id` is the application-specific ID given to puglStartTimer() which + distinguishes this timer from others. It should always be checked in the + event handler, even in applications that register only one timer. +*/ +typedef struct { + PuglEventType type; ///< #PUGL_TIMER + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + uintptr_t id; ///< Timer ID +} PuglTimerEvent; + +/** + Clipboard data offer event. + + This event is sent when a clipboard has data present, possibly with several + datatypes. While handling this event, the types can be investigated with + puglGetClipboardType() to decide whether to accept the offer with + puglAcceptOffer(). +*/ +typedef struct { + PuglEventType type; ///< #PUGL_DATA_OFFER + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds +} PuglDataOfferEvent; + +/** + Clipboard data event. + + This event is sent after accepting a data offer when the data has been + retrieved and converted. While handling this event, the data can be + accessed with puglGetClipboard(). +*/ +typedef struct { + PuglEventType type; ///< #PUGL_DATA + PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values + double time; ///< Time in seconds + uint32_t typeIndex; ///< Index of datatype +} PuglDataEvent; + +/** + Recursive loop enter event. + + This event is sent when the window system enters a recursive loop. The main + loop will be stalled and no expose events will be received while in the + recursive loop. To give the application full control, Pugl does not do any + special handling of this situation, but this event can be used to install a + timer to perform continuous actions (such as drawing) on platforms that do + this. + + - MacOS: A recursive loop is entered while the window is being live resized. + + - Windows: A recursive loop is entered while the window is being live + resized or the menu is shown. + + - X11: A recursive loop is never entered and the event loop runs as usual + while the view is being resized. + + This event type has no extra fields. +*/ +typedef PuglAnyEvent PuglLoopEnterEvent; + +/** + Recursive loop leave event. + + This event is sent after a loop enter event when the recursive loop is + finished and normal iteration will continue. + + This event type has no extra fields. +*/ +typedef PuglAnyEvent PuglLoopLeaveEvent; + +/** + View event. + + This is a union of all event types. The type must be checked to determine + which fields are safe to access. A pointer to PuglEvent can either be cast + to the appropriate type, or the union members used. + + The graphics system may only be accessed when handling certain events. The + graphics context is active for #PUGL_CREATE, #PUGL_DESTROY, #PUGL_CONFIGURE, + and #PUGL_EXPOSE, but only enabled for drawing for #PUGL_EXPOSE. +*/ +typedef union { + PuglAnyEvent any; ///< Valid for all event types + PuglEventType type; ///< Event type + PuglButtonEvent button; ///< #PUGL_BUTTON_PRESS, #PUGL_BUTTON_RELEASE + PuglConfigureEvent configure; ///< #PUGL_CONFIGURE + PuglExposeEvent expose; ///< #PUGL_EXPOSE + PuglKeyEvent key; ///< #PUGL_KEY_PRESS, #PUGL_KEY_RELEASE + PuglTextEvent text; ///< #PUGL_TEXT + PuglCrossingEvent crossing; ///< #PUGL_POINTER_IN, #PUGL_POINTER_OUT + PuglMotionEvent motion; ///< #PUGL_MOTION + PuglScrollEvent scroll; ///< #PUGL_SCROLL + PuglFocusEvent focus; ///< #PUGL_FOCUS_IN, #PUGL_FOCUS_OUT + PuglClientEvent client; ///< #PUGL_CLIENT + PuglTimerEvent timer; ///< #PUGL_TIMER + PuglDataOfferEvent offer; ///< #PUGL_DATA_OFFER + PuglDataEvent data; ///< #PUGL_DATA +} PuglEvent; + +/** + @} + @defgroup status Status + + Most functions return a status code which can be used to check for errors. + + @{ +*/ + +/// Return status code +typedef enum { + PUGL_SUCCESS, ///< Success + PUGL_FAILURE, ///< Non-fatal failure + PUGL_UNKNOWN_ERROR, ///< Unknown system error + PUGL_BAD_BACKEND, ///< Invalid or missing backend + PUGL_BAD_CONFIGURATION, ///< Invalid view configuration + PUGL_BAD_PARAMETER, ///< Invalid parameter + PUGL_BACKEND_FAILED, ///< Backend initialization failed + PUGL_REGISTRATION_FAILED, ///< Class registration failed + PUGL_REALIZE_FAILED, ///< System view realization failed + PUGL_SET_FORMAT_FAILED, ///< Failed to set pixel format + PUGL_CREATE_CONTEXT_FAILED, ///< Failed to create drawing context + PUGL_UNSUPPORTED, ///< Unsupported operation + PUGL_NO_MEMORY, ///< Failed to allocate memory +} PuglStatus; + +/// Return a string describing a status code +PUGL_CONST_API +const char* +puglStrerror(PuglStatus status); + +/** + @} + @defgroup world World + + The top-level context of a Pugl application or plugin. + + The world contains all library-wide state. There is no static data in Pugl, + so it is safe to use multiple worlds in a single process. This is to + facilitate plugins or other situations where it is not possible to share a + world, but a single world should be shared for all views where possible. + + @{ +*/ + +/** + The "world" of application state. + + The world represents everything that is not associated with a particular + view. Several worlds can be created in a single process, but code using + different worlds must be isolated so they are never mixed. Views are + strongly associated with the world they were created in. +*/ +typedef struct PuglWorldImpl PuglWorld; + +/// Handle for the world's opaque user data +typedef void* PuglWorldHandle; + +/// The type of a World +typedef enum { + PUGL_PROGRAM, ///< Top-level application + PUGL_MODULE ///< Plugin or module within a larger application +} PuglWorldType; + +/// World flags +typedef enum { + /** + Set up support for threads if necessary. + + X11: Calls XInitThreads() which is required for some drivers. + */ + PUGL_WORLD_THREADS = 1u << 0u +} PuglWorldFlag; + +/// Bitwise OR of #PuglWorldFlag values +typedef uint32_t PuglWorldFlags; + +/** + Create a new world. + + @param type The type, which dictates what this world is responsible for. + @param flags Flags to control world features. + @return A new world, which must be later freed with puglFreeWorld(). +*/ +PUGL_API +PuglWorld* +puglNewWorld(PuglWorldType type, PuglWorldFlags flags); + +/// Free a world allocated with puglNewWorld() +PUGL_API +void +puglFreeWorld(PuglWorld* world); + +/** + Set the user data for the world. + + This is usually a pointer to a struct that contains all the state which must + be accessed by several views. + + The handle is opaque to Pugl and is not interpreted in any way. +*/ +PUGL_API +void +puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle); + +/// Get the user data for the world +PUGL_API +PuglWorldHandle +puglGetWorldHandle(PuglWorld* world); + +/** + Return a pointer to the native handle of the world. + + X11: Returns a pointer to the `Display`. + + MacOS: Returns a pointer to the `NSApplication`. + + Windows: Returns the `HMODULE` of the calling process. +*/ +PUGL_API +void* +puglGetNativeWorld(PuglWorld* world); + +/** + Set the class name of the application. + + This is a stable identifier for the application, used as the window + class/instance name on X11 and Windows. It is not displayed to the user, + but can be used in scripts and by window managers, so it should be the same + for every instance of the application, but different from other + applications. +*/ +PUGL_API +PuglStatus +puglSetClassName(PuglWorld* world, const char* name); + +/// Get the class name of the application, or null +PUGL_API +const char* +puglGetClassName(const PuglWorld* world); + +/** + Return the time in seconds. + + This is a monotonically increasing clock with high resolution. The returned + time is only useful to compare against other times returned by this + function, its absolute value has no meaning. +*/ +PUGL_API +double +puglGetTime(const PuglWorld* world); + +/** + Update by processing events from the window system. + + This function is a single iteration of the main loop, and should be called + repeatedly to update all views. + + If `timeout` is zero, then this function will not block. Plugins should + always use a timeout of zero to avoid blocking the host. + + If a positive `timeout` is given, then events will be processed for that + amount of time, starting from when this function was called. + + If a negative `timeout` is given, this function will block indefinitely + until an event occurs. + + For continuously animating programs, a timeout that is a reasonable fraction + of the ideal frame period should be used, to minimize input latency by + ensuring that as many input events are consumed as possible before drawing. + + @return #PUGL_SUCCESS if events are read, #PUGL_FAILURE if no events are + read, or an error. +*/ +PUGL_API +PuglStatus +puglUpdate(PuglWorld* world, double timeout); + +/** + @} + @defgroup view View + + A drawable region that receives events. + + A view can be thought of as a window, but does not necessarily correspond to + a top-level window in a desktop environment. For example, a view can be + embedded in some other window, or represent an embedded system where there + is no concept of multiple windows at all. + + @{ +*/ + +/// A drawable region that receives events +typedef struct PuglViewImpl PuglView; + +/** + A graphics backend. + + The backend dictates how graphics are set up for a view, and how drawing is + performed. A backend must be set by calling puglSetBackend() before + realising a view. + + If you are using a local copy of Pugl, it is possible to implement a custom + backend. See the definition of `PuglBackendImpl` in the source code for + details. +*/ +typedef struct PuglBackendImpl PuglBackend; + +/** + A native view handle. + + X11: This is a `Window`. + + MacOS: This is a pointer to an `NSView*`. + + Windows: This is a `HWND`. +*/ +typedef uintptr_t PuglNativeView; + +/// Handle for a view's opaque user data +typedef void* PuglHandle; + +/// A hint for configuring a view +typedef enum { + PUGL_USE_COMPAT_PROFILE, ///< Use compatible (not core) OpenGL profile + PUGL_USE_DEBUG_CONTEXT, ///< True to use a debug OpenGL context + PUGL_CONTEXT_VERSION_MAJOR, ///< OpenGL context major version + PUGL_CONTEXT_VERSION_MINOR, ///< OpenGL context minor version + PUGL_RED_BITS, ///< Number of bits for red channel + PUGL_GREEN_BITS, ///< Number of bits for green channel + PUGL_BLUE_BITS, ///< Number of bits for blue channel + PUGL_ALPHA_BITS, ///< Number of bits for alpha channel + PUGL_DEPTH_BITS, ///< Number of bits for depth buffer + PUGL_STENCIL_BITS, ///< Number of bits for stencil buffer + PUGL_SAMPLES, ///< Number of samples per pixel (AA) + PUGL_DOUBLE_BUFFER, ///< True if double buffering should be used + PUGL_SWAP_INTERVAL, ///< Number of frames between buffer swaps + PUGL_RESIZABLE, ///< True if view should be resizable + PUGL_IGNORE_KEY_REPEAT, ///< True if key repeat events are ignored + PUGL_REFRESH_RATE, ///< Refresh rate in Hz +} PuglViewHint; + +/// The number of #PuglViewHint values +#define PUGL_NUM_VIEW_HINTS ((unsigned)PUGL_REFRESH_RATE + 1u) + +/// A special view hint value +typedef enum { + PUGL_DONT_CARE = -1, ///< Use best available value + PUGL_FALSE = 0, ///< Explicitly false + PUGL_TRUE = 1 ///< Explicitly true +} PuglViewHintValue; + +/** + A hint for configuring/constraining the size of a view. + + The system will attempt to make the view's window adhere to these, but they + are suggestions, not hard constraints. Applications should handle any view + size gracefully. +*/ +typedef enum { + PUGL_DEFAULT_SIZE, ///< Default size + PUGL_MIN_SIZE, ///< Minimum size + PUGL_MAX_SIZE, ///< Maximum size + + /** + Fixed aspect ratio. + + If set, the view's size should be constrained to this aspect ratio. + Mutually exclusive with #PUGL_MIN_ASPECT and #PUGL_MAX_ASPECT. + */ + PUGL_FIXED_ASPECT, + + /** + Minimum aspect ratio. + + If set, the view's size should be constrained to an aspect ratio no lower + than this. Mutually exclusive with #PUGL_FIXED_ASPECT. + */ + PUGL_MIN_ASPECT, + + /** + Maximum aspect ratio. + + If set, the view's size should be constrained to an aspect ratio no higher + than this. Mutually exclusive with #PUGL_FIXED_ASPECT. + */ + PUGL_MAX_ASPECT +} PuglSizeHint; + +/// The number of #PuglSizeHint values +#define PUGL_NUM_SIZE_HINTS ((unsigned)PUGL_MAX_ASPECT + 1u) + +/// A function called when an event occurs +typedef PuglStatus (*PuglEventFunc)(PuglView* view, const PuglEvent* event); + +/** + @defgroup setup Setup + Functions for creating and destroying a view. + @{ +*/ + +/** + Create a new view. + + A newly created view does not correspond to a real system view or window. + It must first be configured, then the system view can be created with + puglRealize(). +*/ +PUGL_API +PuglView* +puglNewView(PuglWorld* world); + +/// Free a view created with puglNewView() +PUGL_API +void +puglFreeView(PuglView* view); + +/// Return the world that `view` is a part of +PUGL_API +PuglWorld* +puglGetWorld(PuglView* view); + +/** + Set the user data for a view. + + This is usually a pointer to a struct that contains all the state which must + be accessed by a view. Everything needed to process events should be stored + here, not in static variables. + + The handle is opaque to Pugl and is not interpreted in any way. +*/ +PUGL_API +void +puglSetHandle(PuglView* view, PuglHandle handle); + +/// Get the user data for a view +PUGL_API +PuglHandle +puglGetHandle(PuglView* view); + +/** + Set the graphics backend to use for a view. + + This must be called once to set the graphics backend before calling + puglRealize(). + + Pugl includes the following backends: + + - puglCairoBackend() + - puglGlBackend() + - puglVulkanBackend() + + Note that backends are modular and not compiled into the main Pugl library + to avoid unnecessary dependencies. To use a particular backend, + applications must link against the appropriate backend library, or be sure + to compile in the appropriate code if using a local copy of Pugl. +*/ +PUGL_API +PuglStatus +puglSetBackend(PuglView* view, const PuglBackend* backend); + +/// Return the graphics backend used by a view +const PuglBackend* +puglGetBackend(const PuglView* view); + +/// Set the function to call when an event occurs +PUGL_API +PuglStatus +puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc); + +/** + Set a hint to configure view properties. + + This only has an effect when called before puglRealize(). +*/ +PUGL_API +PuglStatus +puglSetViewHint(PuglView* view, PuglViewHint hint, int value); + +/** + Get the value for a view hint. + + If the view has been realized, this can be used to get the actual value of a + hint which was initially set to PUGL_DONT_CARE, or has been adjusted from + the suggested value. +*/ +PUGL_API +int +puglGetViewHint(const PuglView* view, PuglViewHint hint); + +/** + Return the scale factor of the view. + + This factor describe how large UI elements (especially text) should be + compared to "normal". For example, 2.0 means the UI should be drawn twice + as large. + + "Normal" is loosely defined, but means a good size on a "standard DPI" + display (around 96 DPI). In other words, the scale 1.0 should have text + that is reasonably sized on a 96 DPI display, and the scale 2.0 should have + text twice that large. +*/ +PUGL_API +double +puglGetScaleFactor(const PuglView* view); + +/** + @} + @defgroup frame Frame + Functions for working with the position and size of a view. + @{ +*/ + +/** + Get the current position and size of the view. + + The position is in screen coordinates with an upper left origin. +*/ +PUGL_API +PuglRect +puglGetFrame(const PuglView* view); + +/** + Set the current position and size of the view. + + The position is in screen coordinates with an upper left origin. + + @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is + unchanged. +*/ +PUGL_API +PuglStatus +puglSetFrame(PuglView* view, PuglRect frame); + +/** + Set the current position of the view. + + @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is + unchanged. +*/ +PUGL_API +PuglStatus +puglSetPosition(PuglView* view, int x, int y); + +/** + Set the current size of the view. + + @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is + unchanged. +*/ +PUGL_API +PuglStatus +puglSetSize(PuglView* view, unsigned width, unsigned height); + +/** + Set a size hint for the view. + + This can be used to set the default, minimum, and maximum size of a view, + as well as the supported range of aspect ratios. + + This should be called before puglRealize() so the initial window for the + view can be configured correctly. + + @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is + not yet realized. +*/ +PUGL_API +PuglStatus +puglSetSizeHint(PuglView* view, + PuglSizeHint hint, + PuglSpan width, + PuglSpan height); + +/** + @} + @defgroup window Window + Functions to control the top-level window of a view. + @{ +*/ + +/** + Set the title of the window. + + This only makes sense for non-embedded views that will have a corresponding + top-level window, and sets the title, typically displayed in the title bar + or in window switchers. +*/ +PUGL_API +PuglStatus +puglSetWindowTitle(PuglView* view, const char* title); + +/// Return the title of the window, or null +PUGL_API +const char* +puglGetWindowTitle(const PuglView* view); + +/** + Set the parent window for embedding a view in an existing window. + + This must be called before puglRealize(), reparenting is not supported. +*/ +PUGL_API +PuglStatus +puglSetParentWindow(PuglView* view, PuglNativeView parent); + +/// Return the parent window this view is embedded in, or null +PUGL_API +PuglNativeView +puglGetParentWindow(const PuglView* view); + +/** + Set the transient parent of the window. + + Set this for transient children like dialogs, to have them properly + associated with their parent window. This should be called before + puglRealize(). + + A view can either have a parent (for embedding) or a transient parent (for + top-level windows like dialogs), but not both. +*/ +PUGL_API +PuglStatus +puglSetTransientParent(PuglView* view, PuglNativeView parent); + +/** + Return the transient parent of the window. + + @return The native handle to the window this view is a transient child of, + or null. +*/ +PUGL_API +PuglNativeView +puglGetTransientParent(const PuglView* view); + +/** + Realize a view by creating a corresponding system view or window. + + After this call, the (initially invisible) underlying system view exists and + can be accessed with puglGetNativeView(). There is currently no + corresponding unrealize function, the system view will be destroyed along + with the view when puglFreeView() is called. + + The view should be fully configured using the above functions before this is + called. This function may only be called once per view. +*/ +PUGL_API +PuglStatus +puglRealize(PuglView* view); + +/** + Show the view. + + If the view has not yet been realized, the first call to this function will + do so automatically. + + If the view is currently hidden, it will be shown and possibly raised to the + top depending on the platform. +*/ +PUGL_API +PuglStatus +puglShow(PuglView* view); + +/// Hide the current window +PUGL_API +PuglStatus +puglHide(PuglView* view); + +/// Return true iff the view is currently visible +PUGL_API +bool +puglGetVisible(const PuglView* view); + +/// Return the native window handle +PUGL_API +PuglNativeView +puglGetNativeView(PuglView* view); + +/** + @} + @defgroup graphics Graphics + Functions for working with the graphics context and scheduling redisplays. + @{ +*/ + +/** + Get the graphics context. + + This is a backend-specific context used for drawing if the backend graphics + API requires one. It is only available during an expose. + + Cairo: Returns a pointer to a + [cairo_t](http://www.cairographics.org/manual/cairo-cairo-t.html). + + All other backends: returns null. +*/ +PUGL_API +void* +puglGetContext(PuglView* view); + +/** + Request a redisplay for the entire view. + + This will cause an expose event to be dispatched later. If called from + within the event handler, the expose should arrive at the end of the current + event loop iteration, though this is not strictly guaranteed on all + platforms. If called elsewhere, an expose will be enqueued to be processed + in the next event loop iteration. +*/ +PUGL_API +PuglStatus +puglPostRedisplay(PuglView* view); + +/** + Request a redisplay of the given rectangle within the view. + + This has the same semantics as puglPostRedisplay(), but allows giving a + precise region for redrawing only a portion of the view. +*/ +PUGL_API +PuglStatus +puglPostRedisplayRect(PuglView* view, PuglRect rect); + +/** + @} + @defgroup interaction Interaction + Functions for interacting with the user and window system. + @{ +*/ + +/** + A mouse cursor type. + + This is a portable subset of mouse cursors that exist on X11, MacOS, and + Windows. +*/ +typedef enum { + PUGL_CURSOR_ARROW, ///< Default pointing arrow + PUGL_CURSOR_CARET, ///< Caret (I-Beam) for text entry + PUGL_CURSOR_CROSSHAIR, ///< Cross-hair + PUGL_CURSOR_HAND, ///< Hand with a pointing finger + PUGL_CURSOR_NO, ///< Operation not allowed + PUGL_CURSOR_LEFT_RIGHT, ///< Left/right arrow for horizontal resize + PUGL_CURSOR_UP_DOWN, ///< Up/down arrow for vertical resize + PUGL_CURSOR_DIAGONAL, ///< Top-left to bottom-right arrow for diagonal resize + PUGL_CURSOR_ANTI_DIAGONAL, ///< Bottom-left to top-right arrow for diagonal resize +} PuglCursor; + +/// The number of #PuglCursor values +#define PUGL_NUM_CURSORS ((unsigned)PUGL_CURSOR_ANTI_DIAGONAL + 1u) + +/** + Grab the keyboard input focus. + + Note that this will fail if the view is not mapped and so should not, for + example, be called immediately after puglShow(). + + @return #PUGL_SUCCESS if the focus was successfully grabbed, or an error. +*/ +PUGL_API +PuglStatus +puglGrabFocus(PuglView* view); + +/// Return whether `view` has the keyboard input focus +PUGL_API +bool +puglHasFocus(const PuglView* view); + +/** + Request data from the general copy/paste clipboard. + + A #PUGL_DATA_OFFER event will be sent if data is available. +*/ +PUGL_API +PuglStatus +puglPaste(PuglView* view); + +/** + Return the number of types available for the data in a clipboard. + + Returns zero if the clipboard is empty. +*/ +PUGL_API +uint32_t +puglGetNumClipboardTypes(const PuglView* view); + +/** + Return the identifier of a type available in a clipboard. + + This is usually a MIME type, but may also be another platform-specific type + identifier. Applications must ignore any type they do not recognize. + + Returns null if `typeIndex` is out of bounds according to + puglGetNumClipboardTypes(). +*/ +PUGL_API +const char* +puglGetClipboardType(const PuglView* view, uint32_t typeIndex); + +/** + Accept data offered from a clipboard. + + To accept data, this must be called while handling a #PUGL_DATA_OFFER event. + Doing so will request the data from the source as the specified type. When + the data is available, a #PUGL_DATA event will be sent to the view which can + then retrieve the data with puglGetClipboard(). + + @param view The view. + + @param offer The data offer event. + + @param typeIndex The index of the type that the view will accept. This is + the `typeIndex` argument to the call of puglGetClipboardType() that returned + the accepted type. +*/ +PUGL_API +PuglStatus +puglAcceptOffer(PuglView* view, + const PuglDataOfferEvent* offer, + uint32_t typeIndex); + +/** + Set the clipboard contents. + + This sets the system clipboard contents, which can be retrieved with + puglGetClipboard() or pasted into other applications. + + @param view The view. + @param type The MIME type of the data, "text/plain" is assumed if `NULL`. + @param data The data to copy to the clipboard. + @param len The length of data in bytes (including terminator if necessary). +*/ +PUGL_API +PuglStatus +puglSetClipboard(PuglView* view, + const char* type, + const void* data, + size_t len); + +/** + Get the clipboard contents. + + This gets the system clipboard contents, which may have been set with + puglSetClipboard() or copied from another application. + + @param view The view. + @param typeIndex Index of the data type to get the item as. + @param[out] len Set to the length of the data in bytes. + @return The clipboard contents, or null. +*/ +PUGL_API +const void* +puglGetClipboard(PuglView* view, uint32_t typeIndex, size_t* len); + +/** + Set the mouse cursor. + + This changes the system cursor that is displayed when the pointer is inside + the view. May fail if setting the cursor is not supported on this system, + for example if compiled on X11 without Xcursor support. + + @return #PUGL_BAD_PARAMETER if the given cursor is invalid, + #PUGL_FAILURE if the cursor is known but loading it system fails. +*/ +PUGL_API +PuglStatus +puglSetCursor(PuglView* view, PuglCursor cursor); + +/** + Request user attention. + + This hints to the system that the window or application requires attention + from the user. The exact effect depends on the platform, but is usually + something like a flashing task bar entry or bouncing application icon. +*/ +PUGL_API +PuglStatus +puglRequestAttention(PuglView* view); + +/** + Activate a repeating timer event. + + This starts a timer which will send a #PuglTimerEvent to `view` every + `timeout` seconds. This can be used to perform some action in a view at a + regular interval with relatively low frequency. Note that the frequency of + timer events may be limited by how often puglUpdate() is called. + + If the given timer already exists, it is replaced. + + @param view The view to begin sending #PUGL_TIMER events to. + + @param id The identifier for this timer. This is an application-specific ID + that should be a low number, typically the value of a constant or `enum` + that starts from 0. There is a platform-specific limit to the number of + supported timers, and overhead associated with each, so applications should + create only a few timers and perform several tasks in one if necessary. + + @param timeout The period, in seconds, of this timer. This is not + guaranteed to have a resolution better than 10ms (the maximum timer + resolution on Windows) and may be rounded up if it is too short. On X11 and + MacOS, a resolution of about 1ms can usually be relied on. + + @return #PUGL_FAILURE if timers are not supported by the system, + #PUGL_UNKNOWN_ERROR if setting the timer failed. +*/ +PUGL_API +PuglStatus +puglStartTimer(PuglView* view, uintptr_t id, double timeout); + +/** + Stop an active timer. + + @param view The view that the timer is set for. + @param id The ID previously passed to puglStartTimer(). + + @return #PUGL_FAILURE if timers are not supported by this system, + #PUGL_UNKNOWN_ERROR if stopping the timer failed. +*/ +PUGL_API +PuglStatus +puglStopTimer(PuglView* view, uintptr_t id); + +/** + Send an event to a view via the window system. + + If supported, the event will be delivered to the view via the event loop + like other events. Note that this function only works for certain event + types. + + Currently, only #PUGL_CLIENT events are supported on all platforms. + + X11: A #PUGL_EXPOSE event can be sent, which is similar to calling + puglPostRedisplayRect(), but will always send a message to the X server, + even when called in an event handler. + + @return #PUGL_UNSUPPORTED if sending events of this type is not supported, + #PUGL_UNKNOWN_ERROR if sending the event failed. +*/ +PUGL_API +PuglStatus +puglSendEvent(PuglView* view, const PuglEvent* event); + +/** + @} +*/ + +#ifndef PUGL_DISABLE_DEPRECATED + +/** + @} + @defgroup deprecated Deprecated API + @{ +*/ + +PUGL_DEPRECATED_BY("PuglCreateEvent") +typedef PuglCreateEvent PuglEventCreate; + +PUGL_DEPRECATED_BY("PuglDestroyEvent") +typedef PuglDestroyEvent PuglEventDestroy; + +PUGL_DEPRECATED_BY("PuglConfigureEvent") +typedef PuglConfigureEvent PuglEventConfigure; + +PUGL_DEPRECATED_BY("PuglMapEvent") +typedef PuglMapEvent PuglEventMap; + +PUGL_DEPRECATED_BY("PuglUnmapEvent") +typedef PuglUnmapEvent PuglEventUnmap; + +PUGL_DEPRECATED_BY("PuglUpdateEvent") +typedef PuglUpdateEvent PuglEventUpdate; + +PUGL_DEPRECATED_BY("PuglExposeEvent") +typedef PuglExposeEvent PuglEventExpose; + +PUGL_DEPRECATED_BY("PuglCloseEvent") +typedef PuglCloseEvent PuglEventClose; + +PUGL_DEPRECATED_BY("PuglFocusEvent") +typedef PuglFocusEvent PuglEventFocus; + +PUGL_DEPRECATED_BY("PuglKeyEvent") +typedef PuglKeyEvent PuglEventKey; + +PUGL_DEPRECATED_BY("PuglTextEvent") +typedef PuglTextEvent PuglEventText; + +PUGL_DEPRECATED_BY("PuglCrossingEvent") +typedef PuglCrossingEvent PuglEventCrossing; + +PUGL_DEPRECATED_BY("PuglButtonEvent") +typedef PuglButtonEvent PuglEventButton; + +PUGL_DEPRECATED_BY("PuglMotionEvent") +typedef PuglMotionEvent PuglEventMotion; + +PUGL_DEPRECATED_BY("PuglScrollEvent") +typedef PuglScrollEvent PuglEventScroll; + +PUGL_DEPRECATED_BY("PuglClientEvent") +typedef PuglClientEvent PuglEventClient; + +PUGL_DEPRECATED_BY("PuglTimerEvent") +typedef PuglTimerEvent PuglEventTimer; + +PUGL_DEPRECATED_BY("PuglLoopEnterEvent") +typedef PuglLoopEnterEvent PuglEventLoopEnter; + +PUGL_DEPRECATED_BY("PuglLoopLeaveEvent") +typedef PuglLoopLeaveEvent PuglEventLoopLeave; + +/** + A native window handle. + + X11: This is a `Window`. + + MacOS: This is a pointer to an `NSView*`. + + Windows: This is a `HWND`. +*/ +PUGL_DEPRECATED_BY("PuglNativeView") +typedef uintptr_t PuglNativeWindow; + +/** + Create a Pugl application and view. + + To create a window, call the various puglInit* functions as necessary, then + call puglRealize(). + + @deprecated Use puglNewApp() and puglNewView(). + + @param pargc Pointer to argument count (currently unused). + @param argv Arguments (currently unused). + @return A newly created view. +*/ +static inline PUGL_DEPRECATED_BY("puglNewView") +PuglView* +puglInit(const int* pargc, char** argv) +{ + (void)pargc; + (void)argv; + + return puglNewView(puglNewWorld(PUGL_MODULE, 0)); +} + +/** + Destroy an app and view created with `puglInit()`. + + @deprecated Use puglFreeApp() and puglFreeView(). +*/ +static inline PUGL_DEPRECATED_BY("puglFreeView") +void +puglDestroy(PuglView* view) +{ + PuglWorld* const world = puglGetWorld(view); + + puglFreeView(view); + puglFreeWorld(world); +} + +/** + Set the window class name before creating a window. +*/ +static inline PUGL_DEPRECATED_BY("puglSetClassName") +void +puglInitWindowClass(PuglView* view, const char* name) +{ + puglSetClassName(puglGetWorld(view), name); +} + +/** + Set the window size before creating a window. + + @deprecated Use puglSetFrame(). +*/ +static inline PUGL_DEPRECATED_BY("puglSetFrame") +void +puglInitWindowSize(PuglView* view, int width, int height) +{ + PuglRect frame = puglGetFrame(view); + + frame.width = (PuglSpan)width; + frame.height = (PuglSpan)height; + + puglSetFrame(view, frame); +} + +/** + Set the minimum window size before creating a window. +*/ +static inline PUGL_DEPRECATED_BY("puglSetMinSize") +void +puglInitWindowMinSize(PuglView* view, int width, int height) +{ + puglSetSizeHint(view, PUGL_MIN_SIZE, (PuglSpan)width, (PuglSpan)height); +} + +/** + Set the window aspect ratio range before creating a window. + + The x and y values here represent a ratio of width to height. To set a + fixed aspect ratio, set the minimum and maximum values to the same ratio. + + Note that setting different minimum and maximum constraints does not + currently work on MacOS (the minimum is used), so only setting a fixed + aspect ratio works properly across all platforms. +*/ +static inline PUGL_DEPRECATED_BY("puglSetAspectRatio") +void +puglInitWindowAspectRatio(PuglView* view, + int minX, + int minY, + int maxX, + int maxY) +{ + puglSetSizeHint(view, PUGL_MIN_ASPECT, (PuglSpan)minX, (PuglSpan)minY); + puglSetSizeHint(view, PUGL_MAX_ASPECT, (PuglSpan)maxX, (PuglSpan)maxY); +} + +/** + Set transient parent before creating a window. + + On X11, parent must be a Window. + On OSX, parent must be an NSView*. +*/ +static inline PUGL_DEPRECATED_BY("puglSetTransientParent") +void +puglInitTransientFor(PuglView* view, uintptr_t parent) +{ + puglSetTransientParent(view, (PuglNativeWindow)parent); +} + +/** + Set transient parent before creating a window. + + @deprecated Use puglSetTransientParent(). +*/ +static inline PUGL_DEPRECATED_BY("puglSetTransientParent") +PuglStatus +puglSetTransientFor(PuglView* view, uintptr_t parent) +{ + return puglSetTransientParent(view, (PuglNativeWindow)parent); +} + +/** + Enable or disable resizing before creating a window. + + @deprecated Use puglSetViewHint() with #PUGL_RESIZABLE. +*/ +static inline PUGL_DEPRECATED_BY("puglSetViewHint") +void +puglInitResizable(PuglView* view, bool resizable) +{ + puglSetViewHint(view, PUGL_RESIZABLE, resizable); +} + +/** + Get the current size of the view. + + @deprecated Use puglGetFrame(). + +*/ +static inline PUGL_DEPRECATED_BY("puglGetFrame") +void +puglGetSize(PuglView* view, int* width, int* height) +{ + const PuglRect frame = puglGetFrame(view); + + *width = (int)frame.width; + *height = (int)frame.height; +} + +/** + Ignore synthetic repeated key events. + + @deprecated Use puglSetViewHint() with #PUGL_IGNORE_KEY_REPEAT. +*/ +static inline PUGL_DEPRECATED_BY("puglSetViewHint") +void +puglIgnoreKeyRepeat(PuglView* view, bool ignore) +{ + puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, ignore); +} + +/** + Set a hint before creating a window. + + @deprecated Use puglSetWindowHint(). +*/ +static inline PUGL_DEPRECATED_BY("puglSetViewHint") +void +puglInitWindowHint(PuglView* view, PuglViewHint hint, int value) +{ + puglSetViewHint(view, hint, value); +} + +/** + Set the parent window before creating a window (for embedding). + + @deprecated Use puglSetWindowParent(). +*/ +static inline PUGL_DEPRECATED_BY("puglSetParentWindow") +void +puglInitWindowParent(PuglView* view, PuglNativeWindow parent) +{ + puglSetParentWindow(view, parent); +} + +/** + Set the graphics backend to use. + + @deprecated Use puglSetBackend(). +*/ +static inline PUGL_DEPRECATED_BY("puglSetBackend") +int +puglInitBackend(PuglView* view, const PuglBackend* backend) +{ + return (int)puglSetBackend(view, backend); +} + +/** + Realize a view by creating a corresponding system view or window. + + The view should be fully configured using the above functions before this is + called. This function may only be called once per view. + + @deprecated Use puglRealize(), or just show the view. +*/ +static inline PUGL_DEPRECATED_BY("puglRealize") +PuglStatus +puglCreateWindow(PuglView* view, const char* title) +{ + puglSetWindowTitle(view, title); + return puglRealize(view); +} + +/** + Block and wait for an event to be ready. + + This can be used in a loop to only process events via puglProcessEvents when + necessary. This function will block indefinitely if no events are + available, so is not appropriate for use in programs that need to perform + regular updates (e.g. animation). + + @deprecated Use puglPollEvents(). +*/ +PUGL_API +PUGL_DEPRECATED_BY("puglPollEvents") +PuglStatus +puglWaitForEvent(PuglView* view); + +/** + Process all pending window events. + + This handles input events as well as rendering, so it should be called + regularly and rapidly enough to keep the UI responsive. This function does + not block if no events are pending. + + @deprecated Use puglDispatchEvents(). +*/ +PUGL_API +PUGL_DEPRECATED_BY("puglDispatchEvents") +PuglStatus +puglProcessEvents(PuglView* view); + +/** + Poll for events that are ready to be processed. + + This polls for events that are ready for any view in the world, potentially + blocking depending on `timeout`. + + @param world The world to poll for events. + + @param timeout Maximum time to wait, in seconds. If zero, the call returns + immediately, if negative, the call blocks indefinitely. + + @return #PUGL_SUCCESS if events are read, #PUGL_FAILURE if not, or an error. + + @deprecated Use puglUpdate(). +*/ +static inline PUGL_DEPRECATED_BY("puglUpdate") +PuglStatus +puglPollEvents(PuglWorld* world, double timeout) +{ + return puglUpdate(world, timeout); +} + +/** + Dispatch any pending events to views. + + This processes all pending events, dispatching them to the appropriate + views. View event handlers will be called in the scope of this call. This + function does not block, if no events are pending then it will return + immediately. + + @deprecated Use puglUpdate(). +*/ +static inline PUGL_DEPRECATED_BY("puglUpdate") +PuglStatus +puglDispatchEvents(PuglWorld* world) +{ + return puglUpdate(world, 0.0); +} + +static inline PUGL_DEPRECATED_BY("puglShow") +PuglStatus +puglShowWindow(PuglView* view) +{ + return puglShow(view); +} + +static inline PUGL_DEPRECATED_BY("puglHide") +PuglStatus +puglHideWindow(PuglView* view) +{ + return puglHide(view); +} + +/** + Set the default size of the view. + + This should be called before puglRealize() to set the default size of the + view, which will be the initial size of the window if this is a top level + view. + + @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is + not yet realized. +*/ +static inline PUGL_DEPRECATED_BY("puglSetSizeHint") +PuglStatus +puglSetDefaultSize(PuglView* view, int width, int height) +{ + return puglSetSizeHint( + view, PUGL_DEFAULT_SIZE, (PuglSpan)width, (PuglSpan)height); +} + +/** + Set the minimum size of the view. + + If an initial minimum size is known, this should be called before + puglRealize() to avoid stutter, though it can be called afterwards as well. + + @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is + not yet realized. +*/ +static inline PUGL_DEPRECATED_BY("puglSetSizeHint") +PuglStatus +puglSetMinSize(PuglView* view, int width, int height) +{ + return puglSetSizeHint( + view, PUGL_MIN_SIZE, (PuglSpan)width, (PuglSpan)height); +} + +/** + Set the maximum size of the view. + + If an initial maximum size is known, this should be called before + puglRealize() to avoid stutter, though it can be called afterwards as well. + + @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is + not yet realized. +*/ +static inline PUGL_DEPRECATED_BY("puglSetSizeHint") +PuglStatus +puglSetMaxSize(PuglView* view, int width, int height) +{ + return puglSetSizeHint( + view, PUGL_MAX_SIZE, (PuglSpan)width, (PuglSpan)height); +} + +/** + Set the view aspect ratio range. + + The x and y values here represent a ratio of width to height. To set a + fixed aspect ratio, set the minimum and maximum values to the same ratio. + + Note that setting different minimum and maximum constraints does not + currently work on MacOS (the minimum is used), so only setting a fixed + aspect ratio works properly across all platforms. + + If an initial aspect ratio is known, this should be called before + puglRealize() to avoid stutter, though it can be called afterwards as well. + + @return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is + not yet realized. +*/ +static inline PUGL_DEPRECATED_BY("puglSetSizeHint") +PuglStatus +puglSetAspectRatio(PuglView* view, int minX, int minY, int maxX, int maxY) +{ + const PuglStatus st0 = + puglSetSizeHint(view, PUGL_MIN_ASPECT, (PuglSpan)minX, (PuglSpan)minY); + + const PuglStatus st1 = + puglSetSizeHint(view, PUGL_MAX_ASPECT, (PuglSpan)maxX, (PuglSpan)maxY); + + return st0 ? st0 : st1; +} + +/// Return the native window handle +static inline PUGL_DEPRECATED_BY("puglGetNativeView") +PuglNativeView +puglGetNativeWindow(PuglView* view) +{ + return puglGetNativeView(view); +} + +#endif // PUGL_DISABLE_DEPRECATED + +/** + @} + @} +*/ + +PUGL_END_DECLS + +#endif // PUGL_PUGL_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/stub.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/stub.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,34 @@ +// Copyright 2019-2020 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_STUB_H +#define PUGL_STUB_H + +#include "pugl/pugl.h" + +PUGL_BEGIN_DECLS + +/** + @defgroup stub Stub + Native graphics support. + @ingroup pugl + @{ +*/ + +/** + Stub graphics backend accessor. + + This backend just creates a simple native window without setting up any + portable graphics API. +*/ +PUGL_CONST_API +const PuglBackend* +puglStubBackend(void); + +/** + @} +*/ + +PUGL_END_DECLS + +#endif // PUGL_STUB_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/vulkan.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/include/pugl/vulkan.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,143 @@ +// Copyright 2012-2020 David Robillard +// SPDX-License-Identifier: ISC + +/* + Note that this header includes Vulkan headers, so if you are writing a + program or plugin that dynamically loads vulkan, you should first define + `VK_NO_PROTOTYPES` before including it. +*/ + +#ifndef PUGL_VULKAN_H +#define PUGL_VULKAN_H + +#include "pugl/pugl.h" + +#include + +#include + +PUGL_BEGIN_DECLS + +/** + @defgroup vulkan Vulkan + Vulkan graphics support. + + Vulkan support differs from OpenGL because almost all most configuration is + done using the Vulkan API itself, rather than by setting view hints to + configure the context. Pugl only provides a minimal loader for loading the + Vulkan library, and a portable function to create a Vulkan surface for a + view, which hides the platform-specific implementation details. + + @ingroup pugl + @{ +*/ + +/** + Dynamic Vulkan loader. + + This can be used to dynamically load the Vulkan library. Applications or + plugins should not link against the Vulkan library, but instead use this at + runtime. This ensures that things will work on as many systems as possible, + and allows errors to be handled gracefully. + + This is not a "loader" in the sense of loading all the required Vulkan + functions (which is the application's responsibility), but just a minimal + implementation to portably load the Vulkan library and get the two functions + that are used to load everything else. + + Note that this owns the loaded Vulkan library, so it must outlive all use of + the Vulkan API. + + @see https://www.khronos.org/registry/vulkan/specs/1.0/html/chap4.html +*/ +typedef struct PuglVulkanLoaderImpl PuglVulkanLoader; + +/** + Create a new dynamic loader for Vulkan functions. + + This dynamically loads the Vulkan library and gets the load functions from + it. + + @return A new Vulkan loader, or null on failure. +*/ +PUGL_API +PuglVulkanLoader* +puglNewVulkanLoader(PuglWorld* world); + +/** + Free a loader created with puglNewVulkanLoader(). + + Note that this closes the Vulkan library, so no Vulkan objects or API may be + used after this is called. +*/ +PUGL_API +void +puglFreeVulkanLoader(PuglVulkanLoader* loader); + +/** + Return the `vkGetInstanceProcAddr` function. + + @return Null if the Vulkan library does not contain this function (which is + unlikely and indicates a broken system). +*/ +PUGL_API +PFN_vkGetInstanceProcAddr +puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader); + +/** + Return the `vkGetDeviceProcAddr` function. + + @return Null if the Vulkan library does not contain this function (which is + unlikely and indicates a broken system). +*/ +PUGL_API +PFN_vkGetDeviceProcAddr +puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader); + +/** + Return the Vulkan instance extensions required to draw to a PuglView. + + This simply returns static strings, it does not access Vulkan or the window + system. The returned array always contains at least "VK_KHR_surface". + + @param[out] count The number of extensions in the returned array. + @return An array of extension name strings. +*/ +PUGL_API +const char* const* +puglGetInstanceExtensions(uint32_t* count); + +/** + Create a Vulkan surface for a Pugl view. + + @param vkGetInstanceProcAddr Accessor for Vulkan functions. + @param view The view the surface is to be displayed on. + @param instance The Vulkan instance. + @param allocator Vulkan allocation callbacks, may be NULL. + @param[out] surface Pointed to a newly created Vulkan surface. + @return `VK_SUCCESS` on success, or a Vulkan error code. +*/ +PUGL_API +VkResult +puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr, + PuglView* view, + VkInstance instance, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface); + +/** + Vulkan graphics backend. + + Pass the returned value to puglSetBackend() to draw to a view with Vulkan. +*/ +PUGL_CONST_API +const PuglBackend* +puglVulkanBackend(void); + +/** + @} +*/ + +PUGL_END_DECLS + +#endif // PUGL_VULKAN_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/.clang-tidy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/.clang-tidy Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,13 @@ +Checks: > + *, + -*-uppercase-literal-suffix, + -*magic-numbers, + -altera*, + -bugprone-easily-swappable-parameters, + -hicpp-multiway-paths-covered, + -hicpp-signed-bitwise, + -llvm-header-guard, + -llvmlibc-*, + -readability-function-cognitive-complexity, +FormatStyle: file +HeaderFilterRegex: 'pugl/.*' diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/attributes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/attributes.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,23 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_ATTRIBUTES_H +#define PUGL_SRC_ATTRIBUTES_H + +// Unused parameter macro to suppresses warnings and make it impossible to use +#if defined(__cplusplus) +# define PUGL_UNUSED(name) +#elif defined(__GNUC__) || defined(__clang__) +# define PUGL_UNUSED(name) name##_unused __attribute__((__unused__)) +#else +# define PUGL_UNUSED(name) name +#endif + +// Unused result macro to warn when an important return status is ignored +#ifndef _MSC_VER +# define PUGL_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define PUGL_WARN_UNUSED_RESULT +#endif + +#endif // PUGL_SRC_ATTRIBUTES_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/common.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/common.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,273 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +// Common implementations of public API functions in the core library + +#include "internal.h" + +#include "platform.h" +#include "types.h" + +#include "pugl/pugl.h" + +#include +#include +#include + +const char* +puglStrerror(const PuglStatus status) +{ + // clang-format off + switch (status) { + case PUGL_SUCCESS: return "Success"; + case PUGL_FAILURE: return "Non-fatal failure"; + case PUGL_UNKNOWN_ERROR: return "Unknown system error"; + case PUGL_BAD_BACKEND: return "Invalid or missing backend"; + case PUGL_BAD_CONFIGURATION: return "Invalid view configuration"; + case PUGL_BAD_PARAMETER: return "Invalid parameter"; + case PUGL_BACKEND_FAILED: return "Backend initialisation failed"; + case PUGL_REGISTRATION_FAILED: return "Class registration failed"; + case PUGL_REALIZE_FAILED: return "View creation failed"; + case PUGL_SET_FORMAT_FAILED: return "Failed to set pixel format"; + case PUGL_CREATE_CONTEXT_FAILED: return "Failed to create drawing context"; + case PUGL_UNSUPPORTED: return "Unsupported operation"; + case PUGL_NO_MEMORY: return "Failed to allocate memory"; + } + // clang-format on + + return "Unknown error"; +} + +PuglWorld* +puglNewWorld(PuglWorldType type, PuglWorldFlags flags) +{ + PuglWorld* world = (PuglWorld*)calloc(1, sizeof(PuglWorld)); + if (!world || !(world->impl = puglInitWorldInternals(type, flags))) { + free(world); + return NULL; + } + + world->startTime = puglGetTime(world); + +#ifdef __EMSCRIPTEN__ + puglSetString(&world->className, "canvas"); +#else + puglSetString(&world->className, "Pugl"); +#endif + + return world; +} + +void +puglFreeWorld(PuglWorld* const world) +{ + puglFreeWorldInternals(world); + free(world->className); + free(world->views); + free(world); +} + +void +puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle) +{ + world->handle = handle; +} + +PuglWorldHandle +puglGetWorldHandle(PuglWorld* world) +{ + return world->handle; +} + +PuglStatus +puglSetClassName(PuglWorld* const world, const char* const name) +{ + puglSetString(&world->className, name); + return PUGL_SUCCESS; +} + +const char* +puglGetClassName(const PuglWorld* world) +{ + return world->className; +} + +static void +puglSetDefaultHints(PuglHints hints) +{ + hints[PUGL_USE_COMPAT_PROFILE] = PUGL_TRUE; + hints[PUGL_CONTEXT_VERSION_MAJOR] = 2; + hints[PUGL_CONTEXT_VERSION_MINOR] = 0; + hints[PUGL_RED_BITS] = 8; + hints[PUGL_GREEN_BITS] = 8; + hints[PUGL_BLUE_BITS] = 8; + hints[PUGL_ALPHA_BITS] = 8; + hints[PUGL_DEPTH_BITS] = 0; + hints[PUGL_STENCIL_BITS] = 0; + hints[PUGL_SAMPLES] = 0; + hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE; + hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE; + hints[PUGL_RESIZABLE] = PUGL_FALSE; + hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE; + hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE; +} + +PuglView* +puglNewView(PuglWorld* const world) +{ + PuglView* view = (PuglView*)calloc(1, sizeof(PuglView)); + if (!view || !(view->impl = puglInitViewInternals(world))) { + free(view); + return NULL; + } + + view->world = world; + view->sizeHints[PUGL_MIN_SIZE].width = 1; + view->sizeHints[PUGL_MIN_SIZE].height = 1; + + puglSetDefaultHints(view->hints); + + // Add to world view list + ++world->numViews; + world->views = + (PuglView**)realloc(world->views, world->numViews * sizeof(PuglView*)); + + world->views[world->numViews - 1] = view; + + return view; +} + +void +puglFreeView(PuglView* view) +{ + if (view->eventFunc && view->backend) { + puglDispatchSimpleEvent(view, PUGL_DESTROY); + } + + // Remove from world view list + PuglWorld* world = view->world; + for (size_t i = 0; i < world->numViews; ++i) { + if (world->views[i] == view) { + if (i == world->numViews - 1) { + world->views[i] = NULL; + } else { + memmove(world->views + i, + world->views + i + 1, + sizeof(PuglView*) * (world->numViews - i - 1)); + world->views[world->numViews - 1] = NULL; + } + --world->numViews; + } + } + + free(view->title); + puglFreeViewInternals(view); + free(view); +} + +PuglWorld* +puglGetWorld(PuglView* view) +{ + return view->world; +} + +void +puglSetHandle(PuglView* view, PuglHandle handle) +{ + view->handle = handle; +} + +PuglHandle +puglGetHandle(PuglView* view) +{ + return view->handle; +} + +PuglStatus +puglSetBackend(PuglView* view, const PuglBackend* backend) +{ + view->backend = backend; + return PUGL_SUCCESS; +} + +const PuglBackend* +puglGetBackend(const PuglView* view) +{ + return view->backend; +} + +PuglStatus +puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc) +{ + view->eventFunc = eventFunc; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetViewHint(PuglView* view, PuglViewHint hint, int value) +{ + if (value == PUGL_DONT_CARE) { + switch (hint) { + case PUGL_USE_COMPAT_PROFILE: + case PUGL_USE_DEBUG_CONTEXT: + case PUGL_CONTEXT_VERSION_MAJOR: + case PUGL_CONTEXT_VERSION_MINOR: + case PUGL_SWAP_INTERVAL: + return PUGL_BAD_PARAMETER; + default: + break; + } + } + + view->hints[hint] = value; + return PUGL_SUCCESS; +} + +int +puglGetViewHint(const PuglView* view, PuglViewHint hint) +{ + return view->hints[hint]; +} + +PuglRect +puglGetFrame(const PuglView* view) +{ + return view->frame; +} + +const char* +puglGetWindowTitle(const PuglView* const view) +{ + return view->title; +} + +PuglStatus +puglSetParentWindow(PuglView* view, PuglNativeView parent) +{ + view->parent = parent; + return PUGL_SUCCESS; +} + +PuglNativeView +puglGetParentWindow(const PuglView* const view) +{ + return view->parent; +} + +PuglNativeView +puglGetTransientParent(const PuglView* const view) +{ + return view->transientParent; +} + +bool +puglGetVisible(const PuglView* view) +{ + return view->visible; +} + +void* +puglGetContext(PuglView* view) +{ + return view->backend->getContext(view); +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/internal.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/internal.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,190 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "internal.h" + +#include "types.h" + +#include "pugl/pugl.h" + +#include +#include +#include +#include + +PuglStatus +puglSetBlob(PuglBlob* const dest, const void* const data, const size_t len) +{ + if (data) { + void* const newData = realloc(dest->data, len + 1); + if (!newData) { + free(dest->data); + dest->len = 0; + return PUGL_NO_MEMORY; + } + + memcpy(newData, data, len); + ((char*)newData)[len] = 0; + + dest->len = len; + dest->data = newData; + } else { + dest->len = 0; + dest->data = NULL; + } + + return PUGL_SUCCESS; +} + +void +puglSetString(char** dest, const char* string) +{ + if (*dest != string) { + const size_t len = strlen(string); + + *dest = (char*)realloc(*dest, len + 1); + strncpy(*dest, string, len + 1); + } +} + +uint32_t +puglDecodeUTF8(const uint8_t* buf) +{ +#define FAIL_IF(cond) \ + do { \ + if (cond) \ + return 0xFFFD; \ + } while (0) + + // http://en.wikipedia.org/wiki/UTF-8 + + if (buf[0] < 0x80) { + return buf[0]; + } + + if (buf[0] < 0xC2) { + return 0xFFFD; + } + + if (buf[0] < 0xE0) { + FAIL_IF((buf[1] & 0xC0u) != 0x80); + return ((uint32_t)buf[0] << 6u) + buf[1] - 0x3080u; + } + + if (buf[0] < 0xF0) { + FAIL_IF((buf[1] & 0xC0u) != 0x80); + FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0); + FAIL_IF((buf[2] & 0xC0u) != 0x80); + return ((uint32_t)buf[0] << 12u) + // + ((uint32_t)buf[1] << 6u) + // + ((uint32_t)buf[2] - 0xE2080u); + } + + if (buf[0] < 0xF5) { + FAIL_IF((buf[1] & 0xC0u) != 0x80); + FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90); + FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90); + FAIL_IF((buf[2] & 0xC0u) != 0x80u); + FAIL_IF((buf[3] & 0xC0u) != 0x80u); + return (((uint32_t)buf[0] << 18u) + // + ((uint32_t)buf[1] << 12u) + // + ((uint32_t)buf[2] << 6u) + // + ((uint32_t)buf[3] - 0x3C82080u)); + } + + return 0xFFFD; +} + +PuglStatus +puglDispatchSimpleEvent(PuglView* view, const PuglEventType type) +{ + assert(type == PUGL_CREATE || type == PUGL_DESTROY || type == PUGL_MAP || + type == PUGL_UNMAP || type == PUGL_UPDATE || type == PUGL_CLOSE || + type == PUGL_LOOP_ENTER || type == PUGL_LOOP_LEAVE); + + const PuglEvent event = {{type, 0}}; + return puglDispatchEvent(view, &event); +} + +static inline bool +puglMustConfigure(PuglView* view, const PuglConfigureEvent* configure) +{ + return !!memcmp(configure, &view->lastConfigure, sizeof(PuglConfigureEvent)); +} + +PuglStatus +puglConfigure(PuglView* view, const PuglEvent* event) +{ + PuglStatus st = PUGL_SUCCESS; + + assert(event->type == PUGL_CONFIGURE); + + view->frame.x = event->configure.x; + view->frame.y = event->configure.y; + view->frame.width = event->configure.width; + view->frame.height = event->configure.height; + + if (puglMustConfigure(view, &event->configure)) { + st = view->eventFunc(view, event); + view->lastConfigure = event->configure; + } + + return st; +} + +PuglStatus +puglExpose(PuglView* view, const PuglEvent* event) +{ + return (event->expose.width > 0.0 && event->expose.height > 0.0) + ? view->eventFunc(view, event) + : PUGL_SUCCESS; +} + +PuglStatus +puglDispatchEvent(PuglView* view, const PuglEvent* event) +{ + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + + switch (event->type) { + case PUGL_NOTHING: + break; + case PUGL_CREATE: + case PUGL_DESTROY: + if (!(st0 = view->backend->enter(view, NULL))) { + st0 = view->eventFunc(view, event); + st1 = view->backend->leave(view, NULL); + } + break; + case PUGL_CONFIGURE: + if (puglMustConfigure(view, &event->configure)) { + if (!(st0 = view->backend->enter(view, NULL))) { + st0 = puglConfigure(view, event); + st1 = view->backend->leave(view, NULL); + } + } + break; + case PUGL_MAP: + if (!view->visible) { + view->visible = true; + st0 = view->eventFunc(view, event); + } + break; + case PUGL_UNMAP: + if (view->visible) { + view->visible = false; + st0 = view->eventFunc(view, event); + } + break; + case PUGL_EXPOSE: + if (!(st0 = view->backend->enter(view, &event->expose))) { + st0 = puglExpose(view, event); + st1 = view->backend->leave(view, &event->expose); + } + break; + default: + st0 = view->eventFunc(view, event); + } + + return st0 ? st0 : st1; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/internal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/internal.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,51 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +// Internal utilities available to platform implementations + +#ifndef PUGL_INTERNAL_H +#define PUGL_INTERNAL_H + +#include "attributes.h" +#include "types.h" + +#include "pugl/pugl.h" + +#include +#include + +PUGL_BEGIN_DECLS + +/// Set `blob` to `data` with length `len`, reallocating if necessary +PuglStatus +puglSetBlob(PuglBlob* dest, const void* data, size_t len); + +/// Reallocate and set `*dest` to `string` +void +puglSetString(char** dest, const char* string); + +/// Return the Unicode code point for `buf` or the replacement character +uint32_t +puglDecodeUTF8(const uint8_t* buf); + +/// Dispatch an event with a simple `type` to `view` +PuglStatus +puglDispatchSimpleEvent(PuglView* view, PuglEventType type); + +/// Process configure event while already in the graphics context +PUGL_WARN_UNUSED_RESULT +PuglStatus +puglConfigure(PuglView* view, const PuglEvent* event); + +/// Process expose event while already in the graphics context +PUGL_WARN_UNUSED_RESULT +PuglStatus +puglExpose(PuglView* view, const PuglEvent* event); + +/// Dispatch `event` to `view`, entering graphics context if necessary +PuglStatus +puglDispatchEvent(PuglView* view, const PuglEvent* event); + +PUGL_END_DECLS + +#endif // PUGL_INTERNAL_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,42 @@ +// Copyright 2012-2020 David Robillard +// Copyright 2017 Hanspeter Portner +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_MAC_H +#define PUGL_SRC_MAC_H + +#include "pugl/pugl.h" + +#import + +#include + +@interface PuglWrapperView : NSView + +- (void)dispatchExpose:(NSRect)rect; +- (void)setReshaped; + +@end + +@interface PuglWindow : NSWindow + +- (void)setPuglview:(PuglView*)view; + +@end + +struct PuglWorldInternalsImpl { + NSApplication* app; + NSAutoreleasePool* autoreleasePool; +}; + +struct PuglInternalsImpl { + NSApplication* app; + PuglWrapperView* wrapperView; + NSView* drawView; + NSCursor* cursor; + PuglWindow* window; + uint32_t mods; + bool mouseTracked; +}; + +#endif // PUGL_SRC_MAC_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac.m Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1726 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2017 Hanspeter Portner +// SPDX-License-Identifier: ISC + +#define GL_SILENCE_DEPRECATION 1 + +#include "mac.h" + +#include "internal.h" +#include "platform.h" + +#include "pugl/pugl.h" + +#import + +#include + +#include + +#ifndef __MAC_10_10 +typedef NSUInteger NSEventModifierFlags; +typedef NSUInteger NSEventSubtype; +#endif + +#ifndef __MAC_10_12 +typedef NSUInteger NSWindowStyleMask; +#endif + +typedef struct { + const char* uti; + const char* mimeType; +} Datatype; + +#define NUM_DATATYPES 16 + +static const Datatype datatypes[NUM_DATATYPES + 1] = { + {"com.apple.pasteboard.promised-file-url", "text/uri-list"}, + {"org.7-zip.7-zip-archive", "application/x-7z-compressed"}, + {"org.gnu.gnu-zip-tar-archive", "application/tar+gzip"}, + {"public.7z-archive", "application/x-7z-compressed"}, + {"public.cpio-archive", "application/x-cpio"}, + {"public.deb-archive", "application/vnd.debian.binary-package"}, + {"public.file-url", "text/uri-list"}, + {"public.html", "text/html"}, + {"public.png", "image/png"}, + {"public.rar-archive", "application/x-rar-compressed"}, + {"public.rpm-archive", "application/x-rpm"}, + {"public.rtf", "text/rtf"}, + {"public.url", "text/uri-list"}, + {"public.utf8-plain-text", "text/plain"}, + {"public.utf8-tab-separated-values-text", "text/tab-separated-values"}, + {"public.xz-archive", "application/x-xz"}, + {NULL, NULL}, +}; + +static NSString* +mimeTypeForUti(const NSString* const uti) +{ + const char* const utiString = [uti UTF8String]; + + // First try internal map to override types the system won't convert sensibly + for (const Datatype* datatype = datatypes; datatype->uti; ++datatype) { + if (!strcmp(utiString, datatype->uti)) { + return [NSString stringWithUTF8String:datatype->mimeType]; + } + } + + // Try to get the MIME type from the system + return (NSString*)CFBridgingRelease(UTTypeCopyPreferredTagWithClass( + (__bridge CFStringRef)uti, kUTTagClassMIMEType)); +} + +static NSString* +utiForMimeType(const NSString* const mimeType) +{ + const char* const mimeTypeString = [mimeType UTF8String]; + + // First try internal map to override types the system won't convert sensibly + for (const Datatype* datatype = datatypes; datatype->mimeType; ++datatype) { + if (!strcmp(mimeTypeString, datatype->mimeType)) { + return [NSString stringWithUTF8String:datatype->uti]; + } + } + + // Try to get the UTI from the system + CFStringRef uti = UTTypeCreatePreferredIdentifierForTag( + kUTTagClassMIMEType, (__bridge CFStringRef)mimeType, NULL); + + return (uti && UTTypeIsDynamic(uti)) ? (NSString*)CFBridgingRelease(uti) + : NULL; +} + +static NSRect +rectToScreen(NSScreen* screen, NSRect rect) +{ + const double screenHeight = [screen frame].size.height; + + rect.origin.y = screenHeight - rect.origin.y - rect.size.height; + return rect; +} + +static NSScreen* +viewScreen(const PuglView* view) +{ + return view->impl->window ? [view->impl->window screen] + : [view->impl->wrapperView window] + ? [[view->impl->wrapperView window] screen] + : [NSScreen mainScreen]; +} + +static NSRect +nsRectToPoints(PuglView* view, const NSRect rect) +{ + const double scaleFactor = [viewScreen(view) backingScaleFactor]; + + return NSMakeRect(rect.origin.x / scaleFactor, + rect.origin.y / scaleFactor, + rect.size.width / scaleFactor, + rect.size.height / scaleFactor); +} + +static NSRect +nsRectFromPoints(PuglView* view, const NSRect rect) +{ + const double scaleFactor = [viewScreen(view) backingScaleFactor]; + + return NSMakeRect(rect.origin.x * scaleFactor, + rect.origin.y * scaleFactor, + rect.size.width * scaleFactor, + rect.size.height * scaleFactor); +} + +static NSPoint +nsPointFromPoints(PuglView* view, const NSPoint point) +{ + const double scaleFactor = [viewScreen(view) backingScaleFactor]; + + return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor); +} + +static NSRect +rectToNsRect(const PuglRect rect) +{ + return NSMakeRect(rect.x, rect.y, rect.width, rect.height); +} + +static NSSize +sizePoints(PuglView* view, const double width, const double height) +{ + const double scaleFactor = [viewScreen(view) backingScaleFactor]; + + return NSMakeSize(width / scaleFactor, height / scaleFactor); +} + +static void +updateViewRect(PuglView* view) +{ + NSWindow* const window = view->impl->window; + if (window) { + const NSRect screenFramePt = [[NSScreen mainScreen] frame]; + const NSRect screenFramePx = nsRectFromPoints(view, screenFramePt); + const NSRect framePt = [window frame]; + const NSRect contentPt = [window contentRectForFrameRect:framePt]; + const NSRect contentPx = nsRectFromPoints(view, contentPt); + const double screenHeight = screenFramePx.size.height; + + view->frame.x = (PuglCoord)contentPx.origin.x; + view->frame.y = + (PuglCoord)(screenHeight - contentPx.origin.y - contentPx.size.height); + + view->frame.width = (PuglSpan)contentPx.size.width; + view->frame.height = (PuglSpan)contentPx.size.height; + } +} + +@implementation PuglWindow { +@public + PuglView* puglview; +} + +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(NSWindowStyleMask)aStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag +{ + (void)flag; + + NSWindow* result = [super initWithContentRect:contentRect + styleMask:aStyle + backing:bufferingType + defer:NO]; + + [result setAcceptsMouseMovedEvents:YES]; + return (PuglWindow*)result; +} + +- (void)setPuglview:(PuglView*)view +{ + puglview = view; + + [self setContentSize:sizePoints(view, view->frame.width, view->frame.height)]; +} + +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + +- (BOOL)canBecomeMainWindow +{ + return YES; +} + +- (void)setIsVisible:(BOOL)flag +{ + if (flag && !puglview->visible) { + const PuglConfigureEvent ev = { + PUGL_CONFIGURE, + 0, + puglview->frame.x, + puglview->frame.y, + puglview->frame.width, + puglview->frame.height, + }; + + PuglEvent configureEvent; + configureEvent.configure = ev; + puglDispatchEvent(puglview, &configureEvent); + puglDispatchSimpleEvent(puglview, PUGL_MAP); + } else if (!flag && puglview->visible) { + puglDispatchSimpleEvent(puglview, PUGL_UNMAP); + } + + puglview->visible = flag; + + [super setIsVisible:flag]; +} + +@end + +@implementation PuglWrapperView { +@public + PuglView* puglview; + NSTrackingArea* trackingArea; + NSMutableAttributedString* markedText; + NSMutableDictionary* userTimers; + id dragSource; + NSDragOperation dragOperation; + size_t dragTypeIndex; + NSString* droppedUriList; + bool reshaped; +} + +- (void)dispatchExpose:(NSRect)rect +{ + const double scaleFactor = [[NSScreen mainScreen] backingScaleFactor]; + + if (reshaped) { + updateViewRect(puglview); + + const PuglConfigureEvent ev = { + PUGL_CONFIGURE, + 0, + puglview->frame.x, + puglview->frame.y, + puglview->frame.width, + puglview->frame.height, + }; + + PuglEvent configureEvent; + configureEvent.configure = ev; + puglDispatchEvent(puglview, &configureEvent); + reshaped = false; + } + + if (![[puglview->impl->drawView window] isVisible]) { + return; + } + + const PuglExposeEvent ev = { + PUGL_EXPOSE, + 0, + (PuglCoord)(rect.origin.x * scaleFactor), + (PuglCoord)(rect.origin.y * scaleFactor), + (PuglSpan)(rect.size.width * scaleFactor), + (PuglSpan)(rect.size.height * scaleFactor), + }; + + PuglEvent exposeEvent; + exposeEvent.expose = ev; + puglDispatchEvent(puglview, &exposeEvent); +} + +- (NSSize)intrinsicContentSize +{ + const PuglViewSize defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE]; + + return (defaultSize.width && defaultSize.height) + ? sizePoints(puglview, defaultSize.width, defaultSize.height) + : NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); +} + +- (BOOL)isFlipped +{ + return YES; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (void)setReshaped +{ + reshaped = true; +} + +static uint32_t +getModifiers(const NSEvent* const ev) +{ + const NSEventModifierFlags modifierFlags = [ev modifierFlags]; + + return (((modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0) | + ((modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0) | + ((modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0) | + ((modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0)); +} + +static PuglKey +keySymToSpecial(const NSEvent* const ev) +{ + NSString* chars = [ev charactersIgnoringModifiers]; + if ([chars length] == 1) { + switch ([chars characterAtIndex:0]) { + case NSF1FunctionKey: + return PUGL_KEY_F1; + case NSF2FunctionKey: + return PUGL_KEY_F2; + case NSF3FunctionKey: + return PUGL_KEY_F3; + case NSF4FunctionKey: + return PUGL_KEY_F4; + case NSF5FunctionKey: + return PUGL_KEY_F5; + case NSF6FunctionKey: + return PUGL_KEY_F6; + case NSF7FunctionKey: + return PUGL_KEY_F7; + case NSF8FunctionKey: + return PUGL_KEY_F8; + case NSF9FunctionKey: + return PUGL_KEY_F9; + case NSF10FunctionKey: + return PUGL_KEY_F10; + case NSF11FunctionKey: + return PUGL_KEY_F11; + case NSF12FunctionKey: + return PUGL_KEY_F12; + case NSDeleteCharacter: + return PUGL_KEY_BACKSPACE; + case NSDeleteFunctionKey: + return PUGL_KEY_DELETE; + case NSLeftArrowFunctionKey: + return PUGL_KEY_LEFT; + case NSUpArrowFunctionKey: + return PUGL_KEY_UP; + case NSRightArrowFunctionKey: + return PUGL_KEY_RIGHT; + case NSDownArrowFunctionKey: + return PUGL_KEY_DOWN; + case NSPageUpFunctionKey: + return PUGL_KEY_PAGE_UP; + case NSPageDownFunctionKey: + return PUGL_KEY_PAGE_DOWN; + case NSHomeFunctionKey: + return PUGL_KEY_HOME; + case NSEndFunctionKey: + return PUGL_KEY_END; + case NSInsertFunctionKey: + return PUGL_KEY_INSERT; + case NSMenuFunctionKey: + return PUGL_KEY_MENU; + case NSScrollLockFunctionKey: + return PUGL_KEY_SCROLL_LOCK; + case NSClearLineFunctionKey: + return PUGL_KEY_NUM_LOCK; + case NSPrintScreenFunctionKey: + return PUGL_KEY_PRINT_SCREEN; + case NSPauseFunctionKey: + return PUGL_KEY_PAUSE; + } + // SHIFT, CTRL, ALT, and SUPER are handled in [flagsChanged] + } + return (PuglKey)0; +} + +- (void)updateTrackingAreas +{ + if (trackingArea != nil) { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + } + + const int opts = (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | + NSTrackingActiveAlways); + trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] + options:opts + owner:self + userInfo:nil]; + [self addTrackingArea:trackingArea]; + [super updateTrackingAreas]; +} + +- (NSPoint)eventLocation:(NSEvent*)event +{ + return nsPointFromPoints( + puglview, [self convertPoint:[event locationInWindow] fromView:nil]); +} + +static void +handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) +{ + const NSPoint wloc = [view eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const PuglCrossingEvent ev = { + type, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + PUGL_CROSSING_NORMAL, + }; + + PuglEvent crossingEvent; + crossingEvent.crossing = ev; + puglDispatchEvent(view->puglview, &crossingEvent); +} + +- (void)mouseEntered:(NSEvent*)event +{ + handleCrossing(self, event, PUGL_POINTER_IN); + [puglview->impl->cursor set]; + puglview->impl->mouseTracked = true; +} + +- (void)mouseExited:(NSEvent*)event +{ + [[NSCursor arrowCursor] set]; + handleCrossing(self, event, PUGL_POINTER_OUT); + puglview->impl->mouseTracked = false; +} + +- (void)cursorUpdate:(NSEvent*)event +{ + (void)event; + [puglview->impl->cursor set]; +} + +- (void)mouseMoved:(NSEvent*)event +{ + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const PuglMotionEvent ev = { + PUGL_MOTION, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + }; + + PuglEvent motionEvent; + motionEvent.motion = ev; + puglDispatchEvent(puglview, &motionEvent); +} + +- (void)mouseDragged:(NSEvent*)event +{ + [self mouseMoved:event]; +} + +- (void)rightMouseDragged:(NSEvent*)event +{ + [self mouseMoved:event]; +} + +- (void)otherMouseDragged:(NSEvent*)event +{ + [self mouseMoved:event]; +} + +- (void)mouseDown:(NSEvent*)event +{ + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const PuglButtonEvent ev = { + PUGL_BUTTON_PRESS, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + (uint32_t)[event buttonNumber], + }; + + PuglEvent pressEvent; + pressEvent.button = ev; + puglDispatchEvent(puglview, &pressEvent); +} + +- (void)mouseUp:(NSEvent*)event +{ + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const PuglButtonEvent ev = { + PUGL_BUTTON_RELEASE, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + (uint32_t)[event buttonNumber], + }; + + PuglEvent releaseEvent; + releaseEvent.button = ev; + puglDispatchEvent(puglview, &releaseEvent); +} + +- (void)rightMouseDown:(NSEvent*)event +{ + [self mouseDown:event]; +} + +- (void)rightMouseUp:(NSEvent*)event +{ + [self mouseUp:event]; +} + +- (void)otherMouseDown:(NSEvent*)event +{ + [self mouseDown:event]; +} + +- (void)otherMouseUp:(NSEvent*)event +{ + [self mouseUp:event]; +} + +- (void)scrollWheel:(NSEvent*)event +{ + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const double dx = [event scrollingDeltaX]; + const double dy = [event scrollingDeltaY]; + const PuglScrollDirection dir = + ((dx == 0.0 && dy > 0.0) + ? PUGL_SCROLL_UP + : ((dx == 0.0 && dy < 0.0) + ? PUGL_SCROLL_DOWN + : ((dy == 0.0 && dx > 0.0) + ? PUGL_SCROLL_RIGHT + : ((dy == 0.0 && dx < 0.0) ? PUGL_SCROLL_LEFT + : PUGL_SCROLL_SMOOTH)))); + + const PuglScrollEvent ev = { + PUGL_SCROLL, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir, + dx, + dy, + }; + + PuglEvent scrollEvent; + scrollEvent.scroll = ev; + puglDispatchEvent(puglview, &scrollEvent); +} + +- (void)keyDown:(NSEvent*)event +{ + if (puglview->hints[PUGL_IGNORE_KEY_REPEAT] && [event isARepeat]) { + return; + } + + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const PuglKey spec = keySymToSpecial(event); + const NSString* chars = [event charactersIgnoringModifiers]; + const char* str = [[chars lowercaseString] UTF8String]; + const uint32_t code = (spec ? spec : puglDecodeUTF8((const uint8_t*)str)); + + const PuglKeyEvent ev = { + PUGL_KEY_PRESS, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + [event keyCode], + (code != 0xFFFD) ? code : 0, + }; + + PuglEvent pressEvent; + pressEvent.key = ev; + puglDispatchEvent(puglview, &pressEvent); + + if (!spec) { + [self interpretKeyEvents:@[event]]; + } +} + +- (void)keyUp:(NSEvent*)event +{ + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + const PuglKey spec = keySymToSpecial(event); + const NSString* chars = [event charactersIgnoringModifiers]; + const char* str = [[chars lowercaseString] UTF8String]; + const uint32_t code = (spec ? spec : puglDecodeUTF8((const uint8_t*)str)); + + const PuglKeyEvent ev = { + PUGL_KEY_RELEASE, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + [event keyCode], + (code != 0xFFFD) ? code : 0, + }; + + PuglEvent releaseEvent; + releaseEvent.key = ev; + puglDispatchEvent(puglview, &releaseEvent); +} + +- (BOOL)hasMarkedText +{ + return [markedText length] > 0; +} + +- (NSRange)markedRange +{ + return (([markedText length] > 0) ? NSMakeRange(0, [markedText length] - 1) + : NSMakeRange(NSNotFound, 0)); +} + +- (NSRange)selectedRange +{ + return NSMakeRange(NSNotFound, 0); +} + +- (void)setMarkedText:(id)string + selectedRange:(NSRange)selected + replacementRange:(NSRange)replacement +{ + (void)selected; + (void)replacement; + [markedText release]; + markedText = + ([(NSObject*)string isKindOfClass:[NSAttributedString class]] + ? [[NSMutableAttributedString alloc] initWithAttributedString:string] + : [[NSMutableAttributedString alloc] initWithString:string]); +} + +- (void)unmarkText +{ + [[markedText mutableString] setString:@""]; +} + +- (NSArray*)validAttributesForMarkedText +{ + return @[]; +} + +- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range + actualRange: + (NSRangePointer)actual +{ + (void)range; + (void)actual; + return nil; +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)point +{ + (void)point; + return 0; +} + +- (NSRect)firstRectForCharacterRange:(NSRange)range + actualRange:(NSRangePointer)actual +{ + (void)range; + (void)actual; + + const NSRect frame = [self bounds]; + return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0); +} + +- (void)doCommandBySelector:(SEL)selector +{ + (void)selector; +} + +- (void)insertText:(id)string replacementRange:(NSRange)replacement +{ + (void)replacement; + + NSEvent* const event = [NSApp currentEvent]; + NSString* const characters = + ([(NSObject*)string isKindOfClass:[NSAttributedString class]] + ? [(NSAttributedString*)string string] + : (NSString*)string); + + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + for (size_t i = 0; i < [characters length]; ++i) { + const uint32_t code = [characters characterAtIndex:i]; + char utf8[8] = {0}; + NSUInteger len = 0; + + [characters getBytes:utf8 + maxLength:sizeof(utf8) + usedLength:&len + encoding:NSUTF8StringEncoding + options:0 + range:NSMakeRange(i, i + 1) + remainingRange:nil]; + + PuglTextEvent ev = { + PUGL_TEXT, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + getModifiers(event), + [event keyCode], + code, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + }; + + memcpy(ev.string, utf8, len); + + PuglEvent textEvent; + textEvent.text = ev; + puglDispatchEvent(puglview, &textEvent); + } +} + +- (void)flagsChanged:(NSEvent*)event +{ + const uint32_t mods = getModifiers(event); + PuglEventType type = PUGL_NOTHING; + PuglKey special = (PuglKey)0; + + if ((mods & PUGL_MOD_SHIFT) != (puglview->impl->mods & PUGL_MOD_SHIFT)) { + type = mods & PUGL_MOD_SHIFT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; + special = PUGL_KEY_SHIFT; + } else if ((mods & PUGL_MOD_CTRL) != (puglview->impl->mods & PUGL_MOD_CTRL)) { + type = mods & PUGL_MOD_CTRL ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; + special = PUGL_KEY_CTRL; + } else if ((mods & PUGL_MOD_ALT) != (puglview->impl->mods & PUGL_MOD_ALT)) { + type = mods & PUGL_MOD_ALT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; + special = PUGL_KEY_ALT; + } else if ((mods & PUGL_MOD_SUPER) != + (puglview->impl->mods & PUGL_MOD_SUPER)) { + type = mods & PUGL_MOD_SUPER ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; + special = PUGL_KEY_SUPER; + } + + if (special != 0) { + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + + const PuglKeyEvent ev = {type, + 0, + [event timestamp], + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + mods, + [event keyCode], + special}; + + PuglEvent keyEvent; + keyEvent.key = ev; + puglDispatchEvent(puglview, &keyEvent); + } + + puglview->impl->mods = mods; +} + +- (BOOL)preservesContentInLiveResize +{ + return NO; +} + +- (void)viewWillStartLiveResize +{ + puglDispatchSimpleEvent(puglview, PUGL_LOOP_ENTER); +} + +- (void)viewWillDraw +{ + puglDispatchSimpleEvent(puglview, PUGL_UPDATE); + [super viewWillDraw]; +} + +- (void)resizeTick +{ + puglPostRedisplay(puglview); +} + +- (void)timerTick:(NSTimer*)userTimer +{ + const NSNumber* userInfo = userTimer.userInfo; + const PuglTimerEvent ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue}; + + PuglEvent timerEvent; + timerEvent.timer = ev; + puglDispatchEvent(puglview, &timerEvent); +} + +- (void)viewDidEndLiveResize +{ + puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE); +} + +@end + +@interface PuglWindowDelegate : NSObject + +- (instancetype)initWithPuglWindow:(PuglWindow*)window; + +@end + +@implementation PuglWindowDelegate { + PuglWindow* window; +} + +- (instancetype)initWithPuglWindow:(PuglWindow*)puglWindow +{ + if ((self = [super init])) { + window = puglWindow; + } + + return self; +} + +- (BOOL)windowShouldClose:(id)sender +{ + (void)sender; + + puglDispatchSimpleEvent(window->puglview, PUGL_CLOSE); + return YES; +} + +- (void)windowDidMove:(NSNotification*)notification +{ + (void)notification; + + updateViewRect(window->puglview); +} + +- (void)windowDidBecomeKey:(NSNotification*)notification +{ + (void)notification; + + PuglEvent ev = {{PUGL_FOCUS_IN, 0}}; + ev.focus.mode = PUGL_CROSSING_NORMAL; + puglDispatchEvent(window->puglview, &ev); +} + +- (void)windowDidResignKey:(NSNotification*)notification +{ + (void)notification; + + PuglEvent ev = {{PUGL_FOCUS_OUT, 0}}; + ev.focus.mode = PUGL_CROSSING_NORMAL; + puglDispatchEvent(window->puglview, &ev); +} + +@end + +PuglWorldInternals* +puglInitWorldInternals(PuglWorldType type, PuglWorldFlags PUGL_UNUSED(flags)) +{ + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); + + impl->app = [NSApplication sharedApplication]; + + if (type == PUGL_PROGRAM) { + impl->autoreleasePool = [NSAutoreleasePool new]; + + [impl->app setActivationPolicy:NSApplicationActivationPolicyRegular]; + } + + return impl; +} + +void +puglFreeWorldInternals(PuglWorld* world) +{ + if (world->impl->autoreleasePool) { + [world->impl->autoreleasePool drain]; + } + + free(world->impl); +} + +void* +puglGetNativeWorld(PuglWorld* world) +{ + return world->impl->app; +} + +PuglInternals* +puglInitViewInternals(PuglWorld* PUGL_UNUSED(world)) +{ + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + + impl->cursor = [NSCursor arrowCursor]; + + return impl; +} + +static NSLayoutConstraint* +puglConstraint(const id item, + const NSLayoutAttribute attribute, + const NSLayoutRelation relation, + const float constant) +{ + return [NSLayoutConstraint constraintWithItem:item + attribute:attribute + relatedBy:relation + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:(CGFloat)constant]; +} + +static PuglStatus +updateSizeHint(PuglView* const view, const PuglSizeHint hint) +{ + const PuglSpan width = view->sizeHints[hint].width; + const PuglSpan height = view->sizeHints[hint].height; + if (!width || !height) { + return PUGL_FAILURE; + } + + switch (hint) { + case PUGL_DEFAULT_SIZE: + break; + + case PUGL_MIN_SIZE: + [view->impl->window setContentMinSize:sizePoints(view, width, height)]; + break; + + case PUGL_MAX_SIZE: + [view->impl->window setContentMaxSize:sizePoints(view, width, height)]; + break; + + case PUGL_FIXED_ASPECT: + [view->impl->window setContentAspectRatio:sizePoints(view, width, height)]; + break; + + case PUGL_MIN_ASPECT: + case PUGL_MAX_ASPECT: + break; + } + + return PUGL_SUCCESS; +} + +static void +updateSizeHints(PuglView* const view) +{ + for (unsigned i = 0u; i < PUGL_NUM_SIZE_HINTS; ++i) { + updateSizeHint(view, (PuglSizeHint)i); + } +} + +PuglStatus +puglRealize(PuglView* view) +{ + PuglInternals* impl = view->impl; + + if (impl->wrapperView) { + return PUGL_FAILURE; + } + + if (!view->backend || !view->backend->configure) { + return PUGL_BAD_BACKEND; + } + + const NSScreen* const screen = [NSScreen mainScreen]; + const double scaleFactor = [screen backingScaleFactor]; + + // Getting depth from the display mode seems tedious, just set usual values + if (view->hints[PUGL_RED_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_RED_BITS] = 8; + } + if (view->hints[PUGL_BLUE_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_BLUE_BITS] = 8; + } + if (view->hints[PUGL_GREEN_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_GREEN_BITS] = 8; + } + if (view->hints[PUGL_ALPHA_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_ALPHA_BITS] = 8; + } + + CGDirectDisplayID displayId = CGMainDisplayID(); + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId); + + // Try to get refresh rate from mode (usually fails) + view->hints[PUGL_REFRESH_RATE] = (int)CGDisplayModeGetRefreshRate(mode); + + CGDisplayModeRelease(mode); + if (view->hints[PUGL_REFRESH_RATE] == 0) { + // Get refresh rate from a display link + // TODO: Keep and actually use the display link for something? + CVDisplayLinkRef link; + CVDisplayLinkCreateWithCGDisplay(displayId, &link); + + const CVTime p = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); + const double r = p.timeScale / (double)p.timeValue; + view->hints[PUGL_REFRESH_RATE] = (int)lrint(r); + + CVDisplayLinkRelease(link); + } + + if (view->frame.width == 0.0 && view->frame.height == 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { + return PUGL_BAD_CONFIGURATION; + } + + const double screenWidthPx = [screen frame].size.width * scaleFactor; + const double screenHeightPx = [screen frame].size.height * scaleFactor; + + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + + if (view->impl->window) { + view->frame.x = (PuglCoord)((screenWidthPx - view->frame.width) / 2.0); + view->frame.y = (PuglCoord)((screenHeightPx - view->frame.height) / 2.0); + } + } + + const NSRect framePx = rectToNsRect(view->frame); + const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor, + framePx.origin.y / scaleFactor, + framePx.size.width / scaleFactor, + framePx.size.height / scaleFactor); + + // Create wrapper view to handle input + impl->wrapperView = [PuglWrapperView alloc]; + impl->wrapperView->puglview = view; + impl->wrapperView->userTimers = [[NSMutableDictionary alloc] init]; + impl->wrapperView->markedText = [[NSMutableAttributedString alloc] init]; + [impl->wrapperView setAutoresizesSubviews:YES]; + [impl->wrapperView initWithFrame:framePt]; + + [impl->wrapperView + addConstraint:puglConstraint(impl->wrapperView, + NSLayoutAttributeWidth, + NSLayoutRelationGreaterThanOrEqual, + view->sizeHints[PUGL_MIN_SIZE].width)]; + + [impl->wrapperView + addConstraint:puglConstraint(impl->wrapperView, + NSLayoutAttributeHeight, + NSLayoutRelationGreaterThanOrEqual, + view->sizeHints[PUGL_MIN_SIZE].height)]; + + if (view->sizeHints[PUGL_MAX_SIZE].width && + view->sizeHints[PUGL_MAX_SIZE].height) { + [impl->wrapperView + addConstraint:puglConstraint(impl->wrapperView, + NSLayoutAttributeWidth, + NSLayoutRelationLessThanOrEqual, + view->sizeHints[PUGL_MAX_SIZE].width)]; + + [impl->wrapperView + addConstraint:puglConstraint(impl->wrapperView, + NSLayoutAttributeHeight, + NSLayoutRelationLessThanOrEqual, + view->sizeHints[PUGL_MAX_SIZE].height)]; + } + + // Create draw view to be rendered to + PuglStatus st = PUGL_SUCCESS; + if ((st = view->backend->configure(view)) || + (st = view->backend->create(view))) { + return st; + } + + // Add draw view to wrapper view + [impl->wrapperView addSubview:impl->drawView]; + [impl->wrapperView setHidden:NO]; + [impl->drawView setHidden:NO]; + + if (view->parent) { + NSView* pview = (NSView*)view->parent; + [pview addSubview:impl->wrapperView]; + [impl->drawView setHidden:NO]; + [[impl->drawView window] makeFirstResponder:impl->wrapperView]; + } else { + unsigned style = + (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask); + if (view->hints[PUGL_RESIZABLE]) { + style |= NSResizableWindowMask; + } + + PuglWindow* window = [[[PuglWindow alloc] + initWithContentRect:rectToScreen([NSScreen mainScreen], framePt) + styleMask:style + backing:NSBackingStoreBuffered + defer:NO] retain]; + [window setPuglview:view]; + + if (view->title) { + NSString* titleString = + [[NSString alloc] initWithBytes:view->title + length:strlen(view->title) + encoding:NSUTF8StringEncoding]; + + [window setTitle:titleString]; + } + + ((NSWindow*)window).delegate = + [[PuglWindowDelegate alloc] initWithPuglWindow:window]; + + impl->window = window; + + updateSizeHints(view); + puglSetFrame(view, view->frame); + + [window setContentView:impl->wrapperView]; + [view->world->impl->app activateIgnoringOtherApps:YES]; + [window makeFirstResponder:impl->wrapperView]; + [window makeKeyAndOrderFront:window]; + [impl->window setIsVisible:NO]; + } + + [impl->wrapperView updateTrackingAreas]; + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + return PUGL_SUCCESS; +} + +PuglStatus +puglShow(PuglView* view) +{ + if (!view->impl->wrapperView) { + const PuglStatus st = puglRealize(view); + if (st) { + return st; + } + } + + if (![view->impl->window isVisible]) { + [view->impl->window setIsVisible:YES]; + [view->impl->drawView setNeedsDisplay:YES]; + updateViewRect(view); + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglHide(PuglView* view) +{ + [view->impl->window setIsVisible:NO]; + return PUGL_SUCCESS; +} + +void +puglFreeViewInternals(PuglView* view) +{ + if (view) { + if (view->backend) { + view->backend->destroy(view); + } + + if (view->impl) { + if (view->impl->wrapperView) { + [view->impl->wrapperView removeFromSuperview]; + view->impl->wrapperView->puglview = NULL; + } + + if (view->impl->window) { + [view->impl->window close]; + } + + if (view->impl->wrapperView) { + [view->impl->wrapperView release]; + } + + if (view->impl->window) { + [view->impl->window release]; + } + + free(view->impl); + } + } +} + +PuglStatus +puglGrabFocus(PuglView* view) +{ + NSWindow* window = [view->impl->wrapperView window]; + + [window makeKeyWindow]; + [window makeFirstResponder:view->impl->wrapperView]; + return PUGL_SUCCESS; +} + +bool +puglHasFocus(const PuglView* view) +{ + PuglInternals* const impl = view->impl; + + return ([[impl->wrapperView window] isKeyWindow] && + [[impl->wrapperView window] firstResponder] == impl->wrapperView); +} + +PuglStatus +puglRequestAttention(PuglView* view) +{ + if (![view->impl->window isKeyWindow]) { + [view->world->impl->app requestUserAttention:NSInformationalRequest]; + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglStartTimer(PuglView* view, uintptr_t id, double timeout) +{ + puglStopTimer(view, id); + + NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id]; + + NSTimer* timer = [NSTimer timerWithTimeInterval:timeout + target:view->impl->wrapperView + selector:@selector(timerTick:) + userInfo:idNumber + repeats:YES]; + + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + + view->impl->wrapperView->userTimers[idNumber] = timer; + + return PUGL_SUCCESS; +} + +PuglStatus +puglStopTimer(PuglView* view, uintptr_t id) +{ + NSNumber* idNumber = [NSNumber numberWithUnsignedLong:id]; + NSTimer* timer = view->impl->wrapperView->userTimers[idNumber]; + + if (timer) { + [view->impl->wrapperView->userTimers removeObjectForKey:timer]; + [timer invalidate]; + return PUGL_SUCCESS; + } + + return PUGL_UNKNOWN_ERROR; +} + +PuglStatus +puglSendEvent(PuglView* view, const PuglEvent* event) +{ + if (event->type == PUGL_CLIENT) { + PuglEvent copiedEvent = *event; + + CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler( + NULL, + kCFRunLoopAfterWaiting, + false, + 0, + ^(CFRunLoopObserverRef, CFRunLoopActivity) { + puglDispatchEvent(view, &copiedEvent); + }); + + CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes); + + CFRelease(observer); + + return PUGL_SUCCESS; + } + + return PUGL_UNSUPPORTED; +} + +#ifndef PUGL_DISABLE_DEPRECATED +PuglStatus +puglWaitForEvent(PuglView* view) +{ + return puglPollEvents(view->world, -1.0); +} +#endif + +PuglStatus +puglUpdate(PuglWorld* world, const double timeout) +{ + @autoreleasepool { + if (world->impl->autoreleasePool != nil) { + NSDate* date = + ((timeout < 0) ? [NSDate distantFuture] + : [NSDate dateWithTimeIntervalSinceNow:timeout]); + + for (NSEvent* ev = NULL; + (ev = [world->impl->app nextEventMatchingMask:NSAnyEventMask + untilDate:date + inMode:NSDefaultRunLoopMode + dequeue:YES]);) { + [world->impl->app sendEvent:ev]; + + if (timeout < 0) { + // Now that we've waited and got an event, set the date to now to avoid + // looping forever + date = [NSDate date]; + } + } + } + + for (size_t i = 0; i < world->numViews; ++i) { + PuglView* const view = world->views[i]; + + if ([[view->impl->drawView window] isVisible]) { + puglDispatchSimpleEvent(view, PUGL_UPDATE); + } + + [view->impl->drawView displayIfNeeded]; + } + } + + return PUGL_SUCCESS; +} + +#ifndef PUGL_DISABLE_DEPRECATED +PuglStatus +puglProcessEvents(PuglView* view) +{ + return puglDispatchEvents(view->world); +} +#endif + +double +puglGetTime(const PuglWorld* world) +{ + return (clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9) - world->startTime; +} + +PuglStatus +puglPostRedisplay(PuglView* view) +{ + [view->impl->drawView setNeedsDisplay:YES]; + return PUGL_SUCCESS; +} + +PuglStatus +puglPostRedisplayRect(PuglView* view, const PuglRect rect) +{ + const NSRect rectPx = rectToNsRect(rect); + + [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; + + return PUGL_SUCCESS; +} + +PuglNativeView +puglGetNativeView(PuglView* view) +{ + return (PuglNativeView)view->impl->wrapperView; +} + +PuglStatus +puglSetWindowTitle(PuglView* view, const char* title) +{ + puglSetString(&view->title, title); + + if (view->impl->window) { + NSString* titleString = + [[NSString alloc] initWithBytes:title + length:strlen(title) + encoding:NSUTF8StringEncoding]; + + [view->impl->window setTitle:titleString]; + } + + return PUGL_SUCCESS; +} + +double +puglGetScaleFactor(const PuglView* const view) +{ + return [viewScreen(view) backingScaleFactor]; +} + +PuglStatus +puglSetFrame(PuglView* view, const PuglRect frame) +{ + PuglInternals* const impl = view->impl; + const NSRect framePx = rectToNsRect(frame); + const NSRect framePt = nsRectToPoints(view, framePx); + + // Update view frame to exactly the requested frame + view->frame = frame; + + if (impl->window) { + const NSRect screenPt = rectToScreen(viewScreen(view), framePt); + + // Move and resize window to fit new content rect + const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; + [impl->window setFrame:winFrame display:NO]; + + // Resize views + const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height); + const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; + [impl->wrapperView setFrame:sizePt]; + [impl->drawView setFrame:sizePt]; + } else { + // Resize view + const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height); + const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; + + [impl->wrapperView setFrame:framePt]; + [impl->drawView setFrame:sizePt]; + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglSetPosition(PuglView* const view, const int x, const int y) +{ + if (x > INT16_MAX || y > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + const PuglRect frame = { + (PuglCoord)x, (PuglCoord)y, view->frame.height, view->frame.height}; + + PuglInternals* const impl = view->impl; + if (impl->window) { + return puglSetFrame(view, frame); + } + + const NSRect framePx = rectToNsRect(frame); + const NSRect framePt = nsRectToPoints(view, framePx); + [impl->wrapperView setFrameOrigin:framePt.origin]; + + const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height); + const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx]; + [impl->drawView setFrameOrigin:drawPt.origin]; + + view->frame = frame; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSize(PuglView* const view, const unsigned width, const unsigned height) +{ + if (width > INT16_MAX || height > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + const PuglRect frame = { + view->frame.x, view->frame.y, (PuglSpan)width, (PuglSpan)height}; + + PuglInternals* const impl = view->impl; + if (impl->window) { + return puglSetFrame(view, frame); + } + + const NSRect framePx = rectToNsRect(frame); + const NSRect framePt = nsRectToPoints(view, framePx); + [impl->wrapperView setFrameSize:framePt.size]; + + const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height); + const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx]; + [impl->drawView setFrameSize:drawPt.size]; + + view->frame = frame; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) +{ + if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) { + return PUGL_BAD_PARAMETER; + } + + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; + + return view->impl->window ? updateSizeHint(view, hint) : PUGL_SUCCESS; +} + +PuglStatus +puglSetTransientParent(PuglView* view, PuglNativeView parent) +{ + view->transientParent = parent; + + if (view->impl->window) { + NSWindow* parentWindow = [(NSView*)parent window]; + if (parentWindow) { + [parentWindow addChildWindow:view->impl->window ordered:NSWindowAbove]; + return PUGL_SUCCESS; + } + } + + return PUGL_FAILURE; +} + +PuglStatus +puglPaste(PuglView* const view) +{ + const PuglDataOfferEvent offer = { + PUGL_DATA_OFFER, + 0, + mach_absolute_time() / 1e9, + }; + + PuglEvent offerEvent; + offerEvent.offer = offer; + puglDispatchEvent(view, &offerEvent); + return PUGL_SUCCESS; +} + +uint32_t +puglGetNumClipboardTypes(const PuglView* PUGL_UNUSED(view)) +{ + NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; + + return pasteboard ? (uint32_t)[[pasteboard types] count] : 0; +} + +const char* +puglGetClipboardType(const PuglView* PUGL_UNUSED(view), + const uint32_t typeIndex) +{ + NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; + if (!pasteboard) { + return NULL; + } + + const NSArray* const types = [pasteboard types]; + if (typeIndex >= [types count]) { + return NULL; + } + + NSString* const uti = [types objectAtIndex:typeIndex]; + NSString* const mimeType = mimeTypeForUti(uti); + + // FIXME: lifetime? + return mimeType ? [mimeType UTF8String] : [uti UTF8String]; +} + +PuglStatus +puglAcceptOffer(PuglView* const view, + const PuglDataOfferEvent* const PUGL_UNUSED(offer), + const uint32_t typeIndex) +{ + PuglWrapperView* const wrapper = view->impl->wrapperView; + NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; + if (!pasteboard) { + return PUGL_BAD_PARAMETER; + } + + const NSArray* const types = [pasteboard types]; + if (typeIndex >= [types count]) { + return PUGL_BAD_PARAMETER; + } + + wrapper->dragOperation = NSDragOperationCopy; + wrapper->dragTypeIndex = typeIndex; + + const PuglDataEvent data = { + PUGL_DATA, 0u, mach_absolute_time() / 1e9, (uint32_t)typeIndex}; + + PuglEvent dataEvent; + dataEvent.data = data; + puglDispatchEvent(view, &dataEvent); + return PUGL_SUCCESS; +} + +const void* +puglGetClipboard(PuglView* const view, + const uint32_t typeIndex, + size_t* const len) +{ + *len = 0; + + NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; + if (!pasteboard) { + return NULL; + } + + const NSArray* const types = [pasteboard types]; + if (typeIndex >= [types count]) { + return NULL; + } + + NSString* const uti = [types objectAtIndex:typeIndex]; + if ([uti isEqualToString:@"public.file-url"] || + [uti isEqualToString:@"com.apple.pasteboard.promised-file-url"]) { + *len = [view->impl->wrapperView->droppedUriList length]; + return [view->impl->wrapperView->droppedUriList UTF8String]; + } + + const NSData* const data = [pasteboard dataForType:uti]; + + *len = [data length]; + return [data bytes]; +} + +static NSCursor* +puglGetNsCursor(const PuglCursor cursor) +{ + SEL cursorSelector = nil; + + switch (cursor) { + case PUGL_CURSOR_ARROW: + return [NSCursor arrowCursor]; + case PUGL_CURSOR_CARET: + return [NSCursor IBeamCursor]; + case PUGL_CURSOR_CROSSHAIR: + return [NSCursor crosshairCursor]; + case PUGL_CURSOR_HAND: + return [NSCursor pointingHandCursor]; + case PUGL_CURSOR_NO: + return [NSCursor operationNotAllowedCursor]; + case PUGL_CURSOR_LEFT_RIGHT: + return [NSCursor resizeLeftRightCursor]; + case PUGL_CURSOR_UP_DOWN: + return [NSCursor resizeUpDownCursor]; + case PUGL_CURSOR_DIAGONAL: + cursorSelector = @selector(_windowResizeNorthWestSouthEastCursor); + break; + case PUGL_CURSOR_ANTI_DIAGONAL: + cursorSelector = @selector(_windowResizeNorthEastSouthWestCursor); + break; + } + + if (cursorSelector && [NSCursor respondsToSelector:cursorSelector]) + { + const id object = [NSCursor performSelector:cursorSelector]; + if ([object isKindOfClass:[NSCursor class]]) + return (NSCursor*)object; + } + + return NULL; +} + +PuglStatus +puglSetCursor(PuglView* view, PuglCursor cursor) +{ + PuglInternals* const impl = view->impl; + NSCursor* const cur = puglGetNsCursor(cursor); + if (!cur) { + return PUGL_FAILURE; + } + + impl->cursor = cur; + + if (impl->mouseTracked) { + [cur set]; + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglSetClipboard(PuglView* PUGL_UNUSED(view), + const char* const type, + const void* const data, + const size_t len) +{ + NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard]; + NSString* const mimeType = [NSString stringWithUTF8String:type]; + NSString* const uti = utiForMimeType(mimeType); + NSData* const blob = [NSData dataWithBytes:data length:len]; + + [pasteboard declareTypes:[NSArray arrayWithObjects:uti, nil] owner:nil]; + + if ([pasteboard setData:blob forType:uti]) { + return PUGL_SUCCESS; + } + + return PUGL_FAILURE; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_cairo.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_cairo.m Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,150 @@ +// Copyright 2019-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "internal.h" +#include "mac.h" +#include "stub.h" + +#include "pugl/cairo.h" + +#include + +#import + +#include + +@interface PuglCairoView : NSView +@end + +@implementation PuglCairoView { +@public + PuglView* puglview; + cairo_surface_t* surface; + cairo_t* cr; +} + +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + + return self; +} + +- (void)resizeWithOldSuperviewSize:(NSSize)oldSize +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + + [super resizeWithOldSuperviewSize:oldSize]; + [wrapper setReshaped]; +} + +- (void)drawRect:(NSRect)rect +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + [wrapper dispatchExpose:rect]; +} + +@end + +static PuglStatus +puglMacCairoCreate(PuglView* view) +{ + PuglInternals* impl = view->impl; + PuglCairoView* drawView = [PuglCairoView alloc]; + + drawView->puglview = view; + [drawView initWithFrame:[impl->wrapperView bounds]]; + if (view->hints[PUGL_RESIZABLE]) { + [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + } else { + [drawView setAutoresizingMask:NSViewNotSizable]; + } + + impl->drawView = drawView; + return PUGL_SUCCESS; +} + +static void +puglMacCairoDestroy(PuglView* view) +{ + PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView; + + [drawView removeFromSuperview]; + [drawView release]; + + view->impl->drawView = nil; +} + +static PuglStatus +puglMacCairoEnter(PuglView* view, const PuglExposeEvent* expose) +{ + PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView; + if (!expose) { + return PUGL_SUCCESS; + } + + assert(!drawView->surface); + assert(!drawView->cr); + + const double scale = 1.0 / [[NSScreen mainScreen] backingScaleFactor]; + CGContextRef context = + (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + + const CGSize sizePx = {(CGFloat)view->frame.width, + (CGFloat)view->frame.height}; + + const CGSize sizePt = CGContextConvertSizeToUserSpace(context, sizePx); + + // Convert coordinates to standard Cairo space + CGContextTranslateCTM(context, 0.0, -sizePt.height); + CGContextScaleCTM(context, scale, -scale); + + drawView->surface = cairo_quartz_surface_create_for_cg_context( + context, (unsigned)sizePx.width, (unsigned)sizePx.height); + + drawView->cr = cairo_create(drawView->surface); + + return PUGL_SUCCESS; +} + +static PuglStatus +puglMacCairoLeave(PuglView* view, const PuglExposeEvent* expose) +{ + PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView; + if (!expose) { + return PUGL_SUCCESS; + } + + assert(drawView->surface); + assert(drawView->cr); + + CGContextRef context = cairo_quartz_surface_get_cg_context(drawView->surface); + + cairo_destroy(drawView->cr); + cairo_surface_destroy(drawView->surface); + drawView->cr = NULL; + drawView->surface = NULL; + + CGContextFlush(context); + + return PUGL_SUCCESS; +} + +static void* +puglMacCairoGetContext(PuglView* view) +{ + return ((PuglCairoView*)view->impl->drawView)->cr; +} + +const PuglBackend* +puglCairoBackend(void) +{ + static const PuglBackend backend = {puglStubConfigure, + puglMacCairoCreate, + puglMacCairoDestroy, + puglMacCairoEnter, + puglMacCairoLeave, + puglMacCairoGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_gl.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_gl.m Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,200 @@ +// Copyright 2019-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "internal.h" +#include "mac.h" +#include "stub.h" + +#include "pugl/gl.h" + +#ifndef __MAC_10_10 +# define NSOpenGLProfileVersion4_1Core NSOpenGLProfileVersion3_2Core +#endif + +@interface PuglOpenGLView : NSOpenGLView +@end + +@implementation PuglOpenGLView { +@public + PuglView* puglview; +} + +- (id)initWithFrame:(NSRect)frame +{ + const bool compat = puglview->hints[PUGL_USE_COMPAT_PROFILE]; + const unsigned samples = (unsigned)puglview->hints[PUGL_SAMPLES]; + const int major = puglview->hints[PUGL_CONTEXT_VERSION_MAJOR]; + const unsigned profile = + ((compat || major < 3) ? NSOpenGLProfileVersionLegacy + : (major >= 4 ? NSOpenGLProfileVersion4_1Core + : NSOpenGLProfileVersion3_2Core)); + + // Set attributes to default if they are unset + // (There is no GLX_DONT_CARE equivalent on MacOS) + if (puglview->hints[PUGL_DEPTH_BITS] == PUGL_DONT_CARE) { + puglview->hints[PUGL_DEPTH_BITS] = 0; + } + if (puglview->hints[PUGL_STENCIL_BITS] == PUGL_DONT_CARE) { + puglview->hints[PUGL_STENCIL_BITS] = 0; + } + if (puglview->hints[PUGL_SAMPLES] == PUGL_DONT_CARE) { + puglview->hints[PUGL_SAMPLES] = 1; + } + if (puglview->hints[PUGL_DOUBLE_BUFFER] == PUGL_DONT_CARE) { + puglview->hints[PUGL_DOUBLE_BUFFER] = 1; + } + if (puglview->hints[PUGL_SWAP_INTERVAL] == PUGL_DONT_CARE) { + puglview->hints[PUGL_SWAP_INTERVAL] = 1; + } + + const unsigned colorSize = (unsigned)(puglview->hints[PUGL_RED_BITS] + + puglview->hints[PUGL_BLUE_BITS] + + puglview->hints[PUGL_GREEN_BITS] + + puglview->hints[PUGL_ALPHA_BITS]); + + // clang-format off + NSOpenGLPixelFormatAttribute pixelAttribs[17] = { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccelerated, + NSOpenGLPFAOpenGLProfile, profile, + NSOpenGLPFAColorSize, colorSize, + NSOpenGLPFADepthSize, (unsigned)puglview->hints[PUGL_DEPTH_BITS], + NSOpenGLPFAStencilSize, (unsigned)puglview->hints[PUGL_STENCIL_BITS], + NSOpenGLPFAMultisample, samples ? 1u : 0u, + NSOpenGLPFASampleBuffers, samples ? 1u : 0u, + NSOpenGLPFASamples, samples, + 0}; + // clang-format on + + NSOpenGLPixelFormat* pixelFormat = + [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelAttribs]; + + if (pixelFormat) { + self = [super initWithFrame:frame pixelFormat:pixelFormat]; + [pixelFormat release]; + } else { + self = [super initWithFrame:frame]; + } + + [self setWantsBestResolutionOpenGLSurface:YES]; + + if (self) { + [[self openGLContext] makeCurrentContext]; + [self reshape]; + [NSOpenGLContext clearCurrentContext]; + } + return self; +} + +- (void)reshape +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + + [super reshape]; + [wrapper setReshaped]; +} + +- (void)drawRect:(NSRect)rect +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + [wrapper dispatchExpose:rect]; +} + +@end + +static PuglStatus +puglMacGlCreate(PuglView* view) +{ + PuglInternals* impl = view->impl; + PuglOpenGLView* drawView = [PuglOpenGLView alloc]; + + drawView->puglview = view; + [drawView initWithFrame:[impl->wrapperView bounds]]; + if (view->hints[PUGL_RESIZABLE]) { + [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + } else { + [drawView setAutoresizingMask:NSViewNotSizable]; + } + + impl->drawView = drawView; + return PUGL_SUCCESS; +} + +static void +puglMacGlDestroy(PuglView* view) +{ + PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView; + + [drawView removeFromSuperview]; + [drawView release]; + + view->impl->drawView = nil; +} + +static PuglStatus +puglMacGlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) +{ + PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView; + if (!drawView) { + return PUGL_FAILURE; + } + + [[drawView openGLContext] makeCurrentContext]; + return PUGL_SUCCESS; +} + +static PuglStatus +puglMacGlLeave(PuglView* view, const PuglExposeEvent* expose) +{ + PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView; + + if (expose) { + [[drawView openGLContext] flushBuffer]; + } + + [NSOpenGLContext clearCurrentContext]; + + return PUGL_SUCCESS; +} + +PuglGlFunc +puglGetProcAddress(const char* name) +{ + CFBundleRef framework = + CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); + + CFStringRef symbol = CFStringCreateWithCString( + kCFAllocatorDefault, name, kCFStringEncodingASCII); + + PuglGlFunc func = + (PuglGlFunc)CFBundleGetFunctionPointerForName(framework, symbol); + + CFRelease(symbol); + + return func; +} + +PuglStatus +puglEnterContext(PuglView* view) +{ + return view->backend->enter(view, NULL); +} + +PuglStatus +puglLeaveContext(PuglView* view) +{ + return view->backend->leave(view, NULL); +} + +const PuglBackend* +puglGlBackend(void) +{ + static const PuglBackend backend = {puglStubConfigure, + puglMacGlCreate, + puglMacGlDestroy, + puglMacGlEnter, + puglMacGlLeave, + puglStubGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_stub.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_stub.m Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,78 @@ +// Copyright 2019-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "internal.h" +#include "mac.h" +#include "stub.h" + +#include "pugl/stub.h" + +#import + +@interface PuglStubView : NSView +@end + +@implementation PuglStubView { +@public + PuglView* puglview; +} + +- (void)resizeWithOldSuperviewSize:(NSSize)oldSize +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + + [super resizeWithOldSuperviewSize:oldSize]; + [wrapper setReshaped]; +} + +- (void)drawRect:(NSRect)rect +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + + [wrapper dispatchExpose:rect]; +} + +@end + +static PuglStatus +puglMacStubCreate(PuglView* view) +{ + PuglInternals* impl = view->impl; + PuglStubView* drawView = [PuglStubView alloc]; + + drawView->puglview = view; + [drawView + initWithFrame:NSMakeRect(0, 0, view->frame.width, view->frame.height)]; + if (view->hints[PUGL_RESIZABLE]) { + [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + } else { + [drawView setAutoresizingMask:NSViewNotSizable]; + } + + impl->drawView = drawView; + return PUGL_SUCCESS; +} + +static void +puglMacStubDestroy(PuglView* view) +{ + PuglStubView* const drawView = (PuglStubView*)view->impl->drawView; + + [drawView removeFromSuperview]; + [drawView release]; + + view->impl->drawView = nil; +} + +const PuglBackend* +puglStubBackend(void) +{ + static const PuglBackend backend = {puglStubConfigure, + puglMacStubCreate, + puglMacStubDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_vulkan.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/mac_vulkan.m Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,197 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#define VK_NO_PROTOTYPES 1 + +#include "internal.h" +#include "mac.h" +#include "stub.h" +#include "types.h" + +#include "pugl/pugl.h" +#include "pugl/stub.h" +#include "pugl/vulkan.h" + +#include +#include + +#import +#import + +#include + +#include +#include + +@interface PuglVulkanView : NSView + +@end + +@implementation PuglVulkanView { +@public + PuglView* puglview; +} + +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + + if (self) { + self.wantsLayer = YES; + self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; + } + + return self; +} + +- (CALayer*)makeBackingLayer +{ + CAMetalLayer* layer = [CAMetalLayer layer]; + [layer setDelegate:self]; + return layer; +} + +- (void)setFrameSize:(NSSize)newSize +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + + [super setFrameSize:newSize]; + [wrapper setReshaped]; + + self.layer.frame = self.bounds; +} + +- (void)displayLayer:(CALayer*)layer +{ + (void)layer; + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + [wrapper dispatchExpose:[self bounds]]; +} + +@end + +static PuglStatus +puglMacVulkanCreate(PuglView* view) +{ + PuglInternals* impl = view->impl; + PuglVulkanView* drawView = [PuglVulkanView alloc]; + const NSRect rect = NSMakeRect(0, 0, view->frame.width, view->frame.height); + + drawView->puglview = view; + [drawView initWithFrame:rect]; + if (view->hints[PUGL_RESIZABLE]) { + [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + } else { + [drawView setAutoresizingMask:NSViewNotSizable]; + } + + impl->drawView = drawView; + return PUGL_SUCCESS; +} + +static void +puglMacVulkanDestroy(PuglView* view) +{ + PuglVulkanView* const drawView = (PuglVulkanView*)view->impl->drawView; + + [drawView removeFromSuperview]; + [drawView release]; + + view->impl->drawView = nil; +} + +struct PuglVulkanLoaderImpl { + void* libvulkan; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; +}; + +PuglVulkanLoader* +puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world)) +{ + PuglVulkanLoader* loader = + (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader)); + if (!loader) { + return NULL; + } + + if (!(loader->libvulkan = dlopen("libvulkan.dylib", RTLD_LAZY))) { + free(loader); + return NULL; + } + + loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym( + loader->libvulkan, "vkGetInstanceProcAddr"); + + loader->vkGetDeviceProcAddr = + (PFN_vkGetDeviceProcAddr)dlsym(loader->libvulkan, "vkGetDeviceProcAddr"); + + return loader; +} + +void +puglFreeVulkanLoader(PuglVulkanLoader* loader) +{ + if (loader) { + dlclose(loader->libvulkan); + free(loader); + } +} + +PFN_vkGetInstanceProcAddr +puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader) +{ + return loader->vkGetInstanceProcAddr; +} + +PFN_vkGetDeviceProcAddr +puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader) +{ + return loader->vkGetDeviceProcAddr; +} + +const PuglBackend* +puglVulkanBackend(void) +{ + static const PuglBackend backend = {puglStubConfigure, + puglMacVulkanCreate, + puglMacVulkanDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext}; + + return &backend; +} + +const char* const* +puglGetInstanceExtensions(uint32_t* const count) +{ + static const char* const extensions[] = {"VK_KHR_surface", + "VK_MVK_macos_surface"}; + + *count = 2; + return extensions; +} + +VkResult +puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr, + PuglView* const view, + VkInstance instance, + const VkAllocationCallbacks* const allocator, + VkSurfaceKHR* const surface) +{ + PuglInternals* const impl = view->impl; + + PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK = + (PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr( + instance, "vkCreateMacOSSurfaceMVK"); + + const VkMacOSSurfaceCreateInfoMVK info = { + VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, + NULL, + 0, + impl->drawView, + }; + + return vkCreateMacOSSurfaceMVK(instance, &info, allocator, surface); +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/platform.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/platform.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,33 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +// The API that a platform implementation must define + +#ifndef PUGL_PLATFORM_H +#define PUGL_PLATFORM_H + +#include "types.h" + +#include "pugl/pugl.h" + +PUGL_BEGIN_DECLS + +/// Allocate and initialise world internals (implemented once per platform) +PuglWorldInternals* +puglInitWorldInternals(PuglWorldType type, PuglWorldFlags flags); + +/// Destroy and free world internals (implemented once per platform) +void +puglFreeWorldInternals(PuglWorld* world); + +/// Allocate and initialise view internals (implemented once per platform) +PuglInternals* +puglInitViewInternals(PuglWorld* world); + +/// Destroy and free view internals (implemented once per platform) +void +puglFreeViewInternals(PuglView* view); + +PUGL_END_DECLS + +#endif // PUGL_PLATFORM_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/stub.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/stub.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,58 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_STUB_H +#define PUGL_SRC_STUB_H + +#include "pugl/pugl.h" + +#include + +PUGL_BEGIN_DECLS + +static inline PuglStatus +puglStubConfigure(PuglView* const view) +{ + (void)view; + return PUGL_SUCCESS; +} + +static inline PuglStatus +puglStubCreate(PuglView* const view) +{ + (void)view; + return PUGL_SUCCESS; +} + +static inline void +puglStubDestroy(PuglView* const view) +{ + (void)view; +} + +static inline PuglStatus +puglStubEnter(PuglView* const view, const PuglExposeEvent* const expose) +{ + (void)view; + (void)expose; + return PUGL_SUCCESS; +} + +static inline PuglStatus +puglStubLeave(PuglView* const view, const PuglExposeEvent* const expose) +{ + (void)view; + (void)expose; + return PUGL_SUCCESS; +} + +static inline void* +puglStubGetContext(PuglView* const view) +{ + (void)view; + return NULL; +} + +PUGL_END_DECLS + +#endif // PUGL_SRC_STUB_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/types.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,91 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_TYPES_H +#define PUGL_SRC_TYPES_H + +#include "attributes.h" + +#include "pugl/pugl.h" + +#include +#include +#include + +/// Platform-specific world internals +typedef struct PuglWorldInternalsImpl PuglWorldInternals; + +/// Platform-specific view internals +typedef struct PuglInternalsImpl PuglInternals; + +/// View hints +typedef int PuglHints[PUGL_NUM_VIEW_HINTS]; + +/// View size (both X and Y coordinates) +typedef struct { + PuglSpan width; + PuglSpan height; +} PuglViewSize; + +/// Blob of arbitrary data +typedef struct { + void* data; ///< Dynamically allocated data + size_t len; ///< Length of data in bytes +} PuglBlob; + +/// Cross-platform view definition +struct PuglViewImpl { + PuglWorld* world; + const PuglBackend* backend; + PuglInternals* impl; + PuglHandle handle; + PuglEventFunc eventFunc; + char* title; + PuglNativeView parent; + uintptr_t transientParent; + PuglRect frame; + PuglConfigureEvent lastConfigure; + PuglHints hints; + PuglViewSize sizeHints[PUGL_NUM_SIZE_HINTS]; + bool visible; +}; + +/// Cross-platform world definition +struct PuglWorldImpl { + PuglWorldInternals* impl; + PuglWorldHandle handle; + char* className; + double startTime; + size_t numViews; + PuglView** views; +}; + +/// Opaque surface used by graphics backend +typedef void PuglSurface; + +/// Graphics backend interface +struct PuglBackendImpl { + /// Get visual information from display and setup view as necessary + PUGL_WARN_UNUSED_RESULT + PuglStatus (*configure)(PuglView*); + + /// Create surface and drawing context + PUGL_WARN_UNUSED_RESULT + PuglStatus (*create)(PuglView*); + + /// Destroy surface and drawing context + void (*destroy)(PuglView*); + + /// Enter drawing context, for drawing if expose is non-null + PUGL_WARN_UNUSED_RESULT + PuglStatus (*enter)(PuglView*, const PuglExposeEvent*); + + /// Leave drawing context, after drawing if expose is non-null + PUGL_WARN_UNUSED_RESULT + PuglStatus (*leave)(PuglView*, const PuglExposeEvent*); + + /// Return the puglGetContext() handle for the application, if any + void* (*getContext)(PuglView*); +}; + +#endif // PUGL_SRC_TYPES_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,984 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "wasm.h" + +#include "internal.h" + +#include + +#include + +#ifdef __cplusplus +# define PUGL_INIT_STRUCT \ + {} +#else +# define PUGL_INIT_STRUCT \ + { \ + 0 \ + } +#endif + +PuglWorldInternals* +puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags) +{ + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); + + impl->scaleFactor = emscripten_get_device_pixel_ratio(); + + printf("DONE: %s %d | -> %f\n", __func__, __LINE__, impl->scaleFactor); + + return impl; +} + +void* +puglGetNativeWorld(PuglWorld*) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + return NULL; +} + +PuglInternals* +puglInitViewInternals(PuglWorld* const world) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + + impl->buttonPressTimeout = -1; + impl->supportsTouch = PUGL_DONT_CARE; // not yet known + +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + impl->supportsClipboardRead = (PuglViewHintValue)EM_ASM_INT({ + if (typeof(navigator.clipboard) !== 'undefined' && typeof(navigator.clipboard.readText) === 'function' && window.isSecureContext) { + return 1; // PUGL_TRUE + } + return 0; // PUGL_FALSE + }); + + impl->supportsClipboardWrite = (PuglViewHintValue)EM_ASM_INT({ + if (typeof(navigator.clipboard) !== 'undefined' && typeof(navigator.clipboard.writeText) === 'function' && window.isSecureContext) { + return 1; // PUGL_TRUE + } + if (typeof(document.queryCommandSupported) !== 'undefined' && document.queryCommandSupported("copy")) { + return 1; // PUGL_TRUE + } + return 0; // PUGL_FALSE + }); +#endif + + return impl; +} + +static PuglStatus +puglDispatchEventWithContext(PuglView* const view, const PuglEvent* event) +{ + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + + if (!(st0 = view->backend->enter(view, NULL))) { + st0 = view->eventFunc(view, event); + st1 = view->backend->leave(view, NULL); + } + + return st0 ? st0 : st1; +} + +static PuglKey +keyCodeToSpecial(const unsigned long code, const unsigned long location) +{ + switch (code) { + case 0x08: return PUGL_KEY_BACKSPACE; + case 0x1B: return PUGL_KEY_ESCAPE; + case 0x2E: return PUGL_KEY_DELETE; + case 0x70: return PUGL_KEY_F1; + case 0x71: return PUGL_KEY_F2; + case 0x72: return PUGL_KEY_F3; + case 0x73: return PUGL_KEY_F4; + case 0x74: return PUGL_KEY_F5; + case 0x75: return PUGL_KEY_F6; + case 0x76: return PUGL_KEY_F7; + case 0x77: return PUGL_KEY_F8; + case 0x78: return PUGL_KEY_F9; + case 0x79: return PUGL_KEY_F10; + case 0x7A: return PUGL_KEY_F11; + case 0x7B: return PUGL_KEY_F12; + case 0x25: return PUGL_KEY_LEFT; + case 0x26: return PUGL_KEY_UP; + case 0x27: return PUGL_KEY_RIGHT; + case 0x28: return PUGL_KEY_DOWN; + case 0x21: return PUGL_KEY_PAGE_UP; + case 0x22: return PUGL_KEY_PAGE_DOWN; + case 0x24: return PUGL_KEY_HOME; + case 0x23: return PUGL_KEY_END; + case 0x2D: return PUGL_KEY_INSERT; + case 0x10: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_SHIFT_R : PUGL_KEY_SHIFT_L; + case 0x11: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_CTRL_R : PUGL_KEY_CTRL_L; + case 0x12: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_ALT_R : PUGL_KEY_ALT_L; + case 0xE0: return location == DOM_KEY_LOCATION_RIGHT ? PUGL_KEY_SUPER_R : PUGL_KEY_SUPER_L; + case 0x5D: return PUGL_KEY_MENU; + case 0x14: return PUGL_KEY_CAPS_LOCK; + case 0x91: return PUGL_KEY_SCROLL_LOCK; + case 0x90: return PUGL_KEY_NUM_LOCK; + case 0x2C: return PUGL_KEY_PRINT_SCREEN; + case 0x13: return PUGL_KEY_PAUSE; + case '\r': return (PuglKey)'\r'; + default: break; + } + + return (PuglKey)0; +} + +static PuglMods +translateModifiers(const EM_BOOL ctrlKey, + const EM_BOOL shiftKey, + const EM_BOOL altKey, + const EM_BOOL metaKey) +{ + return (ctrlKey ? PUGL_MOD_CTRL : 0u) | + (shiftKey ? PUGL_MOD_SHIFT : 0u) | + (altKey ? PUGL_MOD_ALT : 0u) | + (metaKey ? PUGL_MOD_SUPER : 0u); +} + +static bool +decodeCharacterString(const unsigned long keyCode, + const EM_UTF8 key[EM_HTML5_SHORT_STRING_LEN_BYTES], + char str[8]) +{ + if (key[1] == 0) + { + str[0] = key[0]; + return true; + } + + return false; +} + +static EM_BOOL +puglKeyCallback(const int eventType, const EmscriptenKeyboardEvent* const keyEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + if (keyEvent->repeat && view->hints[PUGL_IGNORE_KEY_REPEAT]) + return EM_TRUE; + + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + + const uint state = translateModifiers(keyEvent->ctrlKey, + keyEvent->shiftKey, + keyEvent->altKey, + keyEvent->metaKey); + + const PuglKey special = keyCodeToSpecial(keyEvent->keyCode, keyEvent->location); + + uint key = keyEvent->key[0] >= ' ' && keyEvent->key[0] <= '~' && keyEvent->key[1] == '\0' + ? keyEvent->key[0] + : keyEvent->keyCode; + + if (key >= 'A' && key <= 'Z' && !keyEvent->shiftKey) + key += 'a' - 'A'; + + PuglEvent event = {{PUGL_NOTHING, 0}}; + event.key.type = eventType == EMSCRIPTEN_EVENT_KEYDOWN ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; + event.key.time = keyEvent->timestamp / 1e3; + // event.key.x = xevent.xkey.x; + // event.key.y = xevent.xkey.y; + // event.key.xRoot = xevent.xkey.x_root; + // event.key.yRoot = xevent.xkey.y_root; + event.key.key = special ? special : key; + event.key.keycode = keyEvent->keyCode; + event.key.state = state; + st0 = puglDispatchEventWithContext(view, &event); + + d_debug("key event \n" + "\tdown: %d\n" + "\trepeat: %d\n" + "\tlocation: %d\n" + "\tstate: 0x%x\n" + "\tkey[]: '%s'\n" + "\tcode[]: '%s'\n" + "\tlocale[]: '%s'\n" + "\tkeyCode: 0x%lx:'%c' [deprecated, use key]\n" + "\twhich: 0x%lx:'%c' [deprecated, use key, same as keycode?]\n" + "\tspecial: 0x%x", + eventType == EMSCRIPTEN_EVENT_KEYDOWN, + keyEvent->repeat, + keyEvent->location, + state, + keyEvent->key, + keyEvent->code, + keyEvent->locale, + keyEvent->keyCode, keyEvent->keyCode >= ' ' && keyEvent->keyCode <= '~' ? keyEvent->keyCode : 0, + keyEvent->which, keyEvent->which >= ' ' && keyEvent->which <= '~' ? keyEvent->which : 0, + special); + + if (event.type == PUGL_KEY_PRESS && !special && !(keyEvent->ctrlKey|keyEvent->altKey|keyEvent->metaKey)) { + char str[8] = PUGL_INIT_STRUCT; + + if (decodeCharacterString(keyEvent->keyCode, keyEvent->key, str)) { + d_debug("resulting string is '%s'", str); + + event.text.type = PUGL_TEXT; + event.text.character = event.key.key; + memcpy(event.text.string, str, sizeof(event.text.string)); + st1 = puglDispatchEventWithContext(view, &event); + } + } + + return (st0 ? st0 : st1) == PUGL_SUCCESS ? EM_TRUE : EM_FALSE; +} + +static EM_BOOL +puglMouseCallback(const int eventType, const EmscriptenMouseEvent* const mouseEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + PuglEvent event = {{PUGL_NOTHING, 0}}; + + const double time = mouseEvent->timestamp / 1e3; + const PuglMods state = translateModifiers(mouseEvent->ctrlKey, + mouseEvent->shiftKey, + mouseEvent->altKey, + mouseEvent->metaKey); + + const double scaleFactor = view->world->impl->scaleFactor; + + // workaround missing pointer lock callback, see https://github.com/emscripten-core/emscripten/issues/9681 + EmscriptenPointerlockChangeEvent e; + if (emscripten_get_pointerlock_status(&e) == EMSCRIPTEN_RESULT_SUCCESS) + view->impl->pointerLocked = e.isActive; + + switch (eventType) { + case EMSCRIPTEN_EVENT_MOUSEDOWN: + case EMSCRIPTEN_EVENT_MOUSEUP: + event.button.type = eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? PUGL_BUTTON_PRESS : PUGL_BUTTON_RELEASE; + event.button.time = time; + event.button.x = mouseEvent->targetX * scaleFactor; + event.button.y = mouseEvent->targetY * scaleFactor; + event.button.xRoot = mouseEvent->screenX * scaleFactor; + event.button.yRoot = mouseEvent->screenY * scaleFactor; + event.button.state = state; + switch (mouseEvent->button) { + case 1: + event.button.button = 2; + break; + case 2: + event.button.button = 1; + break; + default: + event.button.button = mouseEvent->button; + break; + } + break; + case EMSCRIPTEN_EVENT_MOUSEMOVE: + event.motion.type = PUGL_MOTION; + event.motion.time = time; + if (view->impl->pointerLocked) { + // adjust local values for delta + const double movementX = mouseEvent->movementX * scaleFactor; + const double movementY = mouseEvent->movementY * scaleFactor; + view->impl->lastMotion.x += movementX; + view->impl->lastMotion.y += movementY; + view->impl->lastMotion.xRoot += movementX; + view->impl->lastMotion.yRoot += movementY; + // now set x, y, xRoot and yRoot + event.motion.x = view->impl->lastMotion.x; + event.motion.y = view->impl->lastMotion.y; + event.motion.xRoot = view->impl->lastMotion.xRoot; + event.motion.yRoot = view->impl->lastMotion.yRoot; + } else { + // cache values for possible pointer lock movement later + view->impl->lastMotion.x = event.motion.x = mouseEvent->targetX * scaleFactor; + view->impl->lastMotion.y = event.motion.y = mouseEvent->targetY * scaleFactor; + view->impl->lastMotion.xRoot = event.motion.xRoot = mouseEvent->screenX * scaleFactor; + view->impl->lastMotion.yRoot = event.motion.yRoot = mouseEvent->screenY * scaleFactor; + } + event.motion.state = state; + break; + case EMSCRIPTEN_EVENT_MOUSEENTER: + case EMSCRIPTEN_EVENT_MOUSELEAVE: + event.crossing.type = eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? PUGL_POINTER_IN : PUGL_POINTER_OUT; + event.crossing.time = time; + event.crossing.x = mouseEvent->targetX * scaleFactor; + event.crossing.y = mouseEvent->targetY * scaleFactor; + event.crossing.xRoot = mouseEvent->screenX * scaleFactor; + event.crossing.yRoot = mouseEvent->screenY * scaleFactor; + event.crossing.state = state; + event.crossing.mode = PUGL_CROSSING_NORMAL; + break; + } + + if (event.type == PUGL_NOTHING) + return EM_FALSE; + + puglDispatchEventWithContext(view, &event); + + // note: we must always return false, otherwise canvas never gets keyboard input + return EM_FALSE; +} + +static void +puglTouchStartDelay(void* const userData) +{ + PuglView* const view = (PuglView*)userData; + PuglInternals* const impl = view->impl; + + impl->buttonPressTimeout = -1; + impl->nextButtonEvent.button.time += 2000; + puglDispatchEventWithContext(view, &impl->nextButtonEvent); +} + +static EM_BOOL +puglTouchCallback(const int eventType, const EmscriptenTouchEvent* const touchEvent, void* const userData) +{ + if (touchEvent->numTouches <= 0) { + return EM_FALSE; + } + + PuglView* const view = (PuglView*)userData; + PuglInternals* const impl = view->impl; + + if (impl->supportsTouch == PUGL_DONT_CARE) { + impl->supportsTouch = PUGL_TRUE; + + // stop using mouse press events which conflict with touch + const char* const className = view->world->className; + emscripten_set_mousedown_callback(className, view, false, NULL); + emscripten_set_mouseup_callback(className, view, false, NULL); + } + + if (!view->visible) { + return EM_FALSE; + } + + PuglEvent event = {{PUGL_NOTHING, 0}}; + + const double time = touchEvent->timestamp / 1e3; + const PuglMods state = translateModifiers(touchEvent->ctrlKey, + touchEvent->shiftKey, + touchEvent->altKey, + touchEvent->metaKey); + + const double scaleFactor = view->world->impl->scaleFactor; + + d_debug("touch %d|%s %d || %ld", + eventType, + eventType == EMSCRIPTEN_EVENT_TOUCHSTART ? "start" : + eventType == EMSCRIPTEN_EVENT_TOUCHEND ? "end" : "cancel", + touchEvent->numTouches, + impl->buttonPressTimeout); + + const EmscriptenTouchPoint* point = &touchEvent->touches[0]; + + if (impl->buttonPressTimeout != -1 || eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL) { + // if we received an event while touch is active, trigger initial click now + if (impl->buttonPressTimeout != -1) { + emscripten_clear_timeout(impl->buttonPressTimeout); + impl->buttonPressTimeout = -1; + if (eventType != EMSCRIPTEN_EVENT_TOUCHCANCEL) { + impl->nextButtonEvent.button.button = 0; + } + } + impl->nextButtonEvent.button.time = time; + puglDispatchEventWithContext(view, &impl->nextButtonEvent); + } + + switch (eventType) { + case EMSCRIPTEN_EVENT_TOUCHEND: + case EMSCRIPTEN_EVENT_TOUCHCANCEL: + event.button.type = PUGL_BUTTON_RELEASE; + event.button.time = time; + event.button.button = eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL ? 1 : 0; + event.button.x = point->targetX * scaleFactor; + event.button.y = point->targetY * scaleFactor; + event.button.xRoot = point->screenX * scaleFactor; + event.button.yRoot = point->screenY * scaleFactor; + event.button.state = state; + break; + + case EMSCRIPTEN_EVENT_TOUCHSTART: + // this event can be used for a couple of things, store it until we know more + event.button.type = PUGL_BUTTON_PRESS; + event.button.time = time; + event.button.button = 1; // if no other event occurs soon, treat it as right-click + event.button.x = point->targetX * scaleFactor; + event.button.y = point->targetY * scaleFactor; + event.button.xRoot = point->screenX * scaleFactor; + event.button.yRoot = point->screenY * scaleFactor; + event.button.state = state; + memcpy(&impl->nextButtonEvent, &event, sizeof(PuglEvent)); + impl->buttonPressTimeout = emscripten_set_timeout(puglTouchStartDelay, 2000, view); + // fall through, moving "mouse" to touch position + + case EMSCRIPTEN_EVENT_TOUCHMOVE: + event.motion.type = PUGL_MOTION; + event.motion.time = time; + event.motion.x = point->targetX * scaleFactor; + event.motion.y = point->targetY * scaleFactor; + event.motion.xRoot = point->screenX * scaleFactor; + event.motion.yRoot = point->screenY * scaleFactor; + event.motion.state = state; + break; + } + + if (event.type == PUGL_NOTHING) + return EM_FALSE; + + puglDispatchEventWithContext(view, &event); + + // FIXME we must always return false?? + return EM_FALSE; +} + +static EM_BOOL +puglFocusCallback(const int eventType, const EmscriptenFocusEvent* /*const focusEvent*/, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + PuglEvent event = {{eventType == EMSCRIPTEN_EVENT_FOCUSIN ? PUGL_FOCUS_IN : PUGL_FOCUS_OUT, 0}}; + event.focus.mode = PUGL_CROSSING_NORMAL; + + puglDispatchEventWithContext(view, &event); + + // note: we must always return false, otherwise canvas never gets proper focus + return EM_FALSE; +} + +static EM_BOOL +puglPointerLockChangeCallback(const int eventType, const EmscriptenPointerlockChangeEvent* event, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + view->impl->pointerLocked = event->isActive; + return EM_TRUE; +} + +static EM_BOOL +puglWheelCallback(const int eventType, const EmscriptenWheelEvent* const wheelEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + if (!view->visible) { + return EM_FALSE; + } + + const double scaleFactor = view->world->impl->scaleFactor; + + PuglEvent event = {{PUGL_SCROLL, 0}}; + event.scroll.time = wheelEvent->mouse.timestamp / 1e3; + event.scroll.x = wheelEvent->mouse.targetX; + event.scroll.y = wheelEvent->mouse.targetY; + event.scroll.xRoot = wheelEvent->mouse.screenX; + event.scroll.yRoot = wheelEvent->mouse.screenY; + event.scroll.state = translateModifiers(wheelEvent->mouse.ctrlKey, + wheelEvent->mouse.shiftKey, + wheelEvent->mouse.altKey, + wheelEvent->mouse.metaKey); + event.scroll.direction = PUGL_SCROLL_SMOOTH; + // FIXME handle wheelEvent->deltaMode + event.scroll.dx = wheelEvent->deltaX * 0.01 * scaleFactor; + event.scroll.dy = -wheelEvent->deltaY * 0.01 * scaleFactor; + + return puglDispatchEventWithContext(view, &event) == PUGL_SUCCESS ? EM_TRUE : EM_FALSE; +} + +static EM_BOOL +puglUiCallback(const int eventType, const EmscriptenUiEvent* const uiEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + const char* const className = view->world->className; + + // FIXME + const int width = EM_ASM_INT({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + canvasWrapper.style.setProperty("--device-pixel-ratio", window.devicePixelRatio); + return canvasWrapper.clientWidth; + }, className); + + const int height = EM_ASM_INT({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + return canvasWrapper.clientHeight; + }, className); + + if (!width || !height) + return EM_FALSE; + + const double scaleFactor = view->world->impl->scaleFactor = emscripten_get_device_pixel_ratio(); + + emscripten_set_canvas_element_size(view->world->className, width * scaleFactor, height * scaleFactor); + + PuglEvent event = {{PUGL_CONFIGURE, 0}}; + event.configure.x = view->frame.x; + event.configure.y = view->frame.y; + event.configure.width = width * scaleFactor; + event.configure.height = height * scaleFactor; + puglDispatchEvent(view, &event); + return EM_TRUE; +} + +static EM_BOOL +puglVisibilityChangeCallback(const int eventType, const EmscriptenVisibilityChangeEvent* const visibilityChangeEvent, void* const userData) +{ + PuglView* const view = (PuglView*)userData; + + view->visible = visibilityChangeEvent->hidden == EM_FALSE; + PuglEvent event = {{ view->visible ? PUGL_MAP : PUGL_UNMAP, 0}}; + puglDispatchEvent(view, &event); + return EM_FALSE; +} + +PuglStatus +puglRealize(PuglView* const view) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + PuglStatus st = PUGL_SUCCESS; + + // Ensure that we do not have a parent + if (view->parent) { + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_FAILURE; + } + + if (!view->backend || !view->backend->configure) { + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_BAD_BACKEND; + } + + const char* const className = view->world->className; + d_stdout("className is %s", className); + + // Set the size to the default if it has not already been set + if (view->frame.width <= 0.0 && view->frame.height <= 0.0) { + PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { + return PUGL_BAD_CONFIGURATION; + } + + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + } + + // Configure and create the backend + if ((st = view->backend->configure(view)) || (st = view->backend->create(view))) { + view->backend->destroy(view); + return st; + } + + if (view->title) { + puglSetWindowTitle(view, view->title); + } + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + PuglEvent event = {{PUGL_CONFIGURE, 0}}; + event.configure.x = view->frame.x; + event.configure.y = view->frame.y; + event.configure.width = view->frame.width; + event.configure.height = view->frame.height; + puglDispatchEvent(view, &event); + + EM_ASM({ + var canvasWrapper = document.getElementById(UTF8ToString($0)).parentElement; + canvasWrapper.style.setProperty("--device-pixel-ratio", window.devicePixelRatio); + }, className); + + emscripten_set_canvas_element_size(className, view->frame.width, view->frame.height); +// emscripten_set_keypress_callback(className, view, false, puglKeyCallback); + emscripten_set_keydown_callback(className, view, false, puglKeyCallback); + emscripten_set_keyup_callback(className, view, false, puglKeyCallback); + emscripten_set_touchstart_callback(className, view, false, puglTouchCallback); + emscripten_set_touchend_callback(className, view, false, puglTouchCallback); + emscripten_set_touchmove_callback(className, view, false, puglTouchCallback); + emscripten_set_touchcancel_callback(className, view, false, puglTouchCallback); + emscripten_set_mousedown_callback(className, view, false, puglMouseCallback); + emscripten_set_mouseup_callback(className, view, false, puglMouseCallback); + emscripten_set_mousemove_callback(className, view, false, puglMouseCallback); + emscripten_set_mouseenter_callback(className, view, false, puglMouseCallback); + emscripten_set_mouseleave_callback(className, view, false, puglMouseCallback); + emscripten_set_focusin_callback(className, view, false, puglFocusCallback); + emscripten_set_focusout_callback(className, view, false, puglFocusCallback); + emscripten_set_wheel_callback(className, view, false, puglWheelCallback); + emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglPointerLockChangeCallback); + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, view, false, puglUiCallback); + emscripten_set_visibilitychange_callback(view, false, puglVisibilityChangeCallback); + + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_SUCCESS; +} + +PuglStatus +puglShow(PuglView* const view) +{ + view->visible = true; + view->impl->needsRepaint = true; + return puglPostRedisplay(view); +} + +PuglStatus +puglHide(PuglView* const view) +{ + view->visible = false; + return PUGL_FAILURE; +} + +void +puglFreeViewInternals(PuglView* const view) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + if (view && view->impl) { + if (view->backend) { + view->backend->destroy(view); + } + free(view->impl->clipboardData); + free(view->impl->timers); + free(view->impl); + } +} + +void +puglFreeWorldInternals(PuglWorld* const world) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + free(world->impl); +} + +PuglStatus +puglGrabFocus(PuglView*) +{ + return PUGL_FAILURE; +} + +double +puglGetScaleFactor(const PuglView* const view) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + return view->world->impl->scaleFactor; +} + +double +puglGetTime(const PuglWorld*) +{ + return emscripten_get_now() / 1e3; +} + +PuglStatus +puglUpdate(PuglWorld* const world, const double timeout) +{ + for (size_t i = 0; i < world->numViews; ++i) { + PuglView* const view = world->views[i]; + + if (!view->visible) { + continue; + } + + puglDispatchSimpleEvent(view, PUGL_UPDATE); + + if (!view->impl->needsRepaint) { + continue; + } + + view->impl->needsRepaint = false; + + PuglEvent event = {{PUGL_EXPOSE, 0}}; + event.expose.x = view->frame.x; + event.expose.y = view->frame.y; + event.expose.width = view->frame.width; + event.expose.height = view->frame.height; + puglDispatchEvent(view, &event); + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglPostRedisplay(PuglView* const view) +{ + view->impl->needsRepaint = true; + return PUGL_SUCCESS; +} + +PuglStatus +puglPostRedisplayRect(PuglView* const view, const PuglRect rect) +{ + view->impl->needsRepaint = true; + return PUGL_FAILURE; +} + +PuglNativeView +puglGetNativeView(PuglView* const view) +{ + return 0; +} + +PuglStatus +puglSetWindowTitle(PuglView* const view, const char* const title) +{ + puglSetString(&view->title, title); + emscripten_set_window_title(title); + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) +{ + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; + return PUGL_SUCCESS; +} + +static EM_BOOL +puglTimerLoopCallback(double timeout, void* const arg) +{ + PuglTimer* const timer = (PuglTimer*)arg; + PuglInternals* const impl = timer->view->impl; + + // only handle active timers + for (uint32_t i=0; inumTimers; ++i) + { + if (impl->timers[i].id == timer->id) + { + PuglEvent event = {{PUGL_TIMER, 0}}; + event.timer.id = timer->id; + puglDispatchEventWithContext(timer->view, &event); + return EM_TRUE; + } + } + + return EM_FALSE; + + // unused + (void)timeout; +} + +PuglStatus +puglStartTimer(PuglView* const view, const uintptr_t id, const double timeout) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + PuglInternals* const impl = view->impl; + const uint32_t timerIndex = impl->numTimers++; + + if (impl->timers == NULL) + impl->timers = (PuglTimer*)malloc(sizeof(PuglTimer)); + else + impl->timers = (PuglTimer*)realloc(impl->timers, sizeof(PuglTimer) * timerIndex); + + PuglTimer* const timer = &impl->timers[timerIndex]; + timer->view = view; + timer->id = id; + + emscripten_set_timeout_loop(puglTimerLoopCallback, timeout * 1e3, timer); + return PUGL_SUCCESS; +} + +PuglStatus +puglStopTimer(PuglView* const view, const uintptr_t id) +{ + printf("DONE: %s %d\n", __func__, __LINE__); + PuglInternals* const impl = view->impl; + + if (impl->timers == NULL || impl->numTimers == 0) + return PUGL_FAILURE; + + for (uint32_t i=0; inumTimers; ++i) + { + if (impl->timers[i].id == id) + { + memmove(impl->timers + i, impl->timers + (i + 1), sizeof(PuglTimer) * (impl->numTimers - 1)); + --impl->numTimers; + return PUGL_SUCCESS; + } + } + + return PUGL_FAILURE; +} + +#ifdef PUGL_WASM_ASYNC_CLIPBOARD +EM_JS(char*, puglGetAsyncClipboardData, (), { + var text = Asyncify.handleSleep(function(wakeUp) { + navigator.clipboard.readText() + .then(function(text) { + wakeUp(text); + }) + .catch(function() { + wakeUp(""); + }); + }); + if (!text.length) { + return null; + } + var length = lengthBytesUTF8(text) + 1; + var str = _malloc(length); + stringToUTF8(text, str, length); + return str; +}); +#endif + +PuglStatus +puglPaste(PuglView* const view) +{ +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + // abort early if we already know it is not supported + if (view->impl->supportsClipboardRead == PUGL_FALSE) { + return PUGL_UNSUPPORTED; + } + + free(view->impl->clipboardData); + view->impl->clipboardData = puglGetAsyncClipboardData(); +#endif + + if (view->impl->clipboardData == NULL) { + return PUGL_FAILURE; + } + + const PuglDataOfferEvent offer = { + PUGL_DATA_OFFER, + 0, + emscripten_get_now() / 1e3, + }; + + PuglEvent offerEvent; + offerEvent.offer = offer; + puglDispatchEvent(view, &offerEvent); + return PUGL_SUCCESS; +} + +PuglStatus +puglAcceptOffer(PuglView* const view, + const PuglDataOfferEvent* const offer, + const uint32_t typeIndex) +{ + if (typeIndex != 0) { + return PUGL_UNSUPPORTED; + } + + const PuglDataEvent data = { + PUGL_DATA, + 0, + emscripten_get_now() / 1e3, + 0, + }; + + PuglEvent dataEvent; + dataEvent.data = data; + puglDispatchEvent(view, &dataEvent); + return PUGL_SUCCESS; +} + +uint32_t +puglGetNumClipboardTypes(const PuglView* const view) +{ + return view->impl->clipboardData != NULL ? 1u : 0u; +} + +const char* +puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex) +{ + return (typeIndex == 0 && view->impl->clipboardData != NULL) + ? "text/plain" + : NULL; +} + +const void* +puglGetClipboard(PuglView* const view, + const uint32_t typeIndex, + size_t* const len) +{ + return view->impl->clipboardData; +} + +PuglStatus +puglSetClipboard(PuglView* const view, + const char* const type, + const void* const data, + const size_t len) +{ + // only utf8 text supported for now + if (type != NULL && strcmp(type, "text/plain") != 0) { + return PUGL_UNSUPPORTED; + } + + const char* const className = view->world->className; + const char* const text = (const char*)data; + +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + // abort early if we already know it is not supported + if (view->impl->supportsClipboardWrite == PUGL_FALSE) { + return PUGL_UNSUPPORTED; + } +#else + puglSetString(&view->impl->clipboardData, text); +#endif + + EM_ASM({ + if (typeof(navigator.clipboard) !== 'undefined' && typeof(navigator.clipboard.writeText) === 'function' && window.isSecureContext) { + navigator.clipboard.writeText(UTF8ToString($1)); + } else { + var canvasClipboardObjName = UTF8ToString($0) + "_clipboard"; + var canvasClipboardElem = document.getElementById(canvasClipboardObjName); + + if (!canvasClipboardElem) { + canvasClipboardElem = document.createElement('textarea'); + canvasClipboardElem.id = canvasClipboardObjName; + canvasClipboardElem.style.position = 'fixed'; + canvasClipboardElem.style.whiteSpace = 'pre'; + canvasClipboardElem.style.zIndex = '-1'; + canvasClipboardElem.setAttribute('readonly', true); + document.body.appendChild(canvasClipboardElem); + } + + canvasClipboardElem.textContent = UTF8ToString($1); + canvasClipboardElem.select(); + document.execCommand("copy"); + } + }, className, text); + + // FIXME proper return status + return PUGL_SUCCESS; +} + +PuglStatus +puglSetCursor(PuglView* const view, const PuglCursor cursor) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + return PUGL_FAILURE; +} + +PuglStatus +puglSetTransientParent(PuglView* const view, const PuglNativeView parent) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + view->transientParent = parent; + return PUGL_FAILURE; +} + +PuglStatus +puglSetPosition(PuglView* const view, const int x, const int y) +{ + printf("TODO: %s %d\n", __func__, __LINE__); + + if (x > INT16_MAX || y > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + view->frame.x = (PuglCoord)x; + view->frame.y = (PuglCoord)y; + return PUGL_FAILURE; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,45 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_WASM_H +#define PUGL_SRC_WASM_H + +// #include "attributes.h" +#include "types.h" + +#include "pugl/pugl.h" + +// #define PUGL_WASM_ASYNC_CLIPBOARD + +struct PuglTimer { + PuglView* view; + uintptr_t id; +}; + +struct PuglWorldInternalsImpl { + double scaleFactor; +}; + +struct LastMotionValues { + double x, y, xRoot, yRoot; +}; + +struct PuglInternalsImpl { + PuglSurface* surface; + bool needsRepaint; + bool pointerLocked; + uint32_t numTimers; + LastMotionValues lastMotion; + long buttonPressTimeout; + PuglEvent nextButtonEvent; +#ifdef PUGL_WASM_ASYNC_CLIPBOARD + PuglViewHintValue supportsClipboardRead; + PuglViewHintValue supportsClipboardWrite; +#endif + PuglViewHintValue supportsTouch; + char* clipboardData; + struct PuglTimer* timers; +}; + +#endif // PUGL_SRC_WASM_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm_gl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm_gl.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,228 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "stub.h" +#include "wasm.h" + +#include "pugl/pugl.h" + +#include +#include + +#include + +// for performance reasons we can keep a single EGL context always active +#define PUGL_WASM_SINGLE_EGL_CONTEXT + +typedef struct { + EGLDisplay display; + EGLConfig config; + EGLContext context; + EGLSurface surface; +} PuglWasmGlSurface; + +static EGLint +puglWasmGlHintValue(const int value) +{ + return value == PUGL_DONT_CARE ? EGL_DONT_CARE : value; +} + +static int +puglWasmGlGetAttrib(const EGLDisplay display, + const EGLConfig config, + const EGLint attrib) +{ + EGLint value = 0; + eglGetConfigAttrib(display, config, attrib, &value); + return value; +} + +static PuglStatus +puglWasmGlConfigure(PuglView* view) +{ + PuglInternals* const impl = view->impl; + + const EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + if (display == EGL_NO_DISPLAY) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + int major, minor; + if (eglInitialize(display, &major, &minor) != EGL_TRUE) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + EGLConfig config; + int numConfigs; + + if (eglGetConfigs(display, &config, 1, &numConfigs) != EGL_TRUE || numConfigs != 1) { + eglTerminate(display); + return PUGL_CREATE_CONTEXT_FAILED; + } + + // clang-format off + const EGLint attrs[] = { + /* + GLX_X_RENDERABLE, True, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + EGL_SAMPLE_BUFFERS, view->hints[PUGL_MULTI_SAMPLE] ? 1 : 0, + */ + EGL_SAMPLES, puglWasmGlHintValue(view->hints[PUGL_SAMPLES]), + EGL_RED_SIZE, puglWasmGlHintValue(view->hints[PUGL_RED_BITS]), + EGL_GREEN_SIZE, puglWasmGlHintValue(view->hints[PUGL_GREEN_BITS]), + EGL_BLUE_SIZE, puglWasmGlHintValue(view->hints[PUGL_BLUE_BITS]), + EGL_ALPHA_SIZE, puglWasmGlHintValue(view->hints[PUGL_ALPHA_BITS]), + EGL_DEPTH_SIZE, puglWasmGlHintValue(view->hints[PUGL_DEPTH_BITS]), + EGL_STENCIL_SIZE, puglWasmGlHintValue(view->hints[PUGL_STENCIL_BITS]), + EGL_NONE + }; + // clang-format on + + if (eglChooseConfig(display, attrs, &config, 1, &numConfigs) != EGL_TRUE || numConfigs != 1) { + eglTerminate(display); + return PUGL_CREATE_CONTEXT_FAILED; + } + + PuglWasmGlSurface* const surface = + (PuglWasmGlSurface*)calloc(1, sizeof(PuglWasmGlSurface)); + impl->surface = surface; + + surface->display = display; + surface->config = config; + surface->context = EGL_NO_SURFACE; + surface->surface = EGL_NO_CONTEXT; + + view->hints[PUGL_RED_BITS] = + puglWasmGlGetAttrib(display, config, EGL_RED_SIZE); + view->hints[PUGL_GREEN_BITS] = + puglWasmGlGetAttrib(display, config, EGL_GREEN_SIZE); + view->hints[PUGL_BLUE_BITS] = + puglWasmGlGetAttrib(display, config, EGL_BLUE_SIZE); + view->hints[PUGL_ALPHA_BITS] = + puglWasmGlGetAttrib(display, config, EGL_ALPHA_SIZE); + view->hints[PUGL_DEPTH_BITS] = + puglWasmGlGetAttrib(display, config, EGL_DEPTH_SIZE); + view->hints[PUGL_STENCIL_BITS] = + puglWasmGlGetAttrib(display, config, EGL_STENCIL_SIZE); + view->hints[PUGL_SAMPLES] = + puglWasmGlGetAttrib(display, config, EGL_SAMPLES); + + // double-buffering is always enabled for EGL + view->hints[PUGL_DOUBLE_BUFFER] = 1; + + return PUGL_SUCCESS; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglWasmGlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) +{ + PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; + if (!surface || !surface->context || !surface->surface) { + return PUGL_FAILURE; + } + +#ifndef PUGL_WASM_SINGLE_EGL_CONTEXT + return eglMakeCurrent(surface->display, surface->surface, surface->surface, surface->context) ? PUGL_SUCCESS : PUGL_FAILURE; +#else + return PUGL_SUCCESS; +#endif +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglWasmGlLeave(PuglView* view, const PuglExposeEvent* expose) +{ + PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; + + if (expose) { // note: swap buffers always enabled for EGL + eglSwapBuffers(surface->display, surface->surface); + } + +#ifndef PUGL_WASM_SINGLE_EGL_CONTEXT + return eglMakeCurrent(surface->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) ? PUGL_SUCCESS : PUGL_FAILURE; +#else + return PUGL_SUCCESS; +#endif +} + +static PuglStatus +puglWasmGlCreate(PuglView* view) +{ + PuglWasmGlSurface* const surface = (PuglWasmGlSurface*)view->impl->surface; + const EGLDisplay display = surface->display; + const EGLConfig config = surface->config; + + const EGLint attrs[] = { + EGL_CONTEXT_CLIENT_VERSION, + view->hints[PUGL_CONTEXT_VERSION_MAJOR], + + EGL_CONTEXT_MAJOR_VERSION, + view->hints[PUGL_CONTEXT_VERSION_MAJOR], + + /* + EGL_CONTEXT_MINOR_VERSION, + view->hints[PUGL_CONTEXT_VERSION_MINOR], + + EGL_CONTEXT_OPENGL_DEBUG, + (view->hints[PUGL_USE_DEBUG_CONTEXT] ? EGL_TRUE : EGL_FALSE), + + EGL_CONTEXT_OPENGL_PROFILE_MASK, + (view->hints[PUGL_USE_COMPAT_PROFILE] + ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT + : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT), + */ + + EGL_NONE + }; + + surface->context = eglCreateContext(display, config, EGL_NO_CONTEXT, attrs); + + if (surface->context == EGL_NO_CONTEXT) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + surface->surface = eglCreateWindowSurface(display, config, 0, NULL); + + if (surface->surface == EGL_NO_SURFACE) { + return PUGL_CREATE_CONTEXT_FAILED; + } + +#ifdef PUGL_WASM_SINGLE_EGL_CONTEXT + eglMakeCurrent(surface->display, surface->surface, surface->surface, surface->context); +#endif + + return PUGL_SUCCESS; +} + +static void +puglWasmGlDestroy(PuglView* view) +{ + PuglWasmGlSurface* surface = (PuglWasmGlSurface*)view->impl->surface; + if (surface) { + const EGLDisplay display = surface->display; + if (surface->surface != EGL_NO_SURFACE) + eglDestroySurface(display, surface->surface); + if (surface->context != EGL_NO_CONTEXT) + eglDestroyContext(display, surface->context); + eglTerminate(display); + free(surface); + view->impl->surface = NULL; + } +} + +const PuglBackend* +puglGlBackend(void) +{ + static const PuglBackend backend = {puglWasmGlConfigure, + puglWasmGlCreate, + puglWasmGlDestroy, + puglWasmGlEnter, + puglWasmGlLeave, + puglStubGetContext}; + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/wasm_stub.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,26 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "pugl/stub.h" + +#include "stub.h" +// #include "types.h" +// #include "wasm.h" + +#include "pugl/pugl.h" + +const PuglBackend* +puglStubBackend(void) +{ + static const PuglBackend backend = { + puglStubConfigure, + puglStubCreate, + puglStubDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext, + }; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1478 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "win.h" + +#include "internal.h" +#include "platform.h" + +#include "pugl/pugl.h" + +#include +#include + +#include +#include +#include +#include +#include + +#ifndef WM_MOUSEWHEEL +# define WM_MOUSEWHEEL 0x020A +#endif +#ifndef WM_MOUSEHWHEEL +# define WM_MOUSEHWHEEL 0x020E +#endif +#ifndef WHEEL_DELTA +# define WHEEL_DELTA 120 +#endif +#ifndef GWLP_USERDATA +# define GWLP_USERDATA (-21) +#endif + +#define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50) +#define PUGL_LOCAL_MARK_MSG (WM_USER + 51) +#define PUGL_LOCAL_CLIENT_MSG (WM_USER + 52) +#define PUGL_USER_TIMER_MIN 9470 + +#ifdef __cplusplus +# define PUGL_INIT_STRUCT \ + {} +#else +# define PUGL_INIT_STRUCT \ + { \ + 0 \ + } +#endif + +typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void); +typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*); +typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*); + +LRESULT CALLBACK +wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +static wchar_t* +puglUtf8ToWideChar(const char* const utf8) +{ + const int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); + if (len > 0) { + wchar_t* result = (wchar_t*)calloc((size_t)len, sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, utf8, -1, result, len); + return result; + } + + return NULL; +} + +static char* +puglWideCharToUtf8(const wchar_t* const wstr, size_t* len) +{ + int n = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); + if (n > 0) { + char* result = (char*)calloc((size_t)n, sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, n, NULL, NULL); + *len = (size_t)n - 1; + return result; + } + + return NULL; +} + +static bool +puglRegisterWindowClass(const char* name) +{ + HMODULE module = NULL; + if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCTSTR)puglRegisterWindowClass, + &module)) { + module = GetModuleHandle(NULL); + } + + WNDCLASSEX wc = PUGL_INIT_STRUCT; + if (GetClassInfoEx(module, name, &wc)) { + return true; // Already registered + } + + wc.cbSize = sizeof(wc); + wc.style = CS_OWNDC; + wc.lpfnWndProc = wndProc; + wc.hInstance = module; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wc.lpszClassName = name; + + return !!RegisterClassEx(&wc); +} + +static unsigned +puglWinGetWindowFlags(const PuglView* const view) +{ + const bool resizable = !!view->hints[PUGL_RESIZABLE]; + const unsigned sizeFlags = resizable ? (WS_SIZEBOX | WS_MAXIMIZEBOX) : 0u; + + return (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | + (view->parent + ? WS_CHILD + : (WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | sizeFlags))); +} + +static unsigned +puglWinGetWindowExFlags(const PuglView* const view) +{ + return WS_EX_NOINHERITLAYOUT | (view->parent ? 0u : WS_EX_APPWINDOW); +} + +static double +puglWinGetViewScaleFactor(HWND hwnd) +{ + const HMODULE shcore = LoadLibrary("Shcore.dll"); + if (!shcore) { + return 1.0; + } + + const PFN_GetProcessDpiAwareness GetProcessDpiAwareness = + (PFN_GetProcessDpiAwareness)GetProcAddress(shcore, + "GetProcessDpiAwareness"); + + const PFN_GetScaleFactorForMonitor GetScaleFactorForMonitor = + (PFN_GetScaleFactorForMonitor)GetProcAddress(shcore, + "GetScaleFactorForMonitor"); + + DWORD dpiAware = 0; + DWORD scaleFactor = 100; + if (GetProcessDpiAwareness && GetScaleFactorForMonitor && + !GetProcessDpiAwareness(NULL, &dpiAware) && dpiAware) { + GetScaleFactorForMonitor( + MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), + &scaleFactor); + } + + FreeLibrary(shcore); + return (double)scaleFactor / 100.0; +} + +PuglWorldInternals* +puglInitWorldInternals(PuglWorldType type, PuglWorldFlags PUGL_UNUSED(flags)) +{ + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); + if (!impl) { + return NULL; + } + + if (type == PUGL_PROGRAM) { + HMODULE user32 = LoadLibrary("user32.dll"); + if (user32) { + PFN_SetProcessDPIAware SetProcessDPIAware = + (PFN_SetProcessDPIAware)GetProcAddress(user32, "SetProcessDPIAware"); + if (SetProcessDPIAware) { + SetProcessDPIAware(); + } + + FreeLibrary(user32); + } + } + + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + impl->timerFrequency = (double)frequency.QuadPart; + + return impl; +} + +void* +puglGetNativeWorld(PuglWorld* PUGL_UNUSED(world)) +{ + return GetModuleHandle(NULL); +} + +PuglInternals* +puglInitViewInternals(PuglWorld* PUGL_UNUSED(world)) +{ + return (PuglInternals*)calloc(1, sizeof(PuglInternals)); +} + +static PuglStatus +puglPollWinEvents(PuglWorld* world, const double timeout) +{ + (void)world; + + if (timeout < 0) { + WaitMessage(); + } else { + MsgWaitForMultipleObjects( + 0, NULL, FALSE, (DWORD)(timeout * 1e3), QS_ALLEVENTS); + } + return PUGL_SUCCESS; +} + +PuglStatus +puglRealize(PuglView* view) +{ + PuglInternals* impl = view->impl; + if (impl->hwnd) { + return PUGL_FAILURE; + } + + // Getting depth from the display mode seems tedious, just set usual values + if (view->hints[PUGL_RED_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_RED_BITS] = 8; + } + if (view->hints[PUGL_BLUE_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_BLUE_BITS] = 8; + } + if (view->hints[PUGL_GREEN_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_GREEN_BITS] = 8; + } + if (view->hints[PUGL_ALPHA_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_ALPHA_BITS] = 8; + } + + // Get refresh rate for resize draw timer + DEVMODEA devMode; + memset(&devMode, 0, sizeof(devMode)); + EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devMode); + view->hints[PUGL_REFRESH_RATE] = (int)devMode.dmDisplayFrequency; + + // Register window class if necessary + if (!puglRegisterWindowClass(view->world->className)) { + return PUGL_REGISTRATION_FAILED; + } + + if (!view->backend || !view->backend->configure) { + return PUGL_BAD_BACKEND; + } + + PuglStatus st = PUGL_SUCCESS; + if ((st = view->backend->configure(view)) || + (st = view->backend->create(view))) { + return st; + } + + if (view->title) { + puglSetWindowTitle(view, view->title); + } + + view->impl->scaleFactor = puglWinGetViewScaleFactor(view->impl->hwnd); + view->impl->cursor = LoadCursor(NULL, IDC_ARROW); + + puglSetFrame(view, view->frame); + SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view); + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + return PUGL_SUCCESS; +} + +PuglStatus +puglShow(PuglView* view) +{ + PuglInternals* impl = view->impl; + + if (!impl->hwnd) { + const PuglStatus st = puglRealize(view); + if (st) { + return st; + } + } + + ShowWindow(impl->hwnd, SW_SHOWNORMAL); + SetFocus(impl->hwnd); + return PUGL_SUCCESS; +} + +PuglStatus +puglHide(PuglView* view) +{ + PuglInternals* impl = view->impl; + + ShowWindow(impl->hwnd, SW_HIDE); + return PUGL_SUCCESS; +} + +void +puglFreeViewInternals(PuglView* view) +{ + if (view) { + if (view->backend) { + view->backend->destroy(view); + } + + ReleaseDC(view->impl->hwnd, view->impl->hdc); + DestroyWindow(view->impl->hwnd); + free(view->impl); + } +} + +void +puglFreeWorldInternals(PuglWorld* world) +{ + UnregisterClass(world->className, NULL); + free(world->impl); +} + +static PuglKey +keySymToSpecial(WPARAM sym) +{ + // clang-format off + switch (sym) { + case VK_F1: return PUGL_KEY_F1; + case VK_F2: return PUGL_KEY_F2; + case VK_F3: return PUGL_KEY_F3; + case VK_F4: return PUGL_KEY_F4; + case VK_F5: return PUGL_KEY_F5; + case VK_F6: return PUGL_KEY_F6; + case VK_F7: return PUGL_KEY_F7; + case VK_F8: return PUGL_KEY_F8; + case VK_F9: return PUGL_KEY_F9; + case VK_F10: return PUGL_KEY_F10; + case VK_F11: return PUGL_KEY_F11; + case VK_F12: return PUGL_KEY_F12; + case VK_BACK: return PUGL_KEY_BACKSPACE; + case VK_DELETE: return PUGL_KEY_DELETE; + case VK_LEFT: return PUGL_KEY_LEFT; + case VK_UP: return PUGL_KEY_UP; + case VK_RIGHT: return PUGL_KEY_RIGHT; + case VK_DOWN: return PUGL_KEY_DOWN; + case VK_PRIOR: return PUGL_KEY_PAGE_UP; + case VK_NEXT: return PUGL_KEY_PAGE_DOWN; + case VK_HOME: return PUGL_KEY_HOME; + case VK_END: return PUGL_KEY_END; + case VK_INSERT: return PUGL_KEY_INSERT; + case VK_SHIFT: + case VK_LSHIFT: return PUGL_KEY_SHIFT_L; + case VK_RSHIFT: return PUGL_KEY_SHIFT_R; + case VK_CONTROL: + case VK_LCONTROL: return PUGL_KEY_CTRL_L; + case VK_RCONTROL: return PUGL_KEY_CTRL_R; + case VK_MENU: + case VK_LMENU: return PUGL_KEY_ALT_L; + case VK_RMENU: return PUGL_KEY_ALT_R; + case VK_LWIN: return PUGL_KEY_SUPER_L; + case VK_RWIN: return PUGL_KEY_SUPER_R; + case VK_CAPITAL: return PUGL_KEY_CAPS_LOCK; + case VK_SCROLL: return PUGL_KEY_SCROLL_LOCK; + case VK_NUMLOCK: return PUGL_KEY_NUM_LOCK; + case VK_SNAPSHOT: return PUGL_KEY_PRINT_SCREEN; + case VK_PAUSE: return PUGL_KEY_PAUSE; + } + // clang-format on + + return (PuglKey)0; +} + +static uint32_t +getModifiers(void) +{ + // clang-format off + return (((GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0u) | + ((GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0u) | + ((GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0u) | + ((GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0u) | + ((GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0u)); + // clang-format on +} + +static void +initMouseEvent(PuglEvent* event, + PuglView* view, + int button, + bool press, + LPARAM lParam) +{ + POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; + ClientToScreen(view->impl->hwnd, &pt); + + if (press) { + SetCapture(view->impl->hwnd); + } else { + ReleaseCapture(); + } + + event->button.time = GetMessageTime() / 1e3; + event->button.type = press ? PUGL_BUTTON_PRESS : PUGL_BUTTON_RELEASE; + event->button.x = GET_X_LPARAM(lParam); + event->button.y = GET_Y_LPARAM(lParam); + event->button.xRoot = pt.x; + event->button.yRoot = pt.y; + event->button.state = getModifiers(); + event->button.button = (uint32_t)button; +} + +static void +initScrollEvent(PuglEvent* event, PuglView* view, LPARAM lParam) +{ + POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; + ScreenToClient(view->impl->hwnd, &pt); + + event->scroll.time = GetMessageTime() / 1e3; + event->scroll.type = PUGL_SCROLL; + event->scroll.x = pt.x; + event->scroll.y = pt.y; + event->scroll.xRoot = GET_X_LPARAM(lParam); + event->scroll.yRoot = GET_Y_LPARAM(lParam); + event->scroll.state = getModifiers(); + event->scroll.dx = 0; + event->scroll.dy = 0; +} + +/// Return the code point for buf, or the replacement character on error +static uint32_t +puglDecodeUTF16(const wchar_t* buf, const int len) +{ + const uint32_t c0 = buf[0]; + const uint32_t c1 = buf[0]; + if (c0 >= 0xD800u && c0 < 0xDC00u) { + if (len < 2) { + return 0xFFFD; // Surrogate, but length is only 1 + } + + if (c1 >= 0xDC00u && c1 <= 0xDFFFu) { + return ((c0 & 0x03FFu) << 10u) + (c1 & 0x03FFu) + 0x10000u; + } + + return 0xFFFD; // Unpaired surrogates + } + + return c0; +} + +static void +initKeyEvent(PuglKeyEvent* event, + PuglView* view, + bool press, + WPARAM wParam, + LPARAM lParam) +{ + POINT rpos = {0, 0}; + GetCursorPos(&rpos); + + POINT cpos = {rpos.x, rpos.y}; + ScreenToClient(view->impl->hwnd, &rpos); + + const unsigned scode = (uint32_t)((lParam & 0xFF0000) >> 16); + const unsigned vkey = + ((wParam == VK_SHIFT) ? MapVirtualKey(scode, MAPVK_VSC_TO_VK_EX) + : (unsigned)wParam); + + const unsigned vcode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC); + const unsigned kchar = MapVirtualKey(vkey, MAPVK_VK_TO_CHAR); + const bool dead = kchar >> (sizeof(UINT) * 8u - 1u) & 1u; + const bool ext = lParam & 0x01000000; + + event->type = press ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; + event->time = GetMessageTime() / 1e3; + event->state = getModifiers(); + event->xRoot = rpos.x; + event->yRoot = rpos.y; + event->x = cpos.x; + event->y = cpos.y; + event->keycode = (uint32_t)((lParam & 0xFF0000) >> 16); + event->key = 0; + + const PuglKey special = keySymToSpecial(vkey); + if (special) { + if (ext && (special == PUGL_KEY_CTRL || special == PUGL_KEY_ALT)) { + event->key = (uint32_t)special + 1u; // Right hand key + } else { + event->key = (uint32_t)special; + } + } else if (!dead) { + // Translate unshifted key + BYTE keyboardState[256] = PUGL_INIT_STRUCT; + wchar_t buf[5] = PUGL_INIT_STRUCT; + + event->key = puglDecodeUTF16( + buf, ToUnicode(vkey, vcode, keyboardState, buf, 4, 1 << 2)); + } +} + +static void +initCharEvent(PuglEvent* event, PuglView* view, WPARAM wParam, LPARAM lParam) +{ + const wchar_t utf16[2] = {(wchar_t)(wParam & 0xFFFFu), + (wchar_t)((wParam >> 16u) & 0xFFFFu)}; + + initKeyEvent(&event->key, view, true, wParam, lParam); + event->type = PUGL_TEXT; + event->text.character = puglDecodeUTF16(utf16, 2); + + if (!WideCharToMultiByte( + CP_UTF8, 0, utf16, 2, event->text.string, 8, NULL, NULL)) { + memset(event->text.string, 0, 8); + } +} + +static bool +ignoreKeyEvent(PuglView* view, LPARAM lParam) +{ + return view->hints[PUGL_IGNORE_KEY_REPEAT] && (lParam & (1 << 30)); +} + +static RECT +handleConfigure(PuglView* view, PuglEvent* event) +{ + RECT rect; + GetClientRect(view->impl->hwnd, &rect); + MapWindowPoints(view->impl->hwnd, + view->parent ? (HWND)view->parent : HWND_DESKTOP, + (LPPOINT)&rect, + 2); + + const LONG width = rect.right - rect.left; + const LONG height = rect.bottom - rect.top; + + view->frame.x = (PuglCoord)rect.left; + view->frame.y = (PuglCoord)rect.top; + + event->configure.type = PUGL_CONFIGURE; + event->configure.x = (PuglCoord)view->frame.x; + event->configure.y = (PuglCoord)view->frame.y; + event->configure.width = (PuglSpan)width; + event->configure.height = (PuglSpan)height; + + return rect; +} + +static void +handleCrossing(PuglView* view, const PuglEventType type, POINT pos) +{ + POINT root_pos = pos; + ClientToScreen(view->impl->hwnd, &root_pos); + + const PuglCrossingEvent ev = { + type, + 0, + GetMessageTime() / 1e3, + (double)pos.x, + (double)pos.y, + (double)root_pos.x, + (double)root_pos.y, + getModifiers(), + PUGL_CROSSING_NORMAL, + }; + + PuglEvent crossingEvent = {{type, 0}}; + crossingEvent.crossing = ev; + puglDispatchEvent(view, &crossingEvent); +} + +static void +constrainAspect(const PuglView* const view, + RECT* const size, + const WPARAM wParam) +{ + const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT]; + const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; + + const float minA = (float)minAspect.width / (float)minAspect.height; + const float maxA = (float)maxAspect.width / (float)maxAspect.height; + const float w = (float)(size->right - size->left); + const float h = (float)(size->bottom - size->top); + const float a = w / h; + + switch (wParam) { + case WMSZ_TOP: + size->top = (a < minA ? (LONG)((float)size->bottom - w * minA) + : a > maxA ? (LONG)((float)size->bottom - w * maxA) + : size->top); + break; + case WMSZ_TOPRIGHT: + case WMSZ_RIGHT: + case WMSZ_BOTTOMRIGHT: + size->right = (a < minA ? (LONG)((float)size->left + h * minA) + : a > maxA ? (LONG)((float)size->left + h * maxA) + : size->right); + break; + case WMSZ_BOTTOM: + size->bottom = (a < minA ? (LONG)((float)size->top + w * minA) + : a > maxA ? (LONG)((float)size->top + w * maxA) + : size->bottom); + break; + case WMSZ_BOTTOMLEFT: + case WMSZ_LEFT: + case WMSZ_TOPLEFT: + size->left = (a < minA ? (LONG)((float)size->right - h * minA) + : a > maxA ? (LONG)((float)size->right - h * maxA) + : size->left); + break; + } +} + +static LRESULT +handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) +{ + PuglEvent event = {{PUGL_NOTHING, 0}}; + RECT rect = {0, 0, 0, 0}; + POINT pt = {0, 0}; + MINMAXINFO* mmi = NULL; + void* dummy_ptr = NULL; + + if (InSendMessageEx(dummy_ptr)) { + event.any.flags |= PUGL_IS_SEND_EVENT; + } + + switch (message) { + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT) { + SetCursor(view->impl->cursor); + } else { + return DefWindowProc(view->impl->hwnd, message, wParam, lParam); + } + break; + case WM_SHOWWINDOW: + if (wParam) { + handleConfigure(view, &event); + puglDispatchEvent(view, &event); + event.type = PUGL_NOTHING; + + RedrawWindow(view->impl->hwnd, + NULL, + NULL, + RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_INTERNALPAINT); + } + + event.any.type = wParam ? PUGL_MAP : PUGL_UNMAP; + break; + case WM_SIZE: + if (wParam == SIZE_MINIMIZED) { + event.type = PUGL_UNMAP; + } else if (!view->visible) { + event.type = PUGL_MAP; + } else { + handleConfigure(view, &event); + InvalidateRect(view->impl->hwnd, NULL, false); + } + break; + case WM_DISPLAYCHANGE: + view->impl->scaleFactor = puglWinGetViewScaleFactor(view->impl->hwnd); + break; + case WM_WINDOWPOSCHANGED: + handleConfigure(view, &event); + break; + case WM_SIZING: + if (view->sizeHints[PUGL_MIN_ASPECT].width) { + constrainAspect(view, (RECT*)lParam, wParam); + return TRUE; + } + break; + case WM_ENTERSIZEMOVE: + case WM_ENTERMENULOOP: + puglDispatchSimpleEvent(view, PUGL_LOOP_ENTER); + break; + case WM_TIMER: + if (wParam >= PUGL_USER_TIMER_MIN) { + PuglEvent ev = {{PUGL_TIMER, 0}}; + ev.timer.id = wParam - PUGL_USER_TIMER_MIN; + puglDispatchEvent(view, &ev); + } + break; + case WM_EXITSIZEMOVE: + case WM_EXITMENULOOP: + puglDispatchSimpleEvent(view, PUGL_LOOP_LEAVE); + break; + case WM_GETMINMAXINFO: + mmi = (MINMAXINFO*)lParam; + mmi->ptMinTrackSize.x = view->sizeHints[PUGL_MIN_SIZE].width; + mmi->ptMinTrackSize.y = view->sizeHints[PUGL_MIN_SIZE].height; + if (view->sizeHints[PUGL_MAX_SIZE].width && + view->sizeHints[PUGL_MAX_SIZE].height) { + mmi->ptMaxTrackSize.x = view->sizeHints[PUGL_MAX_SIZE].width; + mmi->ptMaxTrackSize.y = view->sizeHints[PUGL_MAX_SIZE].height; + } + break; + case WM_PAINT: + GetUpdateRect(view->impl->hwnd, &rect, false); + event.expose.type = PUGL_EXPOSE; + event.expose.x = (PuglCoord)rect.left; + event.expose.y = (PuglCoord)rect.top; + event.expose.width = (PuglSpan)(rect.right - rect.left); + event.expose.height = (PuglSpan)(rect.bottom - rect.top); + break; + case WM_ERASEBKGND: + return true; + case WM_MOUSEMOVE: + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + if (!view->impl->mouseTracked) { + TRACKMOUSEEVENT tme = PUGL_INIT_STRUCT; + + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = view->impl->hwnd; + TrackMouseEvent(&tme); + + handleCrossing(view, PUGL_POINTER_IN, pt); + view->impl->mouseTracked = true; + } + + ClientToScreen(view->impl->hwnd, &pt); + event.motion.type = PUGL_MOTION; + event.motion.time = GetMessageTime() / 1e3; + event.motion.x = GET_X_LPARAM(lParam); + event.motion.y = GET_Y_LPARAM(lParam); + event.motion.xRoot = pt.x; + event.motion.yRoot = pt.y; + event.motion.state = getModifiers(); + break; + case WM_MOUSELEAVE: + GetCursorPos(&pt); + ScreenToClient(view->impl->hwnd, &pt); + handleCrossing(view, PUGL_POINTER_OUT, pt); + view->impl->mouseTracked = false; + break; + case WM_LBUTTONDOWN: + initMouseEvent(&event, view, 0, true, lParam); + break; + case WM_MBUTTONDOWN: + initMouseEvent(&event, view, 2, true, lParam); + break; + case WM_RBUTTONDOWN: + initMouseEvent(&event, view, 1, true, lParam); + break; + case WM_XBUTTONDOWN: + if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) { + initMouseEvent(&event, view, 3, true, lParam); + } else { + initMouseEvent(&event, view, 4, true, lParam); + } + break; + case WM_LBUTTONUP: + initMouseEvent(&event, view, 0, false, lParam); + break; + case WM_MBUTTONUP: + initMouseEvent(&event, view, 2, false, lParam); + break; + case WM_RBUTTONUP: + initMouseEvent(&event, view, 1, false, lParam); + break; + case WM_XBUTTONUP: + if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) { + initMouseEvent(&event, view, 3, false, lParam); + } else { + initMouseEvent(&event, view, 4, false, lParam); + } + break; + case WM_MOUSEWHEEL: + initScrollEvent(&event, view, lParam); + event.scroll.dy = GET_WHEEL_DELTA_WPARAM(wParam) / (double)WHEEL_DELTA; + event.scroll.direction = + (event.scroll.dy > 0 ? PUGL_SCROLL_UP : PUGL_SCROLL_DOWN); + break; + case WM_MOUSEHWHEEL: + initScrollEvent(&event, view, lParam); + event.scroll.dx = GET_WHEEL_DELTA_WPARAM(wParam) / (double)WHEEL_DELTA; + event.scroll.direction = + (event.scroll.dx > 0 ? PUGL_SCROLL_RIGHT : PUGL_SCROLL_LEFT); + break; + case WM_KEYDOWN: + if (!ignoreKeyEvent(view, lParam)) { + initKeyEvent(&event.key, view, true, wParam, lParam); + } + break; + case WM_KEYUP: + initKeyEvent(&event.key, view, false, wParam, lParam); + break; + case WM_CHAR: + initCharEvent(&event, view, wParam, lParam); + break; + case WM_SETFOCUS: + event.type = PUGL_FOCUS_IN; + break; + case WM_KILLFOCUS: + event.type = PUGL_FOCUS_OUT; + break; + case WM_SYSKEYDOWN: + initKeyEvent(&event.key, view, true, wParam, lParam); + break; + case WM_SYSKEYUP: + initKeyEvent(&event.key, view, false, wParam, lParam); + break; + case WM_SYSCHAR: + return TRUE; + case PUGL_LOCAL_CLIENT_MSG: + event.client.type = PUGL_CLIENT; + event.client.data1 = (uintptr_t)wParam; + event.client.data2 = (uintptr_t)lParam; + break; + case WM_QUIT: + case PUGL_LOCAL_CLOSE_MSG: + event.any.type = PUGL_CLOSE; + break; + default: + return DefWindowProc(view->impl->hwnd, message, wParam, lParam); + } + + puglDispatchEvent(view, &event); + + return 0; +} + +PuglStatus +puglGrabFocus(PuglView* view) +{ + SetFocus(view->impl->hwnd); + return PUGL_SUCCESS; +} + +bool +puglHasFocus(const PuglView* view) +{ + return GetFocus() == view->impl->hwnd; +} + +PuglStatus +puglRequestAttention(PuglView* view) +{ + FLASHWINFO info = { + sizeof(FLASHWINFO), view->impl->hwnd, FLASHW_ALL | FLASHW_TIMERNOFG, 1, 0}; + + FlashWindowEx(&info); + + return PUGL_SUCCESS; +} + +PuglStatus +puglStartTimer(PuglView* view, uintptr_t id, double timeout) +{ + const UINT msec = (UINT)floor(timeout * 1000.0); + + return (SetTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id, msec, NULL) + ? PUGL_SUCCESS + : PUGL_UNKNOWN_ERROR); +} + +PuglStatus +puglStopTimer(PuglView* view, uintptr_t id) +{ + return (KillTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id) + ? PUGL_SUCCESS + : PUGL_UNKNOWN_ERROR); +} + +PuglStatus +puglSendEvent(PuglView* view, const PuglEvent* event) +{ + if (event->type == PUGL_CLIENT) { + PostMessage(view->impl->hwnd, + PUGL_LOCAL_CLIENT_MSG, + (WPARAM)event->client.data1, + (LPARAM)event->client.data2); + + return PUGL_SUCCESS; + } + + return PUGL_UNSUPPORTED; +} + +#ifndef PUGL_DISABLE_DEPRECATED +PuglStatus +puglWaitForEvent(PuglView* PUGL_UNUSED(view)) +{ + WaitMessage(); + return PUGL_SUCCESS; +} +#endif + +static PuglStatus +puglDispatchViewEvents(PuglView* view) +{ + /* Windows has no facility to process only currently queued messages, which + causes the event loop to run forever in cases like mouse movement where + the queue is constantly being filled with new messages. To work around + this, we post a message to ourselves before starting, record its time + when it is received, then break the loop on the first message that was + created afterwards. */ + + long markTime = 0; + MSG msg; + while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) { + if (msg.message == PUGL_LOCAL_MARK_MSG) { + markTime = GetMessageTime(); + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + if (markTime != 0 && GetMessageTime() > markTime) { + break; + } + } + } + + return PUGL_SUCCESS; +} + +static PuglStatus +puglDispatchWinEvents(PuglWorld* world) +{ + for (size_t i = 0; i < world->numViews; ++i) { + PostMessage(world->views[i]->impl->hwnd, PUGL_LOCAL_MARK_MSG, 0, 0); + } + + for (size_t i = 0; i < world->numViews; ++i) { + puglDispatchViewEvents(world->views[i]); + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglUpdate(PuglWorld* world, double timeout) +{ + const double startTime = puglGetTime(world); + PuglStatus st = PUGL_SUCCESS; + + if (timeout < 0.0) { + st = puglPollWinEvents(world, timeout); + st = st ? st : puglDispatchWinEvents(world); + } else if (timeout == 0.0) { + st = puglDispatchWinEvents(world); + } else { + const double endTime = startTime + timeout - 0.001; + for (double t = startTime; t < endTime; t = puglGetTime(world)) { + if ((st = puglPollWinEvents(world, endTime - t)) || + (st = puglDispatchWinEvents(world))) { + break; + } + } + } + + for (size_t i = 0; i < world->numViews; ++i) { + if (world->views[i]->visible) { + puglDispatchSimpleEvent(world->views[i], PUGL_UPDATE); + } + + UpdateWindow(world->views[i]->impl->hwnd); + } + + return st; +} + +#ifndef PUGL_DISABLE_DEPRECATED +PuglStatus +puglProcessEvents(PuglView* view) +{ + return puglUpdate(view->world, 0.0); +} +#endif + +LRESULT CALLBACK +wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PuglView* view = (PuglView*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (message) { + case WM_CREATE: + PostMessage(hwnd, WM_SHOWWINDOW, TRUE, 0); + return 0; + case WM_CLOSE: + PostMessage(hwnd, PUGL_LOCAL_CLOSE_MSG, wParam, lParam); + return 0; + case WM_DESTROY: + return 0; + default: + if (view && hwnd == view->impl->hwnd) { + return handleMessage(view, message, wParam, lParam); + } else { + return DefWindowProc(hwnd, message, wParam, lParam); + } + } +} + +double +puglGetTime(const PuglWorld* world) +{ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return ((double)count.QuadPart / world->impl->timerFrequency - + world->startTime); +} + +PuglStatus +puglPostRedisplay(PuglView* view) +{ + InvalidateRect(view->impl->hwnd, NULL, false); + return PUGL_SUCCESS; +} + +PuglStatus +puglPostRedisplayRect(PuglView* view, const PuglRect rect) +{ + const RECT r = {(long)floor(rect.x), + (long)floor(rect.y), + (long)ceil(rect.x + rect.width), + (long)ceil(rect.y + rect.height)}; + + InvalidateRect(view->impl->hwnd, &r, false); + + return PUGL_SUCCESS; +} + +PuglNativeView +puglGetNativeView(PuglView* view) +{ + return (PuglNativeView)view->impl->hwnd; +} + +PuglStatus +puglSetWindowTitle(PuglView* view, const char* title) +{ + puglSetString(&view->title, title); + + if (view->impl->hwnd) { + wchar_t* wtitle = puglUtf8ToWideChar(title); + if (wtitle) { + SetWindowTextW(view->impl->hwnd, wtitle); + free(wtitle); + } + } + + return PUGL_SUCCESS; +} + +static RECT +adjustedWindowRect(PuglView* const view, + const long x, + const long y, + const long width, + const long height) +{ + const unsigned flags = puglWinGetWindowFlags(view); + const unsigned exFlags = puglWinGetWindowExFlags(view); + + RECT rect = {(long)x, (long)y, (long)x + (long)width, (long)y + (long)height}; + AdjustWindowRectEx(&rect, flags, FALSE, exFlags); + return rect; +} + +double +puglGetScaleFactor(const PuglView* const view) +{ + if (view->impl->scaleFactor) { + return view->impl->scaleFactor; + } + return puglWinGetViewScaleFactor(view->parent + ? (HWND)view->parent + : view->transientParent + ? (HWND)view->transientParent + : NULL); +} + +PuglStatus +puglSetFrame(PuglView* view, const PuglRect frame) +{ + if (view->impl->hwnd) { + const RECT rect = + adjustedWindowRect(view, frame.x, frame.y, frame.width, frame.height); + + if (!SetWindowPos(view->impl->hwnd, + HWND_TOP, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER)) { + return PUGL_UNKNOWN_ERROR; + } + } + + view->frame = frame; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetPosition(PuglView* const view, const int x, const int y) +{ + if (x > INT16_MAX || y > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + if (view->impl->hwnd) { + const RECT rect = + adjustedWindowRect(view, x, y, view->frame.width, view->frame.height); + + if (!SetWindowPos(view->impl->hwnd, + HWND_TOP, + rect.left, + rect.top, + 0, + 0, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | + SWP_NOSIZE)) { + return PUGL_UNKNOWN_ERROR; + } + } + + view->frame.x = (PuglCoord)x; + view->frame.y = (PuglCoord)y; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSize(PuglView* const view, const unsigned width, const unsigned height) +{ + if (width > INT16_MAX || height > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + if (view->impl->hwnd) { + const RECT rect = adjustedWindowRect( + view, view->frame.x, view->frame.y, (long)width, (long)height); + + if (!SetWindowPos(view->impl->hwnd, + HWND_TOP, + 0, + 0, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | + SWP_NOMOVE)) { + return PUGL_UNKNOWN_ERROR; + } + } + + view->frame.width = (PuglSpan)width; + view->frame.height = (PuglSpan)height; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) +{ + if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) { + return PUGL_BAD_PARAMETER; + } + + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetTransientParent(PuglView* view, PuglNativeView parent) +{ + if (view->parent) { + return PUGL_FAILURE; + } + + view->transientParent = parent; + + if (view->impl->hwnd) { + SetWindowLongPtr(view->impl->hwnd, GWLP_HWNDPARENT, (LONG_PTR)parent); + return GetLastError() == NO_ERROR ? PUGL_SUCCESS : PUGL_FAILURE; + } + + return PUGL_SUCCESS; +} + +uint32_t +puglGetNumClipboardTypes(const PuglView* const PUGL_UNUSED(view)) +{ + return IsClipboardFormatAvailable(CF_UNICODETEXT) ? 1u : 0u; +} + +const char* +puglGetClipboardType(const PuglView* const PUGL_UNUSED(view), + const uint32_t typeIndex) +{ + return (typeIndex == 0 && IsClipboardFormatAvailable(CF_UNICODETEXT)) + ? "text/plain" + : NULL; +} + +PuglStatus +puglAcceptOffer(PuglView* const view, + const PuglDataOfferEvent* const PUGL_UNUSED(offer), + const uint32_t typeIndex) +{ + if (typeIndex != 0) { + return PUGL_UNSUPPORTED; + } + + const PuglDataEvent data = { + PUGL_DATA, + 0, + GetMessageTime() / 1e3, + 0, + }; + + PuglEvent dataEvent; + dataEvent.data = data; + puglDispatchEvent(view, &dataEvent); + return PUGL_SUCCESS; +} + +const void* +puglGetClipboard(PuglView* const view, + const uint32_t typeIndex, + size_t* const len) +{ + PuglInternals* const impl = view->impl; + + if (typeIndex > 0u || !IsClipboardFormatAvailable(CF_UNICODETEXT) || + !OpenClipboard(impl->hwnd)) { + return NULL; + } + + HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); + wchar_t* wstr = mem ? (wchar_t*)GlobalLock(mem) : NULL; + if (!wstr) { + CloseClipboard(); + return NULL; + } + + free(view->impl->clipboard.data); + view->impl->clipboard.data = + puglWideCharToUtf8(wstr, &view->impl->clipboard.len); + + GlobalUnlock(mem); + CloseClipboard(); + + *len = view->impl->clipboard.len; + return view->impl->clipboard.data; +} + +PuglStatus +puglSetClipboard(PuglView* const view, + const char* const type, + const void* const data, + const size_t len) +{ + PuglInternals* const impl = view->impl; + + PuglStatus st = puglSetBlob(&view->impl->clipboard, data, len); + if (st) { + return st; + } + + if (!!strcmp(type, "text/plain")) { + return PUGL_UNSUPPORTED; + } + + if (!OpenClipboard(impl->hwnd)) { + return PUGL_UNKNOWN_ERROR; + } + + // Measure string and allocate global memory for clipboard + const char* str = (const char*)data; + const int wlen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + HGLOBAL mem = + GlobalAlloc(GMEM_MOVEABLE, (size_t)(wlen + 1) * sizeof(wchar_t)); + if (!mem) { + CloseClipboard(); + return PUGL_UNKNOWN_ERROR; + } + + // Lock global memory + wchar_t* wstr = (wchar_t*)GlobalLock(mem); + if (!wstr) { + GlobalFree(mem); + CloseClipboard(); + return PUGL_UNKNOWN_ERROR; + } + + // Convert string into global memory and set it as clipboard data + MultiByteToWideChar(CP_UTF8, 0, str, (int)len, wstr, wlen); + wstr[wlen] = 0; + GlobalUnlock(mem); + SetClipboardData(CF_UNICODETEXT, mem); + CloseClipboard(); + return PUGL_SUCCESS; +} + +PuglStatus +puglPaste(PuglView* const view) +{ + const PuglDataOfferEvent offer = { + PUGL_DATA_OFFER, + 0, + GetMessageTime() / 1e3, + }; + + PuglEvent offerEvent; + offerEvent.offer = offer; + puglDispatchEvent(view, &offerEvent); + return PUGL_SUCCESS; +} + +static const char* const cursor_ids[] = { + IDC_ARROW, // ARROW + IDC_IBEAM, // CARET + IDC_CROSS, // CROSSHAIR + IDC_HAND, // HAND + IDC_NO, // NO + IDC_SIZEWE, // LEFT_RIGHT + IDC_SIZENS, // UP_DOWN + IDC_SIZENWSE, // DIAGONAL + IDC_SIZENESW, // ANTI_DIAGONAL +}; + +PuglStatus +puglSetCursor(PuglView* view, PuglCursor cursor) +{ + PuglInternals* const impl = view->impl; + const unsigned index = (unsigned)cursor; + const unsigned count = sizeof(cursor_ids) / sizeof(cursor_ids[0]); + + if (index >= count) { + return PUGL_BAD_PARAMETER; + } + + const HCURSOR cur = LoadCursor(NULL, cursor_ids[index]); + if (!cur) { + return PUGL_FAILURE; + } + + impl->cursor = cur; + if (impl->mouseTracked) { + SetCursor(cur); + } + + return PUGL_SUCCESS; +} + +// Semi-public platform API used by backends + +PuglWinPFD +puglWinGetPixelFormatDescriptor(const PuglHints hints) +{ + const int rgbBits = (hints[PUGL_RED_BITS] + // + hints[PUGL_GREEN_BITS] + // + hints[PUGL_BLUE_BITS]); + + const DWORD dwFlags = hints[PUGL_DOUBLE_BUFFER] ? PFD_DOUBLEBUFFER : 0u; + + PuglWinPFD pfd; + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | dwFlags; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = (BYTE)rgbBits; + pfd.cRedBits = (BYTE)hints[PUGL_RED_BITS]; + pfd.cGreenBits = (BYTE)hints[PUGL_GREEN_BITS]; + pfd.cBlueBits = (BYTE)hints[PUGL_BLUE_BITS]; + pfd.cAlphaBits = (BYTE)hints[PUGL_ALPHA_BITS]; + pfd.cDepthBits = (BYTE)hints[PUGL_DEPTH_BITS]; + pfd.cStencilBits = (BYTE)hints[PUGL_STENCIL_BITS]; + pfd.iLayerType = PFD_MAIN_PLANE; + return pfd; +} + +PuglStatus +puglWinCreateWindow(PuglView* const view, + const char* const title, + HWND* const hwnd, + HDC* const hdc) +{ + const char* className = (const char*)view->world->className; + const unsigned winFlags = puglWinGetWindowFlags(view); + const unsigned winExFlags = puglWinGetWindowExFlags(view); + + if (view->frame.width <= 0.0 && view->frame.height <= 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { + return PUGL_BAD_CONFIGURATION; + } + + RECT desktopRect; + GetClientRect(GetDesktopWindow(), &desktopRect); + + const int screenWidth = desktopRect.right - desktopRect.left; + const int screenHeight = desktopRect.bottom - desktopRect.top; + + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + + if (!view->parent) { + view->frame.x = (PuglCoord)((screenWidth - view->frame.width) / 2); + view->frame.y = (PuglCoord)((screenHeight - view->frame.height) / 2); + } + } + + // The meaning of "parent" depends on the window type (WS_CHILD) + PuglNativeView parent = view->parent ? view->parent : view->transientParent; + + // Calculate total window size to accommodate requested view size + RECT wr = {(long)view->frame.x, + (long)view->frame.y, + (long)view->frame.width, + (long)view->frame.height}; + AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags); + + // Create window and get drawing context + if (!(*hwnd = CreateWindowEx(winExFlags, + className, + title, + winFlags, + CW_USEDEFAULT, + CW_USEDEFAULT, + wr.right - wr.left, + wr.bottom - wr.top, + (HWND)parent, + NULL, + NULL, + NULL))) { + return PUGL_REALIZE_FAILED; + } + + if (!(*hdc = GetDC(*hwnd))) { + DestroyWindow(*hwnd); + *hwnd = NULL; + return PUGL_REALIZE_FAILED; + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglWinConfigure(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglStatus st = PUGL_SUCCESS; + + if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) { + return st; + } + + impl->pfd = puglWinGetPixelFormatDescriptor(view->hints); + impl->pfId = ChoosePixelFormat(impl->hdc, &impl->pfd); + + if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) { + ReleaseDC(impl->hwnd, impl->hdc); + DestroyWindow(impl->hwnd); + impl->hwnd = NULL; + impl->hdc = NULL; + return PUGL_SET_FORMAT_FAILED; + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglWinEnter(PuglView* view, const PuglExposeEvent* expose) +{ + if (expose) { + PAINTSTRUCT ps; + BeginPaint(view->impl->hwnd, &ps); + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglWinLeave(PuglView* view, const PuglExposeEvent* expose) +{ + if (expose) { + PAINTSTRUCT ps; + EndPaint(view->impl->hwnd, &ps); + } + + return PUGL_SUCCESS; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,58 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_WIN_H +#define PUGL_SRC_WIN_H + +#include "internal.h" + +#include "pugl/pugl.h" + +#include + +#include + +typedef PIXELFORMATDESCRIPTOR PuglWinPFD; + +struct PuglWorldInternalsImpl { + double timerFrequency; +}; + +struct PuglInternalsImpl { + PuglWinPFD pfd; + int pfId; + HWND hwnd; + HCURSOR cursor; + HDC hdc; + PuglBlob clipboard; + PuglSurface* surface; + double scaleFactor; + bool flashing; + bool mouseTracked; +}; + +PUGL_API +PuglWinPFD +puglWinGetPixelFormatDescriptor(const PuglHints hints); + +PUGL_WARN_UNUSED_RESULT +PUGL_API +PuglStatus +puglWinCreateWindow(PuglView* view, const char* title, HWND* hwnd, HDC* hdc); + +PUGL_WARN_UNUSED_RESULT +PUGL_API +PuglStatus +puglWinConfigure(PuglView* view); + +PUGL_WARN_UNUSED_RESULT +PUGL_API +PuglStatus +puglWinEnter(PuglView* view, const PuglExposeEvent* expose); + +PUGL_WARN_UNUSED_RESULT +PUGL_API +PuglStatus +puglWinLeave(PuglView* view, const PuglExposeEvent* expose); + +#endif // PUGL_SRC_WIN_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_cairo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_cairo.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,163 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "stub.h" +#include "types.h" +#include "win.h" + +#include "pugl/cairo.h" + +#include +#include + +#include + +typedef struct { + cairo_surface_t* surface; + cairo_t* cr; + HDC drawDc; + HBITMAP drawBitmap; +} PuglWinCairoSurface; + +static PuglStatus +puglWinCairoCreateDrawContext(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface; + + surface->drawDc = CreateCompatibleDC(impl->hdc); + surface->drawBitmap = CreateCompatibleBitmap( + impl->hdc, (int)view->frame.width, (int)view->frame.height); + + DeleteObject(SelectObject(surface->drawDc, surface->drawBitmap)); + + return PUGL_SUCCESS; +} + +static PuglStatus +puglWinCairoDestroyDrawContext(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface; + + DeleteDC(surface->drawDc); + DeleteObject(surface->drawBitmap); + + surface->drawDc = NULL; + surface->drawBitmap = NULL; + + return PUGL_SUCCESS; +} + +static PuglStatus +puglWinCairoConfigure(PuglView* view) +{ + const PuglStatus st = puglWinConfigure(view); + + if (!st) { + view->impl->surface = + (PuglWinCairoSurface*)calloc(1, sizeof(PuglWinCairoSurface)); + } + + return st; +} + +static void +puglWinCairoClose(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface; + + cairo_surface_destroy(surface->surface); + + surface->surface = NULL; +} + +static PuglStatus +puglWinCairoOpen(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface; + + if (!(surface->surface = cairo_win32_surface_create(surface->drawDc)) || + cairo_surface_status(surface->surface) || + !(surface->cr = cairo_create(surface->surface)) || + cairo_status(surface->cr)) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + return PUGL_SUCCESS; +} + +static void +puglWinCairoDestroy(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface; + + puglWinCairoClose(view); + puglWinCairoDestroyDrawContext(view); + free(surface); + impl->surface = NULL; +} + +static PuglStatus +puglWinCairoEnter(PuglView* view, const PuglExposeEvent* expose) +{ + PuglStatus st = PUGL_SUCCESS; + + if (expose && !(st = puglWinCairoCreateDrawContext(view)) && + !(st = puglWinCairoOpen(view))) { + PAINTSTRUCT ps; + BeginPaint(view->impl->hwnd, &ps); + } + + return st; +} + +static PuglStatus +puglWinCairoLeave(PuglView* view, const PuglExposeEvent* expose) +{ + PuglInternals* const impl = view->impl; + PuglWinCairoSurface* const surface = (PuglWinCairoSurface*)impl->surface; + + if (expose) { + cairo_surface_flush(surface->surface); + BitBlt(impl->hdc, + 0, + 0, + (int)view->frame.width, + (int)view->frame.height, + surface->drawDc, + 0, + 0, + SRCCOPY); + + puglWinCairoClose(view); + puglWinCairoDestroyDrawContext(view); + + PAINTSTRUCT ps; + EndPaint(view->impl->hwnd, &ps); + } + + return PUGL_SUCCESS; +} + +static void* +puglWinCairoGetContext(PuglView* view) +{ + return ((PuglWinCairoSurface*)view->impl->surface)->cr; +} + +const PuglBackend* +puglCairoBackend() +{ + static const PuglBackend backend = {puglWinCairoConfigure, + puglStubCreate, + puglWinCairoDestroy, + puglWinCairoEnter, + puglWinCairoLeave, + puglWinCairoGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_gl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_gl.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,325 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "stub.h" +#include "types.h" +#include "win.h" + +#include "pugl/gl.h" + +#include + +#include + +#include +#include + +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_ALPHA_BITS_ARB 0x201b +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_TYPE_RGBA_ARB 0x202b +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 + +typedef HGLRC(WINAPI* WglCreateContextAttribs)(HDC, HGLRC, const int*); + +typedef BOOL(WINAPI* WglSwapInterval)(int); + +typedef BOOL(WINAPI* WglChoosePixelFormat)(HDC, + const int*, + const FLOAT*, + UINT, + int*, + UINT*); + +typedef struct { + WglChoosePixelFormat wglChoosePixelFormat; + WglCreateContextAttribs wglCreateContextAttribs; + WglSwapInterval wglSwapInterval; +} PuglWinGlProcs; + +typedef struct { + PuglWinGlProcs procs; + HGLRC hglrc; +} PuglWinGlSurface; + +// Struct to manage the fake window used during configuration +typedef struct { + HWND hwnd; + HDC hdc; +} PuglFakeWindow; + +static PuglStatus +puglWinError(PuglFakeWindow* fakeWin, const PuglStatus status) +{ + if (fakeWin->hwnd) { + ReleaseDC(fakeWin->hwnd, fakeWin->hdc); + DestroyWindow(fakeWin->hwnd); + } + + return status; +} + +static PuglWinGlProcs +puglWinGlGetProcs(void) +{ + const PuglWinGlProcs procs = { + (WglChoosePixelFormat)(wglGetProcAddress("wglChoosePixelFormatARB")), + (WglCreateContextAttribs)(wglGetProcAddress("wglCreateContextAttribsARB")), + (WglSwapInterval)(wglGetProcAddress("wglSwapIntervalEXT"))}; + + return procs; +} + +static PuglStatus +puglWinGlConfigure(PuglView* view) +{ + PuglInternals* impl = view->impl; + + // Set attributes to default if they are unset + // (There is no GLX_DONT_CARE equivalent on Windows) + if (view->hints[PUGL_DEPTH_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_DEPTH_BITS] = 0; + } + if (view->hints[PUGL_STENCIL_BITS] == PUGL_DONT_CARE) { + view->hints[PUGL_STENCIL_BITS] = 0; + } + if (view->hints[PUGL_SAMPLES] == PUGL_DONT_CARE) { + view->hints[PUGL_SAMPLES] = 1; + } + if (view->hints[PUGL_DOUBLE_BUFFER] == PUGL_DONT_CARE) { + view->hints[PUGL_DOUBLE_BUFFER] = 1; + } + if (view->hints[PUGL_SWAP_INTERVAL] == PUGL_DONT_CARE) { + view->hints[PUGL_SWAP_INTERVAL] = 1; + } + + // clang-format off + const int pixelAttrs[] = { + WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, + WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, + WGL_SUPPORT_OPENGL_ARB, GL_TRUE, + WGL_DOUBLE_BUFFER_ARB, view->hints[PUGL_DOUBLE_BUFFER], + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_SAMPLE_BUFFERS_ARB, view->hints[PUGL_SAMPLES] ? 1 : 0, + WGL_SAMPLES_ARB, view->hints[PUGL_SAMPLES], + WGL_RED_BITS_ARB, view->hints[PUGL_RED_BITS], + WGL_GREEN_BITS_ARB, view->hints[PUGL_GREEN_BITS], + WGL_BLUE_BITS_ARB, view->hints[PUGL_BLUE_BITS], + WGL_ALPHA_BITS_ARB, view->hints[PUGL_ALPHA_BITS], + WGL_DEPTH_BITS_ARB, view->hints[PUGL_DEPTH_BITS], + WGL_STENCIL_BITS_ARB, view->hints[PUGL_STENCIL_BITS], + 0, + }; + // clang-format on + + PuglWinGlSurface* const surface = + (PuglWinGlSurface*)calloc(1, sizeof(PuglWinGlSurface)); + impl->surface = surface; + + // Create fake window for getting at GL context + PuglStatus st = PUGL_SUCCESS; + PuglFakeWindow fakeWin = {0, 0}; + static const char* title = "Pugl Configuration"; + if ((st = puglWinCreateWindow(view, title, &fakeWin.hwnd, &fakeWin.hdc))) { + return puglWinError(&fakeWin, st); + } + + // Set pixel format for fake window + const PuglWinPFD fakePfd = puglWinGetPixelFormatDescriptor(view->hints); + const int fakePfId = ChoosePixelFormat(fakeWin.hdc, &fakePfd); + if (!fakePfId || !SetPixelFormat(fakeWin.hdc, fakePfId, &fakePfd)) { + return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED); + } + + // Create fake GL context to get at the functions we need + HGLRC fakeRc = wglCreateContext(fakeWin.hdc); + if (!fakeRc) { + return puglWinError(&fakeWin, PUGL_CREATE_CONTEXT_FAILED); + } + + // Enter fake context and get extension functions + wglMakeCurrent(fakeWin.hdc, fakeRc); + surface->procs = puglWinGlGetProcs(); + + if (surface->procs.wglChoosePixelFormat) { + // Choose pixel format based on attributes + UINT numFormats = 0; + if (!surface->procs.wglChoosePixelFormat( + fakeWin.hdc, pixelAttrs, NULL, 1u, &impl->pfId, &numFormats)) { + return puglWinError(&fakeWin, PUGL_SET_FORMAT_FAILED); + } + + DescribePixelFormat(impl->hdc, impl->pfId, sizeof(impl->pfd), &impl->pfd); + } else { + // Modern extensions not available, use basic pixel format + impl->pfd = fakePfd; + impl->pfId = fakePfId; + } + + // Dispose of fake window and context + wglMakeCurrent(NULL, NULL); + wglDeleteContext(fakeRc); + ReleaseDC(fakeWin.hwnd, fakeWin.hdc); + DestroyWindow(fakeWin.hwnd); + + return PUGL_SUCCESS; +} + +static PuglStatus +puglWinGlCreate(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglWinGlSurface* const surface = (PuglWinGlSurface*)impl->surface; + PuglStatus st = PUGL_SUCCESS; + + const int contextAttribs[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, + view->hints[PUGL_CONTEXT_VERSION_MAJOR], + + WGL_CONTEXT_MINOR_VERSION_ARB, + view->hints[PUGL_CONTEXT_VERSION_MINOR], + + WGL_CONTEXT_FLAGS_ARB, + (view->hints[PUGL_USE_DEBUG_CONTEXT] ? WGL_CONTEXT_DEBUG_BIT_ARB : 0), + + WGL_CONTEXT_PROFILE_MASK_ARB, + (view->hints[PUGL_USE_COMPAT_PROFILE] + ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB + : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB), + + 0}; + + // Create real window with desired pixel format + if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) { + return st; + } + + if (!SetPixelFormat(impl->hdc, impl->pfId, &impl->pfd)) { + ReleaseDC(impl->hwnd, impl->hdc); + DestroyWindow(impl->hwnd); + impl->hwnd = NULL; + impl->hdc = NULL; + return PUGL_SET_FORMAT_FAILED; + } + + // Create GL context + if (surface->procs.wglCreateContextAttribs && + !(surface->hglrc = surface->procs.wglCreateContextAttribs( + impl->hdc, 0, contextAttribs))) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + if (!(surface->hglrc = wglCreateContext(impl->hdc))) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + // Enter context and set swap interval + wglMakeCurrent(impl->hdc, surface->hglrc); + const int swapInterval = view->hints[PUGL_SWAP_INTERVAL]; + if (surface->procs.wglSwapInterval && swapInterval != PUGL_DONT_CARE) { + surface->procs.wglSwapInterval(swapInterval); + } + + return PUGL_SUCCESS; +} + +static void +puglWinGlDestroy(PuglView* view) +{ + PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface; + if (surface) { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(surface->hglrc); + free(surface); + view->impl->surface = NULL; + } +} + +static PuglStatus +puglWinGlEnter(PuglView* view, const PuglExposeEvent* expose) +{ + PuglWinGlSurface* surface = (PuglWinGlSurface*)view->impl->surface; + if (!surface || !surface->hglrc) { + return PUGL_FAILURE; + } + + wglMakeCurrent(view->impl->hdc, surface->hglrc); + + if (expose) { + PAINTSTRUCT ps; + BeginPaint(view->impl->hwnd, &ps); + } + + return PUGL_SUCCESS; +} + +static PuglStatus +puglWinGlLeave(PuglView* view, const PuglExposeEvent* expose) +{ + if (expose) { + PAINTSTRUCT ps; + EndPaint(view->impl->hwnd, &ps); + SwapBuffers(view->impl->hdc); + } + + wglMakeCurrent(NULL, NULL); + return PUGL_SUCCESS; +} + +PuglGlFunc +puglGetProcAddress(const char* name) +{ + const PuglGlFunc func = (PuglGlFunc)wglGetProcAddress(name); + + /* Windows has the annoying property that wglGetProcAddress returns NULL + for functions from OpenGL 1.1, so we fall back to pulling them directly + from opengl32.dll */ + + return func + ? func + : (PuglGlFunc)GetProcAddress(GetModuleHandle("opengl32.dll"), name); +} + +PuglStatus +puglEnterContext(PuglView* view) +{ + return view->backend->enter(view, NULL); +} + +PuglStatus +puglLeaveContext(PuglView* view) +{ + return view->backend->leave(view, NULL); +} + +const PuglBackend* +puglGlBackend(void) +{ + static const PuglBackend backend = {puglWinGlConfigure, + puglWinGlCreate, + puglWinGlDestroy, + puglWinGlEnter, + puglWinGlLeave, + puglStubGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_stub.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,39 @@ +// Copyright 2012-2021 David Robillard +// SPDX-License-Identifier: ISC + +#include "stub.h" +#include "types.h" +#include "win.h" + +#include "pugl/stub.h" + +static PuglStatus +puglWinStubConfigure(PuglView* view) +{ + return puglWinConfigure(view); +} + +static PuglStatus +puglWinStubEnter(PuglView* view, const PuglExposeEvent* expose) +{ + return puglWinEnter(view, expose); +} + +static PuglStatus +puglWinStubLeave(PuglView* view, const PuglExposeEvent* expose) +{ + return puglWinLeave(view, expose); +} + +const PuglBackend* +puglStubBackend(void) +{ + static const PuglBackend backend = {puglWinStubConfigure, + puglStubCreate, + puglStubDestroy, + puglWinStubEnter, + puglWinStubLeave, + puglStubGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_vulkan.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/win_vulkan.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,112 @@ +// Copyright 2012-2021 David Robillard +// SPDX-License-Identifier: ISC + +#define VK_NO_PROTOTYPES 1 + +#include "stub.h" +#include "types.h" +#include "win.h" + +#include "pugl/vulkan.h" + +#include +#include + +#include + +struct PuglVulkanLoaderImpl { + HMODULE libvulkan; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; +}; + +PuglVulkanLoader* +puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world)) +{ + PuglVulkanLoader* loader = + (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader)); + if (!loader) { + return NULL; + } + + if (!(loader->libvulkan = LoadLibrary("vulkan-1.dll"))) { + free(loader); + return NULL; + } + + loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress( + loader->libvulkan, "vkGetInstanceProcAddr"); + + loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)GetProcAddress( + loader->libvulkan, "vkGetDeviceProcAddr"); + + return loader; +} + +void +puglFreeVulkanLoader(PuglVulkanLoader* loader) +{ + if (loader) { + FreeLibrary(loader->libvulkan); + free(loader); + } +} + +PFN_vkGetInstanceProcAddr +puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader) +{ + return loader->vkGetInstanceProcAddr; +} + +PFN_vkGetDeviceProcAddr +puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader) +{ + return loader->vkGetDeviceProcAddr; +} + +const PuglBackend* +puglVulkanBackend() +{ + static const PuglBackend backend = {puglWinConfigure, + puglStubCreate, + puglStubDestroy, + puglWinEnter, + puglWinLeave, + puglStubGetContext}; + + return &backend; +} + +const char* const* +puglGetInstanceExtensions(uint32_t* const count) +{ + static const char* const extensions[] = {"VK_KHR_surface", + "VK_KHR_win32_surface"}; + + *count = 2; + return extensions; +} + +VkResult +puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr, + PuglView* const view, + VkInstance instance, + const VkAllocationCallbacks* const pAllocator, + VkSurfaceKHR* const pSurface) +{ + PuglInternals* const impl = view->impl; + + PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR = + (PFN_vkCreateWin32SurfaceKHR)vkGetInstanceProcAddr( + instance, "vkCreateWin32SurfaceKHR"); + + const VkWin32SurfaceCreateInfoKHR createInfo = { + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, + NULL, + 0, + GetModuleHandle(NULL), + impl->hwnd, + }; + + return vkCreateWin32SurfaceKHR(instance, &createInfo, pAllocator, pSurface); +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1819 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2013 Robin Gareus +// Copyright 2011-2012 Ben Loftis, Harrison Consoles +// SPDX-License-Identifier: ISC + +#include "x11.h" + +#include "attributes.h" +#include "internal.h" +#include "platform.h" +#include "types.h" + +#include "pugl/pugl.h" + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_XRANDR +# include +#endif + +#ifdef HAVE_XSYNC +# include +# include +#endif + +#ifdef HAVE_XCURSOR +# include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef MIN +# define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX +# define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifdef __cplusplus +# define PUGL_INIT_STRUCT \ + {} +#else +# define PUGL_INIT_STRUCT \ + { \ + 0 \ + } +#endif + +enum WmClientStateMessageAction { + WM_STATE_REMOVE, + WM_STATE_ADD, + WM_STATE_TOGGLE +}; + +#define NUM_CURSORS ((unsigned)PUGL_CURSOR_ANTI_DIAGONAL + 1u) + +#ifdef HAVE_XCURSOR +static const char* const cursor_names[NUM_CURSORS] = { + "default", // ARROW + "text", // CARET + "crosshair", // CROSSHAIR + "pointer", // HAND + "not-allowed", // NO + "sb_h_double_arrow", // LEFT_RIGHT + "sb_v_double_arrow", // UP_DOWN + "size_fdiag", // DIAGONAL + "size_bdiag" // ANTI_DIAGONAL +}; +#endif + +static bool +initXSync(PuglWorldInternals* const impl) +{ +#ifdef HAVE_XSYNC + int syncMajor = 0; + int syncMinor = 0; + int errorBase = 0; + XSyncSystemCounter* counters = NULL; + int numCounters = 0; + + if (XSyncQueryExtension(impl->display, &impl->syncEventBase, &errorBase) && + XSyncInitialize(impl->display, &syncMajor, &syncMinor) && + (counters = XSyncListSystemCounters(impl->display, &numCounters))) { + for (int n = 0; n < numCounters; ++n) { + if (!strcmp(counters[n].name, "SERVERTIME")) { + impl->serverTimeCounter = counters[n].counter; + impl->syncSupported = true; + break; + } + } + + XSyncFreeSystemCounterList(counters); + } +#else + (void)impl; +#endif + + return false; +} + +static double +puglX11GetDisplayScaleFactor(Display* const display) +{ + double dpi = 96.0; + const char* const rms = XResourceManagerString(display); + if (rms) { + XrmDatabase db = XrmGetStringDatabase(rms); + if (db) { + XrmValue value = {0u, NULL}; + char* type = NULL; + if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value)) { + if (!type || !strcmp(type, "String")) { + char* end = NULL; + const double xftDpi = strtod(value.addr, &end); + if (xftDpi > 0.0 && xftDpi < HUGE_VAL) { + dpi = xftDpi; + } + } + } + + XrmDestroyDatabase(db); + } + } + + return dpi / 96.0; +} + +PuglWorldInternals* +puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags) +{ + if (type == PUGL_PROGRAM && (flags & PUGL_WORLD_THREADS)) { + XInitThreads(); + } + + Display* display = XOpenDisplay(NULL); + if (!display) { + return NULL; + } + + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); + + impl->display = display; + impl->scaleFactor = puglX11GetDisplayScaleFactor(display); + + // Intern the various atoms we will need + impl->atoms.CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0); + impl->atoms.UTF8_STRING = XInternAtom(display, "UTF8_STRING", 0); + impl->atoms.WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", 0); + impl->atoms.WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", 0); + impl->atoms.PUGL_CLIENT_MSG = XInternAtom(display, "_PUGL_CLIENT_MSG", 0); + impl->atoms.NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", 0); + impl->atoms.NET_WM_STATE = XInternAtom(display, "_NET_WM_STATE", 0); + impl->atoms.NET_WM_STATE_DEMANDS_ATTENTION = + XInternAtom(display, "_NET_WM_STATE_DEMANDS_ATTENTION", 0); + impl->atoms.NET_WM_STATE_HIDDEN = + XInternAtom(display, "_NET_WM_STATE_HIDDEN", 0); + + impl->atoms.TARGETS = XInternAtom(display, "TARGETS", 0); + impl->atoms.text_uri_list = XInternAtom(display, "text/uri-list", 0); + + // Open input method + XSetLocaleModifiers(""); + if (!(impl->xim = XOpenIM(display, NULL, NULL, NULL))) { + XSetLocaleModifiers("@im="); + impl->xim = XOpenIM(display, NULL, NULL, NULL); + } + + XrmInitialize(); + initXSync(impl); + XFlush(display); + + return impl; +} + +void* +puglGetNativeWorld(PuglWorld* const world) +{ + return world->impl->display; +} + +PuglInternals* +puglInitViewInternals(PuglWorld* const world) +{ + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + + impl->clipboard.selection = world->impl->atoms.CLIPBOARD; + impl->clipboard.property = XA_PRIMARY; + +#ifdef HAVE_XCURSOR + impl->cursorName = cursor_names[PUGL_CURSOR_ARROW]; +#endif + + return impl; +} + +static PuglStatus +pollX11Socket(PuglWorld* const world, const double timeout) +{ + if (XPending(world->impl->display) > 0) { + return PUGL_SUCCESS; + } + + const int fd = ConnectionNumber(world->impl->display); + const int nfds = fd + 1; + int ret = 0; + fd_set fds; + FD_ZERO(&fds); // NOLINT + FD_SET(fd, &fds); + + if (timeout < 0.0) { + ret = select(nfds, &fds, NULL, NULL, NULL); + } else { + const long sec = (long)timeout; + const long usec = (long)((timeout - (double)sec) * 1e6); + struct timeval tv = {sec, usec}; + ret = select(nfds, &fds, NULL, NULL, &tv); + } + + return ret < 0 ? PUGL_UNKNOWN_ERROR : PUGL_SUCCESS; +} + +static PuglView* +findView(PuglWorld* const world, const Window window) +{ + for (size_t i = 0; i < world->numViews; ++i) { + if (world->views[i]->impl->win == window) { + return world->views[i]; + } + } + + return NULL; +} + +static PuglStatus +updateSizeHints(const PuglView* const view) +{ + if (!view->impl->win) { + return PUGL_SUCCESS; + } + + Display* display = view->world->impl->display; + XSizeHints sizeHints = PUGL_INIT_STRUCT; + + if (!view->hints[PUGL_RESIZABLE]) { + sizeHints.flags = PBaseSize | PMinSize | PMaxSize; + sizeHints.base_width = (int)view->frame.width; + sizeHints.base_height = (int)view->frame.height; + sizeHints.min_width = (int)view->frame.width; + sizeHints.min_height = (int)view->frame.height; + sizeHints.max_width = (int)view->frame.width; + sizeHints.max_height = (int)view->frame.height; + } else { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (defaultSize.width && defaultSize.height) { + sizeHints.flags |= PBaseSize; + sizeHints.base_width = defaultSize.width; + sizeHints.base_height = defaultSize.height; + } + + const PuglViewSize minSize = view->sizeHints[PUGL_MIN_SIZE]; + if (minSize.width && minSize.height) { + sizeHints.flags |= PMinSize; + sizeHints.min_width = minSize.width; + sizeHints.min_height = minSize.height; + } + + const PuglViewSize maxSize = view->sizeHints[PUGL_MAX_SIZE]; + if (maxSize.width && maxSize.height) { + sizeHints.flags |= PMaxSize; + sizeHints.max_width = maxSize.width; + sizeHints.max_height = maxSize.height; + } + + const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT]; + const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; + if (minAspect.width && minAspect.height && maxAspect.width && + maxAspect.height) { + sizeHints.flags |= PAspect; + sizeHints.min_aspect.x = minAspect.width; + sizeHints.min_aspect.y = minAspect.height; + sizeHints.max_aspect.x = maxAspect.width; + sizeHints.max_aspect.y = maxAspect.height; + } + + const PuglViewSize fixedAspect = view->sizeHints[PUGL_FIXED_ASPECT]; + if (fixedAspect.width && fixedAspect.height) { + sizeHints.flags |= PAspect; + sizeHints.min_aspect.x = fixedAspect.width; + sizeHints.min_aspect.y = fixedAspect.height; + sizeHints.max_aspect.x = fixedAspect.width; + sizeHints.max_aspect.y = fixedAspect.height; + } + } + + XSetNormalHints(display, view->impl->win, &sizeHints); + return PUGL_SUCCESS; +} + +#ifdef HAVE_XCURSOR +static PuglStatus +defineCursorName(PuglView* const view, const char* const name) +{ + PuglInternals* const impl = view->impl; + PuglWorld* const world = view->world; + Display* const display = world->impl->display; + + // Load cursor theme + char* const theme = XcursorGetTheme(display); + if (!theme) { + return PUGL_FAILURE; + } + + // Get the default size and cursor image from it + const int size = XcursorGetDefaultSize(display); + XcursorImage* const image = XcursorLibraryLoadImage(name, theme, size); + if (!image) { + return PUGL_BAD_PARAMETER; + } + + // Load a cursor from the image + const Cursor cur = XcursorImageLoadCursor(display, image); + XcursorImageDestroy(image); + if (!cur) { + return PUGL_UNKNOWN_ERROR; + } + + // Set the view's cursor to the new loaded one + XDefineCursor(display, impl->win, cur); + XFreeCursor(display, cur); + return PUGL_SUCCESS; +} +#endif + +PuglStatus +puglRealize(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + PuglWorld* const world = view->world; + PuglX11Atoms* const atoms = &view->world->impl->atoms; + Display* const display = world->impl->display; + const int screen = DefaultScreen(display); + const Window root = RootWindow(display, screen); + const Window parent = view->parent ? (Window)view->parent : root; + XSetWindowAttributes attr = PUGL_INIT_STRUCT; + PuglStatus st = PUGL_SUCCESS; + + // Ensure that we're unrealized and that a reasonable backend has been set + if (impl->win) { + return PUGL_FAILURE; + } + + if (!view->backend || !view->backend->configure) { + return PUGL_BAD_BACKEND; + } + + // Set the size to the default if it has not already been set + if (view->frame.width <= 0.0 && view->frame.height <= 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { + return PUGL_BAD_CONFIGURATION; + } + + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + } + + // Center top-level windows if a position has not been set + if (!view->parent && !view->frame.x && !view->frame.y) { + const int screenWidth = DisplayWidth(display, screen); + const int screenHeight = DisplayHeight(display, screen); + + view->frame.x = (PuglCoord)((screenWidth - view->frame.width) / 2); + view->frame.y = (PuglCoord)((screenHeight - view->frame.height) / 2); + } + + // Configure the backend to get the visual info + impl->screen = screen; + if ((st = view->backend->configure(view)) || !impl->vi) { + view->backend->destroy(view); + return st ? st : PUGL_BACKEND_FAILED; + } + + // Create a colormap based on the visual info from the backend + attr.colormap = XCreateColormap(display, parent, impl->vi->visual, AllocNone); + + // Set the event mask to request all of the event types we react to + attr.event_mask |= ButtonPressMask; + attr.event_mask |= ButtonReleaseMask; + attr.event_mask |= EnterWindowMask; + attr.event_mask |= ExposureMask; + attr.event_mask |= FocusChangeMask; + attr.event_mask |= KeyPressMask; + attr.event_mask |= KeyReleaseMask; + attr.event_mask |= LeaveWindowMask; + attr.event_mask |= PointerMotionMask; + attr.event_mask |= PropertyChangeMask; + attr.event_mask |= StructureNotifyMask; + attr.event_mask |= VisibilityChangeMask; + + // Create the window + impl->win = XCreateWindow(display, + parent, + view->frame.x, + view->frame.y, + view->frame.width, + view->frame.height, + 0, + impl->vi->depth, + InputOutput, + impl->vi->visual, + CWColormap | CWEventMask, + &attr); + + // Create the backend drawing context/surface + if ((st = view->backend->create(view))) { + return st; + } + +#ifdef HAVE_XRANDR + int ignored = 0; + if (XRRQueryExtension(display, &ignored, &ignored)) { + // Set refresh rate hint to the real refresh rate + XRRScreenConfiguration* conf = XRRGetScreenInfo(display, parent); + short current_rate = XRRConfigCurrentRate(conf); + + view->hints[PUGL_REFRESH_RATE] = current_rate; + XRRFreeScreenConfigInfo(conf); + } +#endif + + updateSizeHints(view); + + XClassHint classHint = {world->className, world->className}; + XSetClassHint(display, impl->win, &classHint); + + if (view->title) { + puglSetWindowTitle(view, view->title); + } + + if (parent == root) { + XSetWMProtocols(display, impl->win, &atoms->WM_DELETE_WINDOW, 1); + } + + if (view->transientParent) { + XSetTransientForHint(display, impl->win, (Window)view->transientParent); + } + + // Create input context + if (world->impl->xim) { + impl->xic = XCreateIC(world->impl->xim, + XNInputStyle, + XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, + impl->win, + XNFocusWindow, + impl->win, + (XIM)0); + } + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + /* Flush before returning for two reasons: so that hints are available to the + view's parent via the X server during embedding, and so that the X server + has a chance to create the window (and make its actual position and size + known) before any children are created. Potential bugs aside, this + increases the chances that an application will be cleanly configured once + on startup with the correct position and size. */ + XFlush(display); + + return PUGL_SUCCESS; +} + +PuglStatus +puglShow(PuglView* const view) +{ + PuglStatus st = view->impl->win ? PUGL_SUCCESS : puglRealize(view); + + if (!st) { + XMapRaised(view->world->impl->display, view->impl->win); + st = puglPostRedisplay(view); + } + + return st; +} + +PuglStatus +puglHide(PuglView* const view) +{ + XUnmapWindow(view->world->impl->display, view->impl->win); + return PUGL_SUCCESS; +} + +static void +clearX11Clipboard(PuglX11Clipboard* const board) +{ + for (unsigned long i = 0; i < board->numFormats; ++i) { + free(board->formatStrings[i]); + board->formatStrings[i] = NULL; + } + + board->source = None; + board->numFormats = 0; + board->acceptedFormatIndex = UINT32_MAX; + board->acceptedFormat = None; + board->data.len = 0; +} + +void +puglFreeViewInternals(PuglView* const view) +{ + if (view && view->impl) { + clearX11Clipboard(&view->impl->clipboard); + free(view->impl->clipboard.data.data); + free(view->impl->clipboard.formats); + free(view->impl->clipboard.formatStrings); + if (view->impl->xic) { + XDestroyIC(view->impl->xic); + } + if (view->backend) { + view->backend->destroy(view); + } + if (view->world->impl->display && view->impl->win) { + XDestroyWindow(view->world->impl->display, view->impl->win); + } + XFree(view->impl->vi); + free(view->impl); + } +} + +void +puglFreeWorldInternals(PuglWorld* const world) +{ + if (world->impl->xim) { + XCloseIM(world->impl->xim); + } + XCloseDisplay(world->impl->display); + free(world->impl->timers); + free(world->impl); +} + +static PuglKey +keySymToSpecial(const KeySym sym) +{ + // clang-format off + switch (sym) { + case XK_F1: return PUGL_KEY_F1; + case XK_F2: return PUGL_KEY_F2; + case XK_F3: return PUGL_KEY_F3; + case XK_F4: return PUGL_KEY_F4; + case XK_F5: return PUGL_KEY_F5; + case XK_F6: return PUGL_KEY_F6; + case XK_F7: return PUGL_KEY_F7; + case XK_F8: return PUGL_KEY_F8; + case XK_F9: return PUGL_KEY_F9; + case XK_F10: return PUGL_KEY_F10; + case XK_F11: return PUGL_KEY_F11; + case XK_F12: return PUGL_KEY_F12; + case XK_Left: return PUGL_KEY_LEFT; + case XK_Up: return PUGL_KEY_UP; + case XK_Right: return PUGL_KEY_RIGHT; + case XK_Down: return PUGL_KEY_DOWN; + case XK_Page_Up: return PUGL_KEY_PAGE_UP; + case XK_Page_Down: return PUGL_KEY_PAGE_DOWN; + case XK_Home: return PUGL_KEY_HOME; + case XK_End: return PUGL_KEY_END; + case XK_Insert: return PUGL_KEY_INSERT; + case XK_Shift_L: return PUGL_KEY_SHIFT_L; + case XK_Shift_R: return PUGL_KEY_SHIFT_R; + case XK_Control_L: return PUGL_KEY_CTRL_L; + case XK_Control_R: return PUGL_KEY_CTRL_R; + case XK_Alt_L: return PUGL_KEY_ALT_L; + case XK_ISO_Level3_Shift: + case XK_Alt_R: return PUGL_KEY_ALT_R; + case XK_Super_L: return PUGL_KEY_SUPER_L; + case XK_Super_R: return PUGL_KEY_SUPER_R; + case XK_Menu: return PUGL_KEY_MENU; + case XK_Caps_Lock: return PUGL_KEY_CAPS_LOCK; + case XK_Scroll_Lock: return PUGL_KEY_SCROLL_LOCK; + case XK_Num_Lock: return PUGL_KEY_NUM_LOCK; + case XK_Print: return PUGL_KEY_PRINT_SCREEN; + case XK_Pause: return PUGL_KEY_PAUSE; + default: break; + } + // clang-format on + + return (PuglKey)0; +} + +static int +lookupString(XIC xic, XEvent* const xevent, char* const str, KeySym* const sym) +{ + Status status = 0; + +#ifdef X_HAVE_UTF8_STRING + const int n = Xutf8LookupString(xic, &xevent->xkey, str, 7, sym, &status); +#else + const int n = XmbLookupString(xic, &xevent->xkey, str, 7, sym, &status); +#endif + + return status == XBufferOverflow ? 0 : n; +} + +static void +translateKey(PuglView* const view, XEvent* const xevent, PuglEvent* const event) +{ + const unsigned state = xevent->xkey.state; + const bool filter = XFilterEvent(xevent, None); + + event->key.keycode = xevent->xkey.keycode; + xevent->xkey.state = 0; + + // Lookup unshifted key + char ustr[8] = {0}; + KeySym sym = 0; + const int ufound = XLookupString(&xevent->xkey, ustr, 8, &sym, NULL); + const PuglKey special = keySymToSpecial(sym); + + event->key.key = + ((special || ufound <= 0) ? special : puglDecodeUTF8((const uint8_t*)ustr)); + + if (xevent->type == KeyPress && !filter && !special && view->impl->xic) { + // Lookup shifted key for possible text event + xevent->xkey.state = state; + + char sstr[8] = {0}; + const int sfound = lookupString(view->impl->xic, xevent, sstr, &sym); + if (sfound > 0) { + // Dispatch key event now + puglDispatchEvent(view, event); + + // "Return" a text event in its place + event->text.type = PUGL_TEXT; + event->text.character = puglDecodeUTF8((const uint8_t*)sstr); + memcpy(event->text.string, sstr, sizeof(sstr)); + } + } +} + +static uint32_t +translateModifiers(const unsigned xstate) +{ + return (((xstate & ShiftMask) ? PUGL_MOD_SHIFT : 0u) | + ((xstate & ControlMask) ? PUGL_MOD_CTRL : 0u) | + ((xstate & Mod1Mask) ? PUGL_MOD_ALT : 0u) | + ((xstate & Mod4Mask) ? PUGL_MOD_SUPER : 0u)); +} + +static PuglStatus +getAtomProperty(PuglView* const view, + const Window window, + const Atom property, + unsigned long* numValues, + Atom** values) +{ + Atom actualType = 0; + int actualFormat = 0; + unsigned long bytesAfter = 0; + + return (XGetWindowProperty(view->world->impl->display, + window, + property, + 0, + LONG_MAX, + False, + XA_ATOM, + &actualType, + &actualFormat, + numValues, + &bytesAfter, + (unsigned char**)values) == Success) + ? PUGL_SUCCESS + : PUGL_FAILURE; +} + +static PuglX11Clipboard* +getX11SelectionClipboard(PuglView* const view, const Atom selection) +{ + return (selection == view->world->impl->atoms.CLIPBOARD) + ? &view->impl->clipboard + : NULL; +} + +static void +setClipboardFormats(PuglView* const view, + PuglX11Clipboard* const board, + const unsigned long numFormats, + const Atom* const formats) +{ + Atom* const newFormats = + (Atom*)realloc(board->formats, numFormats * sizeof(Atom)); + if (!newFormats) { + return; + } + + for (unsigned long i = 0; i < board->numFormats; ++i) { + free(board->formatStrings[i]); + board->formatStrings[i] = NULL; + } + + board->formats = newFormats; + board->numFormats = 0; + + board->formatStrings = + (char**)realloc(board->formatStrings, numFormats * sizeof(char*)); + + for (unsigned long i = 0; i < numFormats; ++i) { + if (formats[i]) { + char* const name = XGetAtomName(view->world->impl->display, formats[i]); + const char* type = NULL; + + if (strchr(name, '/')) { // MIME type (hopefully) + type = name; + } else if (!strcmp(name, "UTF8_STRING")) { // Plain text + type = "text/plain"; + } + + if (type) { + const size_t typeLen = strlen(type); + char* const formatString = (char*)calloc(typeLen + 1, 1); + + memcpy(formatString, type, typeLen + 1); + + board->formats[board->numFormats] = formats[i]; + board->formatStrings[board->numFormats] = formatString; + ++board->numFormats; + } + + XFree(name); + } + } +} + +static PuglEvent +translateClientMessage(PuglView* const view, XClientMessageEvent message) +{ + const PuglX11Atoms* const atoms = &view->world->impl->atoms; + PuglEvent event = {{PUGL_NOTHING, 0}}; + + if (message.message_type == atoms->WM_PROTOCOLS) { + const Atom protocol = (Atom)message.data.l[0]; + if (protocol == atoms->WM_DELETE_WINDOW) { + event.type = PUGL_CLOSE; + } + } else if (message.message_type == atoms->PUGL_CLIENT_MSG) { + event.type = PUGL_CLIENT; + event.client.data1 = (uintptr_t)message.data.l[0]; + event.client.data2 = (uintptr_t)message.data.l[1]; + } + + return event; +} + +static PuglEvent +translatePropertyNotify(PuglView* const view, XPropertyEvent message) +{ + const PuglX11Atoms* const atoms = &view->world->impl->atoms; + + PuglEvent event = {{PUGL_NOTHING, 0}}; + if (message.atom == atoms->NET_WM_STATE) { + unsigned long numHints = 0; + Atom* hints = NULL; + if (getAtomProperty( + view, view->impl->win, message.atom, &numHints, &hints)) { + return event; + } + + bool hidden = false; + for (unsigned long i = 0; i < numHints; ++i) { + if (hints[i] == atoms->NET_WM_STATE_HIDDEN) { + hidden = true; + } + } + + if (hidden && view->visible) { + event.type = PUGL_UNMAP; + } else if (!hidden && !view->visible) { + event.type = PUGL_MAP; + } + + XFree(hints); + } + + return event; +} + +static PuglEvent +translateEvent(PuglView* const view, XEvent xevent) +{ + PuglEvent event = {{PUGL_NOTHING, 0}}; + event.any.flags = xevent.xany.send_event ? PUGL_IS_SEND_EVENT : 0; + + switch (xevent.type) { + case ClientMessage: + event = translateClientMessage(view, xevent.xclient); + break; + case PropertyNotify: + event = translatePropertyNotify(view, xevent.xproperty); + break; + case VisibilityNotify: + event.type = (xevent.xvisibility.state == VisibilityFullyObscured) + ? PUGL_UNMAP + : PUGL_MAP; + break; + case MapNotify: + event.type = PUGL_MAP; + break; + case UnmapNotify: + event.type = PUGL_UNMAP; + break; + case ConfigureNotify: + event.type = PUGL_CONFIGURE; + event.configure.x = (PuglCoord)xevent.xconfigure.x; + event.configure.y = (PuglCoord)xevent.xconfigure.y; + event.configure.width = (PuglSpan)xevent.xconfigure.width; + event.configure.height = (PuglSpan)xevent.xconfigure.height; + break; + case Expose: + event.type = PUGL_EXPOSE; + event.expose.x = (PuglCoord)xevent.xexpose.x; + event.expose.y = (PuglCoord)xevent.xexpose.y; + event.expose.width = (PuglSpan)xevent.xexpose.width; + event.expose.height = (PuglSpan)xevent.xexpose.height; + break; + case MotionNotify: + event.type = PUGL_MOTION; + event.motion.time = (double)xevent.xmotion.time / 1e3; + event.motion.x = xevent.xmotion.x; + event.motion.y = xevent.xmotion.y; + event.motion.xRoot = xevent.xmotion.x_root; + event.motion.yRoot = xevent.xmotion.y_root; + event.motion.state = translateModifiers(xevent.xmotion.state); + if (xevent.xmotion.is_hint == NotifyHint) { + event.motion.flags |= PUGL_IS_HINT; + } + break; + case ButtonPress: + case ButtonRelease: + if (xevent.type == ButtonPress && xevent.xbutton.button >= 4 && + xevent.xbutton.button <= 7) { + event.type = PUGL_SCROLL; + event.scroll.time = (double)xevent.xbutton.time / 1e3; + event.scroll.x = xevent.xbutton.x; + event.scroll.y = xevent.xbutton.y; + event.scroll.xRoot = xevent.xbutton.x_root; + event.scroll.yRoot = xevent.xbutton.y_root; + event.scroll.state = translateModifiers(xevent.xbutton.state); + event.scroll.dx = 0.0; + event.scroll.dy = 0.0; + switch (xevent.xbutton.button) { + case 4: + event.scroll.dy = 1.0; + event.scroll.direction = PUGL_SCROLL_UP; + break; + case 5: + event.scroll.dy = -1.0; + event.scroll.direction = PUGL_SCROLL_DOWN; + break; + case 6: + event.scroll.dx = -1.0; + event.scroll.direction = PUGL_SCROLL_LEFT; + break; + case 7: + event.scroll.dx = 1.0; + event.scroll.direction = PUGL_SCROLL_RIGHT; + break; + } + } else if (xevent.xbutton.button < 4 || xevent.xbutton.button > 7) { + event.button.type = ((xevent.type == ButtonPress) ? PUGL_BUTTON_PRESS + : PUGL_BUTTON_RELEASE); + event.button.time = (double)xevent.xbutton.time / 1e3; + event.button.x = xevent.xbutton.x; + event.button.y = xevent.xbutton.y; + event.button.xRoot = xevent.xbutton.x_root; + event.button.yRoot = xevent.xbutton.y_root; + event.button.state = translateModifiers(xevent.xbutton.state); + event.button.button = xevent.xbutton.button - 1; + if (event.button.button == 1) { + event.button.button = 2; + } else if (event.button.button == 2) { + event.button.button = 1; + } else if (event.button.button >= 7) { + event.button.button -= 4; + } + } + break; + case KeyPress: + case KeyRelease: + event.type = + ((xevent.type == KeyPress) ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE); + event.key.time = (double)xevent.xkey.time / 1e3; + event.key.x = xevent.xkey.x; + event.key.y = xevent.xkey.y; + event.key.xRoot = xevent.xkey.x_root; + event.key.yRoot = xevent.xkey.y_root; + event.key.state = translateModifiers(xevent.xkey.state); + translateKey(view, &xevent, &event); + break; + case EnterNotify: + case LeaveNotify: + event.type = + ((xevent.type == EnterNotify) ? PUGL_POINTER_IN : PUGL_POINTER_OUT); + event.crossing.time = (double)xevent.xcrossing.time / 1e3; + event.crossing.x = xevent.xcrossing.x; + event.crossing.y = xevent.xcrossing.y; + event.crossing.xRoot = xevent.xcrossing.x_root; + event.crossing.yRoot = xevent.xcrossing.y_root; + event.crossing.state = translateModifiers(xevent.xcrossing.state); + event.crossing.mode = PUGL_CROSSING_NORMAL; + if (xevent.xcrossing.mode == NotifyGrab) { + event.crossing.mode = PUGL_CROSSING_GRAB; + } else if (xevent.xcrossing.mode == NotifyUngrab) { + event.crossing.mode = PUGL_CROSSING_UNGRAB; + } + break; + + case FocusIn: + case FocusOut: + event.type = (xevent.type == FocusIn) ? PUGL_FOCUS_IN : PUGL_FOCUS_OUT; + event.focus.mode = PUGL_CROSSING_NORMAL; + if (xevent.xfocus.mode == NotifyGrab) { + event.focus.mode = PUGL_CROSSING_GRAB; + } else if (xevent.xfocus.mode == NotifyUngrab) { + event.focus.mode = PUGL_CROSSING_UNGRAB; + } + break; + + default: + break; + } + + return event; +} + +PuglStatus +puglGrabFocus(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + Display* const display = view->world->impl->display; + XWindowAttributes attrs = PUGL_INIT_STRUCT; + + if (!impl->win || !XGetWindowAttributes(display, impl->win, &attrs)) { + return PUGL_UNKNOWN_ERROR; + } + + if (attrs.map_state != IsViewable) { + return PUGL_FAILURE; + } + + XSetInputFocus(display, impl->win, RevertToNone, CurrentTime); + return PUGL_SUCCESS; +} + +bool +puglHasFocus(const PuglView* const view) +{ + int revertTo = 0; + Window focusedWindow = 0; + XGetInputFocus(view->world->impl->display, &focusedWindow, &revertTo); + return focusedWindow == view->impl->win; +} + +PuglStatus +puglRequestAttention(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + Display* const display = view->world->impl->display; + const PuglX11Atoms* const atoms = &view->world->impl->atoms; + XEvent event = PUGL_INIT_STRUCT; + + event.type = ClientMessage; + event.xclient.window = impl->win; + event.xclient.format = 32; + event.xclient.message_type = atoms->NET_WM_STATE; + event.xclient.data.l[0] = WM_STATE_ADD; + event.xclient.data.l[1] = (long)atoms->NET_WM_STATE_DEMANDS_ATTENTION; + event.xclient.data.l[2] = 0; + event.xclient.data.l[3] = 1; + event.xclient.data.l[4] = 0; + + const Window root = RootWindow(display, impl->screen); + + return XSendEvent(display, + root, + False, + SubstructureNotifyMask | SubstructureRedirectMask, + &event) + ? PUGL_SUCCESS + : PUGL_UNKNOWN_ERROR; +} + +PuglStatus +puglStartTimer(PuglView* const view, const uintptr_t id, const double timeout) +{ +#ifdef HAVE_XSYNC + if (view->world->impl->syncSupported) { + XSyncValue value; + XSyncIntToValue(&value, (int)floor(timeout * 1000.0)); + + PuglWorldInternals* w = view->world->impl; + Display* const display = w->display; + const XSyncCounter counter = w->serverTimeCounter; + const XSyncTestType type = XSyncPositiveTransition; + const XSyncTrigger trigger = {counter, XSyncRelative, value, type}; + XSyncAlarmAttributes attr = {trigger, value, True, XSyncAlarmActive}; + const XSyncAlarm alarm = XSyncCreateAlarm(display, 0x17, &attr); + const PuglTimer timer = {alarm, view, id}; + + if (alarm != None) { + for (size_t i = 0; i < w->numTimers; ++i) { + if (w->timers[i].view == view && w->timers[i].id == id) { + // Replace existing timer + XSyncDestroyAlarm(w->display, w->timers[i].alarm); + w->timers[i] = timer; + return PUGL_SUCCESS; + } + } + + // Add new timer + const size_t size = ++w->numTimers * sizeof(timer); + w->timers = (PuglTimer*)realloc(w->timers, size); + w->timers[w->numTimers - 1] = timer; + return PUGL_SUCCESS; + } + } +#else + (void)view; + (void)id; + (void)timeout; +#endif + + return PUGL_FAILURE; +} + +PuglStatus +puglStopTimer(PuglView* const view, const uintptr_t id) +{ +#ifdef HAVE_XSYNC + PuglWorldInternals* w = view->world->impl; + + for (size_t i = 0; i < w->numTimers; ++i) { + if (w->timers[i].view == view && w->timers[i].id == id) { + XSyncDestroyAlarm(w->display, w->timers[i].alarm); + + if (i == w->numTimers - 1) { + memset(&w->timers[i], 0, sizeof(PuglTimer)); + } else { + memmove(w->timers + i, + w->timers + i + 1, + sizeof(PuglTimer) * (w->numTimers - i - 1)); + + memset(&w->timers[i], 0, sizeof(PuglTimer)); + } + + --w->numTimers; + return PUGL_SUCCESS; + } + } +#else + (void)view; + (void)id; +#endif + + return PUGL_FAILURE; +} + +static XEvent +eventToX(PuglView* const view, const PuglEvent* const event) +{ + XEvent xev = PUGL_INIT_STRUCT; + xev.xany.send_event = True; + + switch (event->type) { + case PUGL_EXPOSE: { + const double x = floor(event->expose.x); + const double y = floor(event->expose.y); + const double w = ceil(event->expose.x + event->expose.width) - x; + const double h = ceil(event->expose.y + event->expose.height) - y; + + xev.xexpose.type = Expose; + xev.xexpose.serial = 0; + xev.xexpose.display = view->world->impl->display; + xev.xexpose.window = view->impl->win; + xev.xexpose.x = (int)x; + xev.xexpose.y = (int)y; + xev.xexpose.width = (int)w; + xev.xexpose.height = (int)h; + break; + } + + case PUGL_CLIENT: + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = view->world->impl->display; + xev.xclient.window = view->impl->win; + xev.xclient.message_type = view->world->impl->atoms.PUGL_CLIENT_MSG; + xev.xclient.format = 32; + xev.xclient.data.l[0] = (long)event->client.data1; + xev.xclient.data.l[1] = (long)event->client.data2; + break; + + default: + break; + } + + return xev; +} + +PuglStatus +puglSendEvent(PuglView* const view, const PuglEvent* const event) +{ + XEvent xev = eventToX(view, event); + + if (xev.type) { + return XSendEvent( + view->world->impl->display, view->impl->win, False, 0, &xev) + ? PUGL_SUCCESS + : PUGL_UNKNOWN_ERROR; + } + + return PUGL_UNSUPPORTED; +} + +#ifndef PUGL_DISABLE_DEPRECATED +PuglStatus +puglWaitForEvent(PuglView* const view) +{ + XEvent xevent; + XPeekEvent(view->world->impl->display, &xevent); + return PUGL_SUCCESS; +} +#endif + +static void +mergeExposeEvents(PuglExposeEvent* const dst, const PuglExposeEvent* const src) +{ + if (!dst->type) { + *dst = *src; + } else { + const int dst_r = dst->x + dst->width; + const int src_r = src->x + src->width; + const int max_x = MAX(dst_r, src_r); + const int dst_b = dst->y + dst->height; + const int src_b = src->y + src->height; + const int max_y = MAX(dst_b, src_b); + + dst->x = (PuglCoord)MIN(dst->x, src->x); + dst->y = (PuglCoord)MIN(dst->y, src->y); + dst->width = (PuglSpan)(max_x - dst->x); + dst->height = (PuglSpan)(max_y - dst->y); + } +} + +static PuglStatus +retrieveSelection(const PuglWorld* const world, + PuglView* const view, + const Atom property, + const Atom type, + PuglBlob* const result) +{ + uint8_t* value = NULL; + Atom actualType = 0u; + int actualFormat = 0; + unsigned long actualNumItems = 0u; + unsigned long bytesAfter = 0u; + + if (XGetWindowProperty(world->impl->display, + view->impl->win, + property, + 0, + 0x1FFFFFFF, + False, + type, + &actualType, + &actualFormat, + &actualNumItems, + &bytesAfter, + &value) != Success) { + return PUGL_FAILURE; + } + + if (value && actualFormat == 8 && bytesAfter == 0) { + puglSetBlob(result, value, actualNumItems); + } + + XFree(value); + return PUGL_SUCCESS; +} + +static void +handleSelectionNotify(const PuglWorld* const world, + PuglView* const view, + const XSelectionEvent* const event) +{ + const PuglX11Atoms* const atoms = &world->impl->atoms; + + Display* const display = view->world->impl->display; + const Atom selection = event->selection; + PuglX11Clipboard* const board = getX11SelectionClipboard(view, selection); + PuglEvent puglEvent = {{PUGL_NOTHING, 0}}; + + if (event->target == atoms->TARGETS) { + // Notification of available datatypes + unsigned long numFormats = 0; + Atom* formats = NULL; + if (!getAtomProperty( + view, event->requestor, event->property, &numFormats, &formats)) { + setClipboardFormats(view, board, numFormats, formats); + + const PuglDataOfferEvent offer = { + PUGL_DATA_OFFER, 0, (double)event->time / 1e3}; + + puglEvent.offer = offer; + board->acceptedFormatIndex = UINT32_MAX; + board->acceptedFormat = None; + + XFree(formats); + } + + } else if (event->selection == atoms->CLIPBOARD && + event->property == XA_PRIMARY && + board->acceptedFormatIndex < board->numFormats) { + // Notification of data from the clipboard + if (!retrieveSelection( + world, view, event->property, event->target, &board->data)) { + board->source = XGetSelectionOwner(display, board->selection); + + const PuglDataEvent data = { + PUGL_DATA, 0u, (double)event->time / 1e3, board->acceptedFormatIndex}; + + puglEvent.data = data; + } + } + + puglDispatchEvent(view, &puglEvent); +} + +static PuglStatus +handleSelectionRequest(const PuglWorld* const world, + PuglView* const view, + const XSelectionRequestEvent* const request) +{ + Display* const display = world->impl->display; + const PuglX11Atoms* const atoms = &world->impl->atoms; + + PuglX11Clipboard* const board = + getX11SelectionClipboard(view, request->selection); + + if (!board) { + return PUGL_UNKNOWN_ERROR; + } + + if (request->target == atoms->TARGETS) { + XChangeProperty(world->impl->display, + request->requestor, + request->property, + XA_ATOM, + 32, + PropModeReplace, + (const uint8_t*)board->formats, + (int)board->numFormats); + } else { + XChangeProperty(world->impl->display, + request->requestor, + request->property, + request->target, + 8, + PropModeReplace, + (const uint8_t*)board->data.data, + (int)board->data.len); + } + + XSelectionEvent note = {SelectionNotify, + request->serial, + False, + display, + request->requestor, + request->selection, + request->target, + request->property, + request->time}; + + return XSendEvent( + world->impl->display, note.requestor, True, 0, (XEvent*)¬e) + ? PUGL_SUCCESS + : PUGL_UNKNOWN_ERROR; +} + +/// Flush pending configure and expose events for all views +PUGL_WARN_UNUSED_RESULT +static PuglStatus +flushExposures(PuglWorld* const world) +{ + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + PuglStatus st2 = PUGL_SUCCESS; + + for (size_t i = 0; i < world->numViews; ++i) { + PuglView* const view = world->views[i]; + + // Send update event so the application can trigger redraws + if (view->visible) { + puglDispatchSimpleEvent(view, PUGL_UPDATE); + } + + // Copy and reset pending events (in case their handlers write new ones) + const PuglEvent configure = view->impl->pendingConfigure; + const PuglEvent expose = view->impl->pendingExpose; + + view->impl->pendingConfigure.type = PUGL_NOTHING; + view->impl->pendingExpose.type = PUGL_NOTHING; + + if (expose.type) { + if (!(st0 = view->backend->enter(view, &expose.expose))) { + if (configure.type) { + st0 = puglConfigure(view, &configure); + } + + st1 = puglExpose(view, &expose); + st2 = view->backend->leave(view, &expose.expose); + } + } else if (configure.type) { + if (!(st0 = view->backend->enter(view, NULL))) { + st0 = puglConfigure(view, &configure); + st1 = view->backend->leave(view, NULL); + } + } + } + + return st0 ? st0 : st1 ? st1 : st2; +} + +static bool +handleTimerEvent(PuglWorld* const world, const XEvent xevent) +{ +#ifdef HAVE_XSYNC + if (xevent.type == world->impl->syncEventBase + XSyncAlarmNotify) { + const XSyncAlarmNotifyEvent* const notify = + ((const XSyncAlarmNotifyEvent*)&xevent); + + for (size_t i = 0; i < world->impl->numTimers; ++i) { + if (world->impl->timers[i].alarm == notify->alarm) { + PuglEvent event = {{PUGL_TIMER, 0}}; + event.timer.id = world->impl->timers[i].id; + puglDispatchEvent(world->impl->timers[i].view, &event); + } + } + + return true; + } +#else + (void)world; + (void)xevent; +#endif + + return false; +} + +static PuglStatus +dispatchCurrentConfiguration(PuglView* const view) +{ + // Get initial window position and size + XWindowAttributes attrs; + XGetWindowAttributes(view->world->impl->display, view->impl->win, &attrs); + + // Build an initial configure event in case the WM doesn't send one + PuglEvent configureEvent = {{PUGL_CONFIGURE, 0}}; + configureEvent.configure.x = (PuglCoord)attrs.x; + configureEvent.configure.y = (PuglCoord)attrs.y; + configureEvent.configure.width = (PuglSpan)attrs.width; + configureEvent.configure.height = (PuglSpan)attrs.height; + + return puglDispatchEvent(view, &configureEvent); +} + +static PuglStatus +dispatchX11Events(PuglWorld* const world) +{ + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + + // Flush output to the server once at the start + Display* display = world->impl->display; + XFlush(display); + + // Process all queued events (without further flushing) + while (XEventsQueued(display, QueuedAfterReading) > 0) { + XEvent xevent; + XNextEvent(display, &xevent); + + if (handleTimerEvent(world, xevent)) { + continue; + } + + PuglView* const view = findView(world, xevent.xany.window); + if (!view) { + continue; + } + + // Handle special events + PuglInternals* const impl = view->impl; + if (xevent.type == KeyRelease && view->hints[PUGL_IGNORE_KEY_REPEAT]) { + XEvent next; + if (XCheckTypedWindowEvent(display, impl->win, KeyPress, &next) && + next.type == KeyPress && next.xkey.time == xevent.xkey.time && + next.xkey.keycode == xevent.xkey.keycode) { + continue; + } + } else if (xevent.type == SelectionClear) { + PuglX11Clipboard* const board = + getX11SelectionClipboard(view, xevent.xselectionclear.selection); + if (board) { + clearX11Clipboard(board); + } + } else if (xevent.type == SelectionNotify) { + handleSelectionNotify(world, view, &xevent.xselection); + } else if (xevent.type == SelectionRequest) { + handleSelectionRequest(world, view, &xevent.xselectionrequest); + } + + // Translate X11 event to Pugl event + const PuglEvent event = translateEvent(view, xevent); + + switch (event.type) { + case PUGL_CONFIGURE: + // Update configure event to be dispatched after loop + view->impl->pendingConfigure = event; + break; + case PUGL_MAP: + // Dispatch an initial configure (if necessary), then the map event + st0 = dispatchCurrentConfiguration(view); + st1 = puglDispatchEvent(view, &event); + break; + case PUGL_EXPOSE: + // Expand expose event to be dispatched after loop + mergeExposeEvents(&view->impl->pendingExpose.expose, &event.expose); + break; + case PUGL_FOCUS_IN: + // Set the input context focus + if (view->impl->xic) { + XSetICFocus(view->impl->xic); + } + break; + case PUGL_FOCUS_OUT: + // Unset the input context focus + if (view->impl->xic) { + XUnsetICFocus(view->impl->xic); + } + break; + default: + // Dispatch event to application immediately + st0 = puglDispatchEvent(view, &event); + break; + } + } + + return st0 ? st0 : st1; +} + +#ifndef PUGL_DISABLE_DEPRECATED +PuglStatus +puglProcessEvents(PuglView* const view) +{ + return puglUpdate(view->world, 0.0); +} +#endif + +PuglStatus +puglUpdate(PuglWorld* const world, const double timeout) +{ + const double startTime = puglGetTime(world); + PuglStatus st0 = PUGL_SUCCESS; + PuglStatus st1 = PUGL_SUCCESS; + + world->impl->dispatchingEvents = true; + + if (timeout < 0.0) { + st0 = pollX11Socket(world, timeout); + st0 = st0 ? st0 : dispatchX11Events(world); + } else if (timeout <= 0.001) { + st0 = dispatchX11Events(world); + } else { + const double endTime = startTime + timeout - 0.001; + double t = startTime; + while (!st0 && t < endTime) { + if (!(st0 = pollX11Socket(world, endTime - t))) { + st0 = dispatchX11Events(world); + } + + t = puglGetTime(world); + } + } + + st1 = flushExposures(world); + + world->impl->dispatchingEvents = false; + + return st0 ? st0 : st1; +} + +double +puglGetTime(const PuglWorld* const world) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) - + world->startTime; +} + +PuglStatus +puglPostRedisplay(PuglView* const view) +{ + const PuglRect rect = {0, 0, view->frame.width, view->frame.height}; + + return puglPostRedisplayRect(view, rect); +} + +PuglStatus +puglPostRedisplayRect(PuglView* const view, const PuglRect rect) +{ + const PuglExposeEvent event = { + PUGL_EXPOSE, 0, rect.x, rect.y, rect.width, rect.height}; + + if (view->world->impl->dispatchingEvents) { + // Currently dispatching events, add/expand expose for the loop end + mergeExposeEvents(&view->impl->pendingExpose.expose, &event); + } else if (view->visible) { + // Not dispatching events, send an X expose so we wake up next time + PuglEvent exposeEvent = {{PUGL_EXPOSE, 0}}; + exposeEvent.expose = event; + return puglSendEvent(view, &exposeEvent); + } + + return PUGL_SUCCESS; +} + +PuglNativeView +puglGetNativeView(PuglView* const view) +{ + return (PuglNativeView)view->impl->win; +} + +PuglStatus +puglSetWindowTitle(PuglView* const view, const char* const title) +{ + Display* display = view->world->impl->display; + const PuglX11Atoms* const atoms = &view->world->impl->atoms; + + puglSetString(&view->title, title); + + if (view->impl->win) { + XStoreName(display, view->impl->win, title); + XChangeProperty(display, + view->impl->win, + atoms->NET_WM_NAME, + atoms->UTF8_STRING, + 8, + PropModeReplace, + (const uint8_t*)title, + (int)strlen(title)); + } + + return PUGL_SUCCESS; +} + +double +puglGetScaleFactor(const PuglView* const view) +{ + return view->world->impl->scaleFactor; +} + +PuglStatus +puglSetFrame(PuglView* const view, const PuglRect frame) +{ + if (view->impl->win) { + if (!XMoveResizeWindow(view->world->impl->display, + view->impl->win, + frame.x, + frame.y, + frame.width, + frame.height)) { + return PUGL_UNKNOWN_ERROR; + } + } + + view->frame = frame; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetPosition(PuglView* const view, const int x, const int y) +{ + Display* const display = view->world->impl->display; + const Window win = view->impl->win; + + if (x > INT16_MAX || y > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + if (win && !XMoveWindow(display, win, x, y)) { + return PUGL_UNKNOWN_ERROR; + } + + view->frame.x = (PuglCoord)x; + view->frame.y = (PuglCoord)y; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSize(PuglView* const view, const unsigned width, const unsigned height) +{ + Display* const display = view->world->impl->display; + const Window win = view->impl->win; + + if (width > INT16_MAX || height > INT16_MAX) { + return PUGL_BAD_PARAMETER; + } + + if (win) { + return XResizeWindow(display, win, width, height) ? PUGL_SUCCESS + : PUGL_UNKNOWN_ERROR; + } + + view->frame.width = (PuglSpan)width; + view->frame.height = (PuglSpan)height; + return PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) +{ + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; + return updateSizeHints(view); +} + +PuglStatus +puglSetTransientParent(PuglView* const view, const PuglNativeView parent) +{ + Display* display = view->world->impl->display; + + view->transientParent = parent; + + if (view->impl->win) { + XSetTransientForHint( + display, view->impl->win, (Window)view->transientParent); + } + + return PUGL_SUCCESS; +} + +const void* +puglGetClipboard(PuglView* const view, + const uint32_t typeIndex, + size_t* const len) +{ + Display* const display = view->world->impl->display; + PuglX11Clipboard* const board = &view->impl->clipboard; + + if (typeIndex != board->acceptedFormatIndex) { + return NULL; + } + + const Window owner = XGetSelectionOwner(display, board->selection); + if (!owner || owner != board->source) { + *len = 0; + return NULL; + } + + *len = board->data.len; + return board->data.data; +} + +PuglStatus +puglAcceptOffer(PuglView* const view, + const PuglDataOfferEvent* const offer, + const uint32_t typeIndex) +{ + (void)offer; + + PuglInternals* const impl = view->impl; + Display* const display = view->world->impl->display; + PuglX11Clipboard* const board = &view->impl->clipboard; + + board->acceptedFormatIndex = typeIndex; + board->acceptedFormat = board->formats[typeIndex]; + + // Request the data in the specified type from the general clipboard + XConvertSelection(display, + board->selection, + board->acceptedFormat, + board->property, + impl->win, + CurrentTime); + + return PUGL_SUCCESS; +} + +PuglStatus +puglPaste(PuglView* const view) +{ + Display* const display = view->world->impl->display; + const PuglX11Atoms* atoms = &view->world->impl->atoms; + const PuglX11Clipboard* board = &view->impl->clipboard; + + // Request a SelectionNotify for TARGETS (available datatypes) + XConvertSelection(display, + board->selection, + atoms->TARGETS, + board->property, + view->impl->win, + CurrentTime); + + return PUGL_SUCCESS; +} + +uint32_t +puglGetNumClipboardTypes(const PuglView* const view) +{ + return (uint32_t)view->impl->clipboard.numFormats; +} + +const char* +puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex) +{ + const PuglX11Clipboard* const board = &view->impl->clipboard; + + return typeIndex < board->numFormats ? board->formatStrings[typeIndex] : NULL; +} + +PuglStatus +puglSetClipboard(PuglView* const view, + const char* const type, + const void* const data, + const size_t len) +{ + PuglInternals* const impl = view->impl; + Display* const display = view->world->impl->display; + PuglX11Clipboard* const board = &view->impl->clipboard; + const PuglStatus st = puglSetBlob(&board->data, data, len); + + if (!st) { + const Atom format = {XInternAtom(display, type, 0)}; + + setClipboardFormats(view, board, 1, &format); + XSetSelectionOwner(display, board->selection, impl->win, CurrentTime); + + board->source = impl->win; + } + + return st; +} + +PuglStatus +puglSetCursor(PuglView* const view, const PuglCursor cursor) +{ +#ifdef HAVE_XCURSOR + PuglInternals* const impl = view->impl; + const unsigned index = (unsigned)cursor; + const unsigned count = sizeof(cursor_names) / sizeof(cursor_names[0]); + if (index >= count) { + return PUGL_BAD_PARAMETER; + } + + const char* const name = cursor_names[index]; + if (!impl->win || impl->cursorName == name) { + return PUGL_SUCCESS; + } + + impl->cursorName = cursor_names[index]; + + return defineCursorName(view, impl->cursorName); +#else + (void)view; + (void)cursor; + return PUGL_FAILURE; +#endif +} + +// Semi-public platform API used by backends + +PuglStatus +puglX11Configure(PuglView* view) +{ + PuglInternals* const impl = view->impl; + Display* const display = view->world->impl->display; + XVisualInfo pat = PUGL_INIT_STRUCT; + int n = 0; + + pat.screen = impl->screen; + if (!(impl->vi = XGetVisualInfo(display, VisualScreenMask, &pat, &n))) { + return PUGL_BAD_CONFIGURATION; + } + + view->hints[PUGL_RED_BITS] = impl->vi->bits_per_rgb; + view->hints[PUGL_GREEN_BITS] = impl->vi->bits_per_rgb; + view->hints[PUGL_BLUE_BITS] = impl->vi->bits_per_rgb; + view->hints[PUGL_ALPHA_BITS] = 0; + + return PUGL_SUCCESS; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,82 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#ifndef PUGL_SRC_X11_H +#define PUGL_SRC_X11_H + +#include "attributes.h" +#include "types.h" + +#include "pugl/pugl.h" + +#include +#include +#include + +#include +#include +#include + +typedef struct { + Atom CLIPBOARD; + Atom UTF8_STRING; + Atom WM_PROTOCOLS; + Atom WM_DELETE_WINDOW; + Atom PUGL_CLIENT_MSG; + Atom NET_WM_NAME; + Atom NET_WM_STATE; + Atom NET_WM_STATE_DEMANDS_ATTENTION; + Atom NET_WM_STATE_HIDDEN; + Atom TARGETS; + Atom text_uri_list; +} PuglX11Atoms; + +typedef struct { + XID alarm; + PuglView* view; + uintptr_t id; +} PuglTimer; + +typedef struct { + Atom selection; + Atom property; + Window source; + Atom* formats; + char** formatStrings; + unsigned long numFormats; + uint32_t acceptedFormatIndex; + Atom acceptedFormat; + PuglBlob data; +} PuglX11Clipboard; + +struct PuglWorldInternalsImpl { + Display* display; + PuglX11Atoms atoms; + XIM xim; + double scaleFactor; + PuglTimer* timers; + size_t numTimers; + XID serverTimeCounter; + int syncEventBase; + bool syncSupported; + bool dispatchingEvents; +}; + +struct PuglInternalsImpl { + XVisualInfo* vi; + Window win; + XIC xic; + PuglSurface* surface; + PuglEvent pendingConfigure; + PuglEvent pendingExpose; + PuglX11Clipboard clipboard; + int screen; + const char* cursorName; +}; + +PUGL_WARN_UNUSED_RESULT +PUGL_API +PuglStatus +puglX11Configure(PuglView* view); + +#endif // PUGL_SRC_X11_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_cairo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_cairo.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,145 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "types.h" +#include "x11.h" + +#include "pugl/cairo.h" +#include "pugl/pugl.h" + +#include +#include +#include + +#include + +typedef struct { + cairo_surface_t* back; + cairo_surface_t* front; + cairo_t* cr; +} PuglX11CairoSurface; + +static void +puglX11CairoClose(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface; + + cairo_surface_destroy(surface->front); + cairo_surface_destroy(surface->back); + surface->front = surface->back = NULL; +} + +static PuglStatus +puglX11CairoOpen(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface; + + surface->back = cairo_xlib_surface_create(view->world->impl->display, + impl->win, + impl->vi->visual, + (int)view->frame.width, + (int)view->frame.height); + + surface->front = + cairo_surface_create_similar(surface->back, + cairo_surface_get_content(surface->back), + (int)view->frame.width, + (int)view->frame.height); + + if (cairo_surface_status(surface->back) || + cairo_surface_status(surface->front)) { + puglX11CairoClose(view); + return PUGL_CREATE_CONTEXT_FAILED; + } + + return PUGL_SUCCESS; +} + +static PuglStatus +puglX11CairoCreate(PuglView* view) +{ + PuglInternals* const impl = view->impl; + + impl->surface = (cairo_surface_t*)calloc(1, sizeof(PuglX11CairoSurface)); + + return PUGL_SUCCESS; +} + +static void +puglX11CairoDestroy(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface; + + puglX11CairoClose(view); + free(surface); +} + +static PuglStatus +puglX11CairoEnter(PuglView* view, const PuglExposeEvent* expose) +{ + PuglInternals* const impl = view->impl; + PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface; + PuglStatus st = PUGL_SUCCESS; + + if (expose && !(st = puglX11CairoOpen(view))) { + surface->cr = cairo_create(surface->front); + st = cairo_status(surface->cr) ? PUGL_CREATE_CONTEXT_FAILED : PUGL_SUCCESS; + } + + return st; +} + +static PuglStatus +puglX11CairoLeave(PuglView* view, const PuglExposeEvent* expose) +{ + PuglInternals* const impl = view->impl; + PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface; + + if (expose) { + // Destroy front context and create a new one for drawing to the back + cairo_destroy(surface->cr); + surface->cr = cairo_create(surface->back); + + // Clip to expose region + cairo_rectangle( + surface->cr, expose->x, expose->y, expose->width, expose->height); + cairo_clip(surface->cr); + + // Paint front onto back + cairo_set_source_surface(surface->cr, surface->front, 0, 0); + cairo_paint(surface->cr); + + // Flush to X and close everything + cairo_destroy(surface->cr); + cairo_surface_flush(surface->back); + puglX11CairoClose(view); + surface->cr = NULL; + } + + return PUGL_SUCCESS; +} + +static void* +puglX11CairoGetContext(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglX11CairoSurface* const surface = (PuglX11CairoSurface*)impl->surface; + + return surface->cr; +} + +const PuglBackend* +puglCairoBackend(void) +{ + static const PuglBackend backend = {puglX11Configure, + puglX11CairoCreate, + puglX11CairoDestroy, + puglX11CairoEnter, + puglX11CairoLeave, + puglX11CairoGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_gl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_gl.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,250 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "attributes.h" +#include "stub.h" +#include "types.h" +#include "x11.h" + +#include "pugl/gl.h" +#include "pugl/pugl.h" + +#include +#include +#include + +#include +#include +#include +#include + +typedef struct { + GLXFBConfig fb_config; + GLXContext ctx; +} PuglX11GlSurface; + +static int +puglX11GlHintValue(const int value) +{ + return value == PUGL_DONT_CARE ? (int)GLX_DONT_CARE : value; +} + +static int +puglX11GlGetAttrib(Display* const display, + GLXFBConfig fb_config, + const int attrib) +{ + int value = 0; + glXGetFBConfigAttrib(display, fb_config, attrib, &value); + return value; +} + +static PuglStatus +puglX11GlConfigure(PuglView* view) +{ + PuglInternals* const impl = view->impl; + const int screen = impl->screen; + Display* const display = view->world->impl->display; + + PuglX11GlSurface* const surface = + (PuglX11GlSurface*)calloc(1, sizeof(PuglX11GlSurface)); + impl->surface = surface; + + // clang-format off + const int attrs[] = { + GLX_X_RENDERABLE, True, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_SAMPLES, puglX11GlHintValue(view->hints[PUGL_SAMPLES]), + GLX_RED_SIZE, puglX11GlHintValue(view->hints[PUGL_RED_BITS]), + GLX_GREEN_SIZE, puglX11GlHintValue(view->hints[PUGL_GREEN_BITS]), + GLX_BLUE_SIZE, puglX11GlHintValue(view->hints[PUGL_BLUE_BITS]), + GLX_ALPHA_SIZE, puglX11GlHintValue(view->hints[PUGL_ALPHA_BITS]), + GLX_DEPTH_SIZE, puglX11GlHintValue(view->hints[PUGL_DEPTH_BITS]), + GLX_STENCIL_SIZE, puglX11GlHintValue(view->hints[PUGL_STENCIL_BITS]), + GLX_DOUBLEBUFFER, puglX11GlHintValue(view->hints[PUGL_DOUBLE_BUFFER]), + None + }; + // clang-format on + + int n_fbc = 0; + GLXFBConfig* fbc = glXChooseFBConfig(display, screen, attrs, &n_fbc); + if (n_fbc <= 0) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + surface->fb_config = fbc[0]; + impl->vi = glXGetVisualFromFBConfig(display, fbc[0]); + + view->hints[PUGL_RED_BITS] = + puglX11GlGetAttrib(display, fbc[0], GLX_RED_SIZE); + view->hints[PUGL_GREEN_BITS] = + puglX11GlGetAttrib(display, fbc[0], GLX_GREEN_SIZE); + view->hints[PUGL_BLUE_BITS] = + puglX11GlGetAttrib(display, fbc[0], GLX_BLUE_SIZE); + view->hints[PUGL_ALPHA_BITS] = + puglX11GlGetAttrib(display, fbc[0], GLX_ALPHA_SIZE); + view->hints[PUGL_DEPTH_BITS] = + puglX11GlGetAttrib(display, fbc[0], GLX_DEPTH_SIZE); + view->hints[PUGL_STENCIL_BITS] = + puglX11GlGetAttrib(display, fbc[0], GLX_STENCIL_SIZE); + view->hints[PUGL_SAMPLES] = puglX11GlGetAttrib(display, fbc[0], GLX_SAMPLES); + view->hints[PUGL_DOUBLE_BUFFER] = + puglX11GlGetAttrib(display, fbc[0], GLX_DOUBLEBUFFER); + + XFree(fbc); + + return PUGL_SUCCESS; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglX11GlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) +{ + PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface; + Display* const display = view->world->impl->display; + if (!surface || !surface->ctx) { + return PUGL_FAILURE; + } + + return glXMakeCurrent(display, view->impl->win, surface->ctx) ? PUGL_SUCCESS + : PUGL_FAILURE; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglX11GlLeave(PuglView* view, const PuglExposeEvent* expose) +{ + Display* const display = view->world->impl->display; + + if (expose && view->hints[PUGL_DOUBLE_BUFFER]) { + glXSwapBuffers(display, view->impl->win); + } + + return glXMakeCurrent(display, None, NULL) ? PUGL_SUCCESS : PUGL_FAILURE; +} + +static PuglStatus +puglX11GlCreate(PuglView* view) +{ + PuglInternals* const impl = view->impl; + PuglX11GlSurface* const surface = (PuglX11GlSurface*)impl->surface; + Display* const display = view->world->impl->display; + GLXFBConfig fb_config = surface->fb_config; + PuglStatus st = PUGL_SUCCESS; + + const int ctx_attrs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, + view->hints[PUGL_CONTEXT_VERSION_MAJOR], + + GLX_CONTEXT_MINOR_VERSION_ARB, + view->hints[PUGL_CONTEXT_VERSION_MINOR], + + GLX_CONTEXT_FLAGS_ARB, + (view->hints[PUGL_USE_DEBUG_CONTEXT] ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), + + GLX_CONTEXT_PROFILE_MASK_ARB, + (view->hints[PUGL_USE_COMPAT_PROFILE] + ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB + : GLX_CONTEXT_CORE_PROFILE_BIT_ARB), + 0}; + + const char* const extensions = + glXQueryExtensionsString(display, view->impl->screen); + + // Try to create a modern context + if (!!strstr(extensions, "GLX_ARB_create_context")) { + PFNGLXCREATECONTEXTATTRIBSARBPROC create_context = + (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress( + (const uint8_t*)"glXCreateContextAttribsARB"); + + surface->ctx = create_context(display, fb_config, 0, True, ctx_attrs); + } + + // If that failed, fall back to the legacy API + if (!surface->ctx) { + surface->ctx = + glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True); + } + + if (!surface->ctx) { + return PUGL_CREATE_CONTEXT_FAILED; + } + + // Set up the swap interval + if (!!strstr(extensions, "GLX_EXT_swap_control")) { + PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = + (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( + (const uint8_t*)"glXSwapIntervalEXT"); + + // Note that some drivers (NVidia) require the context to be entered here + if ((st = puglX11GlEnter(view, NULL))) { + return st; + } + + // Set the swap interval if the user requested a specific value + if (view->hints[PUGL_SWAP_INTERVAL] != PUGL_DONT_CARE) { + glXSwapIntervalEXT(display, impl->win, view->hints[PUGL_SWAP_INTERVAL]); + } + + // Get the actual current swap interval + glXQueryDrawable(display, + impl->win, + GLX_SWAP_INTERVAL_EXT, + (unsigned int*)&view->hints[PUGL_SWAP_INTERVAL]); + + if ((st = puglX11GlLeave(view, NULL))) { + return st; + } + } + + return !glXGetConfig(display, + impl->vi, + GLX_DOUBLEBUFFER, + &view->hints[PUGL_DOUBLE_BUFFER]) + ? PUGL_SUCCESS + : PUGL_UNKNOWN_ERROR; +} + +static void +puglX11GlDestroy(PuglView* view) +{ + PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface; + if (surface) { + glXDestroyContext(view->world->impl->display, surface->ctx); + free(surface); + view->impl->surface = NULL; + } +} + +PuglGlFunc +puglGetProcAddress(const char* name) +{ + return glXGetProcAddress((const uint8_t*)name); +} + +PuglStatus +puglEnterContext(PuglView* view) +{ + return view->backend->enter(view, NULL); +} + +PuglStatus +puglLeaveContext(PuglView* view) +{ + return view->backend->leave(view, NULL); +} + +const PuglBackend* +puglGlBackend(void) +{ + static const PuglBackend backend = {puglX11GlConfigure, + puglX11GlCreate, + puglX11GlDestroy, + puglX11GlEnter, + puglX11GlLeave, + puglStubGetContext}; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_stub.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,25 @@ +// Copyright 2012-2021 David Robillard +// SPDX-License-Identifier: ISC + +#include "pugl/stub.h" + +#include "stub.h" +#include "types.h" +#include "x11.h" + +#include "pugl/pugl.h" + +const PuglBackend* +puglStubBackend(void) +{ + static const PuglBackend backend = { + puglX11Configure, + puglStubCreate, + puglStubDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext, + }; + + return &backend; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_vulkan.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl-upstream/src/x11_vulkan.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,115 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#define VK_NO_PROTOTYPES 1 + +#include "attributes.h" +#include "stub.h" +#include "types.h" +#include "x11.h" + +#include "pugl/pugl.h" +#include "pugl/vulkan.h" + +#include +#include + +#include + +#include +#include + +struct PuglVulkanLoaderImpl { + void* libvulkan; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; +}; + +PuglVulkanLoader* +puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world)) +{ + PuglVulkanLoader* const loader = + (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader)); + + if (!loader || !(loader->libvulkan = dlopen("libvulkan.so", RTLD_LAZY))) { + free(loader); + return NULL; + } + + loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym( + loader->libvulkan, "vkGetInstanceProcAddr"); + + loader->vkGetDeviceProcAddr = + (PFN_vkGetDeviceProcAddr)dlsym(loader->libvulkan, "vkGetDeviceProcAddr"); + + return loader; +} + +void +puglFreeVulkanLoader(PuglVulkanLoader* loader) +{ + if (loader) { + dlclose(loader->libvulkan); + free(loader); + } +} + +PFN_vkGetInstanceProcAddr +puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader) +{ + return loader->vkGetInstanceProcAddr; +} + +PFN_vkGetDeviceProcAddr +puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader) +{ + return loader->vkGetDeviceProcAddr; +} + +const PuglBackend* +puglVulkanBackend(void) +{ + static const PuglBackend backend = {puglX11Configure, + puglStubCreate, + puglStubDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext}; + + return &backend; +} + +const char* const* +puglGetInstanceExtensions(uint32_t* const count) +{ + static const char* const extensions[] = {"VK_KHR_surface", + "VK_KHR_xlib_surface"}; + + *count = 2; + return extensions; +} + +VkResult +puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr, + PuglView* const view, + VkInstance instance, + const VkAllocationCallbacks* const allocator, + VkSurfaceKHR* const surface) +{ + PuglInternals* const impl = view->impl; + PuglWorldInternals* world_impl = view->world->impl; + + PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR = + (PFN_vkCreateXlibSurfaceKHR)vkGetInstanceProcAddr(instance, + "vkCreateXlibSurfaceKHR"); + + const VkXlibSurfaceCreateInfoKHR info = { + VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, + NULL, + 0, + world_impl->display, + impl->win, + }; + + return vkCreateXlibSurfaceKHR(instance, &info, allocator, surface); +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,677 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "pugl.hpp" + +// -------------------------------------------------------------------------------------------------------------------- +// include base headers + +#ifdef DGL_CAIRO +# include +#endif +#ifdef DGL_OPENGL +# include "../OpenGL-include.hpp" +#endif +#ifdef DGL_VULKAN +# include +#endif + +/* we will include all header files used in pugl in their C++ friendly form, then pugl stuff in custom namespace */ +#include +#include +#include +#include +#include +#include + +#if defined(DISTRHO_OS_HAIKU) +# include +# include +# ifdef DGL_OPENGL +# include +# include +# endif +#elif defined(DISTRHO_OS_MAC) +# import +# include +# include +# ifdef DGL_CAIRO +# include +# endif +# ifdef DGL_VULKAN +# import +# include +# endif +#elif defined(DISTRHO_OS_WASM) +# include +# include +# ifdef DGL_OPENGL +# include +# endif +#elif defined(DISTRHO_OS_WINDOWS) +# include +# include +# include +# include +# ifdef DGL_CAIRO +# include +# endif +# ifdef DGL_OPENGL +# include +# endif +# ifdef DGL_VULKAN +# include +# include +# endif +#elif defined(HAVE_X11) +# include +# include +# include +# include +// # include +# include +# include +# include +# include +# include +# include +# ifdef HAVE_XCURSOR +# include +// # include +# endif +# ifdef HAVE_XRANDR +# include +# endif +# ifdef HAVE_XSYNC +# include +# include +# endif +# ifdef DGL_CAIRO +# include +# endif +# ifdef DGL_OPENGL +# include +# endif +# ifdef DGL_VULKAN +# include +# endif +#endif + +#ifndef DGL_FILE_BROWSER_DISABLED +# define FILE_BROWSER_DIALOG_DGL_NAMESPACE +# define FILE_BROWSER_DIALOG_NAMESPACE DGL_NAMESPACE +# define DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED +START_NAMESPACE_DGL +# include "../../distrho/extra/FileBrowserDialogImpl.hpp" +END_NAMESPACE_DGL +# include "../../distrho/extra/FileBrowserDialogImpl.cpp" +#endif + +#ifndef DISTRHO_OS_MAC +START_NAMESPACE_DGL +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +#if defined(DISTRHO_OS_HAIKU) +# include "pugl-extra/haiku.cpp" +# include "pugl-extra/haiku_stub.cpp" +# ifdef DGL_OPENGL +# include "pugl-extra/haiku_gl.cpp" +# endif +#elif defined(DISTRHO_OS_MAC) +# ifndef DISTRHO_MACOS_NAMESPACE_MACRO +# define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, SEP, INTERFACE) NS ## SEP ## INTERFACE +# define DISTRHO_MACOS_NAMESPACE_MACRO(NS, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, _, INTERFACE) +# define PuglCairoView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglCairoView) +# define PuglOpenGLView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglOpenGLView) +# define PuglStubView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglStubView) +# define PuglVulkanView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglVulkanView) +# define PuglWindow DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindow) +# define PuglWindowDelegate DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWindowDelegate) +# define PuglWrapperView DISTRHO_MACOS_NAMESPACE_MACRO(DGL_NAMESPACE, PuglWrapperView) +# endif +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# import "pugl-upstream/src/mac.m" +# import "pugl-upstream/src/mac_stub.m" +# ifdef DGL_CAIRO +# import "pugl-upstream/src/mac_cairo.m" +# endif +# ifdef DGL_OPENGL +# import "pugl-upstream/src/mac_gl.m" +# endif +# ifdef DGL_VULKAN +# import "pugl-upstream/src/mac_vulkan.m" +# endif +# pragma clang diagnostic pop +#elif defined(DISTRHO_OS_WASM) +# include "pugl-extra/wasm.c" +# include "pugl-extra/wasm_stub.c" +# ifdef DGL_OPENGL +# include "pugl-extra/wasm_gl.c" +# endif +#elif defined(DISTRHO_OS_WINDOWS) +# include "pugl-upstream/src/win.c" +# include "pugl-upstream/src/win_stub.c" +# ifdef DGL_CAIRO +# include "pugl-upstream/src/win_cairo.c" +# endif +# ifdef DGL_OPENGL +# include "pugl-upstream/src/win_gl.c" +# endif +# ifdef DGL_VULKAN +# include "pugl-upstream/src/win_vulkan.c" +# endif +#elif defined(HAVE_X11) +# include "pugl-upstream/src/x11.c" +# include "pugl-upstream/src/x11_stub.c" +# ifdef DGL_CAIRO +# include "pugl-upstream/src/x11_cairo.c" +# endif +# ifdef DGL_OPENGL +# include "pugl-upstream/src/x11_gl.c" +# endif +# ifdef DGL_VULKAN +# include "pugl-upstream/src/x11_vulkan.c" +# endif +#endif + +#include "pugl-upstream/src/common.c" +#include "pugl-upstream/src/internal.c" + +// -------------------------------------------------------------------------------------------------------------------- +// DGL specific, expose backend enter + +bool puglBackendEnter(PuglView* const view) +{ + return view->backend->enter(view, nullptr) == PUGL_SUCCESS; +} + +// -------------------------------------------------------------------------------------------------------------------- +// DGL specific, expose backend leave + +bool puglBackendLeave(PuglView* const view) +{ + return view->backend->leave(view, nullptr) == PUGL_SUCCESS; +} + +// -------------------------------------------------------------------------------------------------------------------- +// DGL specific, assigns backend that matches current DGL build + +void puglSetMatchingBackendForCurrentBuild(PuglView* const view) +{ + #ifdef DGL_CAIRO + puglSetBackend(view, puglCairoBackend()); + #endif + #ifdef DGL_OPENGL + puglSetBackend(view, puglGlBackend()); + #endif + #ifdef DGL_VULKAN + puglSetBackend(view, puglVulkanBackend()); + #endif + + if (view->backend != nullptr) + { + #ifdef DGL_OPENGL + #if defined(DGL_USE_GLES2) + puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE); + puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2); + #elif defined(DGL_USE_OPENGL3) + puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE); + puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 3); + #else + puglSetViewHint(view, PUGL_USE_COMPAT_PROFILE, PUGL_TRUE); + puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 2); + #endif + #endif + } + else + { + puglSetBackend(view, puglStubBackend()); + } +} + +// -------------------------------------------------------------------------------------------------------------------- +// bring view window into the foreground, aka "raise" window + +void puglRaiseWindow(PuglView* const view) +{ +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + if (NSWindow* const window = view->impl->window ? view->impl->window + : [view->impl->wrapperView window]) + [window orderFrontRegardless]; +#elif defined(DISTRHO_OS_WASM) + // nothing +#elif defined(DISTRHO_OS_WINDOWS) + SetForegroundWindow(view->impl->hwnd); + SetActiveWindow(view->impl->hwnd); +#elif defined(HAVE_X11) + XRaiseWindow(view->world->impl->display, view->impl->win); +#endif +} + +// -------------------------------------------------------------------------------------------------------------------- +// get scale factor from parent window if possible, fallback to puglGetScaleFactor + +double puglGetScaleFactorFromParent(const PuglView* const view) +{ + const PuglNativeView parent = view->parent ? view->parent : view->transientParent ? view->transientParent : 0; +#if defined(DISTRHO_OS_HAIKU) + // TODO + return 1.0; +#elif defined(DISTRHO_OS_MAC) + // some of these can return 0 as backingScaleFactor, pick the most relevant valid one + const NSWindow* possibleWindows[] = { + parent != 0 ? [(NSView*)parent window] : nullptr, + view->impl->window, + [view->impl->wrapperView window] + }; + for (size_t i=0; iimpl->hwnd; + return puglWinGetViewScaleFactor(hwnd); +#else + return puglGetScaleFactor(view); + // unused + (void)parent; +#endif +} + +// -------------------------------------------------------------------------------------------------------------------- +// Combined puglSetSizeHint using PUGL_MIN_SIZE and PUGL_FIXED_ASPECT + +PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, const uint height, const bool aspect) +{ + view->sizeHints[PUGL_MIN_SIZE].width = width; + view->sizeHints[PUGL_MIN_SIZE].height = height; + + if (aspect) + { + view->sizeHints[PUGL_FIXED_ASPECT].width = width; + view->sizeHints[PUGL_FIXED_ASPECT].height = height; + } + +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + if (view->impl->window) + { + PuglStatus status; + + if ((status = updateSizeHint(view, PUGL_MIN_SIZE)) != PUGL_SUCCESS) + return status; + + if (aspect && (status = updateSizeHint(view, PUGL_FIXED_ASPECT)) != PUGL_SUCCESS) + return status; + } +#elif defined(DISTRHO_OS_WASM) + // nothing +#elif defined(DISTRHO_OS_WINDOWS) + // nothing +#elif defined(HAVE_X11) + if (const PuglStatus status = updateSizeHints(view)) + return status; + + XFlush(view->world->impl->display); +#endif + + return PUGL_SUCCESS; +} + +// -------------------------------------------------------------------------------------------------------------------- +// set view as resizable (or not) during runtime + +void puglSetResizable(PuglView* const view, const bool resizable) +{ + puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); + +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + if (PuglWindow* const window = view->impl->window) + { + const uint style = (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask) + | (resizable ? NSResizableWindowMask : 0x0); + [window setStyleMask:style]; + } + // FIXME use [view setAutoresizingMask:NSViewNotSizable] ? +#elif defined(DISTRHO_OS_WASM) + // nothing +#elif defined(DISTRHO_OS_WINDOWS) + if (const HWND hwnd = view->impl->hwnd) + { + const uint winFlags = resizable ? GetWindowLong(hwnd, GWL_STYLE) | (WS_SIZEBOX | WS_MAXIMIZEBOX) + : GetWindowLong(hwnd, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX); + SetWindowLong(hwnd, GWL_STYLE, winFlags); + } +#elif defined(HAVE_X11) + updateSizeHints(view); +#endif +} + +// -------------------------------------------------------------------------------------------------------------------- +// set window size while also changing default + +PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height) +{ + if (width > INT16_MAX || height > INT16_MAX) + return PUGL_BAD_PARAMETER; + + view->sizeHints[PUGL_DEFAULT_SIZE].width = view->frame.width = static_cast(width); + view->sizeHints[PUGL_DEFAULT_SIZE].height = view->frame.height = static_cast(height); + +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) + // mostly matches upstream pugl, simplified + PuglInternals* const impl = view->impl; + + const PuglRect frame = view->frame; + const NSRect framePx = rectToNsRect(frame); + const NSRect framePt = nsRectToPoints(view, framePx); + + if (PuglWindow* const window = view->impl->window) + { + const NSRect screenPt = rectToScreen(viewScreen(view), framePt); + const NSRect winFrame = [window frameRectForContentRect:screenPt]; + [window setFrame:winFrame display:NO]; + } + + const NSSize sizePx = NSMakeSize(frame.width, frame.height); + const NSSize sizePt = [impl->drawView convertSizeFromBacking:sizePx]; + [impl->wrapperView setFrameSize:sizePt]; + [impl->drawView setFrameSize:sizePt]; +#elif defined(DISTRHO_OS_WASM) + d_stdout("className is %s", view->world->className); + emscripten_set_canvas_element_size(view->world->className, width, height); +#elif defined(DISTRHO_OS_WINDOWS) + // matches upstream pugl, except we re-enter context after resize + if (const HWND hwnd = view->impl->hwnd) + { + const RECT rect = adjustedWindowRect(view, view->frame.x, view->frame.y, + static_cast(width), static_cast(height)); + + if (!SetWindowPos(hwnd, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE)) + return PUGL_UNKNOWN_ERROR; + + // make sure to return context back to ourselves + puglBackendEnter(view); + } +#elif defined(HAVE_X11) + // matches upstream pugl, all in one + if (const Window window = view->impl->win) + { + Display* const display = view->world->impl->display; + + if (! XResizeWindow(display, window, width, height)) + return PUGL_UNKNOWN_ERROR; + + if (const PuglStatus status = updateSizeHints(view)) + return status; + + XFlush(display); + } +#endif + + return PUGL_SUCCESS; +} + +// -------------------------------------------------------------------------------------------------------------------- +// DGL specific, build-specific drawing prepare + +void puglOnDisplayPrepare(PuglView*) +{ + #ifdef DGL_OPENGL + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + #ifndef DGL_USE_OPENGL3 + glLoadIdentity(); + #endif + #endif +} + +// -------------------------------------------------------------------------------------------------------------------- +// DGL specific, build-specific fallback resize + +void puglFallbackOnResize(PuglView* const view) +{ + #ifdef DGL_OPENGL + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + #ifdef DGL_USE_OPENGL3 + glViewport(0, 0, static_cast(view->frame.width), static_cast(view->frame.height)); + #else + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, static_cast(view->frame.width), static_cast(view->frame.height), 0.0, 0.0, 1.0); + glViewport(0, 0, static_cast(view->frame.width), static_cast(view->frame.height)); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + #endif + #else + return; + // unused + (void)view; + #endif +} + +// -------------------------------------------------------------------------------------------------------------------- + +#if defined(DISTRHO_OS_HAIKU) + +// -------------------------------------------------------------------------------------------------------------------- + +#elif defined(DISTRHO_OS_MAC) + +// -------------------------------------------------------------------------------------------------------------------- +// macOS specific, add another view's window as child + +PuglStatus +puglMacOSAddChildWindow(PuglView* const view, PuglView* const child) +{ + if (NSWindow* const viewWindow = view->impl->window ? view->impl->window + : [view->impl->wrapperView window]) + { + if (NSWindow* const childWindow = child->impl->window ? child->impl->window + : [child->impl->wrapperView window]) + { + [viewWindow addChildWindow:childWindow ordered:NSWindowAbove]; + return PUGL_SUCCESS; + } + } + + return PUGL_FAILURE; +} + +// -------------------------------------------------------------------------------------------------------------------- +// macOS specific, remove another view's window as child + +PuglStatus +puglMacOSRemoveChildWindow(PuglView* const view, PuglView* const child) +{ + if (NSWindow* const viewWindow = view->impl->window ? view->impl->window + : [view->impl->wrapperView window]) + { + if (NSWindow* const childWindow = child->impl->window ? child->impl->window + : [child->impl->wrapperView window]) + { + [viewWindow removeChildWindow:childWindow]; + return PUGL_SUCCESS; + } + } + + return PUGL_FAILURE; +} + +// -------------------------------------------------------------------------------------------------------------------- +// macOS specific, center view based on parent coordinates (if there is one) + +void puglMacOSShowCentered(PuglView* const view) +{ + if (puglShow(view) != PUGL_SUCCESS) + return; + + if (view->transientParent != 0) + { + NSWindow* const transientWindow = [(NSView*)view->transientParent window]; + DISTRHO_SAFE_ASSERT_RETURN(transientWindow != nullptr,); + + const NSRect ourFrame = [view->impl->window frame]; + const NSRect transientFrame = [transientWindow frame]; + + const int x = transientFrame.origin.x + (transientFrame.size.width - ourFrame.size.width) / 2; + const int y = transientFrame.origin.y + (transientFrame.size.height - ourFrame.size.height) / 2; + + [view->impl->window setFrameTopLeftPoint:NSMakePoint(x, y)]; + } + else + { + [view->impl->window center]; + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +#elif defined(DISTRHO_OS_WINDOWS) + +// -------------------------------------------------------------------------------------------------------------------- +// win32 specific, call ShowWindow with SW_RESTORE + +void puglWin32RestoreWindow(PuglView* const view) +{ + PuglInternals* impl = view->impl; + DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,); + + ShowWindow(impl->hwnd, SW_RESTORE); + SetFocus(impl->hwnd); +} + +// -------------------------------------------------------------------------------------------------------------------- +// win32 specific, center view based on parent coordinates (if there is one) + +void puglWin32ShowCentered(PuglView* const view) +{ + PuglInternals* impl = view->impl; + DISTRHO_SAFE_ASSERT_RETURN(impl->hwnd != nullptr,); + + RECT rectChild, rectParent; + + if (view->transientParent != 0 && + GetWindowRect(impl->hwnd, &rectChild) && + GetWindowRect((HWND)view->transientParent, &rectParent)) + { + SetWindowPos(impl->hwnd, HWND_TOP, + rectParent.left + (rectParent.right-rectParent.left)/2 - (rectChild.right-rectChild.left)/2, + rectParent.top + (rectParent.bottom-rectParent.top)/2 - (rectChild.bottom-rectChild.top)/2, + 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE); + } + else + { +#ifdef DGL_WINDOWS_ICON_ID + WNDCLASSEX wClass; + std::memset(&wClass, 0, sizeof(wClass)); + + const HINSTANCE hInstance = GetModuleHandle(nullptr); + + if (GetClassInfoEx(hInstance, view->world->className, &wClass)) + wClass.hIcon = LoadIcon(nullptr, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID)); + + SetClassLongPtr(impl->hwnd, GCLP_HICON, (LONG_PTR) LoadIcon(hInstance, MAKEINTRESOURCE(DGL_WINDOWS_ICON_ID))); +#endif + + MONITORINFO mInfo; + std::memset(&mInfo, 0, sizeof(mInfo)); + mInfo.cbSize = sizeof(mInfo); + + if (GetMonitorInfo(MonitorFromWindow(impl->hwnd, MONITOR_DEFAULTTOPRIMARY), &mInfo)) + SetWindowPos(impl->hwnd, HWND_TOP, + mInfo.rcWork.left + (mInfo.rcWork.right - mInfo.rcWork.left - view->frame.width) / 2, + mInfo.rcWork.top + (mInfo.rcWork.bottom - mInfo.rcWork.top - view->frame.height) / 2, + 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE); + else + ShowWindow(impl->hwnd, SW_NORMAL); + } + + SetFocus(impl->hwnd); +} + +// -------------------------------------------------------------------------------------------------------------------- + +#elif defined(DISTRHO_OS_WASM) + +// nothing here yet + +// -------------------------------------------------------------------------------------------------------------------- + +#elif defined(HAVE_X11) + +PuglStatus puglX11UpdateWithoutExposures(PuglWorld* const world) +{ + const bool wasDispatchingEvents = world->impl->dispatchingEvents; + world->impl->dispatchingEvents = true; + PuglStatus st = PUGL_SUCCESS; + + const double startTime = puglGetTime(world); + const double endTime = startTime + 0.03; + + for (double t = startTime; !st && t < endTime; t = puglGetTime(world)) + { + pollX11Socket(world, endTime - t); + st = dispatchX11Events(world); + } + + world->impl->dispatchingEvents = wasDispatchingEvents; + return st; +} + +// -------------------------------------------------------------------------------------------------------------------- +// X11 specific, set dialog window type and pid hints + +void puglX11SetWindowTypeAndPID(const PuglView* const view, const bool isStandalone) +{ + const PuglInternals* const impl = view->impl; + Display* const display = view->world->impl->display; + + const pid_t pid = getpid(); + const Atom _nwp = XInternAtom(display, "_NET_WM_PID", False); + XChangeProperty(display, impl->win, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1); + + const Atom _wt = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); + + Atom _wts[2]; + int numAtoms = 0; + + if (! isStandalone) + _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); + + _wts[numAtoms++] = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False); + + XChangeProperty(display, impl->win, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, numAtoms); +} + +// -------------------------------------------------------------------------------------------------------------------- + +#endif // HAVE_X11 + +#ifndef DISTRHO_OS_MAC +END_NAMESPACE_DGL +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,121 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_PUGL_HPP_INCLUDED +#define DGL_PUGL_HPP_INCLUDED + +#include "../Base.hpp" + +/* we will include all header files used in pugl.h in their C++ friendly form, then pugl stuff in custom namespace */ +#include +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# include +# include +#else +# include +# include +#endif + +// hidden api +#define PUGL_API +#define PUGL_DISABLE_DEPRECATED +#define PUGL_NO_INCLUDE_GL_H +#define PUGL_NO_INCLUDE_GLU_H + +#ifndef DISTRHO_OS_MAC +START_NAMESPACE_DGL +#endif + +#include "pugl-upstream/include/pugl/pugl.h" + +// -------------------------------------------------------------------------------------------------------------------- + +// DGL specific, expose backend enter +bool puglBackendEnter(PuglView* view); + +// DGL specific, expose backend leave +bool puglBackendLeave(PuglView* view); + +// DGL specific, assigns backend that matches current DGL build +void puglSetMatchingBackendForCurrentBuild(PuglView* view); + +// bring view window into the foreground, aka "raise" window +void puglRaiseWindow(PuglView* view); + +// get scale factor from parent window if possible, fallback to puglGetScaleFactor +double puglGetScaleFactorFromParent(const PuglView* view); + +// combined puglSetSizeHint using PUGL_MIN_SIZE, PUGL_MIN_ASPECT and PUGL_MAX_ASPECT +PuglStatus puglSetGeometryConstraints(PuglView* view, uint width, uint height, bool aspect); + +// set view as resizable (or not) during runtime +void puglSetResizable(PuglView* view, bool resizable); + +// set window size while also changing default +PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height); + +// DGL specific, build-specific drawing prepare +void puglOnDisplayPrepare(PuglView* view); + +// DGL specific, build-specific fallback resize +void puglFallbackOnResize(PuglView* view); + +#if defined(DISTRHO_OS_HAIKU) + +// nothing here yet + +#elif defined(DISTRHO_OS_MAC) + +// macOS specific, add another view's window as child +PuglStatus puglMacOSAddChildWindow(PuglView* view, PuglView* child); + +// macOS specific, remove another view's window as child +PuglStatus puglMacOSRemoveChildWindow(PuglView* view, PuglView* child); + +// macOS specific, center view based on parent coordinates (if there is one) +void puglMacOSShowCentered(PuglView* view); + +#elif defined(DISTRHO_OS_WASM) + +// nothing here yet + +#elif defined(DISTRHO_OS_WINDOWS) + +// win32 specific, call ShowWindow with SW_RESTORE +void puglWin32RestoreWindow(PuglView* view); + +// win32 specific, center view based on parent coordinates (if there is one) +void puglWin32ShowCentered(PuglView* view); + +#elif defined(HAVE_X11) + +#define DGL_USING_X11 + +// X11 specific, update world without triggering exposure evente +PuglStatus puglX11UpdateWithoutExposures(PuglWorld* world); + +// X11 specific, set dialog window type and pid hints +void puglX11SetWindowTypeAndPID(const PuglView* view, bool isStandalone); + +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +#ifndef DISTRHO_OS_MAC +END_NAMESPACE_DGL +#endif + +#endif // DGL_PUGL_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/pugl.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/pugl.mm Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1 @@ +pugl.cpp \ No newline at end of file diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/resources/DejaVuSans.ttf Binary file DPF-Prymula-audioplugins/dpf/dgl/src/resources/DejaVuSans.ttf has changed diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dgl/src/resources/LICENSE-DejaVuSans.ttf.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dgl/src/resources/LICENSE-DejaVuSans.ttf.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,97 @@ +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoDetails.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoDetails.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1031 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_DETAILS_HPP_INCLUDED +#define DISTRHO_DETAILS_HPP_INCLUDED + +#include "extra/String.hpp" + +START_NAMESPACE_DISTRHO + +/* -------------------------------------------------------------------------------------------------------------------- + * Audio Port Hints */ + +/** + @defgroup AudioPortHints Audio Port Hints + + Various audio port hints. + @see AudioPort::hints + @{ + */ + +/** + Audio port can be used as control voltage (LV2 and JACK standalone only). + */ +static constexpr const uint32_t kAudioPortIsCV = 0x1; + +/** + Audio port should be used as sidechan (LV2 and VST3 only). + This hint should not be used with CV style ports. + @note non-sidechain audio ports must exist in the plugin if this flag is set. + */ +static constexpr const uint32_t kAudioPortIsSidechain = 0x2; + +/** + CV port has bipolar range (-1 to +1, or -5 to +5 if scaled). + This is merely a hint to tell the host what value range to expect. + */ +static constexpr const uint32_t kCVPortHasBipolarRange = 0x10; + +/** + CV port has negative unipolar range (-1 to 0, or -10 to 0 if scaled). + This is merely a hint to tell the host what value range to expect. + */ +static constexpr const uint32_t kCVPortHasNegativeUnipolarRange = 0x20; + +/** + CV port has positive unipolar range (0 to +1, or 0 to +10 if scaled). + This is merely a hint to tell the host what value range to expect. + */ +static constexpr const uint32_t kCVPortHasPositiveUnipolarRange = 0x40; + +/** + CV port has scaled range to match real values (-5 to +5v bipolar, +/-10 to 0v unipolar). + One other range flag is required if this flag is set. + + When enabled, this makes the port a mod:CVPort, compatible with the MOD Devices platform. + */ +static constexpr const uint32_t kCVPortHasScaledRange = 0x80; + +/** + CV port is optional, allowing hosts that do no CV ports to load the plugin. + When loaded in hosts that don't support CV, the float* buffer for this port will be null. + */ +static constexpr const uint32_t kCVPortIsOptional = 0x100; + +/** @} */ + +/* -------------------------------------------------------------------------------------------------------------------- + * Parameter Hints */ + +/** + @defgroup ParameterHints Parameter Hints + + Various parameter hints. + @see Parameter::hints + @{ + */ + +/** + Parameter is automatable (real-time safe). + @see Plugin::setParameterValue(uint32_t, float) + */ +static constexpr const uint32_t kParameterIsAutomatable = 0x01; + +/** It was a typo, sorry.. */ +DISTRHO_DEPRECATED_BY("kParameterIsAutomatable") +static constexpr const uint32_t kParameterIsAutomable = kParameterIsAutomatable; + +/** + Parameter value is boolean.@n + It's always at either minimum or maximum value. + */ +static constexpr const uint32_t kParameterIsBoolean = 0x02; + +/** + Parameter value is integer. + */ +static constexpr const uint32_t kParameterIsInteger = 0x04; + +/** + Parameter value is logarithmic. + */ +static constexpr const uint32_t kParameterIsLogarithmic = 0x08; + +/** + Parameter is of output type.@n + When unset, parameter is assumed to be of input type. + + Parameter inputs are changed by the host and typically should not be changed by the plugin.@n + One exception is when changing programs, see Plugin::loadProgram().@n + The other exception is with parameter change requests, see Plugin::requestParameterValueChange().@n + Outputs are changed by the plugin and never modified by the host. + + If you are targetting VST2, make sure to order your parameters so that all inputs are before any outputs. + */ +static constexpr const uint32_t kParameterIsOutput = 0x10; + +/** + Parameter value is a trigger.@n + This means the value resets back to its default after each process/run call.@n + Cannot be used for output parameters. + + @note Only officially supported under LV2. For other formats DPF simulates the behaviour. +*/ +static constexpr const uint32_t kParameterIsTrigger = 0x20 | kParameterIsBoolean; + +/** + Parameter should be hidden from the host and user-visible GUIs.@n + It is still saved and handled as any regular parameter, just not visible to the user + (for example in a host generated GUI) + */ +static constexpr const uint32_t kParameterIsHidden = 0x40; + +/** @} */ + +/* -------------------------------------------------------------------------------------------------------------------- + * State Hints */ + +/** + @defgroup StateHints State Hints + + Various state hints. + @see State::hints + @{ + */ + +/** + State is visible and readable by hosts that support string-type plugin parameters. + */ +static constexpr const uint32_t kStateIsHostReadable = 0x01; + +/** + State is writable by the host, allowing users to arbitrarily change the state.@n + For obvious reasons a writable state is also readable by the host. + */ +static constexpr const uint32_t kStateIsHostWritable = 0x02 | kStateIsHostReadable; + +/** + State is a filename path instead of a regular string.@n + The readable and writable hints are required for filenames to work, and thus are automatically set. + */ +static constexpr const uint32_t kStateIsFilenamePath = 0x04 | kStateIsHostWritable; + +/** + State is a base64 encoded string. + */ +static constexpr const uint32_t kStateIsBase64Blob = 0x08; + +/** + State is for Plugin/DSP side only, meaning there is never a need to notify the UI when it changes. + */ +static constexpr const uint32_t kStateIsOnlyForDSP = 0x10; + +/** + State is for UI side only.@n + If the DSP and UI are separate and the UI is not available, this property won't be saved. + */ +static constexpr const uint32_t kStateIsOnlyForUI = 0x20; + +/** @} */ + +/* -------------------------------------------------------------------------------------------------------------------- + * Base Plugin structs */ + +/** + @defgroup BasePluginStructs Base Plugin Structs + @{ + */ + +/** + Parameter designation.@n + Allows a parameter to be specially designated for a task, like bypass. + + Each designation is unique, there must be only one parameter that uses it.@n + The use of designated parameters is completely optional. + + @note Designated parameters have strict ranges. + @see ParameterRanges::adjustForDesignation() + */ +enum ParameterDesignation { + /** + Null or unset designation. + */ + kParameterDesignationNull = 0, + + /** + Bypass designation.@n + When on (> 0.5f), it means the plugin must run in a bypassed state. + */ + kParameterDesignationBypass = 1 +}; + +/** + Predefined Port Groups Ids. + + This enumeration provides a few commonly used groups for convenient use in plugins. + For preventing conflicts with user code, negative values are used here. + When rolling your own port groups, you MUST start their group ids from 0 and they MUST be sequential. + + @see PortGroup + */ +enum PredefinedPortGroupsIds { + /** + Null or unset port group. + */ + kPortGroupNone = (uint32_t)-1, + + /** + A single channel audio group. + */ + kPortGroupMono = (uint32_t)-2, + + /** + A 2-channel discrete stereo audio group, + where the 1st audio port is the left channel and the 2nd port is the right channel. + */ + kPortGroupStereo = (uint32_t)-3 +}; + +/** + Audio Port. + + Can be used as CV port by specifying kAudioPortIsCV in hints,@n + but this is only supported in LV2 and JACK standalone formats. + */ +struct AudioPort { + /** + Hints describing this audio port. + @see AudioPortHints + */ + uint32_t hints; + + /** + The name of this audio port.@n + An audio port name can contain any character, but hosts might have a hard time with non-ascii ones.@n + The name doesn't have to be unique within a plugin instance, but it's recommended. + */ + String name; + + /** + The symbol of this audio port.@n + An audio port symbol is a short restricted name used as a machine and human readable identifier.@n + The first character must be one of _, a-z or A-Z and subsequent characters can be from _, a-z, A-Z and 0-9. + @note Audio port and parameter symbols MUST be unique within a plugin instance. + */ + String symbol; + + /** + The group id that this audio/cv port belongs to. + No group is assigned by default. + + You can use a group from PredefinedPortGroups or roll your own.@n + When rolling your own port groups, you MUST start their group ids from 0 and they MUST be sequential. + @see PortGroup, Plugin::initPortGroup + */ + uint32_t groupId; + + /** + Default constructor for a regular audio port. + */ + AudioPort() noexcept + : hints(0x0), + name(), + symbol(), + groupId(kPortGroupNone) {} +}; + +/** + Parameter ranges.@n + This is used to set the default, minimum and maximum values of a parameter. + + By default a parameter has 0.0 as minimum, 1.0 as maximum and 0.0 as default.@n + When changing this struct values you must ensure maximum > minimum and default is within range. + */ +struct ParameterRanges { + /** + Default value. + */ + float def; + + /** + Minimum value. + */ + float min; + + /** + Maximum value. + */ + float max; + + /** + Default constructor, using 0.0 as default, 0.0 as minimum, 1.0 as maximum. + */ + constexpr ParameterRanges() noexcept + : def(0.0f), + min(0.0f), + max(1.0f) {} + + /** + Constructor using custom values. + */ + constexpr ParameterRanges(float df, float mn, float mx) noexcept + : def(df), + min(mn), + max(mx) {} + + /** + Fix the default value within range. + */ + void fixDefault() noexcept + { + fixValue(def); + } + + /** + Fix a value within range. + */ + void fixValue(float& value) const noexcept + { + if (value < min) + value = min; + else if (value > max) + value = max; + } + + /** + Get a fixed value within range. + */ + float getFixedValue(const float& value) const noexcept + { + if (value <= min) + return min; + if (value >= max) + return max; + return value; + } + + /** + Get a value normalized to 0.0<->1.0. + */ + float getNormalizedValue(const float& value) const noexcept + { + const float normValue = (value - min) / (max - min); + + if (normValue <= 0.0f) + return 0.0f; + if (normValue >= 1.0f) + return 1.0f; + return normValue; + } + + /** + Get a value normalized to 0.0<->1.0. + Overloaded function using double precision values. + */ + double getNormalizedValue(const double& value) const noexcept + { + const double normValue = (value - min) / (max - min); + + if (normValue <= 0.0) + return 0.0; + if (normValue >= 1.0) + return 1.0; + return normValue; + } + + /** + Get a value normalized to 0.0<->1.0, fixed within range. + */ + float getFixedAndNormalizedValue(const float& value) const noexcept + { + if (value <= min) + return 0.0f; + if (value >= max) + return 1.0f; + + const float normValue = (value - min) / (max - min); + + if (normValue <= 0.0f) + return 0.0f; + if (normValue >= 1.0f) + return 1.0f; + + return normValue; + } + + /** + Get a value normalized to 0.0<->1.0, fixed within range. + Overloaded function using double precision values. + */ + double getFixedAndNormalizedValue(const double& value) const noexcept + { + if (value <= min) + return 0.0; + if (value >= max) + return 1.0; + + const double normValue = (value - min) / (max - min); + + if (normValue <= 0.0) + return 0.0; + if (normValue >= 1.0) + return 1.0; + + return normValue; + } + + /** + Get a proper value previously normalized to 0.0<->1.0. + */ + float getUnnormalizedValue(const float& value) const noexcept + { + if (value <= 0.0f) + return min; + if (value >= 1.0f) + return max; + + return value * (max - min) + min; + } + + /** + Get a proper value previously normalized to 0.0<->1.0. + Overloaded function using double precision values. + */ + double getUnnormalizedValue(const double& value) const noexcept + { + if (value <= 0.0) + return min; + if (value >= 1.0) + return max; + + return value * (max - min) + min; + } +}; + +/** + Parameter enumeration value.@n + A string representation of a plugin parameter value.@n + Used together can be used to give meaning to parameter values, working as an enumeration. + */ +struct ParameterEnumerationValue { + /** + Parameter value. + */ + float value; + + /** + String representation of this value. + */ + String label; + + /** + Default constructor, using 0.0 as value and empty label. + */ + ParameterEnumerationValue() noexcept + : value(0.0f), + label() {} + + /** + Constructor using custom values. + */ + ParameterEnumerationValue(float v, const char* l) noexcept + : value(v), + label(l) {} + +#if __cplusplus >= 201703L + /** + Constructor using custom values, constexpr compatible variant. + */ + constexpr ParameterEnumerationValue(float v, const std::string_view& l) noexcept + : value(v), + label(l) {} +#endif +}; + +/** + Details around parameter enumeration values.@n + Wraps ParameterEnumerationValues and provides a few extra details to the host about these values. + */ +struct ParameterEnumerationValues { + /** + Number of elements allocated in @values. + */ + uint8_t count; + + /** + Whether the host is to be restricted to only use enumeration values. + + @note This mode is only a hint! Not all hosts and plugin formats support this mode. + */ + bool restrictedMode; + + /** + Array of @ParameterEnumerationValue items.@n + When assining this pointer manually, it must be allocated on the heap with `new ParameterEnumerationValue[count]`.@n + The array pointer will be automatically deleted later unless @p deleteLater is set to false. + */ + ParameterEnumerationValue* values; + + /** + Whether to take ownership of the @p values pointer.@n + Defaults to true unless stated otherwise. + */ + bool deleteLater; + + /** + Default constructor, for zero enumeration values. + */ + constexpr ParameterEnumerationValues() noexcept + : count(0), + restrictedMode(false), + values(nullptr), + deleteLater(true) {} + + /** + Constructor using custom values.@n + When using this constructor the pointer to @values MUST have been statically declared.@n + It will not be automatically deleted later. + */ + constexpr ParameterEnumerationValues(uint32_t c, bool r, ParameterEnumerationValue* v) noexcept + : count(c), + restrictedMode(r), + values(v), + deleteLater(false) {} + + // constexpr + ~ParameterEnumerationValues() noexcept + { + if (deleteLater) + delete[] values; + } +}; + +/** + Parameter. + */ +struct Parameter { + /** + Hints describing this parameter. + @see ParameterHints + */ + uint32_t hints; + + /** + The name of this parameter.@n + A parameter name can contain any character, but hosts might have a hard time with non-ascii ones.@n + The name doesn't have to be unique within a plugin instance, but it's recommended. + */ + String name; + + /** + The short name of this parameter.@n + Used when displaying the parameter name in a very limited space. + @note This value is optional, the full name is used when the short one is missing. + */ + String shortName; + + /** + The symbol of this parameter.@n + A parameter symbol is a short restricted name used as a machine and human readable identifier.@n + The first character must be one of _, a-z or A-Z and subsequent characters can be from _, a-z, A-Z and 0-9. + @note Parameter symbols MUST be unique within a plugin instance. + */ + String symbol; + + /** + The unit of this parameter.@n + This means something like "dB", "kHz" and "ms".@n + Can be left blank if a unit does not apply to this parameter. + */ + String unit; + + /** + An extensive description/comment about the parameter. + @note This value is optional and only used for LV2. + */ + String description; + + /** + Ranges of this parameter.@n + The ranges describe the default, minimum and maximum values. + */ + ParameterRanges ranges; + + /** + Enumeration details.@n + Can be used to give meaning to parameter values, working as an enumeration. + */ + ParameterEnumerationValues enumValues; + + /** + Designation for this parameter. + */ + ParameterDesignation designation; + + /** + MIDI CC to use by default on this parameter.@n + A value of 0 or 32 (bank change) is considered invalid.@n + Must also be less or equal to 120. + @note This value is only a hint! Hosts might map it automatically or completely ignore it. + */ + uint8_t midiCC; + + /** + The group id that this parameter belongs to. + No group is assigned by default. + + You can use a group from PredefinedPortGroups or roll your own.@n + When rolling your own port groups, you MUST start their group ids from 0 and they MUST be sequential. + @see PortGroup, Plugin::initPortGroup + */ + uint32_t groupId; + + /** + Default constructor for a null parameter. + */ + Parameter() noexcept + : hints(0x0), + name(), + shortName(), + symbol(), + unit(), + ranges(), + enumValues(), + designation(kParameterDesignationNull), + midiCC(0), + groupId(kPortGroupNone) {} + + /** + Constructor using custom values. + */ + Parameter(uint32_t h, const char* n, const char* s, const char* u, float def, float min, float max) noexcept + : hints(h), + name(n), + shortName(), + symbol(s), + unit(u), + ranges(def, min, max), + enumValues(), + designation(kParameterDesignationNull), + midiCC(0), + groupId(kPortGroupNone) {} + +#ifdef DISTRHO_PROPER_CPP11_SUPPORT + /** + Constructor using custom values and enumeration. + Assumes enumeration details should have `restrictedMode` on. + */ + Parameter(uint32_t h, const char* n, const char* s, const char* u, float def, float min, float max, + uint8_t evcount, ParameterEnumerationValue ev[]) noexcept + : hints(h), + name(n), + shortName(), + symbol(s), + unit(u), + ranges(def, min, max), + enumValues(evcount, true, ev), + designation(kParameterDesignationNull), + midiCC(0), + groupId(kPortGroupNone) {} +#endif + +#if __cplusplus >= 201703L + /** + Constructor for constexpr compatible data. + */ + constexpr Parameter(uint32_t h, + const std::string_view& n, + const std::string_view& sn, + const std::string_view& sym, + const std::string_view& u, + const std::string_view& desc) noexcept + : hints(h), + name(n), + shortName(sn), + symbol(sym), + unit(u), + description(desc), + ranges(), + enumValues(), + designation(kParameterDesignationNull), + midiCC(0), + groupId(kPortGroupNone) {} +#endif + + /** + Initialize a parameter for a specific designation. + */ + void initDesignation(ParameterDesignation d) noexcept + { + designation = d; + + switch (d) + { + case kParameterDesignationNull: + break; + case kParameterDesignationBypass: + hints = kParameterIsAutomatable|kParameterIsBoolean|kParameterIsInteger; + name = "Bypass"; + shortName = "Bypass"; + symbol = "dpf_bypass"; + unit = ""; + midiCC = 0; + groupId = kPortGroupNone; + ranges.def = 0.0f; + ranges.min = 0.0f; + ranges.max = 1.0f; + break; + } + } +}; + +#if __cplusplus >= 202001L /* TODO */ +/** + Bypass parameter definition in constexpr form. + */ +static constexpr const Parameter kParameterBypass = { + kParameterIsAutomatable|kParameterIsBoolean|kParameterIsInteger, + "Bypass", "Bypass", "dpf_bypass", "", "", {}, {}, 0, kPortGroupNone, +}; +#endif + +/** + Port Group.@n + Allows to group together audio/cv ports or parameters. + + Each unique group MUST have an unique symbol and a name. + A group can be applied to both inputs and outputs (at the same time). + The same group cannot be used in audio ports and parameters. + + When both audio and parameter groups are used, audio groups MUST be defined first. + That is, group indexes start with audio ports, then parameters. + + An audio port group logically combines ports which should be considered part of the same stream.@n + For example, two audio ports in a group may form a stereo stream. + + A parameter group provides meta-data to the host to indicate that some parameters belong together. + + The use of port groups is completely optional. + + @see Plugin::initPortGroup, AudioPort::group, Parameter::group + */ +struct PortGroup { + /** + The name of this port group.@n + A port group name can contain any character, but hosts might have a hard time with non-ascii ones.@n + The name doesn't have to be unique within a plugin instance, but it's recommended. + */ + String name; + + /** + The symbol of this port group.@n + A port group symbol is a short restricted name used as a machine and human readable identifier.@n + The first character must be one of _, a-z or A-Z and subsequent characters can be from _, a-z, A-Z and 0-9. + @note Port group symbols MUST be unique within a plugin instance. + */ + String symbol; +}; + +/** + State. + + In DPF states refer to key:value string pairs, used to store arbitrary non-parameter data.@n + By default states are completely internal to the plugin and not visible by the host.@n + Flags can be set to allow hosts to see and/or change them. + + TODO API under construction + */ +struct State { + /** + Hints describing this state. + @note Changing these hints can break compatibility with previously saved data. + @see StateHints + */ + uint32_t hints; + + /** + The key or "symbol" of this state.@n + A state key is a short restricted name used as a machine and human readable identifier. + @note State keys MUST be unique within a plugin instance. + TODO define rules for allowed characters, must be usable as URI non-encoded parameters + */ + String key; + + /** + The default value of this state.@n + Can be left empty if considered a valid initial state. + */ + String defaultValue; + + /** + String representation of this state. + */ + String label; + + /** + An extensive description/comment about this state. + @note This value is optional and only used for LV2. + */ + String description; + + #ifdef __MOD_DEVICES__ + /** + The file types that a filename path state supports, written as a comma-separated string without whitespace. + Currently supported file types are: + - audioloop: Audio Loops, meant to be used for looper-style plugins + - audiorecording: Audio Recordings, triggered by plugins and stored in the unit + - audiosample: One-shot Audio Samples, meant to be used for sampler-style plugins + - audiotrack: Audio Tracks, meant to be used as full-performance/song or backtrack + - cabsim: Speaker Cabinets, meant as small IR audio files + - h2drumkit: Hydrogen Drumkits, must use h2drumkit file extension + - ir: Impulse Responses + - midiclip: MIDI Clips, to be used in sync with host tempo, must have mid or midi file extension + - midisong: MIDI Songs, meant to be used as full-performance/song or backtrack + - sf2: SF2 Instruments, must have sf2 or sf3 file extension + - sfz: SFZ Instruments, must have sfz file extension + + @note This is a custom extension only valid in builds MOD Audio. + */ + String fileTypes; + #endif + + /** + Default constructor for a null state. + */ + State() noexcept + : hints(0x0), + key(), + defaultValue(), + label(), + description() {} +}; + +/** + MIDI event. + */ +struct MidiEvent { + /** + Size of internal data. + */ + static constexpr const uint32_t kDataSize = 4; + + /** + Time offset in frames. + */ + uint32_t frame; + + /** + Number of bytes used. + */ + uint32_t size; + + /** + MIDI data.@n + If size > kDataSize, dataExt is used (otherwise null). + + When dataExt is used, the event holder is responsible for + keeping the pointer valid during the entirety of the run function. + */ + uint8_t data[kDataSize]; + const uint8_t* dataExt; +}; + +/** + Time position.@n + The @a playing and @a frame values are always valid.@n + BBT values are only valid when @a bbt.valid is true. + + This struct is inspired by the [JACK Transport API](https://jackaudio.org/api/structjack__position__t.html). + */ +struct TimePosition { + /** + Wherever the host transport is playing/rolling. + */ + bool playing; + + /** + Current host transport position in frames. + @note This value is not always monotonic, + with some plugin hosts assigning it based on a source that can accumulate rounding errors. + */ + uint64_t frame; + + /** + Bar-Beat-Tick time position. + */ + struct BarBeatTick { + /** + Wherever the host transport is using BBT.@n + If false you must not read from this struct. + */ + bool valid; + + /** + Current bar.@n + Should always be > 0.@n + The first bar is bar '1'. + */ + int32_t bar; + + /** + Current beat within bar.@n + Should always be > 0 and <= @a beatsPerBar.@n + The first beat is beat '1'. + */ + int32_t beat; + + /** + Current tick within beat.@n + Should always be >= 0 and < @a ticksPerBeat.@n + The first tick is tick '0'. + @note Fraction part of tick is only available on some plugin formats. + */ + double tick; + + /** + Number of ticks that have elapsed between frame 0 and the first beat of the current measure. + */ + double barStartTick; + + /** + Time signature "numerator". + */ + float beatsPerBar; + + /** + Time signature "denominator". + */ + float beatType; + + /** + Number of ticks within a beat.@n + Usually a moderately large integer with many denominators, such as 1920.0. + */ + double ticksPerBeat; + + /** + Number of beats per minute. + */ + double beatsPerMinute; + + /** + Default constructor for a null BBT time position. + */ + BarBeatTick() noexcept + : valid(false), + bar(0), + beat(0), + tick(0), + barStartTick(0.0), + beatsPerBar(0.0f), + beatType(0.0f), + ticksPerBeat(0.0), + beatsPerMinute(0.0) {} + + /** + Reinitialize this position using the default null initialization. + */ + void clear() noexcept + { + valid = false; + bar = 0; + beat = 0; + tick = 0; + barStartTick = 0.0; + beatsPerBar = 0.0f; + beatType = 0.0f; + ticksPerBeat = 0.0; + beatsPerMinute = 0.0; + } + } bbt; + + /** + Default constructor for a time position. + */ + TimePosition() noexcept + : playing(false), + frame(0), + bbt() {} + + /** + Reinitialize this position using the default null initialization. + */ + void clear() noexcept + { + playing = false; + frame = 0; + bbt.clear(); + } +}; + +/** @} */ + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_DETAILS_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoInfo.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoInfo.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,941 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef DOXYGEN + +#include "src/DistrhoDefines.h" + +START_NAMESPACE_DISTRHO + +/* ------------------------------------------------------------------------------------------------------------ + * Intro */ + +/** + @mainpage DISTRHO %Plugin Framework + + DISTRHO %Plugin Framework (or @b DPF for short) + is a plugin framework designed to make development of new plugins an easy and enjoyable task.@n + It allows developers to create plugins with custom UIs using a simple C++ API.@n + The framework facilitates exporting various different plugin formats from the same code-base. + + DPF can build for LADSPA, DSSI, LV2, VST2, VST3 and CLAP formats.@n + A JACK/Standalone mode is also available, allowing you to quickly test plugins. + + @section Macros + You start by creating a "DistrhoPluginInfo.h" file describing the plugin via macros, see @ref PluginMacros.@n + This file is included during compilation of the main DPF code to select which features to activate for each plugin format. + + For example, a plugin (with %UI) that use states will require LV2 hosts to support Atom and Worker extensions for + message passing from the %UI to the (DSP) plugin.@n + If your plugin does not make use of states, the Worker extension is not set as a required feature. + + @section Plugin + The next step is to create your plugin code by subclassing DPF's Plugin class.@n + You need to pass the number of parameters in the constructor and also the number of programs and states, if any. + + Do note all of DPF code is within its own C++ namespace (@b DISTRHO for DSP/plugin stuff, @b DGL for UI stuff).@n + You can use @ref START_NAMESPACE_DISTRHO / @ref END_NAMESPACE_DISTRHO combo around your code, or globally set @ref USE_NAMESPACE_DISTRHO.@n + These are defined as compiler macros so that you can override the namespace name during build. When in doubt, just follow the examples. + + @section Examples + Let's begin with some examples.@n + Here is one of a stereo audio plugin that simply mutes the host output: + @code + /* DPF plugin include */ + #include "DistrhoPlugin.hpp" + + /* Make DPF related classes available for us to use without any extra namespace references */ + USE_NAMESPACE_DISTRHO; + + /** + Our custom plugin class. + Subclassing `Plugin` from DPF is how this all works. + + By default, only information-related functions and `run` are pure virtual (that is, must be reimplemented). + When enabling certain features (such as programs or states, more on that below), a few extra functions also need to be reimplemented. + */ + class MutePlugin : public Plugin + { + public: + /** + Plugin class constructor. + */ + MutePlugin() + : Plugin(0, 0, 0) // 0 parameters, 0 programs and 0 states + { + } + + protected: + /* ---------------------------------------------------------------------------------------- + * Information */ + + /** + Get the plugin label. + This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters. + */ + const char* getLabel() const override + { + return "Mute"; + } + + /** + Get the plugin author/maker. + */ + const char* getMaker() const override + { + return "DPF"; + } + + /** + Get the plugin license name (a single line of text). + For commercial plugins this should return some short copyright information. + */ + const char* getLicense() const override + { + return "MIT"; + } + + /** + Get the plugin version, in hexadecimal. + */ + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI, VST2 and VST3 plugin formats. + */ + int64_t getUniqueId() const override + { + return d_cconst('M', 'u', 't', 'e'); + } + + /* ---------------------------------------------------------------------------------------- + * Audio/MIDI Processing */ + + /** + Run/process function for plugins without MIDI input. + */ + void run(const float**, float** outputs, uint32_t frames) override + { + // get the left and right audio outputs + float* const outL = outputs[0]; + float* const outR = outputs[1]; + + // mute audio + std::memset(outL, 0, sizeof(float)*frames); + std::memset(outR, 0, sizeof(float)*frames); + } + }; + + /** + Create an instance of the Plugin class. + This is the entry point for DPF plugins. + DPF will call this to either create an instance of your plugin for the host or to fetch some initial information for internal caching. + */ + Plugin* createPlugin() + { + return new MutePlugin(); + } + @endcode + + See the Plugin class for more information. + + @section Parameters + A plugin is nothing without parameters.@n + In DPF parameters can be inputs or outputs.@n + They have hints to describe how they behave plus a name and a symbol identifying them.@n + Parameters also have 'ranges' - a minimum, maximum and default value. + + Input parameters are by default "read-only": the plugin can read them but not change them. + (there are exceptions and possibly a request to the host to change values, more on that below)@n + It's the host responsibility to save, restore and set input parameters. + + Output parameters can be changed at anytime by the plugin.@n + The host will simply read their values and never change them. + + Here's an example of an audio plugin that has 1 input parameter: + @code + class GainPlugin : public Plugin + { + public: + /** + Plugin class constructor. + You must set all parameter values to their defaults, matching ParameterRanges::def. + */ + GainPlugin() + : Plugin(1, 0, 0), // 1 parameter, 0 programs and 0 states + fGain(1.0f) + { + } + + protected: + /* ---------------------------------------------------------------------------------------- + * Information */ + + const char* getLabel() const override + { + return "Gain"; + } + + const char* getMaker() const override + { + return "DPF"; + } + + const char* getLicense() const override + { + return "MIT"; + } + + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + int64_t getUniqueId() const override + { + return d_cconst('G', 'a', 'i', 'n'); + } + + /* ---------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize a parameter. + This function will be called once, shortly after the plugin is created. + */ + void initParameter(uint32_t index, Parameter& parameter) override + { + // we only have one parameter so we can skip checking the index + + parameter.hints = kParameterIsAutomatable; + parameter.name = "Gain"; + parameter.symbol = "gain"; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 2.0f; + parameter.ranges.def = 1.0f; + } + + /* ---------------------------------------------------------------------------------------- + * Internal data */ + + /** + Get the current value of a parameter. + */ + float getParameterValue(uint32_t index) const override + { + // same as before, ignore index check + + return fGain; + } + + /** + Change a parameter value. + */ + void setParameterValue(uint32_t index, float value) override + { + // same as before, ignore index check + + fGain = value; + } + + /* ---------------------------------------------------------------------------------------- + * Audio/MIDI Processing */ + + void run(const float**, float** outputs, uint32_t frames) override + { + // get the mono input and output + const float* const in = inputs[0]; + /* */ float* const out = outputs[0]; + + // apply gain against all samples + for (uint32_t i=0; i < frames; ++i) + out[i] = in[i] * fGain; + } + + private: + float fGain; + }; + @endcode + + See the Parameter struct for more information about parameters. + + @section Programs + Programs in DPF refer to plugin-side presets (usually called "factory presets").@n + This is meant as an initial set of presets provided by plugin authors included in the actual plugin. + + To use programs you must first enable them by setting @ref DISTRHO_PLUGIN_WANT_PROGRAMS to 1 in your DistrhoPluginInfo.h file.@n + When enabled you'll need to override 2 new function in your plugin code, + Plugin::initProgramName(uint32_t, String&) and Plugin::loadProgram(uint32_t). + + Here's an example of a plugin with a "default" program: + @code + class PluginWithPresets : public Plugin + { + public: + PluginWithPresets() + : Plugin(2, 1, 0), // 2 parameters, 1 program and 0 states + fGainL(1.0f), + fGainR(1.0f), + { + } + + protected: + /* ---------------------------------------------------------------------------------------- + * Information */ + + const char* getLabel() const override + { + return "Prog"; + } + + const char* getMaker() const override + { + return "DPF"; + } + + const char* getLicense() const override + { + return "MIT"; + } + + uint32_t getVersion() const override + { + return d_version(1, 0, 0); + } + + int64_t getUniqueId() const override + { + return d_cconst('P', 'r', 'o', 'g'); + } + + /* ---------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize a parameter. + This function will be called once, shortly after the plugin is created. + */ + void initParameter(uint32_t index, Parameter& parameter) override + { + parameter.hints = kParameterIsAutomatable; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 2.0f; + parameter.ranges.def = 1.0f; + + switch (index) + { + case 0: + parameter.name = "Gain Right"; + parameter.symbol = "gainR"; + break; + case 1: + parameter.name = "Gain Left"; + parameter.symbol = "gainL"; + break; + } + } + + /** + Set the name of the program @a index. + This function will be called once, shortly after the plugin is created. + */ + void initProgramName(uint32_t index, String& programName) + { + // we only have one program so we can skip checking the index + + programName = "Default"; + } + + /* ---------------------------------------------------------------------------------------- + * Internal data */ + + /** + Get the current value of a parameter. + */ + float getParameterValue(uint32_t index) const override + { + switch (index) + { + case 0: + return fGainL; + case 1: + return fGainR; + default: + return 0.f; + } + } + + /** + Change a parameter value. + */ + void setParameterValue(uint32_t index, float value) override + { + switch (index) + { + case 0: + fGainL = value; + break; + case 1: + fGainR = value; + break; + } + } + + /** + Load a program. + */ + void loadProgram(uint32_t index) + { + // same as before, ignore index check + + fGainL = 1.0f; + fGainR = 1.0f; + } + + /* ---------------------------------------------------------------------------------------- + * Audio/MIDI Processing */ + + void run(const float**, float** outputs, uint32_t frames) override + { + // get the left and right audio buffers + const float* const inL = inputs[0]; + const float* const inR = inputs[0]; + /* */ float* const outL = outputs[0]; + /* */ float* const outR = outputs[0]; + + // apply gain against all samples + for (uint32_t i=0; i < frames; ++i) + { + outL[i] = inL[i] * fGainL; + outR[i] = inR[i] * fGainR; + } + } + + private: + float fGainL, fGainR; + }; + @endcode + + This is a work-in-progress documentation page. States, MIDI, Latency, Time-Position and UI are still TODO. +*/ + +#if 0 + @section States + describe them + + @section MIDI + describe them + + @section Latency + describe it + + @section Time-Position + describe it + + @section UI + describe them +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Macros */ + +/** + @defgroup PluginMacros Plugin Macros + + C Macros that describe your plugin. (defined in the "DistrhoPluginInfo.h" file) + + With these macros you can tell the host what features your plugin requires.@n + Depending on which macros you enable, new functions will be available to call and/or override. + + All values are either integer or strings.@n + For boolean-like values 1 means 'on' and 0 means 'off'. + + The values defined in this group are for documentation purposes only.@n + All macros are disabled by default. + + Only 4 macros are required, they are: + - @ref DISTRHO_PLUGIN_NAME + - @ref DISTRHO_PLUGIN_NUM_INPUTS + - @ref DISTRHO_PLUGIN_NUM_OUTPUTS + - @ref DISTRHO_PLUGIN_URI + + Additionally, @ref DISTRHO_PLUGIN_CLAP_ID is required if building CLAP plugins. + @{ + */ + +/** + The plugin name.@n + This is used to identify your plugin before a Plugin instance can be created. + @note This macro is required. + */ +#define DISTRHO_PLUGIN_NAME "Plugin Name" + +/** + Number of audio inputs the plugin has. + @note This macro is required. + */ +#define DISTRHO_PLUGIN_NUM_INPUTS 2 + +/** + Number of audio outputs the plugin has. + @note This macro is required. + */ +#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 + +/** + The plugin URI when exporting in LV2 format. + @note This macro is required. + */ +#define DISTRHO_PLUGIN_URI "urn:distrho:name" + +/** + Whether the plugin has a custom %UI. + @see DISTRHO_UI_USE_NANOVG + @see UI + */ +#define DISTRHO_PLUGIN_HAS_UI 1 + +/** + Whether the plugin processing is realtime-safe.@n + TODO - list rtsafe requirements + */ +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 + +/** + Whether the plugin is a synth.@n + @ref DISTRHO_PLUGIN_WANT_MIDI_INPUT is automatically enabled when this is too. + @see DISTRHO_PLUGIN_WANT_MIDI_INPUT + */ +#define DISTRHO_PLUGIN_IS_SYNTH 1 + +/** + Request the minimum buffer size for the input and output event ports.@n + Currently only used in LV2, with a default value of 2048 if unset. + */ +#define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048 + +/** + Whether the plugin has an LV2 modgui. + + This will simply add a "rdfs:seeAlso " on the LV2 manifest.@n + It is up to you to create this file. + */ +#define DISTRHO_PLUGIN_USES_MODGUI 0 + +/** + Enable direct access between the %UI and plugin code. + @see UI::getPluginInstancePointer() + @note DO NOT USE THIS UNLESS STRICTLY NECESSARY!! + Try to avoid it at all costs! + */ +#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 + +/** + Whether the plugin introduces latency during audio or midi processing. + @see Plugin::setLatency(uint32_t) + */ +#define DISTRHO_PLUGIN_WANT_LATENCY 1 + +/** + Whether the plugin wants MIDI input.@n + This is automatically enabled if @ref DISTRHO_PLUGIN_IS_SYNTH is true. + */ +#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1 + +/** + Whether the plugin wants MIDI output. + @see Plugin::writeMidiEvent(const MidiEvent&) + */ +#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1 + +/** + Whether the plugin wants to change its own parameter inputs.@n + Not all hosts or plugin formats support this, + so Plugin::canRequestParameterValueChanges() can be used to query support at runtime. + @see Plugin::requestParameterValueChange(uint32_t, float) + */ +#define DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 1 + +/** + Whether the plugin provides its own internal programs. + @see Plugin::initProgramName(uint32_t, String&) + @see Plugin::loadProgram(uint32_t) + */ +#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 + +/** + Whether the plugin uses internal non-parameter data. + @see Plugin::initState(uint32_t, String&, String&) + @see Plugin::setState(const char*, const char*) + */ +#define DISTRHO_PLUGIN_WANT_STATE 1 + +/** + Whether the plugin implements the full state API. + When this macro is enabled, the plugin must implement a new getState(const char* key) function, which the host calls when saving its session/project. + This is useful for plugins that have custom internal values not exposed to the host as key-value state pairs or parameters. + Most simple effects and synths will not need this. + @note this macro is automatically enabled if a plugin has programs and state, as the key-value state pairs need to be updated when the current program changes. + @see Plugin::getState(const char*) + */ +#define DISTRHO_PLUGIN_WANT_FULL_STATE 1 + +/** + Whether the plugin wants time position information from the host. + @see Plugin::getTimePosition() + */ +#define DISTRHO_PLUGIN_WANT_TIMEPOS 1 + +/** + Whether the %UI uses a custom toolkit implementation based on OpenGL.@n + When enabled, the macros @ref DISTRHO_UI_CUSTOM_INCLUDE_PATH and @ref DISTRHO_UI_CUSTOM_WIDGET_TYPE are required. + */ +#define DISTRHO_UI_USE_CUSTOM 1 + +/** + The include path to the header file used by the custom toolkit implementation. + This path must be relative to dpf/distrho/DistrhoUI.hpp + @see DISTRHO_UI_USE_CUSTOM + */ +#define DISTRHO_UI_CUSTOM_INCLUDE_PATH + +/** + The top-level-widget typedef to use for the custom toolkit. + This widget class MUST be a subclass of DGL TopLevelWindow class. + It is recommended that you keep this widget class inside the DGL namespace, + and define widget type as e.g. DGL_NAMESPACE::MyCustomTopLevelWidget. + @see DISTRHO_UI_USE_CUSTOM + */ +#define DISTRHO_UI_CUSTOM_WIDGET_TYPE + +/** + Default UI width to use when creating initial and temporary windows.@n + Setting this macro allows to skip a temporary UI from being created in certain VST2 and VST3 hosts. + (which would normally be done for knowing the UI size before host creates a window for it) + + Value must match 1x scale factor. + + When this macro is defined, the companion DISTRHO_UI_DEFAULT_HEIGHT macro must be defined as well. + */ +#define DISTRHO_UI_DEFAULT_WIDTH 300 + +/** + Default UI height to use when creating initial and temporary windows.@n + Setting this macro allows to skip a temporary UI from being created in certain VST2 and VST3 hosts. + (which would normally be done for knowing the UI size before host creates a window for it) + + Value must match 1x scale factor. + + When this macro is defined, the companion DISTRHO_UI_DEFAULT_WIDTH macro must be defined as well. + */ +#define DISTRHO_UI_DEFAULT_HEIGHT 300 + +/** + Whether the %UI uses NanoVG for drawing instead of the default raw OpenGL calls.@n + When enabled your %UI instance will subclass @ref NanoWidget instead of @ref Widget. + */ +#define DISTRHO_UI_USE_NANOVG 1 + +/** + Whether the %UI is resizable to any size by the user.@n + By default this is false, and resizing is only allowed under the plugin UI control,@n + Enabling this options makes it possible for the user to resize the plugin UI at anytime. + @see UI::setGeometryConstraints(uint, uint, bool, bool) + */ +#define DISTRHO_UI_USER_RESIZABLE 1 + +/** + The %UI URI when exporting in LV2 format.@n + By default this is set to @ref DISTRHO_PLUGIN_URI with "#UI" as suffix. + */ +#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" + +/** + Custom LV2 category for the plugin.@n + This is a single string, and can be one of the following values: + + - lv2:AllpassPlugin + - lv2:AmplifierPlugin + - lv2:AnalyserPlugin + - lv2:BandpassPlugin + - lv2:ChorusPlugin + - lv2:CombPlugin + - lv2:CompressorPlugin + - lv2:ConstantPlugin + - lv2:ConverterPlugin + - lv2:DelayPlugin + - lv2:DistortionPlugin + - lv2:DynamicsPlugin + - lv2:EQPlugin + - lv2:EnvelopePlugin + - lv2:ExpanderPlugin + - lv2:FilterPlugin + - lv2:FlangerPlugin + - lv2:FunctionPlugin + - lv2:GatePlugin + - lv2:GeneratorPlugin + - lv2:HighpassPlugin + - lv2:InstrumentPlugin + - lv2:LimiterPlugin + - lv2:LowpassPlugin + - lv2:MIDIPlugin + - lv2:MixerPlugin + - lv2:ModulatorPlugin + - lv2:MultiEQPlugin + - lv2:OscillatorPlugin + - lv2:ParaEQPlugin + - lv2:PhaserPlugin + - lv2:PitchPlugin + - lv2:ReverbPlugin + - lv2:SimulatorPlugin + - lv2:SpatialPlugin + - lv2:SpectralPlugin + - lv2:UtilityPlugin + - lv2:WaveshaperPlugin + + See http://lv2plug.in/ns/lv2core for more information. + */ +#define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:Plugin" + +/** + Custom VST3 categories for the plugin.@n + This is a single concatenated string of categories, separated by a @c |. + + Each effect category can be one of the following values: + + - Fx + - Fx|Ambisonics + - Fx|Analyzer + - Fx|Delay + - Fx|Distortion + - Fx|Dynamics + - Fx|EQ + - Fx|Filter + - Fx|Instrument + - Fx|Instrument|External + - Fx|Spatial + - Fx|Generator + - Fx|Mastering + - Fx|Modulation + - Fx|Network + - Fx|Pitch Shift + - Fx|Restoration + - Fx|Reverb + - Fx|Surround + - Fx|Tools + + Each instrument category can be one of the following values: + + - Instrument + - Instrument|Drum + - Instrument|External + - Instrument|Piano + - Instrument|Sampler + - Instrument|Synth + - Instrument|Synth|Sampler + + And extra categories possible for any plugin type: + + - Mono + - Stereo + */ +#define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Stereo" + +/** + Custom CLAP features for the plugin.@n + This is a list of features defined as a string array body, without the terminating @c , or nullptr. + + A top-level category can be set as feature and be one of the following values: + + - instrument + - audio-effect + - note-effect + - analyzer + + The following sub-categories can also be set: + + - synthesizer + - sampler + - drum + - drum-machine + + - filter + - phaser + - equalizer + - de-esser + - phase-vocoder + - granular + - frequency-shifter + - pitch-shifter + + - distortion + - transient-shaper + - compressor + - limiter + + - flanger + - chorus + - delay + - reverb + + - tremolo + - glitch + + - utility + - pitch-correction + - restoration + + - multi-effects + + - mixing + - mastering + + And finally the following audio capabilities can be set: + + - mono + - stereo + - surround + - ambisonic +*/ +#define DISTRHO_PLUGIN_CLAP_FEATURES "audio-effect", "stereo" + +/** + The plugin id when exporting in CLAP format, in reverse URI form. + @note This macro is required when building CLAP plugins +*/ +#define DISTRHO_PLUGIN_CLAP_ID "studio.kx.distrho.effect" + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin Macros */ + +/** + @defgroup ExtraPluginMacros Extra Plugin Macros + + C Macros to customize DPF behaviour. + + These are macros that do not set plugin features or information, but instead change DPF internals. + They are all optional. + + Unless stated otherwise, values are assumed to be a simple/empty define. + @{ + */ + +/** + Whether to enable runtime plugin tests.@n + This will check, during initialization of the plugin, if parameters, programs and states are setup properly.@n + Useful to enable as part of CI, can safely be skipped.@n + Under DPF makefiles this can be enabled by using `make DPF_RUNTIME_TESTING=true`. + + @note Some checks are only available with the GCC compiler, + for detecting if a virtual function has been reimplemented. + */ +#define DPF_RUNTIME_TESTING + +/** + Whether to show parameter outputs in the VST2 plugins.@n + This is disabled (unset) by default, as the VST2 format has no notion of read-only parameters. + */ +#define DPF_VST_SHOW_PARAMETER_OUTPUTS + +/** + Disable all file browser related code.@n + Must be set as compiler macro when building DGL. (e.g. `CXXFLAGS="-DDGL_FILE_BROWSER_DISABLED"`) + */ +#define DGL_FILE_BROWSER_DISABLED + +/** + Disable resource files, like internally used fonts.@n + Must be set as compiler macro when building DGL. (e.g. `CXXFLAGS="-DDGL_NO_SHARED_RESOURCES"`) + */ +#define DGL_NO_SHARED_RESOURCES + +/** + Whether to use OpenGL3 instead of the default OpenGL2 compatility profile. + Under DPF makefiles this can be enabled by using `make USE_OPENGL3=true` on the dgl build step. + + @note This is experimental and incomplete, contributions are welcome and appreciated. + */ +#define DGL_USE_OPENGL3 + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Namespace Macros */ + +/** + @defgroup NamespaceMacros Namespace Macros + + C Macros to use and customize DPF namespaces. + + These are macros that serve as helpers around C++ namespaces, and also as a way to set custom namespaces during a build. + @{ + */ + +/** + Compiler macro that sets the C++ namespace for DPF plugins.@n + If unset during build, it will use the name @b DISTRHO by default. + + Unless you know exactly what you are doing, you do need to modify this value.@n + The only probable useful case for customizing it is if you are building a big collection of very similar DPF-based plugins in your application.@n + For example, having 2 different versions of the same plugin that should behave differently but still exist within the same binary. + + On macOS (where due to Objective-C restrictions all code that interacts with Cocoa needs to be in a flat namespace), + DPF will automatically use the plugin name as prefix to flat namespace functions in order to avoid conflicts. + + So, basically, it is DPF's job to make sure plugin binaries are 100% usable as-is.@n + You typically do not need to care about this at all. + */ +#define DISTRHO_NAMESPACE DISTRHO + +/** + Compiler macro that begins the C++ namespace for @b DISTRHO, as needed for (the DSP side of) plugins.@n + All classes in DPF are within this namespace except for UI/graphics stuff. + @see END_NAMESPACE_DISTRHO + */ +#define START_NAMESPACE_DISTRHO namespace DISTRHO_NAMESPACE { + +/** + Close the namespace previously started by @ref START_NAMESPACE_DISTRHO.@n + This doesn't really need to be a macro, it is just prettier/more consistent that way. + */ +#define END_NAMESPACE_DISTRHO } + +/** + Make the @b DISTRHO namespace available in the current function scope.@n + This is not set by default in order to avoid conflicts with commonly used names such as "Parameter" and "Plugin". + */ +#define USE_NAMESPACE_DISTRHO using namespace DISTRHO_NAMESPACE; + +/* TODO + * + * DISTRHO_MACRO_AS_STRING_VALUE + * DISTRHO_MACRO_AS_STRING + * DISTRHO_PROPER_CPP11_SUPPORT + * DONT_SET_USING_DISTRHO_NAMESPACE + * + */ + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DOXYGEN diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoPlugin.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoPlugin.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,401 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_HPP_INCLUDED +#define DISTRHO_PLUGIN_HPP_INCLUDED + +#include "DistrhoDetails.hpp" +#include "extra/LeakDetector.hpp" +#include "src/DistrhoPluginChecks.h" + +START_NAMESPACE_DISTRHO + +/* ------------------------------------------------------------------------------------------------------------ + * DPF Plugin */ + +/** + @defgroup MainClasses Main Classes + @{ + */ + +/** + DPF Plugin class from where plugin instances are created. + + The public methods (Host state) are called from the plugin to get or set host information.@n + They can be called from a plugin instance at anytime unless stated otherwise.@n + All other methods are to be implemented by the plugin and will be called by the host. + + Shortly after a plugin instance is created, the various init* functions will be called by the host.@n + Host will call activate() before run(), and deactivate() before the plugin instance is destroyed.@n + The host may call deactivate right after activate and vice-versa, but never activate/deactivate consecutively.@n + There is no limit on how many times run() is called, only that activate/deactivate will be called in between. + + The buffer size and sample rate values will remain constant between activate and deactivate.@n + Buffer size is only a hint though, the host might call run() with a higher or lower number of frames. + + Some of this class functions are only available according to some macros. + + DISTRHO_PLUGIN_WANT_PROGRAMS activates program related features.@n + When enabled you need to implement initProgramName() and loadProgram(). + + DISTRHO_PLUGIN_WANT_STATE activates internal state features.@n + When enabled you need to implement initState() and setState(). + + The process function run() changes wherever DISTRHO_PLUGIN_WANT_MIDI_INPUT is enabled or not.@n + When enabled it provides midi input events. + */ +class Plugin +{ +public: + /** + Plugin class constructor.@n + You must set all parameter values to their defaults, matching ParameterRanges::def. + */ + Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount); + + /** + Destructor. + */ + virtual ~Plugin(); + + /* -------------------------------------------------------------------------------------------------------- + * Host state */ + + /** + Get the current buffer size that will probably be used during processing, in frames.@n + This value will remain constant between activate and deactivate. + @note This value is only a hint!@n + Hosts might call run() with a higher or lower number of frames. + @see bufferSizeChanged(uint32_t) + */ + uint32_t getBufferSize() const noexcept; + + /** + Get the current sample rate that will be used during processing.@n + This value will remain constant between activate and deactivate. + @see sampleRateChanged(double) + */ + double getSampleRate() const noexcept; + + /** + Get the bundle path where the plugin resides. + Can return null if the plugin is not available in a bundle (if it is a single binary). + @see getBinaryFilename + @see getResourcePath + */ + const char* getBundlePath() const noexcept; + + /** + Check if this plugin instance is a "dummy" one used for plugin meta-data/information export.@n + When true no processing will be done, the plugin is created only to extract information.@n + In DPF, LADSPA/DSSI, VST2 and VST3 formats create one global instance per plugin binary + while LV2 creates one when generating turtle meta-data. + */ + bool isDummyInstance() const noexcept; + + /** + Check if this plugin instance is a "selftest" one used for automated plugin tests.@n + To enable this mode build with `DPF_RUNTIME_TESTING` macro defined (i.e. set as compiler build flag), + and run the JACK/Standalone executable with "selftest" as its only and single argument. + + A few basic DSP and UI tests will run in self-test mode, with once instance having this function returning true.@n + You can use this chance to do a few tests of your own as well. + */ + bool isSelfTestInstance() const noexcept; + +#if DISTRHO_PLUGIN_WANT_TIMEPOS + /** + Get the current host transport time position.@n + This function should only be called during run().@n + You can call this during other times, but the returned position is not guaranteed to be in sync. + @note TimePosition is not supported in LADSPA and DSSI plugin formats. + */ + const TimePosition& getTimePosition() const noexcept; +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY + /** + Change the plugin audio output latency to @a frames.@n + This function should only be called in the constructor, activate() and run(). + @note This function is only available if DISTRHO_PLUGIN_WANT_LATENCY is enabled. + */ + void setLatency(uint32_t frames) noexcept; +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + /** + Write a MIDI output event.@n + This function must only be called during run().@n + Returns false when the host buffer is full, in which case do not call this again until the next run(). + */ + bool writeMidiEvent(const MidiEvent& midiEvent) noexcept; +#endif + +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + /** + Check if parameter value change requests will work with the current plugin host. + @note This function is only available if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST is enabled. + @see requestParameterValueChange(uint32_t, float) + */ + bool canRequestParameterValueChanges() const noexcept; + + /** + Request a parameter value change from the host. + If successful, this function will automatically trigger a parameter update on the UI side as well. + This function can fail, for example if the host is busy with the parameter for read-only automation. + Some hosts simply do not have this functionality, which can be verified with canRequestParameterValueChanges(). + @note This function is only available if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST is enabled. + */ + bool requestParameterValueChange(uint32_t index, float value) noexcept; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + /** + Set state value and notify the host about the change.@n + This function will call `setState()` and also trigger an update on the UI side as necessary.@n + It must not be called during run.@n + The state must be host readable. + @note this function does nothing on DSSI plugin format, as DSSI only supports UI->DSP messages. + + TODO API under construction + */ + bool updateStateValue(const char* key, const char* value) noexcept; +#endif + +protected: + /* -------------------------------------------------------------------------------------------------------- + * Information */ + + /** + Get the plugin name.@n + Returns DISTRHO_PLUGIN_NAME by default. + */ + virtual const char* getName() const { return DISTRHO_PLUGIN_NAME; } + + /** + Get the plugin label.@n + This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters. + */ + virtual const char* getLabel() const = 0; + + /** + Get an extensive comment/description about the plugin.@n + Optional, returns nothing by default. + */ + virtual const char* getDescription() const { return ""; } + + /** + Get the plugin author/maker. + */ + virtual const char* getMaker() const = 0; + + /** + Get the plugin homepage.@n + Optional, returns nothing by default. + */ + virtual const char* getHomePage() const { return ""; } + + /** + Get the plugin license (a single line of text or a URL).@n + For commercial plugins this should return some short copyright information. + */ + virtual const char* getLicense() const = 0; + + /** + Get the plugin version, in hexadecimal. + @see d_version() + */ + virtual uint32_t getVersion() const = 0; + + /** + Get the plugin unique Id.@n + This value is used by LADSPA, DSSI and VST plugin formats. + @see d_cconst() + */ + virtual int64_t getUniqueId() const = 0; + + /* -------------------------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize the audio port @a index.@n + This function will be called once, shortly after the plugin is created. + */ + virtual void initAudioPort(bool input, uint32_t index, AudioPort& port); + + /** + Initialize the parameter @a index.@n + This function will be called once, shortly after the plugin is created. + */ + virtual void initParameter(uint32_t index, Parameter& parameter); + + /** + Initialize the port group @a groupId.@n + This function will be called once, + shortly after the plugin is created and all audio ports and parameters have been enumerated. + */ + virtual void initPortGroup(uint32_t groupId, PortGroup& portGroup); + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + /** + Set the name of the program @a index.@n + This function will be called once, shortly after the plugin is created.@n + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled. + */ + virtual void initProgramName(uint32_t index, String& programName) = 0; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + /** + Initialize the state @a index.@n + This function will be called once, shortly after the plugin is created.@n + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. + */ + virtual void initState(uint32_t index, State& state); + + DISTRHO_DEPRECATED_BY("initState(uint32_t,State&)") + virtual void initState(uint32_t, String&, String&) {} + + DISTRHO_DEPRECATED_BY("initState(uint32_t,State&)") + virtual bool isStateFile(uint32_t) { return false; } +#endif + + /* -------------------------------------------------------------------------------------------------------- + * Internal data */ + + /** + Get the current value of a parameter.@n + The host may call this function from any context, including realtime processing. + */ + virtual float getParameterValue(uint32_t index) const; + + /** + Change a parameter value.@n + The host may call this function from any context, including realtime processing.@n + When a parameter is marked as automatable, you must ensure no non-realtime operations are performed. + @note This function will only be called for parameter inputs. + */ + virtual void setParameterValue(uint32_t index, float value); + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + /** + Load a program.@n + The host may call this function from any context, including realtime processing.@n + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled. + */ + virtual void loadProgram(uint32_t index); +#endif + +#if DISTRHO_PLUGIN_WANT_FULL_STATE + /** + Get the value of an internal state.@n + The host may call this function from any non-realtime context.@n + Must be implemented by your plugin class if DISTRHO_PLUGIN_WANT_FULL_STATE is enabled. + @note The use of this function breaks compatibility with the DSSI format. + */ + virtual String getState(const char* key) const; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + /** + Change an internal state @a key to @a value.@n + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. + */ + virtual void setState(const char* key, const char* value); +#endif + + /* -------------------------------------------------------------------------------------------------------- + * Audio/MIDI Processing */ + + /** + Activate this plugin. + */ + virtual void activate() {} + + /** + Deactivate this plugin. + */ + virtual void deactivate() {} + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + /** + Run/process function for plugins with MIDI input. + @note Some parameters might be null if there are no audio inputs/outputs or MIDI events. + */ + virtual void run(const float** inputs, float** outputs, uint32_t frames, + const MidiEvent* midiEvents, uint32_t midiEventCount) = 0; +#else + /** + Run/process function for plugins without MIDI input. + @note Some parameters might be null if there are no audio inputs or outputs. + */ + virtual void run(const float** inputs, float** outputs, uint32_t frames) = 0; +#endif + + /* -------------------------------------------------------------------------------------------------------- + * Callbacks (optional) */ + + /** + Optional callback to inform the plugin about a buffer size change.@n + This function will only be called when the plugin is deactivated. + @note This value is only a hint!@n + Hosts might call run() with a higher or lower number of frames. + @see getBufferSize() + */ + virtual void bufferSizeChanged(uint32_t newBufferSize); + + /** + Optional callback to inform the plugin about a sample rate change.@n + This function will only be called when the plugin is deactivated. + @see getSampleRate() + */ + virtual void sampleRateChanged(double newSampleRate); + + // ------------------------------------------------------------------------------------------------------- + +private: + struct PrivateData; + PrivateData* const pData; + friend class PluginExporter; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Plugin) +}; + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Create plugin, entry point */ + +/** + @defgroup EntryPoints Entry Points + @{ + */ + +/** + Create an instance of the Plugin class.@n + This is the entry point for DPF plugins.@n + DPF will call this to either create an instance of your plugin for the host + or to fetch some initial information for internal caching. + */ +extern Plugin* createPlugin(); + +/** @} */ + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_PLUGIN_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoPluginMain.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoPluginMain.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,50 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "src/DistrhoPlugin.cpp" + +#if defined(DISTRHO_PLUGIN_TARGET_CARLA) +# include "src/DistrhoPluginCarla.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_CLAP) +# include "src/DistrhoPluginCLAP.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_JACK) +# include "src/DistrhoPluginJACK.cpp" +#elif (defined(DISTRHO_PLUGIN_TARGET_LADSPA) || defined(DISTRHO_PLUGIN_TARGET_DSSI)) +# include "src/DistrhoPluginLADSPA+DSSI.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_LV2) +# include "src/DistrhoPluginLV2.cpp" +# include "src/DistrhoPluginLV2export.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_VST2) +# include "src/DistrhoPluginVST2.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_VST3) +# include "src/DistrhoPluginVST3.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_SHARED) +DISTRHO_PLUGIN_EXPORT DISTRHO_NAMESPACE::Plugin* createSharedPlugin(); +DISTRHO_PLUGIN_EXPORT DISTRHO_NAMESPACE::Plugin* createSharedPlugin() { return DISTRHO_NAMESPACE::createPlugin(); } +#elif defined(DISTRHO_PLUGIN_TARGET_STATIC) +START_NAMESPACE_DISTRHO +Plugin* createStaticPlugin() { return createPlugin(); } +END_NAMESPACE_DISTRHO +#else +# error unsupported format +#endif + +#if defined(DISTRHO_PLUGIN_TARGET_JACK) +# define DISTRHO_IS_STANDALONE 1 +#else +# define DISTRHO_IS_STANDALONE 0 +#endif +#include "src/DistrhoUtils.cpp" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoPluginUtils.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoPluginUtils.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,215 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_UTILS_HPP_INCLUDED +#define DISTRHO_PLUGIN_UTILS_HPP_INCLUDED + +#include "DistrhoPlugin.hpp" + +START_NAMESPACE_DISTRHO + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin related utilities */ + +/** + @defgroup PluginRelatedUtilities Plugin related utilities + + @{ + */ + +/** + Get the absolute filename of the plugin DSP/UI binary.@n + Under certain systems or plugin formats the binary will be inside the plugin bundle.@n + Also, in some formats or setups, the DSP and UI binaries are in different files. +*/ +const char* getBinaryFilename(); + +/** + Get a string representation of the current plugin format we are building against.@n + This can be "JACK/Standalone", "LADSPA", "DSSI", "LV2", "VST2" or "VST3".@n + This string is purely informational and must not be used to tweak plugin behaviour. + + @note DO NOT CHANGE PLUGIN BEHAVIOUR BASED ON PLUGIN FORMAT. +*/ +const char* getPluginFormatName() noexcept; + +/** + Get the path to where resources are stored within the plugin bundle.@n + Requires a valid plugin bundle path. + + Returns a path inside the bundle where the plugin is meant to store its resources in.@n + This path varies between systems and plugin formats, like so: + + - LV2: /resources (can be stored anywhere inside the bundle really, DPF just uses this one) + - VST2 macOS: /Contents/Resources + - VST2 non-macOS: /resources (see note) + + The other non-mentioned formats do not support bundles.@n + + @note For VST2 on non-macOS systems, this assumes you have your plugin inside a dedicated directory + rather than only shipping with the binary (e.g. /myplugin.dll) +*/ +const char* getResourcePath(const char* bundlePath) noexcept; + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin helper classes */ + +/** + @defgroup PluginHelperClasses Plugin helper classes + + @{ + */ + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 +/** + Handy class to help keep audio buffer in sync with incoming MIDI events. + To use it, create a local variable (on the stack) and call nextEvent() until it returns false. + @code + for (AudioMidiSyncHelper amsh(outputs, frames, midiEvents, midiEventCount); amsh.nextEvent();) + { + float* const outL = amsh.outputs[0]; + float* const outR = amsh.outputs[1]; + + for (uint32_t i=0; i= totalFramesUsed, + firstEventFrame, totalFramesUsed, false); + + midiEventCount = 1; + while (midiEventCount < remainingMidiEventCount) + { + if (midiEvents[midiEventCount].frame == firstEventFrame) + ++midiEventCount; + else + break; + } + + frames = firstEventFrame - totalFramesUsed; + remainingFrames -= frames; + remainingMidiEventCount -= midiEventCount; + totalFramesUsed += frames; + return true; + } + +private: + /** @internal */ + uint32_t remainingFrames; + uint32_t remainingMidiEventCount; + uint32_t totalFramesUsed; +}; +#endif + +/** @} */ + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_PLUGIN_UTILS_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoStandaloneUtils.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoStandaloneUtils.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,99 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_STANDALONE_UTILS_HPP_INCLUDED +#define DISTRHO_STANDALONE_UTILS_HPP_INCLUDED + +#include "src/DistrhoDefines.h" + +START_NAMESPACE_DISTRHO + +/* ------------------------------------------------------------------------------------------------------------ + * Standalone plugin related utilities */ + +/** + @defgroup StandalonePluginRelatedUtilities Plugin related utilities + + When the plugin is running as standalone and JACK is not available, a native audio handling is in place. + It is a very simple handling, auto-connecting to the default audio interface for outputs. + + !!EXPERIMENTAL!! + + Still under development and testing. + + @{ + */ + +/** + Check if the current standalone is using native audio methods. + If this function returns false, you MUST NOT use any other function from this group. +*/ +bool isUsingNativeAudio() noexcept; + +/** + Check if the current standalone supports audio input. +*/ +bool supportsAudioInput(); + +/** + Check if the current standalone supports dynamic buffer size changes. +*/ +bool supportsBufferSizeChanges(); + +/** + Check if the current standalone supports MIDI. +*/ +bool supportsMIDI(); + +/** + Check if the current standalone has audio input enabled. +*/ +bool isAudioInputEnabled(); + +/** + Check if the current standalone has MIDI enabled. +*/ +bool isMIDIEnabled(); + +/** + Get the current buffer size. +*/ +uint getBufferSize(); + +/** + Request permissions to use audio input. + Only valid to call if audio input is supported but not currently enabled. +*/ +bool requestAudioInput(); + +/** + Request change to a new buffer size. +*/ +bool requestBufferSizeChange(uint newBufferSize); + +/** + Request permissions to use MIDI. + Only valid to call if MIDI is supported but not currently enabled. +*/ +bool requestMIDI(); + +/** @} */ + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_STANDALONE_UTILS_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoUI.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoUI.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,408 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_UI_HPP_INCLUDED +#define DISTRHO_UI_HPP_INCLUDED + +#include "DistrhoDetails.hpp" +#include "extra/LeakDetector.hpp" +#include "src/DistrhoPluginChecks.h" + +#ifdef DGL_CAIRO +# include "Cairo.hpp" +#endif +#ifdef DGL_OPENGL +# include "OpenGL.hpp" +#endif +#ifdef DGL_VULKAN +# include "Vulkan.hpp" +#endif + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include "../dgl/Base.hpp" +# include "extra/ExternalWindow.hpp" +typedef DISTRHO_NAMESPACE::ExternalWindow UIWidget; +#elif DISTRHO_UI_USE_CUSTOM +# include DISTRHO_UI_CUSTOM_INCLUDE_PATH +typedef DISTRHO_UI_CUSTOM_WIDGET_TYPE UIWidget; +#elif DISTRHO_UI_USE_CAIRO +# include "../dgl/Cairo.hpp" +typedef DGL_NAMESPACE::CairoTopLevelWidget UIWidget; +#elif DISTRHO_UI_USE_NANOVG +# include "../dgl/NanoVG.hpp" +typedef DGL_NAMESPACE::NanoTopLevelWidget UIWidget; +#else +# include "../dgl/TopLevelWidget.hpp" +typedef DGL_NAMESPACE::TopLevelWidget UIWidget; +#endif + +#if DISTRHO_UI_FILE_BROWSER +# include "extra/FileBrowserDialog.hpp" +#endif +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include +#endif + +START_NAMESPACE_DISTRHO + +class PluginWindow; + +/* ------------------------------------------------------------------------------------------------------------ + * DPF UI */ + +/** + @addtogroup MainClasses + @{ + */ + +/** + DPF UI class from where UI instances are created. + + @note You must call setSize during construction, + @TODO Detailed information about this class. + */ +class UI : public UIWidget +{ +public: + /** + UI class constructor. + The UI should be initialized to a default state that matches the plugin side. + + When @a automaticallyScale is set to true, DPF will automatically scale up the UI + to fit the host/desktop scale factor.@n + It assumes aspect ratio is meant to be kept. + Manually call setGeometryConstraints instead if keeping UI aspect ratio is not required. + */ + UI(uint width = 0, uint height = 0, bool automaticallyScaleAndSetAsMinimumSize = false); + + /** + Destructor. + */ + ~UI() override; + + /* -------------------------------------------------------------------------------------------------------- + * Host state */ + + /** + Check if this UI window is resizable (by the user or window manager). + There are situations where an UI supports resizing but the plugin host does not, so this could return false. + + You might want to add a resize handle for such cases, so the user is still allowed to resize the window. + (programatically resizing a window is always possible, but the same is not true for the window manager) + */ + bool isResizable() const noexcept; + + /** + Get the color used for UI background (i.e. window color) in RGBA format. + Returns 0 by default, in case of error or lack of host support. + + The following example code can be use to extract individual colors: + ``` + const int red = (bgColor >> 24) & 0xff; + const int green = (bgColor >> 16) & 0xff; + const int blue = (bgColor >> 8) & 0xff; + ``` + */ + uint getBackgroundColor() const noexcept; + + /** + Get the color used for UI foreground (i.e. text color) in RGBA format. + Returns 0xffffffff by default, in case of error or lack of host support. + + The following example code can be use to extract individual colors: + ``` + const int red = (fgColor >> 24) & 0xff; + const int green = (fgColor >> 16) & 0xff; + const int blue = (fgColor >> 8) & 0xff; + ``` + */ + uint getForegroundColor() const noexcept; + + /** + Get the current sample rate used in plugin processing. + @see sampleRateChanged(double) + */ + double getSampleRate() const noexcept; + + /** + Get the bundle path where the UI resides.@n + Can return null if the UI is not available in a bundle (if it is a single binary). + @see getBinaryFilename + */ + const char* getBundlePath() const noexcept; + + /** + editParameter. + + Touch/pressed-down event. + Lets the host know the user is tweaking a parameter. + Required in some hosts to record automation. + */ + void editParameter(uint32_t index, bool started); + + /** + setParameterValue. + + Change a parameter value in the Plugin. + */ + void setParameterValue(uint32_t index, float value); + +#if DISTRHO_PLUGIN_WANT_STATE + /** + setState. + @TODO Document this. + */ + void setState(const char* key, const char* value); + + /** + Request a new file from the host, matching the properties of a state key.@n + This will use the native host file browser if available, otherwise a DPF built-in file browser is used.@n + Response will be sent asynchronously to stateChanged, with the matching key and the new file as the value.@n + It is not possible to know if the action was cancelled by the user. + + @return Success if a file-browser was opened, otherwise false. + @note You cannot request more than one file at a time. + */ + bool requestStateFile(const char* key); +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + /** + Send a single MIDI note from the UI to the plugin DSP side.@n + A note with zero velocity will be sent as note-off (MIDI 0x80), otherwise note-on (MIDI 0x90). + */ + void sendNote(uint8_t channel, uint8_t note, uint8_t velocity); +#endif + +#if DISTRHO_UI_FILE_BROWSER + /** + Open a file browser dialog with this window as transient parent.@n + A few options can be specified to setup the dialog. + + If a path is selected, onFileSelected() will be called with the user chosen path. + If the user cancels or does not pick a file, onFileSelected() will be called with nullptr as filename. + + This function does not block the event loop. + + @note This is exactly the same API as provided by the Window class, + but redeclared here so that non-embed/DGL based UIs can still use file browser related functions. + */ + bool openFileBrowser(const DISTRHO_NAMESPACE::FileBrowserOptions& options = FileBrowserOptions()); +#endif + +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + /* -------------------------------------------------------------------------------------------------------- + * Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! */ + + /** + getPluginInstancePointer. + @TODO Document this. + */ + void* getPluginInstancePointer() const noexcept; +#endif + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + /* -------------------------------------------------------------------------------------------------------- + * External UI helpers */ + + /** + Get the bundle path that will be used for the next UI. + @note: This function is only valid during createUI(), + it will return null when called from anywhere else. + */ + static const char* getNextBundlePath() noexcept; + + /** + Get the scale factor that will be used for the next UI. + @note: This function is only valid during createUI(), + it will return 1.0 when called from anywhere else. + */ + static double getNextScaleFactor() noexcept; + +# if DISTRHO_PLUGIN_HAS_EMBED_UI + /** + Get the Window Id that will be used for the next created window. + @note: This function is only valid during createUI(), + it will return 0 when called from anywhere else. + */ + static uintptr_t getNextWindowId() noexcept; +# endif +#endif + +protected: + /* -------------------------------------------------------------------------------------------------------- + * DSP/Plugin Callbacks */ + + /** + A parameter has changed on the plugin side.@n + This is called by the host to inform the UI about parameter changes. + */ + virtual void parameterChanged(uint32_t index, float value) = 0; + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + /** + A program has been loaded on the plugin side.@n + This is called by the host to inform the UI about program changes. + */ + virtual void programLoaded(uint32_t index) = 0; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + /** + A state has changed on the plugin side.@n + This is called by the host to inform the UI about state changes. + */ + virtual void stateChanged(const char* key, const char* value) = 0; +#endif + + /* -------------------------------------------------------------------------------------------------------- + * DSP/Plugin Callbacks (optional) */ + + /** + Optional callback to inform the UI about a sample rate change on the plugin side. + @see getSampleRate() + */ + virtual void sampleRateChanged(double newSampleRate); + + /* -------------------------------------------------------------------------------------------------------- + * UI Callbacks (optional) */ + + /** + UI idle function, called to give idle time to the plugin UI directly from the host. + This is called right after OS event handling and Window idle events (within the same cycle). + There are no guarantees in terms of timing. + @see addIdleCallback(IdleCallback*, uint). + */ + virtual void uiIdle() {} + + /** + Window scale factor function, called when the scale factor changes. + This function is for plugin UIs to be able to override Window::onScaleFactorChanged(double). + + The default implementation does nothing. + WARNING function needs a proper name + */ + virtual void uiScaleFactorChanged(double scaleFactor); + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + /** + Get the types available for the data in a clipboard. + Must only be called within the context of uiClipboardDataOffer. + */ + std::vector getClipboardDataOfferTypes(); + + /** + Window clipboard data offer function, called when clipboard has data present, possibly with several datatypes. + While handling this event, the data types can be investigated with getClipboardDataOfferTypes() to decide whether to accept the offer. + + Reimplement and return a non-zero id to accept the clipboard data offer for a particular type. + UIs must ignore any type they do not recognize. + + The default implementation accepts the "text/plain" mimetype. + */ + virtual uint32_t uiClipboardDataOffer(); + + /** + Windows focus function, called when the window gains or loses the keyboard focus. + This function is for plugin UIs to be able to override Window::onFocus(bool, CrossingMode). + + The default implementation does nothing. + */ + virtual void uiFocus(bool focus, DGL_NAMESPACE::CrossingMode mode); + + /** + Window reshape function, called when the window is resized. + This function is for plugin UIs to be able to override Window::onReshape(uint, uint). + + The plugin UI size will be set right after this function. + The default implementation sets up the drawing context where necessary. + + You should almost never need to override this function. + The most common exception is custom OpenGL setup, but only really needed for custom OpenGL drawing code. + */ + virtual void uiReshape(uint width, uint height); +#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + +#if DISTRHO_UI_FILE_BROWSER + /** + Window file selected function, called when a path is selected by the user, as triggered by openFileBrowser(). + This function is for plugin UIs to be able to override Window::onFileSelected(const char*). + + This action happens after the user confirms the action, so the file browser dialog will be closed at this point. + The default implementation does nothing. + + If you need to use files as plugin state, please setup and use states with kStateIsFilenamePath instead. + */ + virtual void uiFileBrowserSelected(const char* filename); +#endif + + /* -------------------------------------------------------------------------------------------------------- + * UI Resize Handling, internal */ + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + /** + External Window resize function, called when the window is resized. + This is overriden here so the host knows when the UI is resized by you. + @see ExternalWindow::sizeChanged(uint,uint) + */ + void sizeChanged(uint width, uint height) override; +#else + /** + Widget resize function, called when the widget is resized. + This is overriden here so the host knows when the UI is resized by you. + @see Widget::onResize(const ResizeEvent&) + */ + void onResize(const ResizeEvent& ev) override; +#endif + + // ------------------------------------------------------------------------------------------------------- + +private: + struct PrivateData; + PrivateData* const uiData; + friend class PluginWindow; + friend class UIExporter; +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + /** @internal */ + void requestSizeChange(uint width, uint height) override; +#endif + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI) +}; + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * Create UI, entry point */ + +/** + @addtogroup EntryPoints + @{ + */ + +/** + createUI. + @TODO Document this. + */ +extern UI* createUI(); + +/** @} */ + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_UI_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoUIMain.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoUIMain.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,58 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "src/DistrhoUI.cpp" + +// we might be building a plugin with external UI, which works on most formats except VST2/3 +#if ! DISTRHO_PLUGIN_HAS_UI && ! defined(DISTRHO_PLUGIN_VST_HPP_INCLUDED) +# error Trying to build UI without DISTRHO_PLUGIN_HAS_UI set to 1 +#endif + +#if DISTRHO_PLUGIN_HAS_UI + +#if defined(DISTRHO_PLUGIN_TARGET_CARLA) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1 +#elif defined(DISTRHO_PLUGIN_TARGET_CLAP) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1 +#elif defined(DISTRHO_PLUGIN_TARGET_JACK) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1 +#elif defined(DISTRHO_PLUGIN_TARGET_DSSI) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 0 +# include "src/DistrhoUIDSSI.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_LV2) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT DISTRHO_PLUGIN_WANT_DIRECT_ACCESS +# include "src/DistrhoUILV2.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_VST2) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1 +#elif defined(DISTRHO_PLUGIN_TARGET_VST3) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1 +# include "src/DistrhoUIVST3.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_SHARED) || defined(DISTRHO_PLUGIN_TARGET_STATIC) +# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1 +#else +# error unsupported format +#endif + +#if !DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT +# ifdef DISTRHO_PLUGIN_TARGET_DSSI +# define DISTRHO_IS_STANDALONE 1 +# else +# define DISTRHO_IS_STANDALONE 0 +# endif +# include "src/DistrhoUtils.cpp" +#endif + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoUI_macOS.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoUI_macOS.mm Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,54 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +// A few utils declared in DistrhoUI.cpp but defined here because they use Obj-C + +#include "DistrhoDetails.hpp" +#include "src/DistrhoPluginChecks.h" +#include "src/DistrhoDefines.h" + +#if DISTRHO_UI_FILE_BROWSER || DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# import +#endif + +#if DISTRHO_UI_FILE_BROWSER +# define DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED +# define FILE_BROWSER_DIALOG_NAMESPACE DISTRHO_NAMESPACE +# define FILE_BROWSER_DIALOG_DISTRHO_NAMESPACE +START_NAMESPACE_DISTRHO +# include "extra/FileBrowserDialogImpl.hpp" +END_NAMESPACE_DISTRHO +# include "extra/FileBrowserDialogImpl.cpp" +#endif + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include +# include +START_NAMESPACE_DISTRHO +double getDesktopScaleFactor(const uintptr_t parentWindowHandle) +{ + // allow custom scale for testing + if (const char* const scale = getenv("DPF_SCALE_FACTOR")) + return std::max(1.0, std::atof(scale)); + + if (NSView* const parentView = (NSView*)parentWindowHandle) + if (NSWindow* const parentWindow = [parentView window]) + return [parentWindow screen].backingScaleFactor; + + return [NSScreen mainScreen].backingScaleFactor; +} +END_NAMESPACE_DISTRHO +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/DistrhoUtils.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/DistrhoUtils.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,324 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_UTILS_HPP_INCLUDED +#define DISTRHO_UTILS_HPP_INCLUDED + +#include "src/DistrhoDefines.h" + +#include +#include +#include +#include + +#include +#include + +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# include +#else +# include +#endif + +#if defined(DISTRHO_OS_WINDOWS) && defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + +#if ! defined(CARLA_MATH_UTILS_HPP_INCLUDED) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) +namespace std { +inline float fmin(float __x, float __y) + { return __builtin_fminf(__x, __y); } +inline float fmax(float __x, float __y) + { return __builtin_fmaxf(__x, __y); } +inline float rint(float __x) + { return __builtin_rintf(__x); } +inline float round(float __x) + { return __builtin_roundf(__x); } +} +#endif + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#define DISTRHO_MACRO_AS_STRING_VALUE(MACRO) #MACRO +#define DISTRHO_MACRO_AS_STRING(MACRO) DISTRHO_MACRO_AS_STRING_VALUE(MACRO) + +/* -------------------------------------------------------------------------------------------------------------------- + * misc functions */ + +/** + @defgroup MiscellaneousFunctions Miscellaneous functions + + @{ + */ + +/** + Return a 32-bit number from 4 8-bit numbers.@n + The return type is a int64_t for better compatibility with plugin formats that use such numbers. + */ +static inline constexpr +int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept +{ + return (a << 24) | (b << 16) | (c << 8) | (d << 0); +} + +/** + Return an hexadecimal representation of a MAJ.MIN.MICRO version number. + */ +static inline constexpr +uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro) noexcept +{ + return uint32_t(major << 16) | uint32_t(minor << 8) | (micro << 0); +} + +/** + Dummy, no-op function. + */ +static inline +void d_pass() noexcept {} + +/** @} */ + +/* -------------------------------------------------------------------------------------------------------------------- + * string print functions */ + +/** + @defgroup StringPrintFunctions String print functions + + @{ + */ + +/** + Print a string to stdout with newline (gray color). + Does nothing if DEBUG is not defined. + */ +#ifndef DEBUG +# define d_debug(...) +#else +static inline +void d_debug(const char* const fmt, ...) noexcept +{ + try { + va_list args; + va_start(args, fmt); + std::fprintf(stdout, "\x1b[30;1m"); + std::vfprintf(stdout, fmt, args); + std::fprintf(stdout, "\x1b[0m\n"); + va_end(args); + } catch (...) {} +} +#endif + +/** + Print a string to stdout with newline. + */ +static inline +void d_stdout(const char* const fmt, ...) noexcept +{ + try { + va_list args; + va_start(args, fmt); + std::vfprintf(stdout, fmt, args); + std::fprintf(stdout, "\n"); + va_end(args); + } catch (...) {} +} + +/** + Print a string to stderr with newline. + */ +static inline +void d_stderr(const char* const fmt, ...) noexcept +{ + try { + va_list args; + va_start(args, fmt); + std::vfprintf(stderr, fmt, args); + std::fprintf(stderr, "\n"); + va_end(args); + } catch (...) {} +} + +/** + Print a string to stderr with newline (red color). + */ +static inline +void d_stderr2(const char* const fmt, ...) noexcept +{ + try { + va_list args; + va_start(args, fmt); + std::fprintf(stderr, "\x1b[31m"); + std::vfprintf(stderr, fmt, args); + std::fprintf(stderr, "\x1b[0m\n"); + va_end(args); + } catch (...) {} +} + +/** + Print a safe assertion error message. + */ +static inline +void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line); +} + +/** + Print a safe assertion error message, with 1 extra signed integer value. + */ +static inline +void d_safe_assert_int(const char* const assertion, const char* const file, + const int line, const int value) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value); +} + +/** + Print a safe assertion error message, with 1 extra unsigned integer value. + */ +static inline +void d_safe_assert_uint(const char* const assertion, const char* const file, + const int line, const uint value) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value); +} + +/** + Print a safe assertion error message, with 2 extra signed integer values. + */ +static inline +void d_safe_assert_int2(const char* const assertion, const char* const file, + const int line, const int v1, const int v2) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2); +} + +/** + Print a safe assertion error message, with 2 extra unsigned integer values. + */ +static inline +void d_safe_assert_uint2(const char* const assertion, const char* const file, + const int line, const uint v1, const uint v2) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2); +} + +/** + Print a safe assertion error message, with a custom error message. + */ +static inline +void d_custom_safe_assert(const char* const message, const char* const assertion, const char* const file, + const int line) noexcept +{ + d_stderr2("assertion failure: %s, condition \"%s\" in file %s, line %i", message, assertion, file, line); +} + +/** + Print a safe exception error message. + */ +static inline +void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept +{ + d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line); +} + +/** @} */ + +/* -------------------------------------------------------------------------------------------------------------------- + * math functions */ + +/** + @defgroup MathFunctions Math related functions + + @{ + */ + +/** + Safely compare two floating point numbers. + Returns true if they match. + */ +template +static inline constexpr +bool d_isEqual(const T& v1, const T& v2) +{ + return std::abs(v1-v2) < std::numeric_limits::epsilon(); +} + +/** + Safely compare two floating point numbers. + Returns true if they don't match. + */ +template +static inline constexpr +bool d_isNotEqual(const T& v1, const T& v2) +{ + return std::abs(v1-v2) >= std::numeric_limits::epsilon(); +} + +/** + Safely check if a floating point number is zero. + */ +template +static inline constexpr +bool d_isZero(const T& value) +{ + return std::abs(value) < std::numeric_limits::epsilon(); +} + +/** + Safely check if a floating point number is not zero. + */ +template +static inline constexpr +bool d_isNotZero(const T& value) +{ + return std::abs(value) >= std::numeric_limits::epsilon(); +} + +/** + Get next power of 2. + */ +static inline +uint32_t d_nextPowerOf2(uint32_t size) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(size > 0, 0); + + // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + --size; + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size |= size >> 8; + size |= size >> 16; + return ++size; +} + +/** @} */ + +/* -------------------------------------------------------------------------------------------------------------------- + * math functions */ + +#ifndef DONT_SET_USING_DISTRHO_NAMESPACE + // If your code uses a lot of DISTRHO classes, then this will obviously save you + // a lot of typing, but can be disabled by setting DONT_SET_USING_DISTRHO_NAMESPACE. + namespace DISTRHO_NAMESPACE {} + using namespace DISTRHO_NAMESPACE; +#endif + +#endif // DISTRHO_UTILS_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/Base64.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/Base64.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,150 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2016 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_BASE64_HPP_INCLUDED +#define DISTRHO_BASE64_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#include +#include + +// ----------------------------------------------------------------------- +// base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html + +/* + Copyright (C) 2004-2008 René Nyffenegger + + This source code is provided 'as-is', without any express or implied + warranty. In no event will the author 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 source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + 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 source code. + + 3. This notice may not be removed or altered from any source distribution. + + René Nyffenegger rene.nyffenegger@adp-gmbh.ch +*/ + +// ----------------------------------------------------------------------- +// Helpers + +#ifndef DOXYGEN +namespace DistrhoBase64Helpers { + +static const char* const kBase64Chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +static inline +uint8_t findBase64CharIndex(const char c) +{ + static const uint8_t kBase64CharsLen(static_cast(std::strlen(kBase64Chars))); + + for (uint8_t i=0; i d_getChunkFromBase64String(const char* const base64string) +{ + DISTRHO_SAFE_ASSERT_RETURN(base64string != nullptr, std::vector()); + + uint i=0, j=0; + uint charArray3[3], charArray4[4]; + + std::vector ret; + ret.reserve(std::strlen(base64string)*3/4 + 4); + + for (std::size_t l=0, len=std::strlen(base64string); l(c); + + if (i == 4) + { + for (i=0; i<4; ++i) + charArray4[i] = DistrhoBase64Helpers::findBase64CharIndex(static_cast(charArray4[i])); + + charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4); + charArray3[1] = ((charArray4[1] & 0xf) << 4) + ((charArray4[2] & 0x3c) >> 2); + charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3]; + + for (i=0; i<3; ++i) + ret.push_back(static_cast(charArray3[i])); + + i = 0; + } + } + + if (i != 0) + { + for (j=0; j(charArray4[j])); + + for (j=i; j<4; ++j) + charArray4[j] = 0; + + charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4); + charArray3[1] = ((charArray4[1] & 0xf) << 4) + ((charArray4[2] & 0x3c) >> 2); + charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3]; + + for (j=0; i>0 && j(charArray3[j])); + } + + return ret; +} + +// ----------------------------------------------------------------------- + +#endif // DISTRHO_BASE64_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/ExternalWindow.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/ExternalWindow.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,578 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED +#define DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED + +#include "String.hpp" + +#ifndef DISTRHO_OS_WINDOWS +# include +# include +# include +# include +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// ExternalWindow class + +/** + External Window class. + + This is a standalone TopLevelWidget/Window-compatible class, but without any real event handling. + Being compatible with TopLevelWidget/Window, it allows to be used as DPF UI target. + + It can be used to embed non-DPF things or to run a tool in a new process as the "UI". + The uiIdle() function will be called at regular intervals to keep UI running. + There are helper methods in place to launch external tools and keep track of its running state. + + External windows can be setup to run in 3 different modes: + * Embed: + Embed into the host UI, even-loop driven by the host. + This is basically working as a regular plugin UI, as you typically expect them to. + The plugin side does not get control over showing, hiding or closing the window (as usual for plugins). + No restrictions on supported plugin format, everything should work. + Requires DISTRHO_PLUGIN_HAS_EMBED_UI to be set to 1. + + * Semi-external: + The UI is not embed into the host, but the even-loop is still driven by it. + In this mode the host does not have control over the UI except for showing, hiding and setting transient parent. + It is possible to close the window from the plugin, the host will be notified of such case. + Host regularly calls isQuitting() to check if the UI got closed by the user or plugin side. + This mode is only possible in LV2 plugin formats, using lv2ui:showInterface extension. + + * Standalone: + The UI is not embed into the host or uses its event-loop, basically running as standalone. + The host only has control over showing and hiding the window, nothing else. + The UI is still free to close itself at any point. + DPF will keep calling isRunning() to check if it should keep the event-loop running. + Only possible in JACK and DSSI targets, as the UIs are literally standalone applications there. + + Please note that for non-embed windows, you cannot show the window yourself. + The plugin window is only allowed to hide or close itself, a "show" action needs to come from the host. + + A few callbacks are provided so that implementations do not need to care about checking for state changes. + They are not called on construction, but will be everytime something changes either by the host or the window itself. + */ +class ExternalWindow +{ + struct PrivateData; + +public: + /** + Constructor. + */ + explicit ExternalWindow() + : pData() {} + + /** + Constructor for DPF internal use. + */ + explicit ExternalWindow(const PrivateData& data) + : pData(data) {} + + /** + Destructor. + */ + virtual ~ExternalWindow() + { + DISTRHO_SAFE_ASSERT(!pData.visible); + } + + /* -------------------------------------------------------------------------------------------------------- + * ExternalWindow specific calls - Host side calls that you can reimplement for fine-grained funtionality */ + + /** + Check if main-loop is running. + This is used under standalone mode to check whether to keep things running. + Returning false from this function will stop the event-loop and close the window. + */ + virtual bool isRunning() const + { +#ifndef DISTRHO_OS_WINDOWS + if (ext.inUse) + return ext.isRunning(); +#endif + return isVisible(); + } + + /** + Check if we are about to close. + This is used when the event-loop is provided by the host to check if it should close the window. + It is also used in standalone mode right after isRunning() returns false to verify if window needs to be closed. + */ + virtual bool isQuitting() const + { +#ifndef DISTRHO_OS_WINDOWS + return ext.inUse ? ext.isQuitting : pData.isQuitting; +#else + return pData.isQuitting; +#endif + } + + /** + Get the "native" window handle. + This can be reimplemented in order to pass the native window to hosts that can use such informaton. + + Returned value type depends on the platform: + - HaikuOS: This is a pointer to a `BView`. + - MacOS: This is a pointer to an `NSView*`. + - Windows: This is a `HWND`. + - Everything else: This is an [X11] `Window`. + + @note Only available to override if DISTRHO_PLUGIN_HAS_EMBED_UI is set to 1. + */ + virtual uintptr_t getNativeWindowHandle() const noexcept + { + return 0; + } + + /** + Grab the keyboard input focus. + Typically you would setup OS-native methods to bring the window to front and give it focus. + Default implementation does nothing. + */ + virtual void focus() {} + + /* -------------------------------------------------------------------------------------------------------- + * TopLevelWidget-like calls - Information, can be called by either host or plugin */ + +#if DISTRHO_PLUGIN_HAS_EMBED_UI + /** + Whether this Window is embed into another (usually not DGL-controlled) Window. + */ + bool isEmbed() const noexcept + { + return pData.parentWindowHandle != 0; + } +#endif + + /** + Check if this window is visible. + @see setVisible(bool) + */ + bool isVisible() const noexcept + { + return pData.visible; + } + + /** + Whether this Window is running as standalone, that is, without being coupled to a host event-loop. + When in standalone mode, isRunning() is called to check if the event-loop should keep running. + */ + bool isStandalone() const noexcept + { + return pData.isStandalone; + } + + /** + Get width of this window. + Only relevant to hosts when the UI is embedded. + */ + uint getWidth() const noexcept + { + return pData.width; + } + + /** + Get height of this window. + Only relevant to hosts when the UI is embedded. + */ + uint getHeight() const noexcept + { + return pData.height; + } + + /** + Get the scale factor requested for this window. + This is purely informational, and up to developers to choose what to do with it. + */ + double getScaleFactor() const noexcept + { + return pData.scaleFactor; + } + + /** + Get the title of the window previously set with setTitle(). + This is typically displayed in the title bar or in window switchers. + */ + const char* getTitle() const noexcept + { + return pData.title; + } + +#if DISTRHO_PLUGIN_HAS_EMBED_UI + /** + Get the "native" window handle that this window should embed itself into. + Returned value type depends on the platform: + - HaikuOS: This is a pointer to a `BView`. + - MacOS: This is a pointer to an `NSView*`. + - Windows: This is a `HWND`. + - Everything else: This is an [X11] `Window`. + */ + uintptr_t getParentWindowHandle() const noexcept + { + return pData.parentWindowHandle; + } +#endif + + /** + Get the transient window that we should attach ourselves to. + TODO what id? also NSView* on macOS, or NSWindow? + */ + uintptr_t getTransientWindowId() const noexcept + { + return pData.transientWinId; + } + + /* -------------------------------------------------------------------------------------------------------- + * TopLevelWidget-like calls - actions called by either host or plugin */ + + /** + Hide window. + This is the same as calling setVisible(false). + Embed windows should never call this! + @see isVisible(), setVisible(bool) + */ + void hide() + { + setVisible(false); + } + + /** + Hide the UI and gracefully terminate. + Embed windows should never call this! + */ + virtual void close() + { + pData.isQuitting = true; + hide(); +#ifndef DISTRHO_OS_WINDOWS + if (ext.inUse) + terminateAndWaitForExternalProcess(); +#endif + } + + /** + Set width of this window. + Can trigger a sizeChanged callback. + Only relevant to hosts when the UI is embedded. + */ + void setWidth(uint width) + { + setSize(width, getHeight()); + } + + /** + Set height of this window. + Can trigger a sizeChanged callback. + Only relevant to hosts when the UI is embedded. + */ + void setHeight(uint height) + { + setSize(getWidth(), height); + } + + /** + Set size of this window using @a width and @a height values. + Can trigger a sizeChanged callback. + Only relevant to hosts when the UI is embedded. + */ + void setSize(uint width, uint height) + { + DISTRHO_SAFE_ASSERT_UINT_RETURN(width > 1, width,); + DISTRHO_SAFE_ASSERT_UINT_RETURN(height > 1, height,); + + if (pData.width == width && pData.height == height) + return; + + pData.width = width; + pData.height = height; + sizeChanged(width, height); + } + + /** + Set the title of the window, typically displayed in the title bar or in window switchers. + Can trigger a titleChanged callback. + Only relevant to hosts when the UI is not embedded. + */ + void setTitle(const char* title) + { + if (pData.title == title) + return; + + pData.title = title; + titleChanged(title); + } + + /** + Set geometry constraints for the Window when resized by the user. + */ + void setGeometryConstraints(uint minimumWidth, uint minimumHeight, bool keepAspectRatio = false) + { + DISTRHO_SAFE_ASSERT_UINT_RETURN(minimumWidth > 0, minimumWidth,); + DISTRHO_SAFE_ASSERT_UINT_RETURN(minimumHeight > 0, minimumHeight,); + + pData.minWidth = minimumWidth; + pData.minHeight = minimumHeight; + pData.keepAspectRatio = keepAspectRatio; + } + + /* -------------------------------------------------------------------------------------------------------- + * TopLevelWidget-like calls - actions called by the host */ + + /** + Show window. + This is the same as calling setVisible(true). + @see isVisible(), setVisible(bool) + */ + void show() + { + setVisible(true); + } + + /** + Set window visible (or not) according to @a visible. + @see isVisible(), hide(), show() + */ + void setVisible(bool visible) + { + if (pData.visible == visible) + return; + + pData.visible = visible; + visibilityChanged(visible); + } + + /** + Called by the host to set the transient parent window that we should attach ourselves to. + TODO what id? also NSView* on macOS, or NSWindow? + */ + void setTransientWindowId(uintptr_t winId) + { + if (pData.transientWinId == winId) + return; + + pData.transientWinId = winId; + transientParentWindowChanged(winId); + } + +protected: + /* -------------------------------------------------------------------------------------------------------- + * ExternalWindow special calls for running externals tools */ + + bool startExternalProcess(const char* args[]) + { +#ifndef DISTRHO_OS_WINDOWS + ext.inUse = true; + + return ext.start(args); +#else + (void)args; + return false; // TODO +#endif + } + + void terminateAndWaitForExternalProcess() + { +#ifndef DISTRHO_OS_WINDOWS + ext.isQuitting = true; + ext.terminateAndWait(); +#else + // TODO +#endif + } + + /* -------------------------------------------------------------------------------------------------------- + * ExternalWindow specific callbacks */ + + /** + A callback for when the window size changes. + @note WIP this might need to get fed back into the host somehow. + */ + virtual void sizeChanged(uint /* width */, uint /* height */) + { + // unused, meant for custom implementations + } + + /** + A callback for when the window title changes. + @note WIP this might need to get fed back into the host somehow. + */ + virtual void titleChanged(const char* /* title */) + { + // unused, meant for custom implementations + } + + /** + A callback for when the window visibility changes. + @note WIP this might need to get fed back into the host somehow. + */ + virtual void visibilityChanged(bool /* visible */) + { + // unused, meant for custom implementations + } + + /** + A callback for when the transient parent window changes. + */ + virtual void transientParentWindowChanged(uintptr_t /* winId */) + { + // unused, meant for custom implementations + } + +private: + friend class PluginWindow; + friend class UI; + +#ifndef DISTRHO_OS_WINDOWS + struct ExternalProcess { + bool inUse; + bool isQuitting; + mutable pid_t pid; + + ExternalProcess() + : inUse(false), + isQuitting(false), + pid(0) {} + + bool isRunning() const noexcept + { + if (pid <= 0) + return false; + + const pid_t p = ::waitpid(pid, nullptr, WNOHANG); + + if (p == pid || (p == -1 && errno == ECHILD)) + { + d_stdout("NOTICE: Child process exited while idle"); + pid = 0; + return false; + } + + return true; + } + + bool start(const char* args[]) + { + terminateAndWait(); + + pid = vfork(); + + switch (pid) + { + case 0: + execvp(args[0], (char**)args); + _exit(1); + return false; + + case -1: + d_stderr("Could not start external ui"); + return false; + + default: + return true; + } + } + + void terminateAndWait() + { + if (pid <= 0) + return; + + d_stdout("Waiting for external process to stop,,,"); + + bool sendTerm = true; + + for (pid_t p;;) + { + p = ::waitpid(pid, nullptr, WNOHANG); + + switch (p) + { + case 0: + if (sendTerm) + { + sendTerm = false; + ::kill(pid, SIGTERM); + } + break; + + case -1: + if (errno == ECHILD) + { + d_stdout("Done! (no such process)"); + pid = 0; + return; + } + break; + + default: + if (p == pid) + { + d_stdout("Done! (clean wait)"); + pid = 0; + return; + } + break; + } + + // 5 msec + usleep(5*1000); + } + } + } ext; +#endif + + struct PrivateData { + uintptr_t parentWindowHandle; + uintptr_t transientWinId; + uint width; + uint height; + double scaleFactor; + String title; + uint minWidth; + uint minHeight; + bool keepAspectRatio; + bool isQuitting; + bool isStandalone; + bool visible; + + PrivateData() + : parentWindowHandle(0), + transientWinId(0), + width(1), + height(1), + scaleFactor(1.0), + title(), + minWidth(0), + minHeight(0), + keepAspectRatio(false), + isQuitting(false), + isStandalone(false), + visible(false) {} + } pData; + + DISTRHO_DECLARE_NON_COPYABLE(ExternalWindow) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/FileBrowserDialog.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/FileBrowserDialog.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,28 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED +#define DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +START_NAMESPACE_DISTRHO + +#include "FileBrowserDialogImpl.hpp" + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/FileBrowserDialogImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/FileBrowserDialogImpl.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,844 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if !defined(DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED) && !defined(DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED) +# error bad include +#endif +#if !defined(FILE_BROWSER_DIALOG_DISTRHO_NAMESPACE) && !defined(FILE_BROWSER_DIALOG_DGL_NAMESPACE) +# error bad usage +#endif + +#include "ScopedPointer.hpp" +#include "String.hpp" + +#ifdef DISTRHO_OS_MAC +# import +#endif +#ifdef DISTRHO_OS_WASM +# include +#endif +#ifdef DISTRHO_OS_WINDOWS +# include +# include +# include +# include +# include +# include +#else +# include +#endif +#ifdef HAVE_DBUS +# include +#endif +#ifdef HAVE_X11 +# define DBLCLKTME 400 +# include "sofd/libsofd.h" +# include "sofd/libsofd.c" +#endif + +#ifdef FILE_BROWSER_DIALOG_DGL_NAMESPACE +START_NAMESPACE_DGL +using DISTRHO_NAMESPACE::ScopedPointer; +using DISTRHO_NAMESPACE::String; +#else +START_NAMESPACE_DISTRHO +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +// static pointer used for signal null/none action taken +static const char* const kSelectedFileCancelled = "__dpf_cancelled__"; + +#ifdef HAVE_DBUS +static constexpr bool isHexChar(const char c) noexcept +{ + return c >= '0' && c <= 'f' && (c <= '9' || (c >= 'A' && c <= 'F') || c >= 'a'); +} + +static constexpr int toHexChar(const char c) noexcept +{ + return c >= '0' && c <= '9' ? c - '0' : (c >= 'A' && c <= 'F' ? c - 'A' : c - 'a') + 10; +} +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +#ifdef DISTRHO_OS_WASM +# define DISTRHO_WASM_NAMESPACE_MACRO_HELPER(NS, SEP, FUNCTION) NS ## SEP ## FUNCTION +# define DISTRHO_WASM_NAMESPACE_MACRO(NS, FUNCTION) DISTRHO_WASM_NAMESPACE_MACRO_HELPER(NS, _, FUNCTION) +# define DISTRHO_WASM_NAMESPACE_HELPER(NS) #NS +# define DISTRHO_WASM_NAMESPACE(NS) DISTRHO_WASM_NAMESPACE_HELPER(NS) +# define fileBrowserSetPathNamespaced DISTRHO_WASM_NAMESPACE_MACRO(FILE_BROWSER_DIALOG_NAMESPACE, fileBrowserSetPath) +# define fileBrowserSetPathFuncName DISTRHO_WASM_NAMESPACE(FILE_BROWSER_DIALOG_NAMESPACE) "_fileBrowserSetPath" + +// FIXME use world class name as prefix +static bool openWebBrowserFileDialog(const char* const funcname, void* const handle) +{ + const char* const nameprefix = DISTRHO_WASM_NAMESPACE(FILE_BROWSER_DIALOG_NAMESPACE); + + return EM_ASM_INT({ + var canvasFileObjName = UTF8ToString($0) + "_file_open"; + var canvasFileOpenElem = document.getElementById(canvasFileObjName); + + var jsfuncname = UTF8ToString($1); + var jsfunc = Module.cwrap(jsfuncname, 'null', ['number', 'string']); + + if (canvasFileOpenElem) { + document.body.removeChild(canvasFileOpenElem); + } + + canvasFileOpenElem = document.createElement('input'); + canvasFileOpenElem.type = 'file'; + canvasFileOpenElem.id = canvasFileObjName; + canvasFileOpenElem.style.display = 'none'; + document.body.appendChild(canvasFileOpenElem); + + canvasFileOpenElem.onchange = function(e) { + if (!canvasFileOpenElem.files) { + jsfunc($2, ""); + return; + } + + var file = canvasFileOpenElem.files[0]; + var filename = '/' + file.name; + var reader = new FileReader(); + + reader.onloadend = function(e) { + var content = new Uint8Array(reader.result); + Module.FS.writeFile(filename, content); + jsfunc($2, filename); + }; + + reader.readAsArrayBuffer(file); + }; + + canvasFileOpenElem.click(); + return 1; + }, nameprefix, funcname, handle) != 0; +} + +static bool downloadWebBrowserFile(const char* const filename) +{ + const char* const nameprefix = DISTRHO_WASM_NAMESPACE(FILE_BROWSER_DIALOG_NAMESPACE); + + return EM_ASM_INT({ + var canvasFileObjName = UTF8ToString($0) + "_file_save"; + var jsfilename = UTF8ToString($1); + + var canvasFileSaveElem = document.getElementById(canvasFileObjName); + if (canvasFileSaveElem) { + // only 1 file save allowed at once + console.warn("One file save operation already in progress, refusing to open another"); + return 0; + } + + canvasFileSaveElem = document.createElement('a'); + canvasFileSaveElem.download = jsfilename; + canvasFileSaveElem.id = canvasFileObjName; + canvasFileSaveElem.style.display = 'none'; + document.body.appendChild(canvasFileSaveElem); + + var content = Module.FS.readFile('/' + jsfilename); + canvasFileSaveElem.href = URL.createObjectURL(new Blob([content])); + canvasFileSaveElem.click(); + + setTimeout(function() { + URL.revokeObjectURL(canvasFileSaveElem.href); + document.body.removeChild(canvasFileSaveElem); + }, 2000); + return 1; + }, nameprefix, filename) != 0; +} +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +struct FileBrowserData { + const char* selectedFile; + +#ifdef DISTRHO_OS_MAC + NSSavePanel* nsBasePanel; + NSOpenPanel* nsOpenPanel; +#endif +#ifdef HAVE_DBUS + DBusConnection* dbuscon; +#endif +#ifdef HAVE_X11 + Display* x11display; +#endif + +#ifdef DISTRHO_OS_WASM + char* defaultName; + bool saving; +#endif + +#ifdef DISTRHO_OS_WINDOWS + OPENFILENAMEW ofn; + volatile bool threadCancelled; + uintptr_t threadHandle; + std::vector fileNameW; + std::vector startDirW; + std::vector titleW; + const bool saving; + bool isEmbed; + + FileBrowserData(const bool save) + : selectedFile(nullptr), + threadCancelled(false), + threadHandle(0), + fileNameW(32768), + saving(save), + isEmbed(false) + { + std::memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = fileNameW.data(); + ofn.nMaxFile = (DWORD)fileNameW.size(); + } + + ~FileBrowserData() + { + if (cancelAndStop()) + free(); + } + + void setupAndStart(const bool embed, + const char* const startDir, + const char* const windowTitle, + const uintptr_t winId, + const FileBrowserOptions options) + { + isEmbed = embed; + + ofn.hwndOwner = (HWND)winId; + + ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR; + if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked) + ofn.Flags |= OFN_FORCESHOWHIDDEN; + + ofn.FlagsEx = 0x0; + if (options.buttons.showPlaces == FileBrowserOptions::kButtonInvisible) + ofn.FlagsEx |= OFN_EX_NOPLACESBAR; + + startDirW.resize(std::strlen(startDir) + 1); + if (MultiByteToWideChar(CP_UTF8, 0, startDir, -1, startDirW.data(), static_cast(startDirW.size()))) + ofn.lpstrInitialDir = startDirW.data(); + + titleW.resize(std::strlen(windowTitle) + 1); + if (MultiByteToWideChar(CP_UTF8, 0, windowTitle, -1, titleW.data(), static_cast(titleW.size()))) + ofn.lpstrTitle = titleW.data(); + + uint threadId; + threadCancelled = false; + threadHandle = _beginthreadex(nullptr, 0, _run, this, 0, &threadId); + } + + bool cancelAndStop() + { + threadCancelled = true; + + if (threadHandle == 0) + return true; + + // if previous dialog running, carefully close its window + const HWND owner = isEmbed ? GetParent(ofn.hwndOwner) : ofn.hwndOwner; + + if (owner != nullptr && owner != INVALID_HANDLE_VALUE) + { + const HWND window = GetWindow(owner, GW_HWNDFIRST); + + if (window != nullptr && window != INVALID_HANDLE_VALUE) + { + SendMessage(window, WM_SYSCOMMAND, SC_CLOSE, 0); + SendMessage(window, WM_CLOSE, 0, 0); + WaitForSingleObject((HANDLE)threadHandle, 5000); + } + } + + if (threadHandle == 0) + return true; + + // not good if thread still running, but let's close the handle anyway + CloseHandle((HANDLE)threadHandle); + threadHandle = 0; + return false; + } + + void run() + { + const char* nextFile = nullptr; + + if (saving ? GetSaveFileNameW(&ofn) : GetOpenFileNameW(&ofn)) + { + if (threadCancelled) + { + threadHandle = 0; + return; + } + + // back to UTF-8 + std::vector fileNameA(4 * 32768); + if (WideCharToMultiByte(CP_UTF8, 0, fileNameW.data(), -1, + fileNameA.data(), (int)fileNameA.size(), + nullptr, nullptr)) + { + nextFile = strdup(fileNameA.data()); + } + } + + if (threadCancelled) + { + threadHandle = 0; + return; + } + + if (nextFile == nullptr) + nextFile = kSelectedFileCancelled; + + selectedFile = nextFile; + threadHandle = 0; + } + + static unsigned __stdcall _run(void* const arg) + { + // CoInitializeEx(nullptr, COINIT_MULTITHREADED); + static_cast(arg)->run(); + // CoUninitialize(); + _endthreadex(0); + return 0; + } +#else // DISTRHO_OS_WINDOWS + FileBrowserData(const bool save) + : selectedFile(nullptr) + { +#ifdef DISTRHO_OS_MAC + if (save) + { + nsOpenPanel = nullptr; + nsBasePanel = [[NSSavePanel savePanel]retain]; + } + else + { + nsOpenPanel = [[NSOpenPanel openPanel]retain]; + nsBasePanel = nsOpenPanel; + } +#endif +#ifdef DISTRHO_OS_WASM + defaultName = nullptr; + saving = save; +#endif +#ifdef HAVE_DBUS + if ((dbuscon = dbus_bus_get(DBUS_BUS_SESSION, nullptr)) != nullptr) + dbus_connection_set_exit_on_disconnect(dbuscon, false); +#endif +#ifdef HAVE_X11 + x11display = XOpenDisplay(nullptr); +#endif + + // maybe unused + return; (void)save; + } + + ~FileBrowserData() + { +#ifdef DISTRHO_OS_MAC + [nsBasePanel release]; +#endif +#ifdef DISTRHO_OS_WASM + std::free(defaultName); +#endif +#ifdef HAVE_DBUS + if (dbuscon != nullptr) + dbus_connection_unref(dbuscon); +#endif +#ifdef HAVE_X11 + if (x11display != nullptr) + XCloseDisplay(x11display); +#endif + + free(); + } +#endif + + void free() + { + if (selectedFile == nullptr) + return; + + if (selectedFile == kSelectedFileCancelled || std::strcmp(selectedFile, kSelectedFileCancelled) == 0) + { + selectedFile = nullptr; + return; + } + + std::free(const_cast(selectedFile)); + selectedFile = nullptr; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +#ifdef DISTRHO_OS_WASM +extern "C" { +EMSCRIPTEN_KEEPALIVE +void fileBrowserSetPathNamespaced(FileBrowserHandle handle, const char* filename) +{ + handle->free(); + + if (filename != nullptr && filename[0] != '\0') + handle->selectedFile = strdup(filename); + else + handle->selectedFile = kSelectedFileCancelled; +} +} +#endif + +FileBrowserHandle fileBrowserCreate(const bool isEmbed, + const uintptr_t windowId, + const double scaleFactor, + const FileBrowserOptions& options) +{ + String startDir(options.startDir); + + if (startDir.isEmpty()) + { +#ifdef DISTRHO_OS_WINDOWS + if (char* const cwd = _getcwd(nullptr, 0)) +#else + if (char* const cwd = getcwd(nullptr, 0)) +#endif + { + startDir = cwd; + std::free(cwd); + } + } + + DISTRHO_SAFE_ASSERT_RETURN(startDir.isNotEmpty(), nullptr); + + if (! startDir.endsWith(DISTRHO_OS_SEP)) + startDir += DISTRHO_OS_SEP_STR; + + String windowTitle(options.title); + + if (windowTitle.isEmpty()) + windowTitle = "FileBrowser"; + + ScopedPointer handle(new FileBrowserData(options.saving)); + +#ifdef DISTRHO_OS_MAC +# if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 + // unsupported + d_stderr2("fileBrowserCreate is unsupported on macos < 10.8"); + return nullptr; +# else + NSSavePanel* const nsBasePanel = handle->nsBasePanel; + DISTRHO_SAFE_ASSERT_RETURN(nsBasePanel != nullptr, nullptr); + + if (! options.saving) + { + NSOpenPanel* const nsOpenPanel = handle->nsOpenPanel; + DISTRHO_SAFE_ASSERT_RETURN(nsOpenPanel != nullptr, nullptr); + + [nsOpenPanel setAllowsMultipleSelection:NO]; + [nsOpenPanel setCanChooseDirectories:NO]; + [nsOpenPanel setCanChooseFiles:YES]; + } + + [nsBasePanel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:startDir]]]; + + // TODO file filter using allowedContentTypes: [UTType] + + if (options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleChecked) + [nsBasePanel setAllowsOtherFileTypes:YES]; + if (options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked) + [nsBasePanel setShowsHiddenFiles:YES]; + + NSString* const titleString = [[NSString alloc] + initWithBytes:windowTitle + length:strlen(windowTitle) + encoding:NSUTF8StringEncoding]; + [nsBasePanel setTitle:titleString]; + + FileBrowserData* const handleptr = handle.get(); + + dispatch_async(dispatch_get_main_queue(), ^ + { + [nsBasePanel beginSheetModalForWindow:[(NSView*)windowId window] + completionHandler:^(NSModalResponse result) + { + if (result == NSModalResponseOK && [[nsBasePanel URL] isFileURL]) + { + NSString* const path = [[nsBasePanel URL] path]; + handleptr->selectedFile = strdup([path UTF8String]); + } + else + { + handleptr->selectedFile = kSelectedFileCancelled; + } + }]; + }); +# endif +#endif + +#ifdef DISTRHO_OS_WASM + if (options.saving) + { + const size_t len = options.defaultName != nullptr ? strlen(options.defaultName) : 0; + DISTRHO_SAFE_ASSERT_RETURN(len != 0, nullptr); + + char* const filename = static_cast(malloc(len + 2)); + filename[0] = '/'; + std::memcpy(filename + 1, options.defaultName, len + 1); + + handle->defaultName = strdup(options.defaultName); + handle->selectedFile = filename; + return handle.release(); + } + + const char* const funcname = fileBrowserSetPathFuncName; + if (openWebBrowserFileDialog(funcname, handle.get())) + return handle.release(); + + return nullptr; +#endif + +#ifdef DISTRHO_OS_WINDOWS + handle->setupAndStart(isEmbed, startDir, windowTitle, windowId, options); +#endif + +#ifdef HAVE_DBUS + // optional, can be null + DBusConnection* const dbuscon = handle->dbuscon; + + // https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.FileChooser + if (dbuscon != nullptr) + { + // if this is the first time we are calling into DBus, check if things are working + static bool checkAvailable = !dbus_bus_name_has_owner(dbuscon, "org.freedesktop.portal.Desktop", nullptr); + + if (checkAvailable) + { + checkAvailable = false; + + if (DBusMessage* const msg = dbus_message_new_method_call("org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.FileChooser", + "version")) + { + if (DBusMessage* const reply = dbus_connection_send_with_reply_and_block(dbuscon, msg, 250, nullptr)) + dbus_message_unref(reply); + + dbus_message_unref(msg); + } + } + + // Any subsquent calls should have this DBus service active + if (dbus_bus_name_has_owner(dbuscon, "org.freedesktop.portal.Desktop", nullptr)) + { + if (DBusMessage* const msg = dbus_message_new_method_call("org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.FileChooser", + options.saving ? "SaveFile" : "OpenFile")) + { + #ifdef HAVE_X11 + char windowIdStr[32]; + memset(windowIdStr, 0, sizeof(windowIdStr)); + snprintf(windowIdStr, sizeof(windowIdStr)-1, "x11:%llx", (ulonglong)windowId); + const char* windowIdStrPtr = windowIdStr; + #endif + + dbus_message_append_args(msg, + #ifdef HAVE_X11 + DBUS_TYPE_STRING, &windowIdStrPtr, + #endif + DBUS_TYPE_STRING, &windowTitle, + DBUS_TYPE_INVALID); + + DBusMessageIter iter, array; + dbus_message_iter_init_append(msg, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &array); + + { + DBusMessageIter dict, variant, variantArray; + const char* const current_folder_key = "current_folder"; + const char* const current_folder_val = startDir.buffer(); + + dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, nullptr, &dict); + dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, ¤t_folder_key); + dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, "ay", &variant); + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, "y", &variantArray); + dbus_message_iter_append_fixed_array(&variantArray, DBUS_TYPE_BYTE, + ¤t_folder_val, startDir.length()+1); + dbus_message_iter_close_container(&variant, &variantArray); + dbus_message_iter_close_container(&dict, &variant); + dbus_message_iter_close_container(&array, &dict); + } + + dbus_message_iter_close_container(&iter, &array); + + dbus_connection_send(dbuscon, msg, nullptr); + + dbus_message_unref(msg); + return handle.release(); + } + } + } +#endif + +#ifdef HAVE_X11 + Display* const x11display = handle->x11display; + DISTRHO_SAFE_ASSERT_RETURN(x11display != nullptr, nullptr); + + // unsupported at the moment + if (options.saving) + return nullptr; + + DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(0, startDir) == 0, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(x_fib_configure(1, windowTitle) == 0, nullptr); + + const int button1 = options.buttons.showHidden == FileBrowserOptions::kButtonVisibleChecked ? 1 + : options.buttons.showHidden == FileBrowserOptions::kButtonVisibleUnchecked ? 0 : -1; + const int button2 = options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleChecked ? 1 + : options.buttons.showPlaces == FileBrowserOptions::kButtonVisibleUnchecked ? 0 : -1; + const int button3 = options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleChecked ? 1 + : options.buttons.listAllFiles == FileBrowserOptions::kButtonVisibleUnchecked ? 0 : -1; + + x_fib_cfg_buttons(1, button1); + x_fib_cfg_buttons(2, button2); + x_fib_cfg_buttons(3, button3); + + if (x_fib_show(x11display, windowId, 0, 0, scaleFactor + 0.5) != 0) + return nullptr; +#endif + + return handle.release(); + + // might be unused + (void)isEmbed; + (void)windowId; + (void)scaleFactor; +} + +// -------------------------------------------------------------------------------------------------------------------- +// returns true if dialog was closed (with or without a file selection) + +bool fileBrowserIdle(const FileBrowserHandle handle) +{ +#ifdef HAVE_DBUS + if (DBusConnection* dbuscon = handle->dbuscon) + { + while (dbus_connection_dispatch(dbuscon) == DBUS_DISPATCH_DATA_REMAINS) {} + dbus_connection_read_write_dispatch(dbuscon, 0); + + if (DBusMessage* const message = dbus_connection_pop_message(dbuscon)) + { + const char* const interface = dbus_message_get_interface(message); + const char* const member = dbus_message_get_member(message); + + if (interface != nullptr && std::strcmp(interface, "org.freedesktop.portal.Request") == 0 + && member != nullptr && std::strcmp(member, "Response") == 0) + { + do { + DBusMessageIter iter; + dbus_message_iter_init(message, &iter); + + // starts with uint32 for return/exit code + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32); + + uint32_t ret = 1; + dbus_message_iter_get_basic(&iter, &ret); + + if (ret != 0) + break; + + // next must be array + dbus_message_iter_next(&iter); + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY); + + // open dict array + DBusMessageIter dictArray; + dbus_message_iter_recurse(&iter, &dictArray); + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dictArray) == DBUS_TYPE_DICT_ENTRY); + + // open containing dict + DBusMessageIter dict; + dbus_message_iter_recurse(&dictArray, &dict); + + // look for dict with string "uris" + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRING); + + const char* key = nullptr; + dbus_message_iter_get_basic(&dict, &key); + DISTRHO_SAFE_ASSERT_BREAK(key != nullptr); + + // keep going until we find it + while (std::strcmp(key, "uris") != 0) + { + key = nullptr; + dbus_message_iter_next(&dictArray); + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dictArray) == DBUS_TYPE_DICT_ENTRY); + + dbus_message_iter_recurse(&dictArray, &dict); + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRING); + + dbus_message_iter_get_basic(&dict, &key); + DISTRHO_SAFE_ASSERT_BREAK(key != nullptr); + } + + if (key == nullptr) + break; + + // then comes variant + dbus_message_iter_next(&dict); + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_VARIANT); + + DBusMessageIter variant; + dbus_message_iter_recurse(&dict, &variant); + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&variant) == DBUS_TYPE_ARRAY); + + // open variant array (variant type is string) + DBusMessageIter variantArray; + dbus_message_iter_recurse(&variant, &variantArray); + DISTRHO_SAFE_ASSERT_BREAK(dbus_message_iter_get_arg_type(&variantArray) == DBUS_TYPE_STRING); + + const char* value = nullptr; + dbus_message_iter_get_basic(&variantArray, &value); + + // and finally we have our dear value, just make sure it is local + DISTRHO_SAFE_ASSERT_BREAK(value != nullptr); + + if (const char* const localvalue = std::strstr(value, "file:///")) + { + if (char* const decodedvalue = strdup(localvalue + 7)) + { + for (char* s = decodedvalue; (s = std::strchr(s, '%')) != nullptr; ++s) + { + if (! isHexChar(s[1]) || ! isHexChar(s[2])) + continue; + + const int decodedNum = toHexChar(s[1]) * 0x10 + toHexChar(s[2]); + + char replacementChar; + switch (decodedNum) + { + case 0x20: replacementChar = ' '; break; + case 0x22: replacementChar = '\"'; break; + case 0x23: replacementChar = '#'; break; + case 0x25: replacementChar = '%'; break; + case 0x3c: replacementChar = '<'; break; + case 0x3e: replacementChar = '>'; break; + case 0x5b: replacementChar = '['; break; + case 0x5c: replacementChar = '\\'; break; + case 0x5d: replacementChar = ']'; break; + case 0x5e: replacementChar = '^'; break; + case 0x60: replacementChar = '`'; break; + case 0x7b: replacementChar = '{'; break; + case 0x7c: replacementChar = '|'; break; + case 0x7d: replacementChar = '}'; break; + case 0x7e: replacementChar = '~'; break; + default: continue; + } + + s[0] = replacementChar; + std::memmove(s + 1, s + 3, std::strlen(s) - 2); + } + + handle->selectedFile = decodedvalue; + } + } + + } while(false); + + if (handle->selectedFile == nullptr) + handle->selectedFile = kSelectedFileCancelled; + } + } + } +#endif + +#ifdef HAVE_X11 + Display* const x11display = handle->x11display; + + if (x11display == nullptr) + return false; + + XEvent event; + while (XPending(x11display) > 0) + { + XNextEvent(x11display, &event); + + if (x_fib_handle_events(x11display, &event) == 0) + continue; + + if (x_fib_status() > 0) + handle->selectedFile = x_fib_filename(); + else + handle->selectedFile = kSelectedFileCancelled; + + x_fib_close(x11display); + XCloseDisplay(x11display); + handle->x11display = nullptr; + break; + } +#endif + + return handle->selectedFile != nullptr; +} + +// -------------------------------------------------------------------------------------------------------------------- +// close sofd file dialog + +void fileBrowserClose(const FileBrowserHandle handle) +{ +#ifdef DISTRHO_OS_WASM + if (handle->saving && fileBrowserGetPath(handle) != nullptr) + downloadWebBrowserFile(handle->defaultName); +#endif + +#ifdef HAVE_X11 + if (Display* const x11display = handle->x11display) + x_fib_close(x11display); +#endif + + delete handle; +} + +// -------------------------------------------------------------------------------------------------------------------- +// get path chosen via sofd file dialog + +const char* fileBrowserGetPath(const FileBrowserHandle handle) +{ + if (const char* const selectedFile = handle->selectedFile) + if (selectedFile != kSelectedFileCancelled && std::strcmp(selectedFile, kSelectedFileCancelled) != 0) + return selectedFile; + + return nullptr; +} + +// -------------------------------------------------------------------------------------------------------------------- + +#ifdef FILE_BROWSER_DIALOG_DGL_NAMESPACE +END_NAMESPACE_DGL +#else +END_NAMESPACE_DISTRHO +#endif + +#undef FILE_BROWSER_DIALOG_DISTRHO_NAMESPACE +#undef FILE_BROWSER_DIALOG_DGL_NAMESPACE +#undef FILE_BROWSER_DIALOG_NAMESPACE + +#undef fileBrowserSetPathNamespaced +#undef fileBrowserSetPathFuncName diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/FileBrowserDialogImpl.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/FileBrowserDialogImpl.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,121 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if !defined(DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED) && !defined(DGL_FILE_BROWSER_DIALOG_HPP_INCLUDED) +# error bad include +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// File Browser Dialog stuff + +struct FileBrowserData; +typedef FileBrowserData* FileBrowserHandle; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + File browser options, for customizing the file browser dialog.@n + By default the file browser dialog will be work as "open file" in the current working directory. +*/ +struct FileBrowserOptions { + /** Whether we are saving, opening files otherwise (default) */ + bool saving; + + /** Default filename when saving, required in some platforms (basename without path separators) */ + const char* defaultName; + + /** Start directory, uses current working directory if null */ + const char* startDir; + + /** File browser dialog window title, uses "FileBrowser" if null */ + const char* title; + + // TODO file filter + + /** + File browser button state. + This allows to customize the behaviour of the file browse dialog buttons. + Note these are merely hints, not all systems support them. + */ + enum ButtonState { + kButtonInvisible, + kButtonVisibleUnchecked, + kButtonVisibleChecked, + }; + + /** + File browser buttons. + */ + struct Buttons { + /** Whether to list all files vs only those with matching file extension */ + ButtonState listAllFiles; + /** Whether to show hidden files */ + ButtonState showHidden; + /** Whether to show list of places (bookmarks) */ + ButtonState showPlaces; + + /** Constructor for default values */ + Buttons() + : listAllFiles(kButtonVisibleChecked), + showHidden(kButtonVisibleUnchecked), + showPlaces(kButtonVisibleChecked) {} + } buttons; + + /** Constructor for default values */ + FileBrowserOptions() + : saving(false), + defaultName(nullptr), + startDir(nullptr), + title(nullptr), + buttons() {} +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + Create a new file browser dialog. + + @p isEmbed: Whether the window this dialog belongs to is an embed/child window (needed to close dialog on Windows) + @p windowId: The native window id to attach this dialog to as transient parent (X11 Window, HWND or NSView*) + @p scaleFactor: Scale factor to use (only used on X11) + @p options: Extra options, optional + By default the file browser dialog will work as "open file" in the current working directory. +*/ +FileBrowserHandle fileBrowserCreate(bool isEmbed, + uintptr_t windowId, + double scaleFactor, + const FileBrowserOptions& options = FileBrowserOptions()); + +/** + Idle the file browser dialog handle.@n + Returns true if dialog was closed (with or without a file selection), + in which case this idle function must not be called anymore for this handle. + You can then call fileBrowserGetPath to know the selected file (or null if cancelled). +*/ +bool fileBrowserIdle(const FileBrowserHandle handle); + +/** + Close and free the file browser dialog, handle must not be used afterwards. +*/ +void fileBrowserClose(const FileBrowserHandle handle); + +/** + Get the path chosen by the user or null.@n + Should only be called after fileBrowserIdle returns true. +*/ +const char* fileBrowserGetPath(const FileBrowserHandle handle); + +// -------------------------------------------------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/LeakDetector.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/LeakDetector.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,166 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2016 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_LEAK_DETECTOR_HPP_INCLUDED +#define DISTRHO_LEAK_DETECTOR_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// The following code was based from juce-core LeakDetector class + +/** + Copyright (C) 2013 Raw Material Software Ltd. + + Permission is granted to use this software under the terms of the ISC license + http://www.isc.org/downloads/software-support-policy/isc-license/ + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, + OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + OF THIS SOFTWARE. +*/ + +/** A good old-fashioned C macro concatenation helper. + This combines two items (which may themselves be macros) into a single string, + avoiding the pitfalls of the ## macro operator. +*/ +#define DISTRHO_JOIN_MACRO_HELPER(a, b) a ## b +#define DISTRHO_JOIN_MACRO(item1, item2) DISTRHO_JOIN_MACRO_HELPER(item1, item2) + +#if defined(DEBUG) && !defined(NDEBUG) +/** This macro lets you embed a leak-detecting object inside a class.\n + To use it, simply declare a DISTRHO_LEAK_DETECTOR(YourClassName) inside a private section + of the class declaration. E.g. + \code + class MyClass + { + public: + MyClass(); + void blahBlah(); + + private: + DISTRHO_LEAK_DETECTOR(MyClass) + }; + \endcode +*/ +# define DISTRHO_LEAK_DETECTOR(ClassName) \ + friend class DISTRHO_NAMESPACE::LeakedObjectDetector; \ + static const char* getLeakedObjectClassName() noexcept { return #ClassName; } \ + DISTRHO_NAMESPACE::LeakedObjectDetector DISTRHO_JOIN_MACRO(leakDetector_, ClassName); + +# define DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ClassName) \ + DISTRHO_DECLARE_NON_COPYABLE(ClassName) \ + DISTRHO_LEAK_DETECTOR(ClassName) +#else +/** Don't use leak detection on release builds. */ +# define DISTRHO_LEAK_DETECTOR(ClassName) +# define DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ClassName) \ + DISTRHO_DECLARE_NON_COPYABLE(ClassName) +#endif + +//============================================================================== +/** + Embedding an instance of this class inside another class can be used as a low-overhead + way of detecting leaked instances. + + This class keeps an internal static count of the number of instances that are + active, so that when the app is shutdown and the static destructors are called, + it can check whether there are any left-over instances that may have been leaked. + + To use it, use the DISTRHO_LEAK_DETECTOR macro as a simple way to put one in your + class declaration. +*/ +template +class LeakedObjectDetector +{ +public: + //============================================================================== + LeakedObjectDetector() noexcept { ++(getCounter().numObjects); } + LeakedObjectDetector(const LeakedObjectDetector&) noexcept { ++(getCounter().numObjects); } + + ~LeakedObjectDetector() noexcept + { + if (--(getCounter().numObjects) < 0) + { + /** If you hit this, then you've managed to delete more instances of this class than you've + created.. That indicates that you're deleting some dangling pointers. + + Note that although this assertion will have been triggered during a destructor, it might + not be this particular deletion that's at fault - the incorrect one may have happened + at an earlier point in the program, and simply not been detected until now. + + Most errors like this are caused by using old-fashioned, non-RAII techniques for + your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays, + ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs! + */ + d_stderr2("*** Dangling pointer deletion! Class: '%s', Count: %i", getLeakedObjectClassName(), getCounter().numObjects); + } + } + +private: + //============================================================================== + class LeakCounter + { + public: + LeakCounter() noexcept + : numObjects(0) {} + + ~LeakCounter() noexcept + { + if (numObjects > 0) + { + /** If you hit this, then you've leaked one or more objects of the type specified by + the 'OwnerClass' template parameter - the name should have been printed by the line above. + + If you're leaking, it's probably because you're using old-fashioned, non-RAII techniques for + your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays, + ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs! + */ + d_stderr2("*** Leaked objects detected: %i instance(s) of class '%s'", numObjects, getLeakedObjectClassName()); + } + } + + // this should be an atomic... + volatile int numObjects; + }; + + static const char* getLeakedObjectClassName() noexcept + { + return OwnerClass::getLeakedObjectClassName(); + } + + static LeakCounter& getCounter() noexcept + { + static LeakCounter counter; + return counter; + } +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_LEAK_DETECTOR_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/LibraryUtils.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/LibraryUtils.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,136 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_LIBRARY_UTILS_HPP_INCLUDED +#define DISTRHO_LIBRARY_UTILS_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#ifdef DISTRHO_OS_WINDOWS +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include +typedef HMODULE lib_t; +#else +# include +typedef void* lib_t; +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// library related calls + +/* + * Open 'filename' library (must not be null). + * May return null, in which case "lib_error" has the error. + */ +static inline +lib_t lib_open(const char* const filename) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); + + try { +#ifdef DISTRHO_OS_WINDOWS + return ::LoadLibraryA(filename); +#else + return ::dlopen(filename, RTLD_NOW|RTLD_LOCAL); +#endif + } DISTRHO_SAFE_EXCEPTION_RETURN("lib_open", nullptr); +} + +/* + * Close a previously opened library (must not be null). + * If false is returned, "lib_error" has the error. + */ +static inline +bool lib_close(const lib_t lib) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(lib != nullptr, false); + + try { +#ifdef DISTRHO_OS_WINDOWS + return ::FreeLibrary(lib); +#else + return (::dlclose(lib) == 0); +#endif + } DISTRHO_SAFE_EXCEPTION_RETURN("lib_close", false); +} + +/* + * Get a library symbol (must not be null). + * Returns null if the symbol is not found. + */ +template +static inline +Func lib_symbol(const lib_t lib, const char* const symbol) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(lib != nullptr, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', nullptr); + + try { +#ifdef DISTRHO_OS_WINDOWS +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-function-type" +# endif + return (Func)::GetProcAddress(lib, symbol); +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic pop +# endif +#else + return (Func)(uintptr_t)::dlsym(lib, symbol); +#endif + } DISTRHO_SAFE_EXCEPTION_RETURN("lib_symbol", nullptr); +} + +/* + * Return the last operation error ('filename' must not be null). + * May return null. + */ +static inline +const char* lib_error(const char* const filename) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); + +#ifdef DISTRHO_OS_WINDOWS + static char libError[2048+1]; + std::memset(libError, 0, sizeof(libError)); + + try { + const DWORD winErrorCode = ::GetLastError(); + const int winErrorFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS; + LPVOID winErrorString; + + ::FormatMessage(winErrorFlags, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr); + + std::snprintf(libError, 2048, "%s: error code %li: %s", filename, winErrorCode, (const char*)winErrorString); + ::LocalFree(winErrorString); + } DISTRHO_SAFE_EXCEPTION("lib_error"); + + return (libError[0] != '\0') ? libError : nullptr; +#else + return ::dlerror(); +#endif +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_LIBRARY_UTILS_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/Mutex.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/Mutex.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,398 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_MUTEX_HPP_INCLUDED +#define DISTRHO_MUTEX_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#ifdef DISTRHO_OS_WINDOWS +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include +#endif + +// FIXME make Mutex stop relying on pthread +#ifdef _MSC_VER +#define DISTRHO_OS_WINDOWS__TODO +#pragma NOTE(DPF Mutex implementation is TODO on MSVC) +#else +#include +#endif + +START_NAMESPACE_DISTRHO + +class Signal; + +// ----------------------------------------------------------------------- +// Mutex class + +class Mutex +{ +public: + /* + * Constructor. + */ + Mutex(const bool inheritPriority = true) noexcept + #ifdef DISTRHO_OS_WINDOWS__TODO + #else + : fMutex() + #endif + { + #ifdef DISTRHO_OS_WINDOWS__TODO + #else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_setprotocol(&attr, inheritPriority ? PTHREAD_PRIO_INHERIT : PTHREAD_PRIO_NONE); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&fMutex, &attr); + pthread_mutexattr_destroy(&attr); + #endif + } + + /* + * Destructor. + */ + ~Mutex() noexcept + { + #ifdef DISTRHO_OS_WINDOWS__TODO + #else + pthread_mutex_destroy(&fMutex); + #endif + } + + /* + * Lock the mutex. + */ + bool lock() const noexcept + { + #ifdef DISTRHO_OS_WINDOWS__TODO + #else + return (pthread_mutex_lock(&fMutex) == 0); + #endif + } + + /* + * Try to lock the mutex. + * Returns true if successful. + */ + bool tryLock() const noexcept + { + #ifdef DISTRHO_OS_WINDOWS__TODO + #else + return (pthread_mutex_trylock(&fMutex) == 0); + #endif + } + + /* + * Unlock the mutex. + */ + void unlock() const noexcept + { + #ifdef DISTRHO_OS_WINDOWS__TODO + #else + pthread_mutex_unlock(&fMutex); + #endif + } + +private: + #ifdef DISTRHO_OS_WINDOWS__TODO + #else + mutable pthread_mutex_t fMutex; + #endif + + DISTRHO_DECLARE_NON_COPYABLE(Mutex) +}; + +// ----------------------------------------------------------------------- +// RecursiveMutex class + +class RecursiveMutex +{ +public: + /* + * Constructor. + */ + RecursiveMutex() noexcept + #ifdef DISTRHO_OS_WINDOWS + : fSection() + #else + : fMutex() + #endif + { + #ifdef DISTRHO_OS_WINDOWS + InitializeCriticalSection(&fSection); + #else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&fMutex, &attr); + pthread_mutexattr_destroy(&attr); + #endif + } + + /* + * Destructor. + */ + ~RecursiveMutex() noexcept + { + #ifdef DISTRHO_OS_WINDOWS + DeleteCriticalSection(&fSection); + #else + pthread_mutex_destroy(&fMutex); + #endif + } + + /* + * Lock the mutex. + */ + bool lock() const noexcept + { + #ifdef DISTRHO_OS_WINDOWS + EnterCriticalSection(&fSection); + return true; + #else + return (pthread_mutex_lock(&fMutex) == 0); + #endif + } + + /* + * Try to lock the mutex. + * Returns true if successful. + */ + bool tryLock() const noexcept + { + #ifdef DISTRHO_OS_WINDOWS + return (TryEnterCriticalSection(&fSection) != FALSE); + #else + return (pthread_mutex_trylock(&fMutex) == 0); + #endif + } + + /* + * Unlock the mutex. + */ + void unlock() const noexcept + { + #ifdef DISTRHO_OS_WINDOWS + LeaveCriticalSection(&fSection); + #else + pthread_mutex_unlock(&fMutex); + #endif + } + +private: + #ifdef DISTRHO_OS_WINDOWS + mutable CRITICAL_SECTION fSection; + #else + mutable pthread_mutex_t fMutex; + #endif + + DISTRHO_DECLARE_NON_COPYABLE(RecursiveMutex) +}; + +#ifndef _MSC_VER +// ----------------------------------------------------------------------- +// Signal class + +class Signal +{ +public: + /* + * Constructor. + */ + Signal() noexcept + : fCondition(), + fMutex(), + fTriggered(false) + { + pthread_condattr_t cattr; + pthread_condattr_init(&cattr); + pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE); + pthread_cond_init(&fCondition, &cattr); + pthread_condattr_destroy(&cattr); + + pthread_mutexattr_t mattr; + pthread_mutexattr_init(&mattr); + pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT); + pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&fMutex, &mattr); + pthread_mutexattr_destroy(&mattr); + } + + /* + * Destructor. + */ + ~Signal() noexcept + { + pthread_cond_destroy(&fCondition); + pthread_mutex_destroy(&fMutex); + } + + /* + * Wait for a signal. + */ + void wait() noexcept + { + pthread_mutex_lock(&fMutex); + + while (! fTriggered) + { + try { + pthread_cond_wait(&fCondition, &fMutex); + } DISTRHO_SAFE_EXCEPTION("pthread_cond_wait"); + } + + fTriggered = false; + + pthread_mutex_unlock(&fMutex); + } + + /* + * Wake up all waiting threads. + */ + void signal() noexcept + { + pthread_mutex_lock(&fMutex); + + if (! fTriggered) + { + fTriggered = true; + pthread_cond_broadcast(&fCondition); + } + + pthread_mutex_unlock(&fMutex); + } + +private: + pthread_cond_t fCondition; + pthread_mutex_t fMutex; + volatile bool fTriggered; + + DISTRHO_PREVENT_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPYABLE(Signal) +}; +#endif // _MSC_VER + +// ----------------------------------------------------------------------- +// Helper class to lock&unlock a mutex during a function scope. + +template +class ScopeLocker +{ +public: + ScopeLocker(const Mutex& mutex) noexcept + : fMutex(mutex) + { + fMutex.lock(); + } + + ~ScopeLocker() noexcept + { + fMutex.unlock(); + } + +private: + const Mutex& fMutex; + + DISTRHO_PREVENT_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPYABLE(ScopeLocker) +}; + +// ----------------------------------------------------------------------- +// Helper class to try-lock&unlock a mutex during a function scope. + +template +class ScopeTryLocker +{ +public: + ScopeTryLocker(const Mutex& mutex) noexcept + : fMutex(mutex), + fLocked(mutex.tryLock()) {} + + ScopeTryLocker(const Mutex& mutex, const bool forceLock) noexcept + : fMutex(mutex), + fLocked(forceLock ? mutex.lock() : mutex.tryLock()) {} + + ~ScopeTryLocker() noexcept + { + if (fLocked) + fMutex.unlock(); + } + + bool wasLocked() const noexcept + { + return fLocked; + } + + bool wasNotLocked() const noexcept + { + return !fLocked; + } + +private: + const Mutex& fMutex; + const bool fLocked; + + DISTRHO_PREVENT_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPYABLE(ScopeTryLocker) +}; + +// ----------------------------------------------------------------------- +// Helper class to unlock&lock a mutex during a function scope. + +template +class ScopeUnlocker +{ +public: + ScopeUnlocker(const Mutex& mutex) noexcept + : fMutex(mutex) + { + fMutex.unlock(); + } + + ~ScopeUnlocker() noexcept + { + fMutex.lock(); + } + +private: + const Mutex& fMutex; + + DISTRHO_PREVENT_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPYABLE(ScopeUnlocker) +}; + +// ----------------------------------------------------------------------- +// Define types + +typedef ScopeLocker MutexLocker; +typedef ScopeLocker RecursiveMutexLocker; + +typedef ScopeTryLocker MutexTryLocker; +typedef ScopeTryLocker RecursiveMutexTryLocker; + +typedef ScopeUnlocker MutexUnlocker; +typedef ScopeUnlocker RecursiveMutexUnlocker; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_MUTEX_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/RingBuffer.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/RingBuffer.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,788 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_RING_BUFFER_HPP_INCLUDED +#define DISTRHO_RING_BUFFER_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// Buffer structs + +/** + Base structure for all RingBuffer containers. + This struct details the data model used in DPF's RingBuffer class. + + DPF RingBuffer uses a struct just like this one to store positions, buffer data, size, etc. + The RingBuffer itself takes ownership of this struct and uses it to store any needed data. + This allows to dynamically change the way its ring buffer is allocated, simply by changing the template type. + For example, `RingBufferControl` will create a ring buffer with heap memory, which can be of any size. + In the same vein, `RingBufferControl` will create a ring buffer with stack memory, + directly tied to the RingBufferControl it belongs to. + + The main idea behind this model is to allow RingBufferControl over memory created elsewhere, + for example shared memory area. + One can create/place the Buffer struct in shared memory, and point RingBufferControl to it, + thus avoiding the pitfalls of sharing access to a non trivially-copyable/POD C++ class. + + Unlike other ring buffers, an extra variable is used to track pending writes. + This is so we can write a few bytes at a time and later mark the whole operation as complete, + thus avoiding the issue of reading data too early from the other side. + For example, write the size of some data first, and then the actual data. + The reading side will only see data available once size + data is completely written and "committed". + */ +struct HeapBuffer { + /** + Size of the buffer, allocated in @a buf. + If the size is fixed (stack buffer), this variable can be static. + */ + uint32_t size; + + /** + Current writing position, headmost position of the buffer. + Increments when writing. + */ + uint32_t head; + + /** + Current reading position, last used position of the buffer. + Increments when reading. + head == tail means empty buffer. + */ + uint32_t tail; + + /** + Temporary position of head until a commitWrite() is called. + If buffer writing fails, wrtn will be back to head position thus ignoring the last operation(s). + If buffer writing succeeds, head will be set to this variable. + */ + uint32_t wrtn; + + /** + Boolean used to check if a write operation failed. + This ensures we don't get incomplete writes. + */ + bool invalidateCommit; + + /** + Pointer to buffer data. + This can be either stack or heap data, depending on the usecase. + */ + uint8_t* buf; +}; + +/** + RingBufferControl compatible struct with a relatively small stack size (4k bytes). + @see HeapBuffer +*/ +struct SmallStackBuffer { + static const uint32_t size = 4096; + uint32_t head, tail, wrtn; + bool invalidateCommit; + uint8_t buf[size]; +}; + +/** + RingBufferControl compatible struct with a relatively big stack size (16k bytes). + @see HeapBuffer +*/ +struct BigStackBuffer { + static const uint32_t size = 16384; + uint32_t head, tail, wrtn; + bool invalidateCommit; + uint8_t buf[size]; +}; + +/** + RingBufferControl compatible struct with a huge stack size (64k bytes). + @see HeapBuffer +*/ +struct HugeStackBuffer { + static const uint32_t size = 65536; + uint32_t head, tail, wrtn; + bool invalidateCommit; + uint8_t buf[size]; +}; + +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# define HeapBuffer_INIT {0, 0, 0, 0, false, nullptr} +# define StackBuffer_INIT {0, 0, 0, false, {0}} +#else +# define HeapBuffer_INIT +# define StackBuffer_INIT +#endif + +// ----------------------------------------------------------------------- +// RingBufferControl templated class + +/** + DPF built-in RingBuffer class. + RingBufferControl takes one buffer struct to take control over, and operates over it. + + This is meant for single-writer, single-reader type of control. + Writing and reading is wait and lock-free. + + Typically usage involves: + ``` + // definition + HeapRingBuffer myHeapBuffer; // or RingBufferControl class for more control + + // construction, only needed for heap buffers + myHeapBuffer.createBuffer(8192); + + // writing data + myHeapBuffer.writeUInt(size); + myHeapBuffer.writeCustomData(someOtherData, size); + myHeapBuffer.commitWrite(); + + // reading data + if (myHeapBuffer.isDataAvailableForReading()) + { + uint32_t size; + if (myHeapBuffer.readUInt(size) && readCustomData(&anotherData, size)) + { + // do something with "anotherData" + } + } + ``` + + @see HeapBuffer + */ +template +class RingBufferControl +{ +public: + /* + * Constructor for uninitialised ring buffer. + * A call to setRingBuffer is required to tied this control to a ring buffer struct; + * + */ + RingBufferControl() noexcept + : buffer(nullptr), + errorReading(false), + errorWriting(false) {} + + /* + * Destructor. + */ + virtual ~RingBufferControl() noexcept {} + + // ------------------------------------------------------------------- + // check operations + + /* + * Check if there is any data available for reading, regardless of size. + */ + bool isDataAvailableForReading() const noexcept; + + /* + * Check if ring buffer is empty (that is, there is nothing to read). + */ + bool isEmpty() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr, false); + + return (buffer->buf == nullptr || buffer->head == buffer->tail); + } + + /* + * Get the size of the data available to read. + */ + uint32_t getReadableDataSize() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr, 0); + + const uint32_t wrap = buffer->head > buffer->tail ? 0 : buffer->size; + + return wrap + buffer->head - buffer->tail; + } + + /* + * Get the size of the data available to write. + */ + uint32_t getWritableDataSize() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr, 0); + + const uint32_t wrap = (buffer->tail > buffer->wrtn) ? 0 : buffer->size; + + return wrap + buffer->tail - buffer->wrtn; + } + + // ------------------------------------------------------------------- + // clear/reset operations + + /* + * Clear the entire ring buffer data, marking the buffer as empty. + * Requires a buffer struct tied to this class. + */ + void clearData() noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr,); + + buffer->head = 0; + buffer->tail = 0; + buffer->wrtn = 0; + buffer->invalidateCommit = false; + + std::memset(buffer->buf, 0, buffer->size); + } + + // ------------------------------------------------------------------- + // read operations + + /* + * Read a single boolean value. + * Returns false if reading fails. + */ + bool readBool() noexcept + { + bool b = false; + return tryRead(&b, sizeof(bool)) ? b : false; + } + + /* + * Read a single 8-bit byte. + * Returns 0 if reading fails. + */ + uint8_t readByte() noexcept + { + uint8_t B = 0; + return tryRead(&B, sizeof(uint8_t)) ? B : 0; + } + + /* + * Read a short 16-bit integer. + * Returns 0 if reading fails. + */ + int16_t readShort() noexcept + { + int16_t s = 0; + return tryRead(&s, sizeof(int16_t)) ? s : 0; + } + + /* + * Read a short unsigned 16-bit integer. + * Returns 0 if reading fails. + */ + uint16_t readUShort() noexcept + { + uint16_t us = 0; + return tryRead(&us, sizeof(uint16_t)) ? us : 0; + } + + /* + * Read a regular 32-bit integer. + * Returns 0 if reading fails. + */ + int32_t readInt() noexcept + { + int32_t i = 0; + return tryRead(&i, sizeof(int32_t)) ? i : 0; + } + + /* + * Read an unsigned 32-bit integer. + * Returns 0 if reading fails. + */ + uint32_t readUInt() noexcept + { + uint32_t ui = 0; + return tryRead(&ui, sizeof(int32_t)) ? ui : 0; + } + + /* + * Read a long 64-bit integer. + * Returns 0 if reading fails. + */ + int64_t readLong() noexcept + { + int64_t l = 0; + return tryRead(&l, sizeof(int64_t)) ? l : 0; + } + + /* + * Read a long unsigned 64-bit integer. + * Returns 0 if reading fails. + */ + uint64_t readULong() noexcept + { + uint64_t ul = 0; + return tryRead(&ul, sizeof(int64_t)) ? ul : 0; + } + + /* + * Read a single-precision floating point number. + * Returns 0 if reading fails. + */ + float readFloat() noexcept + { + float f = 0.0f; + return tryRead(&f, sizeof(float)) ? f : 0.0f; + } + + /* + * Read a double-precision floating point number. + * Returns 0 if reading fails. + */ + double readDouble() noexcept + { + double d = 0.0; + return tryRead(&d, sizeof(double)) ? d : 0.0; + } + + /*! + * Read an arbitrary amount of data, specified by @a size. + * data pointer must be non-null, and size > 0. + * + * Returns true if reading succeeds. + * In case of failure, @a data pointer is automatically cleared by @a size bytes. + */ + bool readCustomData(void* const data, const uint32_t size) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(size > 0, false); + + if (tryRead(data, size)) + return true; + + std::memset(data, 0, size); + return false; + } + + /*! + * Read a custom data type specified by the template typename used, + * with size being automatically deduced by the compiler (through the use of sizeof). + * + * Returns true if reading succeeds. + * In case of failure, @a type value is automatically cleared by its deduced size. + */ + template + bool readCustomType(T& type) noexcept + { + if (tryRead(&type, sizeof(T))) + return true; + + std::memset(&type, 0, sizeof(T)); + return false; + } + + // ------------------------------------------------------------------- + // write operations + + /* + * Write a single boolean value. + */ + bool writeBool(const bool value) noexcept + { + return tryWrite(&value, sizeof(bool)); + } + + /* + * Write a single 8-bit byte. + */ + bool writeByte(const uint8_t value) noexcept + { + return tryWrite(&value, sizeof(uint8_t)); + } + + /* + * Write a short 16-bit integer. + */ + bool writeShort(const int16_t value) noexcept + { + return tryWrite(&value, sizeof(int16_t)); + } + + /* + * Write a short unsigned 16-bit integer. + */ + bool writeUShort(const uint16_t value) noexcept + { + return tryWrite(&value, sizeof(uint16_t)); + } + + /* + * Write a regular 32-bit integer. + */ + bool writeInt(const int32_t value) noexcept + { + return tryWrite(&value, sizeof(int32_t)); + } + + /* + * Write an unsigned 32-bit integer. + */ + bool writeUInt(const uint32_t value) noexcept + { + return tryWrite(&value, sizeof(uint32_t)); + } + + /* + * Write a long 64-bit integer. + */ + bool writeLong(const int64_t value) noexcept + { + return tryWrite(&value, sizeof(int64_t)); + } + + /* + * Write a long unsigned 64-bit integer. + */ + bool writeULong(const uint64_t value) noexcept + { + return tryWrite(&value, sizeof(uint64_t)); + } + + /* + * Write a single-precision floating point number. + */ + bool writeFloat(const float value) noexcept + { + return tryWrite(&value, sizeof(float)); + } + + /* + * Write a double-precision floating point number. + */ + bool writeDouble(const double value) noexcept + { + return tryWrite(&value, sizeof(double)); + } + + /*! + * Write an arbitrary amount of data, specified by @a size. + * data pointer must be non-null, and size > 0. + */ + bool writeCustomData(const void* const data, const uint32_t size) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(size > 0, false); + + return tryWrite(data, size); + } + + /*! + * Write a custom data type specified by the template typename used, + * with size being automatically deduced by the compiler (through the use of sizeof). + */ + template + bool writeCustomType(const T& type) noexcept + { + return tryWrite(&type, sizeof(T)); + } + + // ------------------------------------------------------------------- + + /*! + * Commit all previous write operations to the ringbuffer. + * If a write operation has previously failed, this will reset/invalidate the previous write attempts. + */ + bool commitWrite() noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr, false); + + if (buffer->invalidateCommit) + { + buffer->wrtn = buffer->head; + buffer->invalidateCommit = false; + return false; + } + + // nothing to commit? + DISTRHO_SAFE_ASSERT_RETURN(buffer->head != buffer->wrtn, false); + + // all ok + buffer->head = buffer->wrtn; + errorWriting = false; + return true; + } + + // ------------------------------------------------------------------- + + /* + * Tie this ring buffer control to a ring buffer struct, optionally clearing its data. + */ + void setRingBuffer(BufferStruct* const ringBuf, const bool clearRingBufferData) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != ringBuf,); + + buffer = ringBuf; + + if (clearRingBufferData && ringBuf != nullptr) + clearData(); + } + + // ------------------------------------------------------------------- + +protected: + /** @internal try reading from the buffer, can fail. */ + bool tryRead(void* const buf, const uint32_t size) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr, false); + #if defined(__clang__) + # pragma clang diagnostic push + # pragma clang diagnostic ignored "-Wtautological-pointer-compare" + #endif + DISTRHO_SAFE_ASSERT_RETURN(buffer->buf != nullptr, false); + #if defined(__clang__) + # pragma clang diagnostic pop + #endif + DISTRHO_SAFE_ASSERT_RETURN(buf != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(size > 0, false); + DISTRHO_SAFE_ASSERT_RETURN(size < buffer->size, false); + + // empty + if (buffer->head == buffer->tail) + return false; + + uint8_t* const bytebuf(static_cast(buf)); + + const uint32_t head(buffer->head); + const uint32_t tail(buffer->tail); + const uint32_t wrap((head > tail) ? 0 : buffer->size); + + if (size > wrap + head - tail) + { + if (! errorReading) + { + errorReading = true; + d_stderr2("RingBuffer::tryRead(%p, %lu): failed, not enough space", buf, (ulong)size); + } + return false; + } + + uint32_t readto(tail + size); + + if (readto > buffer->size) + { + readto -= buffer->size; + + if (size == 1) + { + std::memcpy(bytebuf, buffer->buf + tail, 1); + } + else + { + const uint32_t firstpart(buffer->size - tail); + std::memcpy(bytebuf, buffer->buf + tail, firstpart); + std::memcpy(bytebuf + firstpart, buffer->buf, readto); + } + } + else + { + std::memcpy(bytebuf, buffer->buf + tail, size); + + if (readto == buffer->size) + readto = 0; + } + + buffer->tail = readto; + errorReading = false; + return true; + } + + /** @internal try writing to the buffer, can fail. */ + bool tryWrite(const void* const buf, const uint32_t size) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(buf != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(size > 0, false); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(size < buffer->size, size, buffer->size, false); + + const uint8_t* const bytebuf(static_cast(buf)); + + const uint32_t tail(buffer->tail); + const uint32_t wrtn(buffer->wrtn); + const uint32_t wrap((tail > wrtn) ? 0 : buffer->size); + + if (size >= wrap + tail - wrtn) + { + if (! errorWriting) + { + errorWriting = true; + d_stderr2("RingBuffer::tryWrite(%p, %lu): failed, not enough space", buf, (ulong)size); + } + buffer->invalidateCommit = true; + return false; + } + + uint32_t writeto(wrtn + size); + + if (writeto > buffer->size) + { + writeto -= buffer->size; + + if (size == 1) + { + std::memcpy(buffer->buf, bytebuf, 1); + } + else + { + const uint32_t firstpart(buffer->size - wrtn); + std::memcpy(buffer->buf + wrtn, bytebuf, firstpart); + std::memcpy(buffer->buf, bytebuf + firstpart, writeto); + } + } + else + { + std::memcpy(buffer->buf + wrtn, bytebuf, size); + + if (writeto == buffer->size) + writeto = 0; + } + + buffer->wrtn = writeto; + return true; + } + +private: + /** Buffer struct pointer. */ + BufferStruct* buffer; + + /** Whether read errors have been printed to terminal. */ + bool errorReading; + + /** Whether write errors have been printed to terminal. */ + bool errorWriting; + + DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPYABLE(RingBufferControl) +}; + +template +inline bool RingBufferControl::isDataAvailableForReading() const noexcept +{ + return (buffer != nullptr && buffer->head != buffer->tail); +} + +template <> +inline bool RingBufferControl::isDataAvailableForReading() const noexcept +{ + return (buffer != nullptr && buffer->buf != nullptr && buffer->head != buffer->tail); +} + +// ----------------------------------------------------------------------- +// RingBuffer using heap space + +/** + RingBufferControl with a heap buffer. + This is a convenience class that provides a method for creating and destroying the heap data. + Requires the use of createBuffer(uint32_t) to make the ring buffer usable. +*/ +class HeapRingBuffer : public RingBufferControl +{ +public: + /** Constructor. */ + HeapRingBuffer() noexcept + : heapBuffer(HeapBuffer_INIT) + { +#ifndef DISTRHO_PROPER_CPP11_SUPPORT + std::memset(&heapBuffer, 0, sizeof(heapBuffer)); +#endif + } + + /** Destructor. */ + ~HeapRingBuffer() noexcept override + { + if (heapBuffer.buf == nullptr) + return; + + delete[] heapBuffer.buf; + heapBuffer.buf = nullptr; + } + + /** Create a buffer of the specified size. */ + bool createBuffer(const uint32_t size) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.buf == nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(size > 0, false); + + const uint32_t p2size = d_nextPowerOf2(size); + + try { + heapBuffer.buf = new uint8_t[p2size]; + } DISTRHO_SAFE_EXCEPTION_RETURN("HeapRingBuffer::createBuffer", false); + + heapBuffer.size = p2size; + setRingBuffer(&heapBuffer, true); + return true; + } + + /** Delete the previously allocated buffer. */ + void deleteBuffer() noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.buf != nullptr,); + + setRingBuffer(nullptr, false); + + delete[] heapBuffer.buf; + heapBuffer.buf = nullptr; + heapBuffer.size = 0; + } + + void copyFromAndClearOther(HeapRingBuffer& other) + { + DISTRHO_SAFE_ASSERT_RETURN(other.heapBuffer.size == heapBuffer.size,); + + std::memcpy(&heapBuffer, &other.heapBuffer, sizeof(HeapBuffer) - sizeof(uint8_t*)); + std::memcpy(heapBuffer.buf, other.heapBuffer.buf, sizeof(uint8_t) * heapBuffer.size); + other.clearData(); + } + +private: + /** The heap buffer used for this class. */ + HeapBuffer heapBuffer; + + DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPYABLE(HeapRingBuffer) +}; + +// ----------------------------------------------------------------------- +// RingBuffer using small stack space + +/** + RingBufferControl with an included small stack buffer. + No setup is necessary, this class is usable as-is. +*/ +class SmallStackRingBuffer : public RingBufferControl +{ +public: + /** Constructor. */ + SmallStackRingBuffer() noexcept + : stackBuffer(StackBuffer_INIT) + { +#ifndef DISTRHO_PROPER_CPP11_SUPPORT + std::memset(&stackBuffer, 0, sizeof(stackBuffer)); +#endif + setRingBuffer(&stackBuffer, true); + } + +private: + /** The small stack buffer used for this class. */ + SmallStackBuffer stackBuffer; + + DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION + DISTRHO_DECLARE_NON_COPYABLE(SmallStackRingBuffer) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_RING_BUFFER_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/Runner.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/Runner.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,251 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_RUNNER_HPP_INCLUDED +#define DISTRHO_RUNNER_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#ifndef DISTRHO_OS_WASM +# include "Thread.hpp" +#else +# include "String.hpp" +# include +#endif + +START_NAMESPACE_DISTRHO + +#ifdef DISTRHO_RUNNER_INDIRECT_WASM_CALLS +long d_emscripten_set_interval(void (*)(void*), double, void*); +void d_emscripten_clear_interval(long); +#else +# define d_emscripten_set_interval emscripten_set_interval +# define d_emscripten_clear_interval emscripten_clear_interval +#endif + +// ------------------------------------------------------------------------------------------------------------------- +// Runner class + +/** + Runner class for DPF. + + This is a handy class that handles "idle" time in either background or main thread, + whichever is more suitable to the target platform. + Typically background threads on desktop platforms, main thread on web. + + A single function is expected to be implemented by subclasses, + which directly allows it to stop the runner by returning false. + + You can use it for quick operations that do not need to be handled in the main thread if possible. + The target is to spread out execution over many runs, instead of spending a lot of time on a single task. + */ +class Runner +{ +protected: + /* + * Constructor. + */ + Runner(const char* const runnerName = nullptr) noexcept + #ifndef DISTRHO_OS_WASM + : fRunnerThread(this, runnerName), + fTimeInterval(0) + #else + : fRunnerName(runnerName), + fIntervalId(0) + #endif + { + } + + /* + * Destructor. + */ + virtual ~Runner() /*noexcept*/ + { + DISTRHO_SAFE_ASSERT(! isRunnerActive()); + + stopRunner(); + } + + /* + * Virtual function to be implemented by the subclass. + * Return true to keep running, false to stop execution. + */ + virtual bool run() = 0; + + /* + * Check if the runner should stop. + * To be called from inside the runner to know if a stop request has been made. + */ + bool shouldRunnerStop() const noexcept + { + #ifndef DISTRHO_OS_WASM + return fRunnerThread.shouldThreadExit(); + #else + return fIntervalId == 0; + #endif + } + + // --------------------------------------------------------------------------------------------------------------- + +public: + /* + * Check if the runner is active. + */ + bool isRunnerActive() noexcept + { + #ifndef DISTRHO_OS_WASM + return fRunnerThread.isThreadRunning(); + #else + return fIntervalId != 0; + #endif + } + + /* + * Start the thread. + */ + bool startRunner(const uint timeIntervalMilliseconds = 0) noexcept + { + #ifndef DISTRHO_OS_WASM + DISTRHO_SAFE_ASSERT_RETURN(!fRunnerThread.isThreadRunning(), false); + fTimeInterval = timeIntervalMilliseconds; + return fRunnerThread.startThread(); + #else + DISTRHO_SAFE_ASSERT_RETURN(fIntervalId == 0, false); + fIntervalId = d_emscripten_set_interval(_entryPoint, timeIntervalMilliseconds, this); + return true; + #endif + } + + /* + * Stop the runner. + * This will signal the runner to stop if active, and wait until it finishes. + */ + bool stopRunner() noexcept + { + #ifndef DISTRHO_OS_WASM + return fRunnerThread.stopThread(-1); + #else + signalRunnerShouldStop(); + return true; + #endif + } + + /* + * Tell the runner to stop as soon as possible. + */ + void signalRunnerShouldStop() noexcept + { + #ifndef DISTRHO_OS_WASM + fRunnerThread.signalThreadShouldExit(); + #else + if (fIntervalId != 0) + { + d_emscripten_clear_interval(fIntervalId); + fIntervalId = 0; + } + #endif + } + + // --------------------------------------------------------------------------------------------------------------- + + /* + * Returns the name of the runner. + * This is the name that gets set in the constructor. + */ + const String& getRunnerName() const noexcept + { + #ifndef DISTRHO_OS_WASM + return fRunnerThread.getThreadName(); + #else + return fRunnerName; + #endif + } + + // --------------------------------------------------------------------------------------------------------------- + +private: +#ifndef DISTRHO_OS_WASM + class RunnerThread : public Thread + { + Runner* const runner; + + public: + RunnerThread(Runner* const r, const char* const rn) + : Thread(rn), + runner(r) {} + + protected: + void run() override + { + const uint timeInterval = runner->fTimeInterval; + + while (!shouldThreadExit()) + { + bool stillRunning = false; + + try { + stillRunning = runner->run(); + } catch(...) {} + + if (stillRunning && !shouldThreadExit()) + { + if (timeInterval != 0) + d_msleep(timeInterval); + + // FIXME + // pthread_yield(); + continue; + } + + break; + } + } + } fRunnerThread; + + uint fTimeInterval; +#else + const String fRunnerName; + long fIntervalId; + + void _runEntryPoint() noexcept + { + bool stillRunning = false; + + try { + stillRunning = run(); + } catch(...) {} + + if (fIntervalId != 0 && !stillRunning) + { + d_emscripten_clear_interval(fIntervalId); + fIntervalId = 0; + } + } + + static void _entryPoint(void* const userData) noexcept + { + static_cast(userData)->_runEntryPoint(); + } +#endif + + DISTRHO_DECLARE_NON_COPYABLE(Runner) +}; + +// ------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_RUNNER_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedDenormalDisable.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedDenormalDisable.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,112 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_SCOPED_DENORMAL_DISABLE_HPP_INCLUDED +#define DISTRHO_SCOPED_DENORMAL_DISABLE_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#ifdef __SSE2_MATH__ +# include +#endif + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- +// ScopedDenormalDisable class definition + +/** + ScopedDenormalDisable is a handy class for disabling denormal numbers during a function scope. + Denormal numbers can happen in IIR or other types of filters, they are often very slow. + + Use this class with care! Messing up with the global state is bound to make some hosts unhappy. + */ +class ScopedDenormalDisable { +public: + /* + * Constructor. + * Current cpu flags will saved, then denormals-as-zero and flush-to-zero set on top. + */ + inline ScopedDenormalDisable() noexcept; + + /* + * Destructor. + * CPU flags will be restored to the value obtained in the constructor. + */ + inline ~ScopedDenormalDisable() noexcept + { + setFlags(oldflags); + } + +private: + #if defined(__SSE2_MATH__) + typedef uint cpuflags_t; + #elif defined(__aarch64__) + typedef uint64_t cpuflags_t; + #elif defined(__arm__) && !defined(__SOFTFP__) + typedef uint32_t cpuflags_t; + #else + typedef char cpuflags_t; + #endif + + // retrieved on constructor, reset to it on destructor + cpuflags_t oldflags; + + // helper function to set cpu flags + inline void setFlags(cpuflags_t flags) noexcept; + + DISTRHO_DECLARE_NON_COPYABLE(ScopedDenormalDisable) + DISTRHO_PREVENT_HEAP_ALLOCATION +}; + +// -------------------------------------------------------------------------------------------------------------------- +// ScopedDenormalDisable class implementation + +inline ScopedDenormalDisable::ScopedDenormalDisable() noexcept + : oldflags(0) +{ + #if defined(__SSE2_MATH__) + oldflags = _mm_getcsr(); + setFlags(oldflags | 0x8040); + #elif defined(__aarch64__) + __asm__ __volatile__("mrs %0, fpcr" : "=r" (oldflags)); + setFlags(oldflags | 0x1000000); + __asm__ __volatile__("isb"); + #elif defined(__arm__) && !defined(__SOFTFP__) + __asm__ __volatile__("vmrs %0, fpscr" : "=r" (oldflags)); + setFlags(oldflags | 0x1000000); + #endif +} + +inline void ScopedDenormalDisable::setFlags(const cpuflags_t flags) noexcept +{ + #if defined(__SSE2_MATH__) + _mm_setcsr(flags); + #elif defined(__aarch64__) + __asm__ __volatile__("msr fpcr, %0" :: "r" (flags)); + #elif defined(__arm__) && !defined(__SOFTFP__) + __asm__ __volatile__("vmsr fpscr, %0" :: "r" (flags)); + #else + // unused + (void)flags; + #endif +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_SCOPED_DENORMAL_DISABLE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedPointer.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedPointer.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,251 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2016 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_SCOPED_POINTER_HPP_INCLUDED +#define DISTRHO_SCOPED_POINTER_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#include + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// The following code was based from juce-core ScopedPointer class + +/** + Copyright (C) 2013 Raw Material Software Ltd. + + Permission is granted to use this software under the terms of the ISC license + http://www.isc.org/downloads/software-support-policy/isc-license/ + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, + OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + OF THIS SOFTWARE. +*/ + +//============================================================================== +/** + This class holds a pointer which is automatically deleted when this object goes + out of scope. + + Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer + gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or + as member variables is a good way to use RAII to avoid accidentally leaking dynamically + created objects. + + A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer + to an object. If you use the assignment operator to assign a different object to a + ScopedPointer, the old one will be automatically deleted. + + A const ScopedPointer is guaranteed not to lose ownership of its object or change the + object to which it points during its lifetime. This means that making a copy of a const + ScopedPointer is impossible, as that would involve the new copy taking ownership from the + old one. + + If you need to get a pointer out of a ScopedPointer without it being deleted, you + can use the release() method. + + Something to note is the main difference between this class and the std::auto_ptr class, + which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr + requires that you always call get() to retrieve the pointer. The advantages of providing + the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much + exactly the same way as a raw pointer. The disadvantage is that the compiler is free to + use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult + to return a ScopedPointer as the result of a function. To avoid this causing errors, + ScopedPointer contains an overloaded constructor that should cause a syntax error in these + circumstances, but it does mean that instead of returning a ScopedPointer from a function, + you'd need to return a raw pointer (or use a std::auto_ptr instead). +*/ +template +class ScopedPointer +{ +public: + //============================================================================== + /** Creates a ScopedPointer containing a null pointer. */ + ScopedPointer() noexcept + : object(nullptr) {} + + /** Creates a ScopedPointer that owns the specified object. */ + ScopedPointer(ObjectType* const objectToTakePossessionOf) noexcept + : object(objectToTakePossessionOf) {} + + /** Creates a ScopedPointer that takes its pointer from another ScopedPointer. + + Because a pointer can only belong to one ScopedPointer, this transfers + the pointer from the other object to this one, and the other object is reset to + be a null pointer. + */ + ScopedPointer(ScopedPointer& objectToTransferFrom) noexcept + : object(objectToTransferFrom.object) + { + objectToTransferFrom.object = nullptr; + } + + /** Destructor. + This will delete the object that this ScopedPointer currently refers to. + */ + ~ScopedPointer() + { + delete object; + } + + /** Changes this ScopedPointer to point to a new object. + + Because a pointer can only belong to one ScopedPointer, this transfers + the pointer from the other object to this one, and the other object is reset to + be a null pointer. + + If this ScopedPointer already points to an object, that object + will first be deleted. + */ + ScopedPointer& operator=(ScopedPointer& objectToTransferFrom) + { + if (this != objectToTransferFrom.getAddress()) + { + // Two ScopedPointers should never be able to refer to the same object - if + // this happens, you must have done something dodgy! + DISTRHO_SAFE_ASSERT_RETURN(object == nullptr || object != objectToTransferFrom.object, *this); + + ObjectType* const oldObject = object; + object = objectToTransferFrom.object; + objectToTransferFrom.object = nullptr; + delete oldObject; + } + + return *this; + } + + /** Changes this ScopedPointer to point to a new object. + + If this ScopedPointer already points to an object, that object + will first be deleted. + + The pointer that you pass in may be a nullptr. + */ + ScopedPointer& operator=(ObjectType* const newObjectToTakePossessionOf) + { + if (object != newObjectToTakePossessionOf) + { + ObjectType* const oldObject = object; + object = newObjectToTakePossessionOf; + delete oldObject; + } + + return *this; + } + + //============================================================================== + /** Returns the object that this ScopedPointer refers to. */ + operator ObjectType*() const noexcept { return object; } + + /** Returns the object that this ScopedPointer refers to. */ + ObjectType* get() const noexcept { return object; } + + /** Returns the object that this ScopedPointer refers to. */ + ObjectType& getObject() const noexcept { return *object; } + + /** Returns the object that this ScopedPointer refers to. */ + ObjectType& operator*() const noexcept { return *object; } + + /** Lets you access methods and properties of the object that this ScopedPointer refers to. */ + ObjectType* operator->() const noexcept { return object; } + + //============================================================================== + /** Removes the current object from this ScopedPointer without deleting it. + This will return the current object, and set the ScopedPointer to a null pointer. + */ + ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; } + + //============================================================================== + /** Swaps this object with that of another ScopedPointer. + The two objects simply exchange their pointers. + */ + void swapWith(ScopedPointer& other) noexcept + { + // Two ScopedPointers should never be able to refer to the same object - if + // this happens, you must have done something dodgy! + DISTRHO_SAFE_ASSERT_RETURN(object != other.object || this == other.getAddress() || object == nullptr,); + + std::swap(object, other.object); + } + +private: + //============================================================================== + ObjectType* object; + + // (Required as an alternative to the overloaded & operator). + const ScopedPointer* getAddress() const noexcept { return this; } + +#ifndef _MSC_VER // (MSVC can't deal with multiple copy constructors) + /* The copy constructors are private to stop people accidentally copying a const ScopedPointer + (the compiler would let you do so by implicitly casting the source to its raw object pointer). + + A side effect of this is that in a compiler that doesn't support C++11, you may hit an + error when you write something like this: + + ScopedPointer m = new MyClass(); // Compile error: copy constructor is private. + + Even though the compiler would normally ignore the assignment here, it can't do so when the + copy constructor is private. It's very easy to fix though - just write it like this: + + ScopedPointer m (new MyClass()); // Compiles OK + + It's probably best to use the latter form when writing your object declarations anyway, as + this is a better representation of the code that you actually want the compiler to produce. + */ +# ifdef DISTRHO_PROPER_CPP11_SUPPORT + ScopedPointer(const ScopedPointer&) = delete; + ScopedPointer& operator=(const ScopedPointer&) = delete; +# else + ScopedPointer(const ScopedPointer&); + ScopedPointer& operator=(const ScopedPointer&); +# endif +#endif +}; + +//============================================================================== +/** Compares a ScopedPointer with another pointer. + This can be handy for checking whether this is a null pointer. +*/ +template +bool operator==(const ScopedPointer& pointer1, ObjectType* const pointer2) noexcept +{ + return static_cast(pointer1) == pointer2; +} + +/** Compares a ScopedPointer with another pointer. + This can be handy for checking whether this is a null pointer. +*/ +template +bool operator!=(const ScopedPointer& pointer1, ObjectType* const pointer2) noexcept +{ + return static_cast(pointer1) != pointer2; +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_SCOPED_POINTER_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedSafeLocale.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedSafeLocale.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,136 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED +#define DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#include + +#if ! (defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)) +# define DISTRHO_USE_NEWLOCALE +#endif + +#if defined(DISTRHO_OS_WINDOWS) && __MINGW64_VERSION_MAJOR >= 5 +# define DISTRHO_USE_CONFIGTHREADLOCALE +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// ScopedSafeLocale class definition + +/** + ScopedSafeLocale is a handy class for setting current locale to C on constructor, and revert back on destructor. + It tries to be thread-safe, but it is not always possible. + + Put it inside a scope of code where string conversions happen to ensure they are consistent across many systems. + For example: + + ``` + // stack buffer to put converted float value in + char strbuf[0xff]; + + { + // safe locale operations during this scope + const ScopedSafeLocale sl; + snprintf(strbuf, 0xff, "%f", value); + } + + // do something with `strbuf` now, locale is reverted and left just as it was before + ``` + */ +class ScopedSafeLocale { +public: + /* + * Constructor. + * Current system locale will saved, while "C" is set as the next one to use. + */ + inline ScopedSafeLocale() noexcept; + + /* + * Destructor. + * System locale will revert back to the one saved during constructor. + */ + inline ~ScopedSafeLocale() noexcept; + +private: +#ifdef DISTRHO_USE_NEWLOCALE + locale_t newloc, oldloc; +#else +# ifdef DISTRHO_USE_CONFIGTHREADLOCALE + const int oldthreadloc; +# endif + char* const oldloc; +#endif + + DISTRHO_DECLARE_NON_COPYABLE(ScopedSafeLocale) + DISTRHO_PREVENT_HEAP_ALLOCATION +}; + +// ----------------------------------------------------------------------- +// ScopedSafeLocale class implementation + +#ifdef DISTRHO_USE_NEWLOCALE +static constexpr const locale_t kNullLocale = (locale_t)nullptr; +#endif + +inline ScopedSafeLocale::ScopedSafeLocale() noexcept +#ifdef DISTRHO_USE_NEWLOCALE + : newloc(::newlocale(LC_NUMERIC_MASK, "C", kNullLocale)), + oldloc(newloc != kNullLocale ? ::uselocale(newloc) : kNullLocale) {} +#else +# ifdef DISTRHO_USE_CONFIGTHREADLOCALE + : oldthreadloc(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)), +# else + : +# endif + oldloc(strdup(::setlocale(LC_NUMERIC, nullptr))) +{ + ::setlocale(LC_NUMERIC, "C"); +} +#endif + +inline ScopedSafeLocale::~ScopedSafeLocale() noexcept +{ +#ifdef DISTRHO_USE_NEWLOCALE + if (oldloc != kNullLocale) + ::uselocale(oldloc); + if (newloc != kNullLocale) + ::freelocale(newloc); +#else // DISTRHO_USE_NEWLOCALE + if (oldloc != nullptr) + { + ::setlocale(LC_NUMERIC, oldloc); + std::free(oldloc); + } + +# ifdef DISTRHO_USE_CONFIGTHREADLOCALE + if (oldthreadloc != -1) + _configthreadlocale(oldthreadloc); +# endif +#endif // DISTRHO_USE_NEWLOCALE +} + +// ----------------------------------------------------------------------- + +#undef DISTRHO_USE_CONFIGTHREADLOCALE +#undef DISTRHO_USE_NEWLOCALE + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_SCOPED_SAFE_LOCALE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/Sleep.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/Sleep.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,71 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2016 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_SLEEP_HPP_INCLUDED +#define DISTRHO_SLEEP_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#ifdef DISTRHO_OS_WINDOWS +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include +#else +# include +#endif + +// ----------------------------------------------------------------------- +// d_*sleep + +/* + * Sleep for 'secs' seconds. + */ +static inline +void d_sleep(const uint secs) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(secs > 0,); + + try { +#ifdef DISTRHO_OS_WINDOWS + ::Sleep(secs * 1000); +#else + ::sleep(secs); +#endif + } DISTRHO_SAFE_EXCEPTION("d_sleep"); +} + +/* + * Sleep for 'msecs' milliseconds. + */ +static inline +void d_msleep(const uint msecs) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(msecs > 0,); + + try { +#ifdef DISTRHO_OS_WINDOWS + ::Sleep(msecs); +#else + ::usleep(msecs * 1000); +#endif + } DISTRHO_SAFE_EXCEPTION("d_msleep"); +} + +// ----------------------------------------------------------------------- + +#endif // DISTRHO_SLEEP_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/String.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/String.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1010 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_STRING_HPP_INCLUDED +#define DISTRHO_STRING_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" +#include "../extra/ScopedSafeLocale.hpp" + +#include + +#if __cplusplus >= 201703L +# include +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// String class + +class String +{ +public: + // ------------------------------------------------------------------- + // constructors (no explicit conversions allowed) + + /* + * Empty string. + */ + explicit String() noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) {} + + /* + * Simple character. + */ + explicit String(const char c) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char ch[2]; + ch[0] = c; + ch[1] = '\0'; + + _dup(ch); + } + + /* + * Simple char string. + */ + explicit String(char* const strBuf, const bool reallocData = true) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + if (reallocData || strBuf == nullptr) + { + _dup(strBuf); + } + else + { + fBuffer = strBuf; + fBufferLen = std::strlen(strBuf); + fBufferAlloc = true; + } + } + + /* + * Simple const char string. + */ + explicit String(const char* const strBuf) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + _dup(strBuf); + } + + #if __cplusplus >= 201703L + /* + * constexpr compatible variant. + */ + explicit constexpr String(const std::string_view& strView) noexcept + : fBuffer(const_cast(strView.data())), + fBufferLen(strView.size()), + fBufferAlloc(false) {} + #endif + + /* + * Integer. + */ + explicit String(const int value) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + std::snprintf(strBuf, 0xff, "%d", value); + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + /* + * Unsigned integer, possibly in hexadecimal. + */ + explicit String(const unsigned int value, const bool hexadecimal = false) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value); + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + /* + * Long integer. + */ + explicit String(const long value) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + std::snprintf(strBuf, 0xff, "%ld", value); + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + /* + * Long unsigned integer, possibly hexadecimal. + */ + explicit String(const unsigned long value, const bool hexadecimal = false) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value); + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + /* + * Long long integer. + */ + explicit String(const long long value) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + std::snprintf(strBuf, 0xff, "%lld", value); + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + /* + * Long long unsigned integer, possibly hexadecimal. + */ + explicit String(const unsigned long long value, const bool hexadecimal = false) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + std::snprintf(strBuf, 0xff, hexadecimal ? "0x%llx" : "%llu", value); + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + /* + * Single-precision floating point number. + */ + explicit String(const float value) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + + { + const ScopedSafeLocale ssl; + std::snprintf(strBuf, 0xff, "%.12g", static_cast(value)); + } + + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + /* + * Double-precision floating point number. + */ + explicit String(const double value) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + char strBuf[0xff+1]; + + { + const ScopedSafeLocale ssl; + std::snprintf(strBuf, 0xff, "%.24g", value); + } + + strBuf[0xff] = '\0'; + + _dup(strBuf); + } + + // ------------------------------------------------------------------- + // non-explicit constructor + + /* + * Create string from another string. + */ + String(const String& str) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + _dup(str.fBuffer); + } + + // ------------------------------------------------------------------- + // destructor + + /* + * Destructor. + */ + ~String() noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fBuffer != nullptr,); + + if (fBufferAlloc) + std::free(fBuffer); + + fBuffer = nullptr; + fBufferLen = 0; + fBufferAlloc = false; + } + + // ------------------------------------------------------------------- + // public methods + + /* + * Get length of the string. + */ + std::size_t length() const noexcept + { + return fBufferLen; + } + + /* + * Check if the string is empty. + */ + bool isEmpty() const noexcept + { + return (fBufferLen == 0); + } + + /* + * Check if the string is not empty. + */ + bool isNotEmpty() const noexcept + { + return (fBufferLen != 0); + } + + /* + * Check if the string contains a specific character, case-sensitive. + */ + bool contains(const char c) const noexcept + { + for (std::size_t i=0; i= '0' && fBuffer[pos] <= '9'); + } + + /* + * Check if the string starts with the character 'c'. + */ + bool startsWith(const char c) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(c != '\0', false); + + return (fBufferLen > 0 && fBuffer[0] == c); + } + + /* + * Check if the string starts with the string 'prefix'. + */ + bool startsWith(const char* const prefix) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(prefix != nullptr, false); + + const std::size_t prefixLen(std::strlen(prefix)); + + if (fBufferLen < prefixLen) + return false; + + return (std::strncmp(fBuffer, prefix, prefixLen) == 0); + } + + /* + * Check if the string ends with the character 'c'. + */ + bool endsWith(const char c) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(c != '\0', false); + + return (fBufferLen > 0 && fBuffer[fBufferLen-1] == c); + } + + /* + * Check if the string ends with the string 'suffix'. + */ + bool endsWith(const char* const suffix) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(suffix != nullptr, false); + + const std::size_t suffixLen(std::strlen(suffix)); + + if (fBufferLen < suffixLen) + return false; + + return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0); + } + + /* + * Find the first occurrence of character 'c' in the string. + * Returns "length()" if the character is not found. + */ + std::size_t find(const char c, bool* const found = nullptr) const noexcept + { + if (fBufferLen == 0 || c == '\0') + { + if (found != nullptr) + *found = false; + return fBufferLen; + } + + for (std::size_t i=0; i < fBufferLen; ++i) + { + if (fBuffer[i] == c) + { + if (found != nullptr) + *found = true; + return i; + } + } + + if (found != nullptr) + *found = false; + return fBufferLen; + } + + /* + * Find the first occurrence of string 'strBuf' in the string. + * Returns "length()" if the string is not found. + */ + std::size_t find(const char* const strBuf, bool* const found = nullptr) const noexcept + { + if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0') + { + if (found != nullptr) + *found = false; + return fBufferLen; + } + + if (char* const subStrBuf = std::strstr(fBuffer, strBuf)) + { + const ssize_t ret(subStrBuf - fBuffer); + + if (ret < 0) + { + // should never happen! + d_safe_assert_int("ret >= 0", __FILE__, __LINE__, int(ret)); + + if (found != nullptr) + *found = false; + return fBufferLen; + } + + if (found != nullptr) + *found = true; + return static_cast(ret); + } + + if (found != nullptr) + *found = false; + return fBufferLen; + } + + /* + * Find the last occurrence of character 'c' in the string. + * Returns "length()" if the character is not found. + */ + std::size_t rfind(const char c, bool* const found = nullptr) const noexcept + { + if (fBufferLen == 0 || c == '\0') + { + if (found != nullptr) + *found = false; + return fBufferLen; + } + + for (std::size_t i=fBufferLen; i > 0; --i) + { + if (fBuffer[i-1] == c) + { + if (found != nullptr) + *found = true; + return i-1; + } + } + + if (found != nullptr) + *found = false; + return fBufferLen; + } + + /* + * Find the last occurrence of string 'strBuf' in the string. + * Returns "length()" if the string is not found. + */ + std::size_t rfind(const char* const strBuf, bool* const found = nullptr) const noexcept + { + if (found != nullptr) + *found = false; + + if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0') + return fBufferLen; + + const std::size_t strBufLen(std::strlen(strBuf)); + + std::size_t ret = fBufferLen; + const char* tmpBuf = fBuffer; + + for (std::size_t i=0; i < fBufferLen; ++i) + { + if (std::strstr(tmpBuf+1, strBuf) == nullptr && std::strncmp(tmpBuf, strBuf, strBufLen) == 0) + { + if (found != nullptr) + *found = true; + break; + } + + --ret; + ++tmpBuf; + } + + return fBufferLen-ret; + } + + /* + * Clear the string. + */ + void clear() noexcept + { + truncate(0); + } + + /* + * Replace all occurrences of character 'before' with character 'after'. + */ + String& replace(const char before, const char after) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(before != '\0' /* && after != '\0' */, *this); + + for (std::size_t i=0; i < fBufferLen; ++i) + { + if (fBuffer[i] == before) + fBuffer[i] = after; + } + + return *this; + } + + /* + * Remove all occurrences of character 'c', shifting and truncating the string as necessary. + */ + String& remove(const char c) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(c != '\0', *this); + + if (fBufferLen == 0) + return *this; + + for (std::size_t i=0; i < fBufferLen; ++i) + { + if (fBuffer[i] == c) + { + --fBufferLen; + std::memmove(fBuffer+i, fBuffer+i+1, fBufferLen-i); + } + } + + fBuffer[fBufferLen] = '\0'; + return *this; + } + + /* + * Truncate the string to size 'n'. + */ + String& truncate(const std::size_t n) noexcept + { + if (n >= fBufferLen) + return *this; + + fBuffer[n] = '\0'; + fBufferLen = n; + + return *this; + } + + /* + * Convert all non-basic characters to '_'. + */ + String& toBasic() noexcept + { + for (std::size_t i=0; i < fBufferLen; ++i) + { + if (fBuffer[i] >= '0' && fBuffer[i] <= '9') + continue; + if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z') + continue; + if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z') + continue; + if (fBuffer[i] == '_') + continue; + + fBuffer[i] = '_'; + } + + return *this; + } + + /* + * Convert all ascii characters to lowercase. + */ + String& toLower() noexcept + { + static const char kCharDiff('a' - 'A'); + + for (std::size_t i=0; i < fBufferLen; ++i) + { + if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z') + fBuffer[i] = static_cast(fBuffer[i] + kCharDiff); + } + + return *this; + } + + /* + * Convert all ascii characters to uppercase. + */ + String& toUpper() noexcept + { + static const char kCharDiff('a' - 'A'); + + for (std::size_t i=0; i < fBufferLen; ++i) + { + if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z') + fBuffer[i] = static_cast(fBuffer[i] - kCharDiff); + } + + return *this; + } + + /* + * Create a new string where all non-basic characters are converted to '_'. + * @see toBasic() + */ + String asBasic() const noexcept + { + String s(*this); + return s.toBasic(); + } + + /* + * Create a new string where all ascii characters are converted lowercase. + * @see toLower() + */ + String asLower() const noexcept + { + String s(*this); + return s.toLower(); + } + + /* + * Create a new string where all ascii characters are converted to uppercase. + * @see toUpper() + */ + String asUpper() const noexcept + { + String s(*this); + return s.toUpper(); + } + + /* + * Direct access to the string buffer (read-only). + */ + const char* buffer() const noexcept + { + return fBuffer; + } + + /* + * Get and release the string buffer, while also clearing this string. + * This allows to keep a pointer to the buffer after this object is deleted. + * Result must be freed. + */ + char* getAndReleaseBuffer() noexcept + { + char* ret = fBufferLen > 0 ? fBuffer : nullptr; + fBuffer = _null(); + fBufferLen = 0; + fBufferAlloc = false; + return ret; + } + + // ------------------------------------------------------------------- + // base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html + // Copyright (C) 2004-2008 René Nyffenegger + + static String asBase64(const void* const data, const std::size_t dataSize) + { + static const char* const kBase64Chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +#ifndef _MSC_VER + const std::size_t kTmpBufSize = std::min(d_nextPowerOf2(static_cast(dataSize/3)), 65536U); +#else + constexpr std::size_t kTmpBufSize = 65536U; +#endif + + const uchar* bytesToEncode((const uchar*)data); + + uint i=0, j=0; + uint charArray3[3], charArray4[4]; + + char strBuf[kTmpBufSize + 1]; + strBuf[kTmpBufSize] = '\0'; + std::size_t strBufIndex = 0; + + String ret; + + for (std::size_t s=0; s> 2; + charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4); + charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6); + charArray4[3] = charArray3[2] & 0x3f; + + for (i=0; i<4; ++i) + strBuf[strBufIndex++] = kBase64Chars[charArray4[i]]; + + if (strBufIndex >= kTmpBufSize-7) + { + strBuf[strBufIndex] = '\0'; + strBufIndex = 0; + ret += strBuf; + } + + i = 0; + } + } + + if (i != 0) + { + for (j=i; j<3; ++j) + charArray3[j] = '\0'; + + charArray4[0] = (charArray3[0] & 0xfc) >> 2; + charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4); + charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6); + charArray4[3] = charArray3[2] & 0x3f; + + for (j=0; j<4 && i<3 && j 0) ? size : std::strlen(strBuf); + fBuffer = (char*)std::malloc(fBufferLen+1); + + if (fBuffer == nullptr) + { + fBuffer = _null(); + fBufferLen = 0; + fBufferAlloc = false; + return; + } + + fBufferAlloc = true; + + std::strcpy(fBuffer, strBuf); + fBuffer[fBufferLen] = '\0'; + } + else + { + DISTRHO_SAFE_ASSERT_UINT(size == 0, static_cast(size)); + + // don't recreate null string + if (! fBufferAlloc) + return; + + DISTRHO_SAFE_ASSERT(fBuffer != nullptr); + std::free(fBuffer); + + fBuffer = _null(); + fBufferLen = 0; + fBufferAlloc = false; + } + } + + DISTRHO_PREVENT_HEAP_ALLOCATION +}; + +// ----------------------------------------------------------------------- + +static inline +String operator+(const String& strBefore, const char* const strBufAfter) noexcept +{ + if (strBufAfter == nullptr || strBufAfter[0] == '\0') + return strBefore; + if (strBefore.isEmpty()) + return String(strBufAfter); + + const std::size_t strBeforeLen = strBefore.length(); + const std::size_t strBufAfterLen = std::strlen(strBufAfter); + const std::size_t newBufSize = strBeforeLen + strBufAfterLen; + char* const newBuf = (char*)malloc(newBufSize + 1); + DISTRHO_SAFE_ASSERT_RETURN(newBuf != nullptr, String()); + + std::memcpy(newBuf, strBefore.buffer(), strBeforeLen); + std::memcpy(newBuf + strBeforeLen, strBufAfter, strBufAfterLen + 1); + + return String(newBuf, false); +} + +static inline +String operator+(const char* const strBufBefore, const String& strAfter) noexcept +{ + if (strAfter.isEmpty()) + return String(strBufBefore); + if (strBufBefore == nullptr || strBufBefore[0] == '\0') + return strAfter; + + const std::size_t strBufBeforeLen = std::strlen(strBufBefore); + const std::size_t strAfterLen = strAfter.length(); + const std::size_t newBufSize = strBufBeforeLen + strAfterLen; + char* const newBuf = (char*)malloc(newBufSize + 1); + DISTRHO_SAFE_ASSERT_RETURN(newBuf != nullptr, String()); + + std::memcpy(newBuf, strBufBefore, strBufBeforeLen); + std::memcpy(newBuf + strBufBeforeLen, strAfter.buffer(), strAfterLen + 1); + + return String(newBuf, false); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_STRING_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/Thread.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/Thread.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,344 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_THREAD_HPP_INCLUDED +#define DISTRHO_THREAD_HPP_INCLUDED + +#include "Mutex.hpp" +#include "Sleep.hpp" +#include "String.hpp" + +#ifdef DISTRHO_OS_LINUX +# include +#endif + +#ifdef DISTRHO_OS_WASM +# error Threads do not work under wasm! +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// Thread class + +class Thread +{ +protected: + /* + * Constructor. + */ + Thread(const char* const threadName = nullptr) noexcept + : fLock(), + fSignal(), + fName(threadName), + #ifdef PTW32_DLLPORT + fHandle({nullptr, 0}), + #else + fHandle(0), + #endif + fShouldExit(false) {} + + /* + * Destructor. + */ + virtual ~Thread() /*noexcept*/ + { + DISTRHO_SAFE_ASSERT(! isThreadRunning()); + + stopThread(-1); + } + + /* + * Virtual function to be implemented by the subclass. + */ + virtual void run() = 0; + + // ------------------------------------------------------------------- + +public: + /* + * Check if the thread is running. + */ + bool isThreadRunning() const noexcept + { + #ifdef PTW32_DLLPORT + return (fHandle.p != nullptr); + #else + return (fHandle != 0); + #endif + } + + /* + * Check if the thread should exit. + */ + bool shouldThreadExit() const noexcept + { + return fShouldExit; + } + + /* + * Start the thread. + */ + bool startThread(const bool withRealtimePriority = false) noexcept + { + // check if already running + DISTRHO_SAFE_ASSERT_RETURN(! isThreadRunning(), true); + + pthread_t handle; + + pthread_attr_t attr; + pthread_attr_init(&attr); + + struct sched_param sched_param = {}; + + if (withRealtimePriority) + { + #ifdef __MOD_DEVICES__ + int rtprio; + const char* const srtprio = std::getenv("MOD_PLUGIN_THREAD_PRIORITY"); + if (srtprio != nullptr && (rtprio = std::atoi(srtprio)) > 0) + sched_param.sched_priority = rtprio - 1; + else + #endif + sched_param.sched_priority = 80; + + #ifndef DISTRHO_OS_HAIKU + if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) == 0 && + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) == 0 && + #ifndef DISTRHO_OS_WINDOWS + (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0 || + pthread_attr_setschedpolicy(&attr, SCHED_RR) == 0) && + #endif + pthread_attr_setschedparam(&attr, &sched_param) == 0) + { + d_stdout("Thread setup with realtime priority successful"); + } + else + #endif + { + d_stdout("Thread setup with realtime priority failed, going with normal priority instead"); + pthread_attr_destroy(&attr); + pthread_attr_init(&attr); + } + } + + const MutexLocker ml(fLock); + + fShouldExit = false; + + bool ok = pthread_create(&handle, &attr, _entryPoint, this) == 0; + pthread_attr_destroy(&attr); + + if (withRealtimePriority && !ok) + { + d_stdout("Thread with realtime priority failed on creation, going with normal priority instead"); + pthread_attr_init(&attr); + ok = pthread_create(&handle, &attr, _entryPoint, this) == 0; + pthread_attr_destroy(&attr); + } + + DISTRHO_SAFE_ASSERT_RETURN(ok, false); + #ifdef PTW32_DLLPORT + DISTRHO_SAFE_ASSERT_RETURN(handle.p != nullptr, false); + #else + DISTRHO_SAFE_ASSERT_RETURN(handle != 0, false); + #endif + pthread_detach(handle); + _copyFrom(handle); + + // wait for thread to start + fSignal.wait(); + return true; + } + + /* + * Stop the thread. + * In the 'timeOutMilliseconds': + * = 0 -> no wait + * > 0 -> wait timeout value + * < 0 -> wait forever + */ + bool stopThread(const int timeOutMilliseconds) noexcept + { + const MutexLocker ml(fLock); + + if (isThreadRunning()) + { + signalThreadShouldExit(); + + if (timeOutMilliseconds != 0) + { + // Wait for the thread to stop + int timeOutCheck = (timeOutMilliseconds == 1 || timeOutMilliseconds == -1) ? timeOutMilliseconds : timeOutMilliseconds/2; + + for (; isThreadRunning();) + { + d_msleep(2); + + if (timeOutCheck < 0) + continue; + + if (timeOutCheck > 0) + timeOutCheck -= 1; + else + break; + } + } + + if (isThreadRunning()) + { + // should never happen! + d_stderr2("assertion failure: \"! isThreadRunning()\" in file %s, line %i", __FILE__, __LINE__); + + // copy thread id so we can clear our one + pthread_t threadId; + _copyTo(threadId); + _init(); + + pthread_detach(threadId); + return false; + } + } + + return true; + } + + /* + * Tell the thread to stop as soon as possible. + */ + void signalThreadShouldExit() noexcept + { + fShouldExit = true; + } + + // ------------------------------------------------------------------- + + /* + * Returns the name of the thread. + * This is the name that gets set in the constructor. + */ + const String& getThreadName() const noexcept + { + return fName; + } + + /* + * Returns the Id/handle of the thread. + */ + pthread_t getThreadId() const noexcept + { + return fHandle; + } + + /* + * Changes the name of the caller thread. + */ + static void setCurrentThreadName(const char* const name) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); + + #ifdef DISTRHO_OS_LINUX + prctl(PR_SET_NAME, name, 0, 0, 0); + #endif + #if defined(__GLIBC__) && (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012 && !defined(DISTRHO_OS_GNU_HURD) + pthread_setname_np(pthread_self(), name); + #endif + } + + // ------------------------------------------------------------------- + +private: + Mutex fLock; // Thread lock + Signal fSignal; // Thread start wait signal + const String fName; // Thread name + volatile pthread_t fHandle; // Handle for this thread + volatile bool fShouldExit; // true if thread should exit + + /* + * Init pthread type. + */ + void _init() noexcept + { + #ifdef PTW32_DLLPORT + fHandle.p = nullptr; + fHandle.x = 0; + #else + fHandle = 0; + #endif + } + + /* + * Copy our pthread type from another var. + */ + void _copyFrom(const pthread_t& handle) noexcept + { + #ifdef PTW32_DLLPORT + fHandle.p = handle.p; + fHandle.x = handle.x; + #else + fHandle = handle; + #endif + } + + /* + * Copy our pthread type to another var. + */ + void _copyTo(volatile pthread_t& handle) const noexcept + { + #ifdef PTW32_DLLPORT + handle.p = fHandle.p; + handle.x = fHandle.x; + #else + handle = fHandle; + #endif + } + + /* + * Thread entry point. + */ + void _runEntryPoint() noexcept + { + if (fName.isNotEmpty()) + setCurrentThreadName(fName); + + // report ready + fSignal.signal(); + + try { + run(); + } catch(...) {} + + // done + _init(); + } + + /* + * Thread entry point. + */ + static void* _entryPoint(void* userData) noexcept + { + static_cast(userData)->_runEntryPoint(); + return nullptr; + } + + DISTRHO_DECLARE_NON_COPYABLE(Thread) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_THREAD_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/ValueSmoother.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/ValueSmoother.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,204 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2021 Jean Pierre Cimalando + * Copyright (C) 2021-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED +#define DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * @brief An exponential smoother for control values + * + * This continually smooths a value towards a defined target, + * using a low-pass filter of the 1st order, which creates an exponential curve. + * + * The length of the curve is defined by a T60 constant, + * which is the time it takes for a 1-to-0 smoothing to fall to -60dB. + * + * Note that this smoother has asymptotical behavior, + * and it must not be assumed that the final target is ever reached. + */ +class ExponentialValueSmoother { + float coef; + float target; + float mem; + float tau; + float sampleRate; + +public: + ExponentialValueSmoother() + : coef(0.f), + target(0.f), + mem(0.f), + tau(0.f), + sampleRate(0.f) {} + + void setSampleRate(const float newSampleRate) noexcept + { + if (d_isNotEqual(sampleRate, newSampleRate)) + { + sampleRate = newSampleRate; + updateCoef(); + } + } + + void setTimeConstant(const float newT60) noexcept + { + const float newTau = newT60 * (float)(1.0 / 6.91); + + if (d_isNotEqual(tau, newTau)) + { + tau = newTau; + updateCoef(); + } + } + + float getCurrentValue() const noexcept + { + return mem; + } + + float getTargetValue() const noexcept + { + return target; + } + + void setTargetValue(const float newTarget) noexcept + { + target = newTarget; + } + + void clearToTargetValue() noexcept + { + mem = target; + } + + inline float peek() const noexcept + { + return mem * coef + target * (1.f - coef); + } + + inline float next() noexcept + { + return (mem = mem * coef + target * (1.f - coef)); + } + +private: + void updateCoef() noexcept + { + coef = std::exp(-1.f / (tau * sampleRate)); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * @brief A linear smoother for control values + * + * This continually smooths a value towards a defined target, using linear segments. + * + * The duration of the smoothing segment is defined by the given time constant. + * Every time the target changes, a new segment restarts for the whole duration of the time constant. + * + * Note that this smoother, unlike an exponential smoother, eventually should converge to its target value. + */ +class LinearValueSmoother { + float step; + float target; + float mem; + float tau; + float sampleRate; + +public: + LinearValueSmoother() + : step(0.f), + target(0.f), + mem(0.f), + tau(0.f), + sampleRate(0.f) {} + + void setSampleRate(const float newSampleRate) noexcept + { + if (d_isNotEqual(sampleRate, newSampleRate)) + { + sampleRate = newSampleRate; + updateStep(); + } + } + + void setTimeConstant(const float newTau) noexcept + { + if (d_isNotEqual(tau, newTau)) + { + tau = newTau; + updateStep(); + } + } + + float getCurrentValue() const noexcept + { + return mem; + } + + float getTargetValue() const noexcept + { + return target; + } + + void setTargetValue(const float newTarget) noexcept + { + if (d_isNotEqual(target, newTarget)) + { + target = newTarget; + updateStep(); + } + } + + void clearToTargetValue() noexcept + { + mem = target; + } + + inline float peek() const noexcept + { + const float dy = target - mem; + return mem + std::copysign(std::fmin(std::abs(dy), std::abs(step)), dy); + } + + inline float next() noexcept + { + const float y0 = mem; + const float dy = target - y0; + return (mem = y0 + std::copysign(std::fmin(std::abs(dy), std::abs(step)), dy)); + } + +private: + void updateStep() noexcept + { + step = (target - mem) / (tau * sampleRate); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/sofd/libsofd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/sofd/libsofd.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2482 @@ +/* libSOFD - Simple Open File Dialog [for X11 without toolkit] + * + * Copyright (C) 2014 Robin Gareus + * + * 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. + */ + +/* Test and example: + * gcc -Wall -D SOFD_TEST -g -o sofd libsofd.c -lX11 + * + * public API documentation and example code at the bottom of this file + * + * This small lib may one day include openGL rendering and + * wayland window support, but not today. Today we celebrate + * 30 years of X11. + */ + +#ifdef SOFD_TEST +#define HAVE_X11 +#include "libsofd.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wnarrowing" +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnarrowing" +#endif + +// shared 'recently used' implementation +// sadly, xbel does not qualify as simple. +// hence we use a simple format alike the +// gtk-bookmark list (one file per line) + +#define MAX_RECENT_ENTRIES 24 +#define MAX_RECENT_AGE (15552000) // 180 days (in sec) + +typedef struct { + char path[1024]; + time_t atime; +} FibRecentFile; + +static FibRecentFile *_recentlist = NULL; +static unsigned int _recentcnt = 0; +static uint8_t _recentlock = 0; + +static int fib_isxdigit (const char x) { + if ( + (x >= '0' && x <= '9') + || + (x >= 'a' && x <= 'f') + || + (x >= 'A' && x <= 'F') + ) return 1; + return 0; +} + +static void decode_3986 (char *str) { + int len = strlen (str); + int idx = 0; + while (idx + 2 < len) { + char *in = &str[idx]; + if (('%' == *in) && fib_isxdigit (in[1]) && fib_isxdigit (in[2])) { + char hexstr[3]; + hexstr[0] = in[1]; + hexstr[1] = in[2]; + hexstr[2] = 0; + long hex = strtol (hexstr, NULL, 16); + *in = hex; + memmove (&str[idx+1], &str[idx + 3], len - idx - 2); + len -= 2; + } + ++idx; + } +} + +static char *encode_3986 (const char *str) { + size_t alloc, newlen; + char *ns = NULL; + unsigned char in; + size_t i = 0; + size_t length; + + if (!str) return strdup (""); + + alloc = strlen (str) + 1; + newlen = alloc; + + ns = (char*) malloc (alloc); + + length = alloc; + while (--length) { + in = *str; + + switch (in) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '_': case '~': case '.': case '-': + case '/': case ',': // XXX not in RFC3986 + ns[i++] = in; + break; + default: + newlen += 2; /* this'll become a %XX */ + if (newlen > alloc) { + alloc *= 2; + ns = (char*) realloc (ns, alloc); + } + snprintf (&ns[i], 4, "%%%02X", in); + i += 3; + break; + } + ++str; + } + ns[i] = 0; + return ns; +} + +void x_fib_free_recent () { + free (_recentlist); + _recentlist = NULL; + _recentcnt = 0; +} + +static int cmp_recent (const void *p1, const void *p2) { + FibRecentFile *a = (FibRecentFile*) p1; + FibRecentFile *b = (FibRecentFile*) p2; + if (a->atime == b->atime) return 0; + return a->atime < b->atime; +} + +int x_fib_add_recent (const char *path, time_t atime) { + unsigned int i; + struct stat fs; + if (_recentlock) { return -1; } + if (access (path, R_OK)) { + return -1; + } + if (stat (path, &fs)) { + return -1; + } + if (!S_ISREG (fs.st_mode)) { + return -1; + } + if (atime == 0) atime = time (NULL); + if (MAX_RECENT_AGE > 0 && atime + MAX_RECENT_AGE < time (NULL)) { + return -1; + } + + for (i = 0; i < _recentcnt; ++i) { + if (!strcmp (_recentlist[i].path, path)) { + if (_recentlist[i].atime < atime) { + _recentlist[i].atime = atime; + } + qsort (_recentlist, _recentcnt, sizeof(FibRecentFile), cmp_recent); + return _recentcnt; + } + } + _recentlist = (FibRecentFile*)realloc (_recentlist, (_recentcnt + 1) * sizeof(FibRecentFile)); + _recentlist[_recentcnt].atime = atime; + strcpy (_recentlist[_recentcnt].path, path); + qsort (_recentlist, _recentcnt + 1, sizeof(FibRecentFile), cmp_recent); + + if (_recentcnt >= MAX_RECENT_ENTRIES) { + return (_recentcnt); + } + return (++_recentcnt); +} + +#ifdef PATHSEP +#undef PATHSEP +#endif + +#ifdef PLATFORM_WINDOWS +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +static void mkpath(const char *dir) { + char tmp[1024]; + char *p; + size_t len; + + snprintf (tmp, sizeof(tmp), "%s", dir); + len = strlen(tmp); + if (tmp[len - 1] == '/') + tmp[len - 1] = 0; + for (p = tmp + 1; *p; ++p) + if(*p == DIRSEP) { + *p = 0; +#ifdef PLATFORM_WINDOWS + mkdir(tmp); +#else + mkdir(tmp, 0755); +#endif + *p = DIRSEP; + } +#ifdef PLATFORM_WINDOWS + mkdir(tmp); +#else + mkdir(tmp, 0755); +#endif +} + +int x_fib_save_recent (const char *fn) { + if (_recentlock) { return -1; } + if (!fn) { return -1; } + if (_recentcnt < 1 || !_recentlist) { return -1; } + unsigned int i; + char *dn = strdup (fn); + mkpath (dirname (dn)); + free (dn); + + FILE *rf = fopen (fn, "w"); + if (!rf) return -1; + + qsort (_recentlist, _recentcnt, sizeof(FibRecentFile), cmp_recent); + for (i = 0; i < _recentcnt; ++i) { + char *n = encode_3986 (_recentlist[i].path); + fprintf (rf, "%s %lu\n", n, _recentlist[i].atime); + free (n); + } + fclose (rf); + return 0; +} + +int x_fib_load_recent (const char *fn) { + char tmp[1024]; + if (_recentlock) { return -1; } + if (!fn) { return -1; } + x_fib_free_recent (); + if (access (fn, R_OK)) { + return -1; + } + FILE *rf = fopen (fn, "r"); + if (!rf) return -1; + while (fgets (tmp, sizeof(tmp), rf) + && strlen (tmp) > 1 + && strlen (tmp) < sizeof(tmp)) + { + char *s; + tmp[strlen (tmp) - 1] = '\0'; // strip newline + if (!(s = strchr (tmp, ' '))) { // find name <> atime sep + continue; + } + *s = '\0'; + time_t t = atol (++s); + decode_3986 (tmp); + x_fib_add_recent (tmp, t); + } + fclose (rf); + return 0; +} + +unsigned int x_fib_recent_count () { + return _recentcnt; +} + +const char *x_fib_recent_at (unsigned int i) { + if (i >= _recentcnt) + return NULL; + return _recentlist[i].path; +} + +#ifdef PLATFORM_WINDOWS +#define PATHSEP "\\" +#else +#define PATHSEP "/" +#endif + +const char *x_fib_recent_file(const char *appname) { + static char recent_file[1024]; + assert(!strchr(appname, '/')); + const char *xdg = getenv("XDG_DATA_HOME"); + if (xdg && (strlen(xdg) + strlen(appname) + 10) < sizeof(recent_file)) { + sprintf(recent_file, "%s" PATHSEP "%s" PATHSEP "recent", xdg, appname); + return recent_file; + } +#ifdef PLATFORM_WINDOWS + const char * homedrive = getenv("HOMEDRIVE"); + const char * homepath = getenv("HOMEPATH"); + if (homedrive && homepath && (strlen(homedrive) + strlen(homepath) + strlen(appname) + 29) < PATH_MAX) { + sprintf(recent_file, "%s%s" PATHSEP "Application Data" PATHSEP "%s" PATHSEP "recent.txt", homedrive, homepath, appname); + return recent_file; + } +#elif defined PLATFORM_OSX + const char *home = getenv("HOME"); + if (home && (strlen(home) + strlen(appname) + 29) < sizeof(recent_file)) { + sprintf(recent_file, "%s/Library/Preferences/%s/recent", home, appname); + return recent_file; + } +#else + const char *home = getenv("HOME"); + if (home && (strlen(home) + strlen(appname) + 22) < sizeof(recent_file)) { + sprintf(recent_file, "%s/.local/share/%s/recent", home, appname); + return recent_file; + } +#endif + return NULL; +} + +#ifdef HAVE_X11 +#include + +#include +#include +#include +#include +#include + +#if defined(__linux__) || defined(__linux) +#define HAVE_MNTENT +#include +#endif + +#ifndef MIN +#define MIN(A,B) ( (A) < (B) ? (A) : (B) ) +#endif + +#ifndef MAX +#define MAX(A,B) ( (A) < (B) ? (B) : (A) ) +#endif + +static Window _fib_win = 0; +static GC _fib_gc = 0; +static XColor _c_gray0, _c_gray1, _c_gray2, _c_gray3, _c_gray4, _c_gray5; +static Font _fibfont = 0; +static Pixmap _pixbuffer = None; + +static int _fib_width = 100; +static int _fib_height = 100; +static int _btn_w = 0; +static int _btn_span = 0; +static double _scalefactor = 1; + +static int _fib_font_height = 0; +static int _fib_dir_indent = 0; +static int _fib_spc_norm = 0; +static int _fib_font_ascent = 0; +static int _fib_font_vsep = 0; +static int _fib_font_size_width = 0; +static int _fib_font_time_width = 0; +static int _fib_place_width = 0; + +static int _scrl_f = 0; +static int _scrl_y0 = -1; +static int _scrl_y1 = -1; +static int _scrl_my = -1; +static int _scrl_mf = -1; +static int _view_p = -1; + +static int _fsel = -1; +static int _hov_b = -1; +static int _hov_f = -1; +static int _hov_p = -1; +static int _hov_h = -1; +static int _hov_l = -1; +static int _hov_s = -1; +static int _sort = 0; +static int _columns = 0; +static int _fib_filter_fn = 1; +static int _fib_hidden_fn = 0; +static int _fib_show_places = 0; + +static uint8_t _fib_mapped = 0; +static uint8_t _fib_resized = 0; +static unsigned long _dblclk = 0; + +static int _status = -2; +static char _rv_open[1024] = ""; + +static char _fib_cfg_custom_places[1024] = ""; +static char _fib_cfg_custom_font[256] = ""; +static char _fib_cfg_title[128] = "xjadeo - Open Video File"; + +typedef struct { + char name[256]; + int x0; + int xw; +} FibPathButton; + +typedef struct { + char name[256]; + char strtime[32]; + char strsize[32]; + int ssizew; + off_t size; + time_t mtime; + uint8_t flags; // 2: selected, 4: isdir 8: recent-entry + FibRecentFile *rfp; +} FibFileEntry; + +typedef struct { + char text[24]; + uint8_t flags; // 2: selected, 4: toggle, 8 disable + int x0; + int tw; + int xw; + void (*callback)(Display*); +} FibButton; + +typedef struct { + char name[256]; + char path[1024]; + uint8_t flags; // 1: hover, 2: selected, 4:add sep +} FibPlace; + +static char _cur_path[1024] = ""; +static FibFileEntry *_dirlist = NULL; +static FibPathButton *_pathbtn = NULL; +static FibPlace *_placelist = NULL; +static int _dircount = 0; +static int _pathparts = 0; +static int _placecnt = 0; + +static FibButton _btn_ok; +static FibButton _btn_cancel; +static FibButton _btn_filter; +static FibButton _btn_places; +static FibButton _btn_hidden; +static FibButton *_btns[] = {&_btn_places, &_btn_filter, &_btn_hidden, &_btn_cancel, &_btn_ok}; + +static int (*_fib_filter_function)(const char *filename); + +/* hardcoded layout */ +#define DSEP 6 // px; horiz space beween elements, also l+r margin for file-list +#define PSEP 4 // px; horiz space beween paths +#define FILECOLUMN (17 * _fib_dir_indent) //px; min width of file-column +#define LISTTOP 2.7 //em; top of the file-browser list +#define LISTBOT 4.75 //em; bottom of the file-browers list +#define BTNBTMMARGIN 0.75 //em; height/margin of the button row +#define BTNPADDING 2 // px - only used for open/cancel buttons +#define SCROLLBARW (3 + (_fib_spc_norm&~1)) //px; - should be SCROLLBARW = (N * 2 + 3) +#define SCROLLBOXH 10 //px; arrow box top+bottom +#define PLACESW _fib_place_width //px; +#define PLACESWMAX (15 *_fib_spc_norm) //px; +#define PATHBTNTOP _fib_font_vsep //px; offset by (_fib_font_ascent); +#define FAREAMRGB 3 //px; base L+R margin +#define FAREAMRGR (FAREAMRGB + 1) //px; right margin of file-area + 1 (line width) +#define FAREAMRGL (_fib_show_places ? PLACESW / _scalefactor + FAREAMRGB : FAREAMRGB) //px; left margin of file-area +#define TEXTSEP 4 //px; +#define FAREATEXTL (FAREAMRGL + TEXTSEP) //px; filename text-left FAREAMRGL + TEXTSEP +#define SORTBTNOFF -10 //px; + +#ifndef DBLCLKTME +#define DBLCLKTME 200 //msec; double click time +#endif + +#define DRAW_OUTLINE +#define DOUBLE_BUFFER +#define LIST_ENTRY_HOVER + +static int query_font_geometry (Display *dpy, GC gc, const char *txt, int *w, int *h, int *a, int *d) { + XCharStruct text_structure; + int font_direction, font_ascent, font_descent; + XFontStruct *fontinfo = XQueryFont (dpy, XGContextFromGC (gc)); + + if (!fontinfo) { return -1; } + XTextExtents (fontinfo, txt, strlen (txt), &font_direction, &font_ascent, &font_descent, &text_structure); + if (w) *w = XTextWidth (fontinfo, txt, strlen (txt)); + if (h) *h = text_structure.ascent + text_structure.descent; + if (a) *a = text_structure.ascent; + if (d) *d = text_structure.descent; +#ifndef DISTRHO_OS_HAIKU // FIXME + XFreeFontInfo (NULL, fontinfo, 1); +#endif + return 0; +} + +static void VDrawRectangle (Display *dpy, Drawable d, GC gc, int x, int y, unsigned int w, unsigned int h) { +#ifdef DRAW_OUTLINE + XSetForeground (dpy, gc, _c_gray5.pixel); + XDrawLine (dpy, d, gc, x + 1, y + h, x + w, y + h); + XDrawLine (dpy, d, gc, x + w, y + 1, x + w, y + h); + XDrawLine (dpy, d, gc, x + 1, y, x + w, y); + XDrawLine (dpy, d, gc, x, y + 1, x, y + h); +#else + const unsigned long blackColor = BlackPixel (dpy, DefaultScreen (dpy)); + XSetForeground (dpy, _fib_gc, blackColor); + XDrawRectangle (dpy, d, gc, x, y, w, h); +#endif +} + +static void fib_expose (Display *dpy, Window realwin) { + int i; + XID win; + if (!_fib_mapped) return; + + if (_fib_resized +#ifdef DOUBLE_BUFFER + || !_pixbuffer +#endif + ) + { +#ifdef DOUBLE_BUFFER + unsigned int w = 0, h = 0; + if (_pixbuffer != None) { + Window ignored_w; + int ignored_i; + unsigned int ignored_u; + XGetGeometry(dpy, _pixbuffer, &ignored_w, &ignored_i, &ignored_i, &w, &h, &ignored_u, &ignored_u); + if (_fib_width != (int)w || _fib_height != (int)h) { + XFreePixmap (dpy, _pixbuffer); + _pixbuffer = None; + } + } + if (_pixbuffer == None) { + XWindowAttributes wa; + XGetWindowAttributes (dpy, realwin, &wa); + _pixbuffer = XCreatePixmap (dpy, realwin, _fib_width, _fib_height, wa.depth); + } +#endif + if (_pixbuffer != None) { + XSetForeground (dpy, _fib_gc, _c_gray1.pixel); + XFillRectangle (dpy, _pixbuffer, _fib_gc, 0, 0, _fib_width, _fib_height); + } else { + XSetForeground (dpy, _fib_gc, _c_gray1.pixel); + XFillRectangle (dpy, realwin, _fib_gc, 0, 0, _fib_width, _fib_height); + } + _fib_resized = 0; + } + + if (_pixbuffer == None) { + win = realwin; + } else { + win = _pixbuffer; + } + + // Top Row: dirs and up navigation + + int ppw = 0; + int ppx = FAREAMRGB * _scalefactor; + + for (i = _pathparts - 1; i >= 0; --i) { + ppw += _pathbtn[i].xw + PSEP * _scalefactor; + if (ppw >= _fib_width - PSEP * _scalefactor - _pathbtn[0].xw - FAREAMRGB * _scalefactor) break; // XXX, first change is from "/" to "<", NOOP + } + ++i; + // border-less "<" parent/up, IFF space is limited + if (i > 0) { + if (0 == _hov_p || (_hov_p > 0 && _hov_p < _pathparts - 1)) { + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + } else { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } + XDrawString (dpy, win, _fib_gc, ppx, PATHBTNTOP, "<", 1); + ppx += _pathbtn[0].xw + PSEP * _scalefactor; + if (i == _pathparts) --i; + } + + _view_p = i; + + while (i < _pathparts) { + if (i == _hov_p) { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } else { + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + } + XFillRectangle (dpy, win, _fib_gc, + ppx + 1, PATHBTNTOP - _fib_font_ascent, + _pathbtn[i].xw - 1, _fib_font_height); + VDrawRectangle (dpy, win, _fib_gc, + ppx, PATHBTNTOP - _fib_font_ascent, + _pathbtn[i].xw, _fib_font_height); + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, ppx + 1 + BTNPADDING, PATHBTNTOP, + _pathbtn[i].name, strlen (_pathbtn[i].name)); + _pathbtn[i].x0 = ppx; // current position + ppx += _pathbtn[i].xw + PSEP * _scalefactor; + ++i; + } + + // middle, scroll list of file names + const int ltop = LISTTOP * _fib_font_vsep; + const int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + const int fsel_height = 4 * _scalefactor + llen * _fib_font_vsep; + const int fsel_width = _fib_width - (FAREAMRGL + FAREAMRGR) * _scalefactor - (llen < _dircount ? SCROLLBARW * _scalefactor : 0); + const int t_x = FAREATEXTL * _scalefactor; + int t_s = FAREATEXTL * _scalefactor + fsel_width; + int t_t = FAREATEXTL * _scalefactor + fsel_width; + + // check which colums can be visible + // depending on available width of window. + _columns = 0; + if (fsel_width > FILECOLUMN + _fib_font_size_width + _fib_font_time_width) { + _columns |= 2; + t_s = FAREAMRGL * _scalefactor + fsel_width - _fib_font_time_width - TEXTSEP * _scalefactor; + } + if (fsel_width > FILECOLUMN + _fib_font_size_width) { + _columns |= 1; + t_t = t_s - _fib_font_size_width - TEXTSEP * _scalefactor; + } + + int fstop = _scrl_f; // first entry in scroll position + const int ttop = ltop - _fib_font_height + _fib_font_ascent; + + if (fstop > 0 && fstop + llen > _dircount) { + fstop = MAX (0, _dircount - llen); + _scrl_f = fstop; + } + + // list header + XSetForeground (dpy, _fib_gc, _c_gray3.pixel); + XFillRectangle (dpy, win, _fib_gc, FAREAMRGL * _scalefactor, ltop - _fib_font_vsep, fsel_width, _fib_font_vsep); + + // draw background of file list + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + XFillRectangle (dpy, win, _fib_gc, FAREAMRGL * _scalefactor, ltop, fsel_width, fsel_height); + +#ifdef DRAW_OUTLINE + VDrawRectangle (dpy, win, _fib_gc, + FAREAMRGL * _scalefactor, + ltop - _fib_font_vsep - 1, + _fib_width - (FAREAMRGL + FAREAMRGR) * _scalefactor, + fsel_height + _fib_font_vsep + 1); +#endif + + switch (_hov_h) { + case 1: + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + XFillRectangle (dpy, win, _fib_gc, + t_x + _fib_dir_indent - (TEXTSEP - 1) * _scalefactor, + ltop - _fib_font_vsep, + t_t - t_x - _fib_dir_indent - 1 * _scalefactor, + _fib_font_vsep); + break; + case 2: + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + XFillRectangle (dpy, win, _fib_gc, + t_t - (TEXTSEP - 1) * _scalefactor, + ltop - _fib_font_vsep, + _fib_font_size_width + (TEXTSEP - 1) * _scalefactor, + _fib_font_vsep); + break; + case 3: + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + XFillRectangle (dpy, win, _fib_gc, + t_s - (TEXTSEP - 1) * _scalefactor, + ltop - _fib_font_vsep, + TEXTSEP * 2 * _scalefactor + _fib_font_time_width - 1 * _scalefactor, + _fib_font_vsep); + break; + default: + break; + } + + // column headings and sort order + int arp = MAX (2 * _scalefactor, _fib_font_height / 5); // arrow scale + const int trioff = _fib_font_height - _fib_font_ascent - arp + 1 * _scalefactor; + XPoint ptri[4] = { {0, ttop - trioff }, {arp, -arp - arp - 1 * _scalefactor}, {-arp - arp, 0}, {arp, arp + arp + 1 * _scalefactor}}; + if (_sort & 1) { + ptri[0].y = ttop -arp - arp - 1 * _scalefactor; + ptri[1].y *= -1; + ptri[3].y *= -1; + } + switch (_sort) { + case 0: + case 1: + ptri[0].x = t_t + (SORTBTNOFF + 2) * _scalefactor - arp; + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XFillPolygon (dpy, win, _fib_gc, ptri, 3, Convex, CoordModePrevious); + XDrawLines (dpy, win, _fib_gc, ptri, 4, CoordModePrevious); + break; + case 2: + case 3: + if (_columns & 1) { + ptri[0].x = t_s + (SORTBTNOFF + 2) * _scalefactor - arp; + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XFillPolygon (dpy, win, _fib_gc, ptri, 3, Convex, CoordModePrevious); + XDrawLines (dpy, win, _fib_gc, ptri, 4, CoordModePrevious); + } + break; + case 4: + case 5: + if (_columns & 2) { + ptri[0].x = FAREATEXTL * _scalefactor + fsel_width + (SORTBTNOFF + 2) * _scalefactor - arp; + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XFillPolygon (dpy, win, _fib_gc, ptri, 3, Convex, CoordModePrevious); + XDrawLines (dpy, win, _fib_gc, ptri, 4, CoordModePrevious); + } + break; + } + +#if 0 // bottom header bottom border + XSetForeground (dpy, _fib_gc, _c_gray5.pixel); + XSetLineAttributes (dpy, _fib_gc, 1, LineOnOffDash, CapButt, JoinMiter); + XDrawLine (dpy, win, _fib_gc, + FAREAMRGL + 1, ltop, + FAREAMRGL + fsel_width, ltop); + XSetLineAttributes (dpy, _fib_gc, 1, LineSolid, CapButt, JoinMiter); +#endif + + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + XDrawLine (dpy, win, _fib_gc, + t_x + _fib_dir_indent - TEXTSEP * _scalefactor, ltop - _fib_font_vsep + 3 * _scalefactor, + t_x + _fib_dir_indent - TEXTSEP * _scalefactor, ltop - 3 * _scalefactor); + + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, t_x + _fib_dir_indent, ttop, "Name", 4); + + if (_columns & 1) { + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + XDrawLine (dpy, win, _fib_gc, + t_t - TEXTSEP * _scalefactor, ltop - _fib_font_vsep + 3 * _scalefactor, + t_t - TEXTSEP * _scalefactor, ltop - 3 * _scalefactor); + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, t_t, ttop, "Size", 4); + } + + if (_columns & 2) { + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + XDrawLine (dpy, win, _fib_gc, + t_s - TEXTSEP * _scalefactor, ltop - _fib_font_vsep + 3 * _scalefactor, + t_s - TEXTSEP * _scalefactor, ltop - 3 * _scalefactor); + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + if (_pathparts > 0) + XDrawString (dpy, win, _fib_gc, t_s, ttop, "Last Modified", 13); + else + XDrawString (dpy, win, _fib_gc, t_s, ttop, "Last Used", 9); + } + + // scrollbar sep + if (llen < _dircount) { + const int sx0 = _fib_width - (SCROLLBARW + FAREAMRGR) * _scalefactor; + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + XDrawLine (dpy, win, _fib_gc, + sx0 - 1, ltop - _fib_font_vsep, +#ifdef DRAW_OUTLINE + sx0 - 1, ltop + fsel_height +#else + sx0 - 1, ltop - 1 +#endif + ); + } + + // clip area for file-name + XRectangle clp = {(FAREAMRGL + 1) * _scalefactor, ltop, + t_t - (FAREAMRGL + TEXTSEP * 2 + 1) * _scalefactor, fsel_height}; + + // list files in view + for (i = 0; i < llen; ++i) { + const int j = i + fstop; + if (j >= _dircount) break; + + const int t_y = ltop + (i+1) * _fib_font_vsep - 4; + + if (_dirlist[j].flags & 2) { + XSetForeground (dpy, _fib_gc, _c_gray5.pixel); + XFillRectangle (dpy, win, _fib_gc, + FAREAMRGL * _scalefactor, t_y - _fib_font_ascent, fsel_width, _fib_font_height); + } + /* + if (_hov_f == j && !(_dirlist[j].flags & 2)) { + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + } + */ + if (_dirlist[j].flags & 4) { + XSetForeground (dpy, _fib_gc, (_dirlist[j].flags & 2) ? _c_gray3.pixel : _c_gray5.pixel); + XDrawString (dpy, win, _fib_gc, t_x, t_y, "D", 1); + } + XSetClipRectangles (dpy, _fib_gc, 0, 0, &clp, 1, Unsorted); + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, + t_x + _fib_dir_indent, t_y, + _dirlist[j].name, strlen (_dirlist[j].name)); + XSetClipMask (dpy, _fib_gc, None); + + if (_columns & 1) // right-aligned 'size' + XDrawString (dpy, win, _fib_gc, + t_s - (TEXTSEP + 2) * _scalefactor - _dirlist[j].ssizew, t_y, + _dirlist[j].strsize, strlen (_dirlist[j].strsize)); + if (_columns & 2) + XDrawString (dpy, win, _fib_gc, + t_s, t_y, + _dirlist[j].strtime, strlen (_dirlist[j].strtime)); + } + + // scrollbar + if (llen < _dircount) { + float sl = (fsel_height + _fib_font_vsep - (SCROLLBOXH + SCROLLBOXH) * _scalefactor) / (float) _dircount; + sl = MAX ((8. * _scalefactor / llen), sl); // 8px min height of scroller + const int sy1 = llen * sl; + const float mx = (fsel_height + _fib_font_vsep - (SCROLLBOXH + SCROLLBOXH) * _scalefactor - sy1) / (float)(_dircount - llen); + const int sy0 = fstop * mx; + const int sx0 = _fib_width - (SCROLLBARW + FAREAMRGR) * _scalefactor; + const int stop = ltop - _fib_font_vsep; + + _scrl_y0 = stop + SCROLLBOXH * _scalefactor + sy0; + _scrl_y1 = _scrl_y0 + sy1; + + assert (fstop + llen <= _dircount); + // scroll-bar background + XSetForeground (dpy, _fib_gc, _c_gray1.pixel); + XFillRectangle (dpy, win, _fib_gc, sx0, stop, SCROLLBARW * _scalefactor, fsel_height + _fib_font_vsep); + + // scroller + if (_hov_s == 0 || _hov_s == 1 || _hov_s == 2) { + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + } else { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } + XFillRectangle (dpy, win, _fib_gc, sx0 + 1 * _scalefactor, stop + SCROLLBOXH * _scalefactor + sy0, (SCROLLBARW - 2) * _scalefactor, sy1); + + int scrw = (SCROLLBARW -3) / 2 * _scalefactor; + // arrows top and bottom + if (_hov_s == 1) { + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + } else { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } + XPoint ptst[4] = { {sx0 + 1 * _scalefactor, stop + 8 * _scalefactor}, {scrw, -7 * _scalefactor}, {scrw, 7 * _scalefactor}, {-2 * scrw, 0}}; + XFillPolygon (dpy, win, _fib_gc, ptst, 3, Convex, CoordModePrevious); + XDrawLines (dpy, win, _fib_gc, ptst, 4, CoordModePrevious); + + if (_hov_s == 2) { + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + } else { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } + XPoint ptsb[4] = { {sx0 + 1 * _scalefactor, ltop + fsel_height - 9 * _scalefactor}, {2*scrw, 0}, {-scrw, 7 * _scalefactor}, {-scrw, -7 * _scalefactor}}; + XFillPolygon (dpy, win, _fib_gc, ptsb, 3, Convex, CoordModePrevious); + XDrawLines (dpy, win, _fib_gc, ptsb, 4, CoordModePrevious); + } else { + _scrl_y0 = _scrl_y1 = -1; + } + + if (_fib_show_places) { + assert (_placecnt > 0); + + // heading + XSetForeground (dpy, _fib_gc, _c_gray3.pixel); + XFillRectangle (dpy, win, _fib_gc, FAREAMRGB * _scalefactor, ltop - _fib_font_vsep, PLACESW - TEXTSEP * _scalefactor, _fib_font_vsep); + + // body + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + XFillRectangle (dpy, win, _fib_gc, FAREAMRGB * _scalefactor, ltop, PLACESW - TEXTSEP * _scalefactor, fsel_height); + +#ifdef DRAW_OUTLINE + VDrawRectangle (dpy, win, _fib_gc, FAREAMRGB * _scalefactor, ltop - _fib_font_vsep -1, PLACESW - TEXTSEP * _scalefactor, fsel_height + _fib_font_vsep + 1); +#endif + + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, (FAREAMRGB + TEXTSEP) * _scalefactor, ttop, "Places", 6); + + XRectangle pclip = {(FAREAMRGB + 1) * _scalefactor, ltop, PLACESW - (TEXTSEP + 1) * _scalefactor, fsel_height}; + XSetClipRectangles (dpy, _fib_gc, 0, 0, &pclip, 1, Unsorted); + const int plx = (FAREAMRGB + TEXTSEP) * _scalefactor; + for (i = 0; i < llen && i < _placecnt; ++i) { + const int ply = ltop + (i+1) * _fib_font_vsep - 4 * _scalefactor; + if (i == _hov_l) { + XSetForeground (dpy, _fib_gc, _c_gray5.pixel); + XFillRectangle (dpy, win, _fib_gc, FAREAMRGB * _scalefactor, ltop + i * _fib_font_vsep, PLACESW - TEXTSEP * _scalefactor, _fib_font_vsep); + } + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, + plx, ply, + _placelist[i].name, strlen (_placelist[i].name)); + if (_placelist[i].flags & 4) { + XSetForeground (dpy, _fib_gc, _c_gray5.pixel); + const int plly = ply - _fib_font_ascent + _fib_font_height + 1 * _scalefactor; + const int pllx0 = FAREAMRGB * _scalefactor; + const int pllx1 = FAREAMRGB * _scalefactor + PLACESW - TEXTSEP * _scalefactor; + XDrawLine (dpy, win, _fib_gc, pllx0, plly, pllx1, plly); + } + } + XSetClipMask (dpy, _fib_gc, None); + + if (_placecnt > llen) { + const int plly = ltop + fsel_height - _fib_font_height + _fib_font_ascent; + const int pllx0 = FAREAMRGB * _scalefactor + (PLACESW - TEXTSEP * _scalefactor) * .75; + const int pllx1 = FAREAMRGB * _scalefactor + PLACESW - TEXTSEP * 2 * _scalefactor; + + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XSetLineAttributes (dpy, _fib_gc, 1 * _scalefactor, LineOnOffDash, CapButt, JoinMiter); + XDrawLine (dpy, win, _fib_gc, pllx0, plly, pllx1, plly); + XSetLineAttributes (dpy, _fib_gc, 1 * _scalefactor, LineSolid, CapButt, JoinMiter); + } + } + + // Bottom Buttons + const int numb = sizeof(_btns) / sizeof(FibButton*); + int xtra = _fib_width - _btn_span; + const int cbox = _fib_font_ascent - 2 * _scalefactor; + const int bbase = _fib_height - BTNBTMMARGIN * _fib_font_vsep - BTNPADDING * _scalefactor; + const int cblw = cbox > 20 * _scalefactor + ? 5 * _scalefactor + : (cbox > 9 * _scalefactor ? 3 : 1) * _scalefactor; + + int bx = FAREAMRGB * _scalefactor; + for (i = 0; i < numb; ++i) { + if (_btns[i]->flags & 8) { continue; } + if (_btns[i]->flags & 4) { + // checkbutton + const int cby0 = bbase - cbox + (1 + BTNPADDING) * _scalefactor; + if (i == _hov_b) { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } else { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } + XDrawRectangle (dpy, win, _fib_gc, + bx, cby0 - 1, cbox + 1, cbox + 1); + + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, BTNPADDING * _scalefactor + bx + _fib_font_ascent, bbase + (BTNPADDING + 1) * _scalefactor, + _btns[i]->text, strlen (_btns[i]->text)); + + if (i == _hov_b) { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } else { + /* if (_btns[i]->flags & 2) { + XSetForeground (dpy, _fib_gc, _c_gray1.pixel); + } else */ { + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + } + } + XFillRectangle (dpy, win, _fib_gc, + bx+1, cby0, cbox, cbox); + + if (_btns[i]->flags & 2) { + XSetLineAttributes (dpy, _fib_gc, cblw, LineSolid, CapRound, JoinMiter); + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawLine (dpy, win, _fib_gc, + bx + 2, cby0 + 1, + bx + cbox - 1, cby0 + cbox - 2); + XDrawLine (dpy, win, _fib_gc, + bx + cbox - 1, cby0 + 1, + bx + 2, cby0 + cbox - 2); + XSetLineAttributes (dpy, _fib_gc, 1, LineSolid, CapButt, JoinMiter); + } + } else { + if (xtra > 0) { + bx += xtra; + xtra = 0; + } + // pushbutton + + uint8_t can_hover = 1; // special case + if (_btns[i] == &_btn_ok) { + if (_fsel < 0 || _fsel >= _dircount) { + can_hover = 0; + } + } + + if (can_hover && i == _hov_b) { + XSetForeground (dpy, _fib_gc, _c_gray0.pixel); + } else { + XSetForeground (dpy, _fib_gc, _c_gray2.pixel); + } + XFillRectangle (dpy, win, _fib_gc, + bx + 1, bbase - _fib_font_ascent, + _btn_w - 1, _fib_font_height + BTNPADDING * 2 * _scalefactor); + VDrawRectangle (dpy, win, _fib_gc, + bx, bbase - _fib_font_ascent, + _btn_w, _fib_font_height + BTNPADDING * 2 * _scalefactor); + XSetForeground (dpy, _fib_gc, _c_gray4.pixel); + XDrawString (dpy, win, _fib_gc, bx + (_btn_w - _btns[i]->tw) * .5, 1 + bbase + BTNPADDING * _scalefactor, + _btns[i]->text, strlen (_btns[i]->text)); + } + _btns[i]->x0 = bx; + bx += _btns[i]->xw + DSEP * _scalefactor; + } + + if (_pixbuffer != None) { + XCopyArea(dpy, _pixbuffer, realwin, _fib_gc, 0, 0, _fib_width, _fib_height, 0, 0); + } + XFlush (dpy); +} + +static void fib_reset () { + _hov_p = _hov_f = _hov_h = _hov_l = -1; + _scrl_f = 0; + _fib_resized = 1; +} + +static int cmp_n_up (const void *p1, const void *p2) { + FibFileEntry *a = (FibFileEntry*) p1; + FibFileEntry *b = (FibFileEntry*) p2; + if ((a->flags & 4) && !(b->flags & 4)) return -1; + if (!(a->flags & 4) && (b->flags & 4)) return 1; + return strcmp (a->name, b->name); +} + +static int cmp_n_down (const void *p1, const void *p2) { + FibFileEntry *a = (FibFileEntry*) p1; + FibFileEntry *b = (FibFileEntry*) p2; + if ((a->flags & 4) && !(b->flags & 4)) return -1; + if (!(a->flags & 4) && (b->flags & 4)) return 1; + return strcmp (b->name, a->name); +} + +static int cmp_t_up (const void *p1, const void *p2) { + FibFileEntry *a = (FibFileEntry*) p1; + FibFileEntry *b = (FibFileEntry*) p2; + if ((a->flags & 4) && !(b->flags & 4)) return -1; + if (!(a->flags & 4) && (b->flags & 4)) return 1; + if (a->mtime == b->mtime) return 0; + return a->mtime > b->mtime ? -1 : 1; +} + +static int cmp_t_down (const void *p1, const void *p2) { + FibFileEntry *a = (FibFileEntry*) p1; + FibFileEntry *b = (FibFileEntry*) p2; + if ((a->flags & 4) && !(b->flags & 4)) return -1; + if (!(a->flags & 4) && (b->flags & 4)) return 1; + if (a->mtime == b->mtime) return 0; + return a->mtime > b->mtime ? 1 : -1; +} + +static int cmp_s_up (const void *p1, const void *p2) { + FibFileEntry *a = (FibFileEntry*) p1; + FibFileEntry *b = (FibFileEntry*) p2; + if ((a->flags & 4) && (b->flags & 4)) return 0; // dir, no size, retain order + if ((a->flags & 4) && !(b->flags & 4)) return -1; + if (!(a->flags & 4) && (b->flags & 4)) return 1; + if (a->size == b->size) return 0; + return a->size > b->size ? -1 : 1; +} + +static int cmp_s_down (const void *p1, const void *p2) { + FibFileEntry *a = (FibFileEntry*) p1; + FibFileEntry *b = (FibFileEntry*) p2; + if ((a->flags & 4) && (b->flags & 4)) return 0; // dir, no size, retain order + if ((a->flags & 4) && !(b->flags & 4)) return -1; + if (!(a->flags & 4) && (b->flags & 4)) return 1; + if (a->size == b->size) return 0; + return a->size > b->size ? 1 : -1; +} + +static void fmt_size (Display *dpy, FibFileEntry *f) { + if (f->size > 10995116277760) { + sprintf (f->strsize, "%.0f TB", f->size / 1099511627776.f); + } + if (f->size > 1099511627776) { + sprintf (f->strsize, "%.1f TB", f->size / 1099511627776.f); + } + else if (f->size > 10737418240) { + sprintf (f->strsize, "%.0f GB", f->size / 1073741824.f); + } + else if (f->size > 1073741824) { + sprintf (f->strsize, "%.1f GB", f->size / 1073741824.f); + } + else if (f->size > 10485760) { + sprintf (f->strsize, "%.0f MB", f->size / 1048576.f); + } + else if (f->size > 1048576) { + sprintf (f->strsize, "%.1f MB", f->size / 1048576.f); + } + else if (f->size > 10240) { + sprintf (f->strsize, "%.0f KB", f->size / 1024.f); + } + else if (f->size >= 1000) { + sprintf (f->strsize, "%.1f KB", f->size / 1024.f); + } + else { + sprintf (f->strsize, "%.0f B", f->size / 1.f); + } + int sw = 0; + query_font_geometry (dpy, _fib_gc, f->strsize, &sw, NULL, NULL, NULL); + if (sw > _fib_font_size_width) { + _fib_font_size_width = sw; + } + f->ssizew = sw; +} + +static void fmt_time (Display *dpy, FibFileEntry *f) { + struct tm *tmp; + tmp = localtime (&f->mtime); + if (!tmp) { + return; + } + strftime (f->strtime, sizeof(f->strtime), "%F %H:%M", tmp); + + int tw = 0; + query_font_geometry (dpy, _fib_gc, f->strtime, &tw, NULL, NULL, NULL); + if (tw > _fib_font_time_width) { + _fib_font_time_width = tw; + } +} + +static void fib_resort (const char * sel) { + if (_dircount < 1) { return; } + int (*sortfn)(const void *p1, const void *p2); + switch (_sort) { + case 1: sortfn = &cmp_n_down; break; + case 2: sortfn = &cmp_s_down; break; + case 3: sortfn = &cmp_s_up; break; + case 4: sortfn = &cmp_t_down; break; + case 5: sortfn = &cmp_t_up; break; + default: + sortfn = &cmp_n_up; + break; + } + qsort (_dirlist, _dircount, sizeof(_dirlist[0]), sortfn); + int i; + for (i = 0; i < _dircount && sel; ++i) { + if (!strcmp (_dirlist[i].name, sel)) { + _fsel = i; + break; + } + } +} + +static void fib_select (Display *dpy, int item) { + if (_fsel >= 0) { + _dirlist[_fsel].flags &= ~2; + } + _fsel = item; + if (_fsel >= 0 && _fsel < _dircount) { + _dirlist[_fsel].flags |= 2; + const int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + if (_fsel < _scrl_f) { + _scrl_f = _fsel; + } + else if (_fsel >= _scrl_f + llen) { + _scrl_f = 1 + _fsel - llen; + } + } else { + _fsel = -1; + } + + fib_expose (dpy, _fib_win); +} + +static inline int fib_filter (const char *name) { + if (_fib_filter_function) { + return _fib_filter_function (name); + } else { + return 1; + } +} + +static void fib_pre_opendir (Display *dpy) { + if (_dirlist) free (_dirlist); + if (_pathbtn) free (_pathbtn); + _dirlist = NULL; + _pathbtn = NULL; + _dircount = 0; + _pathparts = 0; + query_font_geometry (dpy, _fib_gc, "Size ", &_fib_font_size_width, NULL, NULL, NULL); + fib_reset (); + _fsel = -1; +} + +static void fib_post_opendir (Display *dpy, const char *sel) { + if (_dircount > 0) + _fsel = 0; // select first + else + _fsel = -1; + fib_resort (sel); + + if (_dircount > 0 && _fsel >= 0) { + fib_select (dpy, _fsel); + } else { + fib_expose (dpy, _fib_win); + } +} + +static int fib_dirlistadd (Display *dpy, const int i, const char* path, const char *name, time_t mtime) { + char tp[1024]; + struct stat fs; + if (!_fib_hidden_fn && name[0] == '.') return -1; + if (!strcmp (name, ".")) return -1; + if (!strcmp (name, "..")) return -1; + strcpy (tp, path); + strcat (tp, name); + if (access (tp, R_OK)) { + return -1; + } + if (stat (tp, &fs)) { + return -1; + } + assert (i < _dircount); // could happen if dir changes while we're reading. + if (i >= _dircount) return -1; + if (S_ISDIR (fs.st_mode)) { + _dirlist[i].flags |= 4; + } + else if (S_ISREG (fs.st_mode)) { + if (!fib_filter (name)) return -1; + } +#if 0 // only needed with lstat() + else if (S_ISLNK (fs.st_mode)) { + if (!fib_filter (name)) return -1; + } +#endif + else { + return -1; + } + strcpy (_dirlist[i].name, name); + _dirlist[i].mtime = mtime > 0 ? mtime : fs.st_mtime; + _dirlist[i].size = fs.st_size; + if (!(_dirlist[i].flags & 4)) + fmt_size (dpy, &_dirlist[i]); + fmt_time (dpy, &_dirlist[i]); + return 0; +} + +static int fib_openrecent (Display *dpy, const char *sel) { + int i; + unsigned int j; + assert (_recentcnt > 0); + fib_pre_opendir (dpy); + query_font_geometry (dpy, _fib_gc, "Last Used", &_fib_font_time_width, NULL, NULL, NULL); + _dirlist = (FibFileEntry*) calloc (_recentcnt, sizeof(FibFileEntry)); + _dircount = _recentcnt; + for (j = 0, i = 0; j < _recentcnt; ++j) { + char base[1024]; + char *s = strrchr (_recentlist[j].path, '/'); + if (!s || !*++s) continue; + size_t len = (s - _recentlist[j].path); + strncpy (base, _recentlist[j].path, len); + base[len] = '\0'; + if (!fib_dirlistadd (dpy, i, base, s, _recentlist[j].atime)) { + _dirlist[i].rfp = &_recentlist[j]; + _dirlist[i].flags |= 8; + ++i; + } + } + _dircount = i; + fib_post_opendir (dpy, sel); + return _dircount; +} + +static int fib_opendir (Display *dpy, const char* path, const char *sel) { + char *t0, *t1; + int i; + + assert (path); + + if (strlen (path) == 0 && _recentcnt > 0) { // XXX we should use a better indication for this + strcpy (_cur_path, ""); + return fib_openrecent (dpy, sel); + } + + assert (strlen (path) < sizeof(_cur_path) -1); + assert (strlen (path) > 0); + assert (strstr (path, "//") == NULL); + assert (path[0] == '/'); + + fib_pre_opendir (dpy); + + query_font_geometry (dpy, _fib_gc, "Last Modified", &_fib_font_time_width, NULL, NULL, NULL); + DIR *dir = opendir (path); + if (!dir) { + strcpy (_cur_path, "/"); + } else { + int i; + struct dirent *de; + if (path != _cur_path) + strcpy (_cur_path, path); + + if (_cur_path[strlen (_cur_path) -1] != '/') + strcat (_cur_path, "/"); + + while ((de = readdir (dir))) { + if (!_fib_hidden_fn && de->d_name[0] == '.') continue; + ++_dircount; + } + + if (_dircount > 0) + _dirlist = (FibFileEntry*) calloc (_dircount, sizeof(FibFileEntry)); + + rewinddir (dir); + + i = 0; + while ((de = readdir (dir))) { + if (!fib_dirlistadd (dpy, i, _cur_path, de->d_name, 0)) + ++i; + } + _dircount = i; + closedir (dir); + } + + t0 = _cur_path; + while (*t0 && (t0 = strchr (t0, '/'))) { + ++_pathparts; + ++t0; + } + assert (_pathparts > 0); + _pathbtn = (FibPathButton*) calloc (_pathparts + 1, sizeof(FibPathButton)); + + t1 = _cur_path; + i = 0; + while (*t1 && (t0 = strchr (t1, '/'))) { + if (i == 0) { + strcpy (_pathbtn[i].name, "/"); + } else { + *t0 = 0; + strcpy (_pathbtn[i].name, t1); + } + query_font_geometry (dpy, _fib_gc, _pathbtn[i].name, &_pathbtn[i].xw, NULL, NULL, NULL); + _pathbtn[i].xw += BTNPADDING + BTNPADDING; + *t0 = '/'; + t1 = t0 + 1; + ++i; + } + fib_post_opendir (dpy, sel); + return _dircount; +} + +static int fib_open (Display *dpy, int item) { + char tp[1024]; + if (_dirlist[item].flags & 8) { + assert (_dirlist[item].rfp); + strcpy (_rv_open, _dirlist[item].rfp->path); + _status = 1; + return 0; + } + strcpy (tp, _cur_path); + strcat (tp, _dirlist[item].name); + if (_dirlist[item].flags & 4) { + fib_opendir (dpy, tp, NULL); + return 0; + } else { + _status = 1; + strcpy (_rv_open, tp); + } + return 0; +} + +static void cb_cancel (Display *dpy) { + _status = -1; + + // unused + return; (void)dpy; +} + +static void cb_open (Display *dpy) { + if (_fsel >= 0 && _fsel < _dircount) { + fib_open (dpy, _fsel); + } +} + +static void sync_button_states () { + if (_fib_show_places) + _btn_places.flags |= 2; + else + _btn_places.flags &= ~2; + if (_fib_filter_fn) // inverse -> show all + _btn_filter.flags &= ~2; + else + _btn_filter.flags |= 2; + if (_fib_hidden_fn) + _btn_hidden.flags |= 2; + else + _btn_hidden.flags &= ~2; +} + +static void cb_places (Display *dpy) { + _fib_show_places = ! _fib_show_places; + if (_placecnt < 1) + _fib_show_places = 0; + sync_button_states (); + _fib_resized = 1; + fib_expose (dpy, _fib_win); +} + +static void cb_filter (Display *dpy) { + _fib_filter_fn = ! _fib_filter_fn; + sync_button_states (); + char *sel = _fsel >= 0 ? strdup (_dirlist[_fsel].name) : NULL; + fib_opendir (dpy, _cur_path, sel); + free (sel); +} + +static void cb_hidden (Display *dpy) { + _fib_hidden_fn = ! _fib_hidden_fn; + sync_button_states (); + char *sel = _fsel >= 0 ? strdup (_dirlist[_fsel].name) : NULL; + fib_opendir (dpy, _cur_path, sel); + free (sel); +} + +static int fib_widget_at_pos (Display *dpy, int x, int y, int *it) { + const int btop = _fib_height - BTNBTMMARGIN * _fib_font_vsep - _fib_font_ascent - BTNPADDING * _scalefactor; + const int bbot = btop + _fib_font_height + BTNPADDING * 2 * _scalefactor; + const int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + const int ltop = LISTTOP * _fib_font_vsep; + const int fbot = ltop + 4 * _scalefactor + llen * _fib_font_vsep; + const int ptop = PATHBTNTOP - _fib_font_ascent; + assert (it); + + // paths at top + if (y > ptop && y < ptop + _fib_font_height && _view_p >= 0 && _pathparts > 0) { + int i = _view_p; + *it = -1; + if (i > 0) { // special case '<' + if (x > FAREAMRGB * _scalefactor && x <= FAREAMRGB * _scalefactor + _pathbtn[0].xw) { + *it = _view_p - 1; + i = _pathparts; + } + } + while (i < _pathparts) { + if (x >= _pathbtn[i].x0 && x <= _pathbtn[i].x0 + _pathbtn[i].xw) { + *it = i; + break; + } + ++i; + } + assert (*it < _pathparts); + if (*it >= 0) return 1; + else return 0; + } + + // buttons at bottom + if (y > btop && y < bbot) { + size_t i; + *it = -1; + for (i = 0; i < sizeof(_btns) / sizeof(FibButton*); ++i) { + const int bx = _btns[i]->x0; + if (_btns[i]->flags & 8) { continue; } + if (x > bx && x < bx + _btns[i]->xw) { + *it = i; + } + } + if (*it >= 0) return 3; + else return 0; + } + + // main file area + if (y >= ltop - _fib_font_vsep && y < fbot && x > FAREAMRGL * _scalefactor && x < _fib_width - FAREAMRGR * _scalefactor) { + // scrollbar + if (_scrl_y0 > 0 && x >= _fib_width - (FAREAMRGR + SCROLLBARW) * _scalefactor && x <= _fib_width - FAREAMRGR * _scalefactor) { + if (y >= _scrl_y0 && y < _scrl_y1) { + *it = 0; + } else if (y >= _scrl_y1) { + *it = 2; + } else { + *it = 1; + } + return 4; + } + // file-list + else if (y >= ltop) { + const int item = (y - ltop) / _fib_font_vsep + _scrl_f; + *it = -1; + if (item >= 0 && item < _dircount) { + *it = item; + } + if (*it >= 0) return 2; + else return 0; + } + else { + *it = -1; + const int fsel_width = _fib_width - (FAREAMRGL + FAREAMRGR) * _scalefactor - (llen < _dircount ? SCROLLBARW * _scalefactor : 0); + const int t_s = FAREAMRGL * _scalefactor + fsel_width - _fib_font_time_width - TEXTSEP * 2 * _scalefactor; + const int t_t = FAREAMRGL * _scalefactor + fsel_width - TEXTSEP * _scalefactor - _fib_font_size_width - ((_columns & 2) ? ( _fib_font_time_width + TEXTSEP * 2 * _scalefactor) : 0); + if (x >= fsel_width + FAREAMRGL * _scalefactor) ; + else if ((_columns & 2) && x >= t_s) *it = 3; + else if ((_columns & 1) && x >= t_t) *it = 2; + else if (x >= FAREATEXTL * _scalefactor + _fib_dir_indent - TEXTSEP * _scalefactor) *it = 1; + if (*it >= 0) return 5; + else return 0; + } + } + + // places list + if (_fib_show_places && y >= ltop && y < fbot && x > FAREAMRGB * _scalefactor && x < (FAREAMRGL - FAREAMRGB) * _scalefactor) { + const int item = (y - ltop) / _fib_font_vsep; + *it = -1; + if (item >= 0 && item < _placecnt) { + *it = item; + } + if (*it >= 0) return 6; + else return 0; + } + + return 0; + + // unused + (void)dpy; +} + +static void fib_update_hover (Display *dpy, int need_expose, const int type, const int item) { + int hov_p = -1; + int hov_b = -1; + int hov_h = -1; + int hov_s = -1; +#ifdef LIST_ENTRY_HOVER + int hov_f = -1; + int hov_l = -1; +#endif + + switch (type) { + case 1: hov_p = item; break; + case 3: hov_b = item; break; + case 4: hov_s = item; break; + case 5: hov_h = item; break; +#ifdef LIST_ENTRY_HOVER + case 6: hov_l = item; break; + case 2: hov_f = item; break; +#endif + default: break; + } +#ifdef LIST_ENTRY_HOVER + if (hov_f != _hov_f) { _hov_f = hov_f; need_expose = 1; } + if (hov_l != _hov_l) { _hov_l = hov_l; need_expose = 1; } +#endif + if (hov_b != _hov_b) { _hov_b = hov_b; need_expose = 1; } + if (hov_p != _hov_p) { _hov_p = hov_p; need_expose = 1; } + if (hov_h != _hov_h) { _hov_h = hov_h; need_expose = 1; } + if (hov_s != _hov_s) { _hov_s = hov_s; need_expose = 1; } + + if (need_expose) { + fib_expose (dpy, _fib_win); + } +} + +static void fib_motion (Display *dpy, int x, int y) { + int it = -1; + + if (_scrl_my >= 0) { + const int sdiff = y - _scrl_my; + const int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + const int fsel_height = 4 + llen * _fib_font_vsep; + const float sl = (fsel_height + _fib_font_vsep - (SCROLLBOXH + SCROLLBOXH)) / (float) _dircount; + + int news = _scrl_mf + sdiff / sl; + if (news < 0) news = 0; + if (news >= (_dircount - llen)) news = _dircount - llen; + if (news != _scrl_f) { + _scrl_f = news; + fib_expose (dpy, _fib_win); + } + return; + } + + const int type = fib_widget_at_pos (dpy, x, y, &it); + fib_update_hover (dpy, 0, type, it); +} + +static void fib_mousedown (Display *dpy, int x, int y, int btn, unsigned long time) { + int it; + switch (fib_widget_at_pos (dpy, x, y, &it)) { + case 4: // scrollbar + if (btn == 1) { + _dblclk = 0; + if (it == 0) { + _scrl_my = y; + _scrl_mf = _scrl_f; + } else { + int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + if (llen < 2) llen = 2; + int news = _scrl_f; + if (it == 1) { + news -= llen - 1; + } else { + news += llen - 1; + } + if (news < 0) news = 0; + if (news >= (_dircount - llen)) news = _dircount - llen; + if (news != _scrl_f && _scrl_y0 >= 0) { + assert (news >=0); + _scrl_f = news; + fib_update_hover (dpy, 1, 4, it); + } + } + } + break; + case 2: // file-list + if (btn == 4 || btn == 5) { + const int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + int news = _scrl_f + ((btn == 4) ? - 1 : 1); + if (news < 0) news = 0; + if (news >= (_dircount - llen)) news = _dircount - llen; + if (news != _scrl_f && _scrl_y0 >= 0) { + assert (news >=0); + _scrl_f = news; + fib_update_hover (dpy, 1, 0, 0); + } + _dblclk = 0; + } + else if (btn == 1 && it >= 0 && it < _dircount) { + if (_fsel == it) { + if (time - _dblclk < DBLCLKTME) { + fib_open (dpy, it); + _dblclk = 0; + } + _dblclk = time; + } else { + fib_select (dpy, it); + _dblclk = time; + } + /* + if (_fsel >= 0) { + if (!(_dirlist[_fsel].flags & 4)); + } + */ + } + break; + case 1: // paths + assert (_fsel < _dircount); + assert (it >= 0 && it < _pathparts); + { + int i = 0; + char path[1024] = "/"; + while (++i <= it) { + strcat (path, _pathbtn[i].name); + strcat (path, "/"); + } + char *sel = NULL; + if (i < _pathparts) + sel = strdup (_pathbtn[i].name); + else if (i == _pathparts && _fsel >= 0) + sel = strdup (_dirlist[_fsel].name); + fib_opendir (dpy, path, sel); + free (sel); + } + break; + case 3: // btn + if (btn == 1 && _btns[it]->callback) { + _btns[it]->callback (dpy); + } + break; + case 5: // sort + if (btn == 1) { + switch (it) { + case 1: if (_sort == 0) _sort = 1; else _sort = 0; break; + case 2: if (_sort == 2) _sort = 3; else _sort = 2; break; + case 3: if (_sort == 4) _sort = 5; else _sort = 4; break; + } + if (_fsel >= 0) { + assert (_dirlist && _dircount >= _fsel); + _dirlist[_fsel].flags &= ~2; + char *sel = strdup (_dirlist[_fsel].name); + fib_resort (sel); + free (sel); + } else { + fib_resort (NULL); + _fsel = -1; + } + fib_reset (); + _hov_h = it; + fib_select (dpy, _fsel); + } + break; + case 6: + if (btn == 1 && it >= 0 && it < _placecnt) { + fib_opendir (dpy, _placelist[it].path, NULL); + } + break; + default: + break; + } +} + +static void fib_mouseup (Display *dpy, int x, int y, int btn, unsigned long time) { + _scrl_my = -1; + + // unused + return; (void)dpy; (void)x; (void)y; (void)btn; (void)time; +} + +static void add_place_raw (Display *dpy, const char *name, const char *path) { + _placelist = (FibPlace*) realloc (_placelist, (_placecnt + 1) * sizeof(FibPlace)); + strcpy (_placelist[_placecnt].path, path); + strcpy (_placelist[_placecnt].name, name); + _placelist[_placecnt].flags = 0; + + int sw = -1; + query_font_geometry (dpy, _fib_gc, name, &sw, NULL, NULL, NULL); + if (sw > _fib_place_width) { + _fib_place_width = sw; + } + ++_placecnt; +} + +static int add_place_places (Display *dpy, const char *name, const char *url) { + char const * path; + struct stat fs; + int i; + if (!url || strlen (url) < 1) return -1; + if (!name || strlen (name) < 1) return -1; + if (url[0] == '/') { + path = url; + } + else if (!strncmp (url, "file:///", 8)) { + path = &url[7]; + } + else { + return -1; + } + + if (access (path, R_OK)) { + return -1; + } + if (stat (path, &fs)) { + return -1; + } + if (!S_ISDIR (fs.st_mode)) { + return -1; + } + + for (i = 0; i < _placecnt; ++i) { + if (!strcmp (path, _placelist[i].path)) { + return -1; + } + } + add_place_raw (dpy, name, path); + return 0; +} + +static int parse_gtk_bookmarks (Display *dpy, const char *fn) { + char tmp[1024]; + if (access (fn, R_OK)) { + return -1; + } + FILE *bm = fopen (fn, "r"); + if (!bm) return -1; + int found = 0; + while (fgets (tmp, sizeof(tmp), bm) + && strlen (tmp) > 1 + && strlen (tmp) < sizeof(tmp)) + { + char *s, *n; + tmp[strlen (tmp) - 1] = '\0'; // strip newline + if ((s = strchr (tmp, ' '))) { + *s = '\0'; + n = strdup (++s); + decode_3986 (tmp); + if (!add_place_places (dpy, n, tmp)) { + ++found; + } + free (n); + } else if ((s = strrchr (tmp, '/'))) { + n = strdup (++s); + decode_3986 (tmp); + if (!add_place_places (dpy, n, tmp)) { + ++found; + } + free (n); + } + } + fclose (bm); + return found; +} + +#ifdef HAVE_MNTENT +static const char *ignore_mountpoints[] = { + "/bin", "/boot", "/dev", "/etc", + "/lib", "/live", "/mnt", "/opt", + "/root", "/sbin", "/srv", "/tmp", + "/usr", "/var", "/proc", "/sbin", + "/net", "/sys" +}; + +static const char *ignore_fs[] = { + "auto", "autofs", + "debugfs", "devfs", + "devpts", "ecryptfs", + "fusectl", "kernfs", + "linprocfs", "proc", + "ptyfs", "rootfs", + "selinuxfs", "sysfs", + "tmpfs", "usbfs", + "nfsd", "rpc_pipefs", +}; + +static const char *ignore_devices[] = { + "binfmt_", "devpts", + "gvfs", "none", + "nfsd", "sunrpc", + "/dev/loop", "/dev/vn" +}; + +static int check_mount (const char *mountpoint, const char *fs, const char *device) { + size_t i; + if (!mountpoint || !fs || !device) return -1; + //printf("%s %s %s\n", mountpoint, fs, device); + for (i = 0 ; i < sizeof(ignore_mountpoints) / sizeof(char*); ++i) { + if (!strncmp (mountpoint, ignore_mountpoints[i], strlen (ignore_mountpoints[i]))) { + return 1; + } + } + if (!strncmp (mountpoint, "/home", 5)) { + return 1; + } + for (i = 0 ; i < sizeof(ignore_fs) / sizeof(char*); ++i) { + if (!strncmp (fs, ignore_fs[i], strlen (ignore_fs[i]))) { + return 1; + } + } + for (i = 0 ; i < sizeof(ignore_devices) / sizeof(char*); ++i) { + if (!strncmp (device, ignore_devices[i], strlen (ignore_devices[i]))) { + return 1; + } + } + return 0; +} + +static int read_mtab (Display *dpy, const char *mtab) { + FILE *mt = fopen (mtab, "r"); + if (!mt) return -1; + int found = 0; + struct mntent *mntent; + while ((mntent = getmntent (mt)) != NULL) { + char *s; + if (check_mount (mntent->mnt_dir, mntent->mnt_type, mntent->mnt_fsname)) + continue; + + if ((s = strrchr (mntent->mnt_dir, '/'))) { + ++s; + } else { + s = mntent->mnt_dir; + } + if (!add_place_places (dpy, s, mntent->mnt_dir)) { + ++found; + } + } + fclose (mt); + return found; +} +#endif + +static void populate_places (Display *dpy) { + char tmp[1024]; + int spacer = -1; + if (_placecnt > 0) return; + _fib_place_width = 0; + + if (_recentcnt > 0) { + add_place_raw (dpy, "Recently Used", ""); + _placelist[0].flags |= 4; + } + + add_place_places (dpy, "Home", getenv ("HOME")); + + if (getenv ("HOME")) { + strcpy (tmp, getenv ("HOME")); + strcat (tmp, "/Desktop"); + add_place_places (dpy, "Desktop", tmp); + } + + add_place_places (dpy, "Filesystem", "/"); + + if (_placecnt > 0) spacer = _placecnt -1; + + if (strlen (_fib_cfg_custom_places) > 0) { + parse_gtk_bookmarks (dpy, _fib_cfg_custom_places); + } + +#ifdef HAVE_MNTENT + if (read_mtab (dpy, "/proc/mounts") < 1) { + read_mtab (dpy, "/etc/mtab"); + } +#endif + + int parsed_bookmarks = 0; + if (!parsed_bookmarks && getenv ("HOME")) { + strcpy (tmp, getenv ("HOME")); + strcat (tmp, "/.gtk-bookmarks"); + if (parse_gtk_bookmarks (dpy, tmp) > 0) { + parsed_bookmarks = 1; + } + } + if (!parsed_bookmarks && getenv ("XDG_CONFIG_HOME")) { + strcpy (tmp, getenv ("XDG_CONFIG_HOME")); + strcat (tmp, "/gtk-3.0/bookmarks"); + if (parse_gtk_bookmarks (dpy, tmp) > 0) { + parsed_bookmarks = 1; + } + } + if (!parsed_bookmarks && getenv ("HOME")) { + strcpy (tmp, getenv ("HOME")); + strcat (tmp, "/.config/gtk-3.0/bookmarks"); + if (parse_gtk_bookmarks (dpy, tmp) > 0) { + parsed_bookmarks = 1; + } + } + if (_fib_place_width > 0) { + _fib_place_width = MIN (_fib_place_width + TEXTSEP + _fib_dir_indent /*extra*/ , PLACESWMAX); + } + if (spacer > 0 && spacer < _placecnt -1) { + _placelist[ spacer ].flags |= 4; + } +} + +static uint8_t font_err = 0; +static int x_error_handler (Display *d, XErrorEvent *e) { + font_err = 1; + return 0; + + // unused + (void)d; (void)e; +} + +int x_fib_show (Display *dpy, Window parent, int x, int y, double scalefactor) { + if (_fib_win) { + XSetInputFocus (dpy, _fib_win, RevertToParent, CurrentTime); + return -1; + } + + _status = 0; + _rv_open[0] = '\0'; + + Colormap colormap = DefaultColormap (dpy, DefaultScreen (dpy)); + _c_gray1.flags = DoRed | DoGreen | DoBlue; + _c_gray0.red = _c_gray0.green = _c_gray0.blue = 0x5000; // 95% hover prelight + _c_gray1.red = _c_gray1.green = _c_gray1.blue = 0x1100; // 93% window bg, scrollbar-fg + _c_gray2.red = _c_gray2.green = _c_gray2.blue = 0x1c00; // 83% button & list bg + _c_gray3.red = _c_gray3.green = _c_gray3.blue = 0x0a00; // 75% heading + scrollbar-bg + _c_gray4.red = _c_gray4.green = _c_gray4.blue = 0xd600; // 40% prelight text, sep lines + _c_gray5.red = _c_gray5.green = _c_gray5.blue = 0x3000; // 20% 3D border + + if (!XAllocColor (dpy, colormap, &_c_gray0)) return -1; + if (!XAllocColor (dpy, colormap, &_c_gray1)) return -1; + if (!XAllocColor (dpy, colormap, &_c_gray2)) return -1; + if (!XAllocColor (dpy, colormap, &_c_gray3)) return -1; + if (!XAllocColor (dpy, colormap, &_c_gray4)) return -1; + if (!XAllocColor (dpy, colormap, &_c_gray5)) return -1; + + XSetWindowAttributes attr; + memset (&attr, 0, sizeof(XSetWindowAttributes)); + attr.border_pixel = _c_gray2.pixel; + + attr.event_mask = ExposureMask | KeyPressMask + | ButtonPressMask | ButtonReleaseMask + | ConfigureNotify | StructureNotifyMask + | PointerMotionMask | LeaveWindowMask; + + _fib_win = XCreateWindow ( + dpy, DefaultRootWindow (dpy), + x, y, _fib_width * scalefactor, _fib_height * scalefactor, + 1, CopyFromParent, InputOutput, CopyFromParent, + CWEventMask | CWBorderPixel, &attr); + + _scalefactor = scalefactor; + + if (!_fib_win) { return 1; } + + if (parent) + XSetTransientForHint (dpy, _fib_win, parent); + + XStoreName (dpy, _fib_win, "Select File"); + + Atom wmDelete = XInternAtom (dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols (dpy, _fib_win, &wmDelete, 1); + + _fib_gc = XCreateGC (dpy, _fib_win, 0, NULL); + XSetLineAttributes (dpy, _fib_gc, 1, LineSolid, CapButt, JoinMiter); + const char dl[1] = {1}; + XSetDashes (dpy, _fib_gc, 0, dl, 1); + + int (*handler)(Display *, XErrorEvent *) = XSetErrorHandler (&x_error_handler); + +#define _XTESTFONT(FN) \ + { \ + font_err = 0; \ + _fibfont = XLoadFont (dpy, FN); \ + XSetFont (dpy, _fib_gc, _fibfont); \ + XSync (dpy, False); \ + } + + font_err = 1; + if (getenv ("XJFONT")) _XTESTFONT (getenv ("XJFONT")); + if (font_err && strlen (_fib_cfg_custom_font) > 0) _XTESTFONT (_fib_cfg_custom_font); + if (scalefactor >= 2.5) { + if (font_err) _XTESTFONT ("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-*-verdana-medium-r-normal-*-18-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-20-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-18-*-*-*-*-*-*-*"); + } else if (scalefactor >= 2) { + if (font_err) _XTESTFONT ("-*-helvetica-medium-r-normal-*-16-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-*-verdana-medium-r-normal-*-16-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-18-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-16-*-*-*-*-*-*-*"); + } else if (scalefactor >= 1.5) { + if (font_err) _XTESTFONT ("-*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-*-verdana-medium-r-normal-*-14-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-15-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*"); + } else { + if (font_err) _XTESTFONT ("-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-*-verdana-medium-r-normal-*-12-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"); + if (font_err) _XTESTFONT ("-misc-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*"); + } + if (font_err) _fibfont = None; + XSync (dpy, False); + XSetErrorHandler (handler); + + if (_fib_font_height == 0) { // 1st time only + query_font_geometry (dpy, _fib_gc, "D ", &_fib_dir_indent, NULL, NULL, NULL); + query_font_geometry (dpy, _fib_gc, "_", &_fib_spc_norm, NULL, NULL, NULL); + if (query_font_geometry (dpy, _fib_gc, "|0Yy", NULL, &_fib_font_height, &_fib_font_ascent, NULL)) { + XFreeGC (dpy, _fib_gc); + XDestroyWindow (dpy, _fib_win); + _fib_win = 0; + return -1; + } + _fib_font_height += 3 * scalefactor; + _fib_font_ascent += 2 * scalefactor; + _fib_font_vsep = _fib_font_height + 2 * scalefactor; + } + + populate_places (dpy); + + strcpy (_btn_ok.text, "Open"); + strcpy (_btn_cancel.text, "Cancel"); + strcpy (_btn_filter.text, "List All Files"); + strcpy (_btn_places.text, "Show Places"); + strcpy (_btn_hidden.text, "Show Hidden"); + + _btn_ok.callback = &cb_open; + _btn_cancel.callback = &cb_cancel; + _btn_filter.callback = &cb_filter; + _btn_places.callback = &cb_places; + _btn_hidden.callback = &cb_hidden; + _btn_filter.flags |= 4; + _btn_places.flags |= 4; + _btn_hidden.flags |= 4; + + if (!_fib_filter_function) { + _btn_filter.flags |= 8; + } + + size_t i; + int btncnt = 0; + _btn_w = 0; + _btn_span = 0; + for (i = 0; i < sizeof(_btns) / sizeof(FibButton*); ++i) { + if (_btns[i]->flags & 8) { continue; } + query_font_geometry (dpy, _fib_gc, _btns[i]->text, &_btns[i]->tw, NULL, NULL, NULL); + if (_btns[i]->flags & 4) { + _btn_span += _btns[i]->tw + _fib_font_ascent + TEXTSEP * scalefactor; + } else { + ++btncnt; + if (_btns[i]->tw > _btn_w) + _btn_w = _btns[i]->tw; + } + } + + _btn_w += (BTNPADDING + BTNPADDING + TEXTSEP + TEXTSEP + TEXTSEP) * scalefactor; + _btn_span += _btn_w * btncnt + DSEP * scalefactor * (i - 1) + (FAREAMRGR + FAREAMRGB) * scalefactor; + + for (i = 0; i < sizeof(_btns) / sizeof(FibButton*); ++i) { + if (_btns[i]->flags & 8) { continue; } + if (_btns[i]->flags & 4) { + _btns[i]->xw = _btns[i]->tw + _fib_font_ascent + TEXTSEP * scalefactor; + } else { + _btns[i]->xw = _btn_w; + } + } + + sync_button_states () ; + + _fib_height = _fib_font_vsep * 15.8 * (1.0 + (scalefactor - 1.0) / 2.0); + _fib_width = MAX (_btn_span, 480 * scalefactor); + + XResizeWindow (dpy, _fib_win, _fib_width, _fib_height); + + XTextProperty x_wname, x_iname; + XSizeHints hints; + XWMHints wmhints; + + hints.flags = PSize | PMinSize; + hints.min_width = _btn_span; + hints.min_height = 8 * _fib_font_vsep; + + char *w_name = & _fib_cfg_title[0]; + + wmhints.input = True; + wmhints.flags = InputHint; + if (XStringListToTextProperty (&w_name, 1, &x_wname) && + XStringListToTextProperty (&w_name, 1, &x_iname)) + { + XSetWMProperties (dpy, _fib_win, &x_wname, &x_iname, NULL, 0, &hints, &wmhints, NULL); + XFree (x_wname.value); + XFree (x_iname.value); + } + + XSetWindowBackground (dpy, _fib_win, _c_gray1.pixel); + + _fib_mapped = 0; + XMapRaised (dpy, _fib_win); + + if (!strlen (_cur_path) || !fib_opendir (dpy, _cur_path, NULL)) { + fib_opendir (dpy, getenv ("HOME") ? getenv ("HOME") : "/", NULL); + } + +#if 0 + XGrabPointer (dpy, _fib_win, True, + ButtonReleaseMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | StructureNotifyMask, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + XGrabKeyboard (dpy, _fib_win, True, GrabModeAsync, GrabModeAsync, CurrentTime); + //XSetInputFocus (dpy, parent, RevertToNone, CurrentTime); +#endif + _recentlock = 1; + return 0; +} + +void x_fib_close (Display *dpy) { + if (!_fib_win) return; + XFreeGC (dpy, _fib_gc); + XDestroyWindow (dpy, _fib_win); + _fib_win = 0; + free (_dirlist); + _dirlist = NULL; + free (_pathbtn); + _pathbtn = NULL; + if (_fibfont != None) XUnloadFont (dpy, _fibfont); + _fibfont = None; + free (_placelist); + _placelist = NULL; + _dircount = 0; + _pathparts = 0; + _placecnt = 0; + if (_pixbuffer != None) XFreePixmap (dpy, _pixbuffer); + _pixbuffer = None; + Colormap colormap = DefaultColormap (dpy, DefaultScreen (dpy)); + XFreeColors (dpy, colormap, &_c_gray0.pixel, 1, 0); + XFreeColors (dpy, colormap, &_c_gray1.pixel, 1, 0); + XFreeColors (dpy, colormap, &_c_gray2.pixel, 1, 0); + XFreeColors (dpy, colormap, &_c_gray3.pixel, 1, 0); + XFreeColors (dpy, colormap, &_c_gray4.pixel, 1, 0); + XFreeColors (dpy, colormap, &_c_gray5.pixel, 1, 0); + _recentlock = 0; +} + +int x_fib_handle_events (Display *dpy, XEvent *event) { + if (!_fib_win) return 0; + if (_status) return 0; + if (event->xany.window != _fib_win) { + return 0; + } + + switch (event->type) { + case MapNotify: + _fib_mapped = 1; + break; + case UnmapNotify: + _fib_mapped = 0; + break; + case LeaveNotify: + fib_update_hover (dpy, 1, 0, 0); + break; + case ClientMessage: + if (!strcmp (XGetAtomName (dpy, event->xclient.message_type), "WM_PROTOCOLS")) { + _status = -1; + } + break; + case ConfigureNotify: + if ( + (event->xconfigure.width > 1 && event->xconfigure.height > 1) + && + (event->xconfigure.width != _fib_width || event->xconfigure.height != _fib_height) + ) + { + _fib_width = event->xconfigure.width; + _fib_height = event->xconfigure.height; + _fib_resized = 1; + } + break; + case Expose: + if (event->xexpose.count == 0) { + fib_expose (dpy, event->xany.window); + } + break; + case MotionNotify: + fib_motion (dpy, event->xmotion.x, event->xmotion.y); + if (event->xmotion.is_hint == NotifyHint) { + XGetMotionEvents (dpy, event->xany.window, CurrentTime, CurrentTime, NULL); + } + break; + case ButtonPress: + fib_mousedown (dpy, event->xbutton.x, event->xbutton.y, event->xbutton.button, event->xbutton.time); + break; + case ButtonRelease: + fib_mouseup (dpy, event->xbutton.x, event->xbutton.y, event->xbutton.button, event->xbutton.time); + break; + case KeyRelease: + break; + case KeyPress: + { + KeySym key; + char buf[100]; + static XComposeStatus stat; + XLookupString (&event->xkey, buf, sizeof(buf), &key, &stat); + switch (key) { + case XK_Escape: + _status = -1; + break; + case XK_Up: + if (_fsel > 0) { + fib_select (dpy, _fsel - 1); + } + break; + case XK_Down: + if (_fsel < _dircount -1) { + fib_select ( dpy, _fsel + 1); + } + break; + case XK_Page_Up: + if (_fsel > 0) { + int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + if (llen < 1) llen = 1; else --llen; + int fs = MAX (0, _fsel - llen); + fib_select ( dpy, fs); + } + break; + case XK_Page_Down: + if (_fsel < _dircount) { + int llen = (_fib_height - LISTBOT * _fib_font_vsep) / _fib_font_vsep; + if (llen < 1) llen = 1; else --llen; + int fs = MIN (_dircount - 1, _fsel + llen); + fib_select ( dpy, fs); + } + break; + case XK_Left: + if (_pathparts > 1) { + int i = 0; + char path[1024] = "/"; + while (++i < _pathparts - 1) { + strcat (path, _pathbtn[i].name); + strcat (path, "/"); + } + char *sel = strdup (_pathbtn[_pathparts-1].name); + fib_opendir (dpy, path, sel); + free (sel); + } + break; + case XK_Right: + if (_fsel >= 0 && _fsel < _dircount) { + if (_dirlist[_fsel].flags & 4) { + cb_open (dpy); + } + } + break; + case XK_Return: + cb_open (dpy); + break; + default: + if ((key >= XK_a && key <= XK_z) || (key >= XK_0 && key <= XK_9)) { + int i; + for (i = 0; i < _dircount; ++i) { + int j = (_fsel + i + 1) % _dircount; + char kcmp = _dirlist[j].name[0]; + if (kcmp > 0x40 && kcmp <= 0x5A) kcmp |= 0x20; + if (kcmp == (char)key) { + fib_select ( dpy, j); + break; + } + } + } + break; + } + } + break; + } + + if (_status) { + x_fib_close (dpy); + } + return _status; +} + +int x_fib_status () { + return _status; +} + +int x_fib_configure (int k, const char *v) { + if (_fib_win) { return -1; } + switch (k) { + case 0: + if (strlen (v) >= sizeof(_cur_path) -1) return -2; + if (strlen (v) < 1) return -2; + if (v[0] != '/') return -2; + if (strstr (v, "//")) return -2; + strncpy (_cur_path, v, sizeof(_cur_path)); + break; + case 1: + if (strlen (v) >= sizeof(_fib_cfg_title) -1) return -2; + strncpy (_fib_cfg_title, v, sizeof(_fib_cfg_title)); + break; + case 2: + if (strlen (v) >= sizeof(_fib_cfg_custom_font) -1) return -2; + strncpy (_fib_cfg_custom_font, v, sizeof(_fib_cfg_custom_font)); + break; + case 3: + if (strlen (v) >= sizeof(_fib_cfg_custom_places) -1) return -2; + strncpy (_fib_cfg_custom_places, v, sizeof(_fib_cfg_custom_places)); + break; + default: + return -2; + } + return 0; +} + +int x_fib_cfg_buttons (int k, int v) { + if (_fib_win) { return -1; } + switch (k) { + case 1: + if (v < 0) { + _btn_hidden.flags |= 8; + } else { + _btn_hidden.flags &= ~8; + } + if (v == 1) { + _btn_hidden.flags |= 2; + _fib_hidden_fn = 1; + } else if (v == 0) { + _btn_hidden.flags &= 2; + _fib_hidden_fn = 0; + } + break; + case 2: + if (v < 0) { + _btn_places.flags |= 8; + } else { + _btn_places.flags &= ~8; + } + if (v == 1) { + _btn_places.flags |= 2; + _fib_show_places = 1; + } else if (v == 0) { + _btn_places.flags &= ~2; + _fib_show_places = 0; + } + break; + case 3: + // NB. filter button is automatically hidden + // IFF the filter-function is NULL. + if (v < 0) { + _btn_filter.flags |= 8; + } else { + _btn_filter.flags &= ~8; + } + if (v == 1) { + _btn_filter.flags &= ~2; // inverse - 'show all' = !filter + _fib_filter_fn = 1; + } else if (v == 0) { + _btn_filter.flags |= 2; + _fib_filter_fn = 0; + } + break; + default: + return -2; + } + return 0; +} + +int x_fib_cfg_filter_callback (int (*cb)(const char*)) { + if (_fib_win) { return -1; } + _fib_filter_function = cb; + return 0; +} + +char *x_fib_filename () { + if (_status > 0 && !_fib_win) + return strdup (_rv_open); + else + return NULL; +} +#endif // HAVE_X11 + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic pop +#endif + +/* example usage */ +#ifdef SOFD_TEST + +static int fib_filter_movie_filename (const char *name) { + if (!_fib_filter_fn) return 1; + const int l3 = strlen (name) - 3; + const int l4 = l3 - 1; + const int l5 = l4 - 1; + const int l6 = l5 - 1; + const int l9 = l6 - 3; + if ( + (l4 > 0 && ( + !strcasecmp (&name[l4], ".avi") + || !strcasecmp (&name[l4], ".mov") + || !strcasecmp (&name[l4], ".ogg") + || !strcasecmp (&name[l4], ".ogv") + || !strcasecmp (&name[l4], ".mpg") + || !strcasecmp (&name[l4], ".mov") + || !strcasecmp (&name[l4], ".mp4") + || !strcasecmp (&name[l4], ".mkv") + || !strcasecmp (&name[l4], ".vob") + || !strcasecmp (&name[l4], ".asf") + || !strcasecmp (&name[l4], ".avs") + || !strcasecmp (&name[l4], ".dts") + || !strcasecmp (&name[l4], ".flv") + || !strcasecmp (&name[l4], ".m4v") + )) || + (l5 > 0 && ( + !strcasecmp (&name[l5], ".h264") + || !strcasecmp (&name[l5], ".webm") + )) || + (l6 > 0 && ( + !strcasecmp (&name[l6], ".dirac") + )) || + (l9 > 0 && ( + !strcasecmp (&name[l9], ".matroska") + )) || + (l3 > 0 && ( + !strcasecmp (&name[l3], ".dv") + || !strcasecmp (&name[l3], ".ts") + )) + ) + { + return 1; + } + return 0; +} + +int main (int argc, char **argv) { + Display* dpy = XOpenDisplay (0); + if (!dpy) return -1; + + x_fib_cfg_filter_callback (fib_filter_movie_filename); + x_fib_configure (1, "Open Movie File"); + x_fib_load_recent ("/tmp/sofd.recent"); + x_fib_show (dpy, 0, 300, 300); + + while (1) { + XEvent event; + while (XPending (dpy) > 0) { + XNextEvent (dpy, &event); + if (x_fib_handle_events (dpy, &event)) { + if (x_fib_status () > 0) { + char *fn = x_fib_filename (); + printf ("OPEN '%s'\n", fn); + x_fib_add_recent (fn, time (NULL)); + free (fn); + } + } + } + if (x_fib_status ()) { + break; + } + usleep (80000); + } + x_fib_close (dpy); + + x_fib_save_recent ("/tmp/sofd.recent"); + + x_fib_free_recent (); + XCloseDisplay (dpy); + return 0; +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/extra/sofd/libsofd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/sofd/libsofd.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,194 @@ +/* libSOFD - Simple Open File Dialog [for X11 without toolkit] + * + * Copyright (C) 2014 Robin Gareus + * + * 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. + */ + +#ifndef LIBSOFD_H +#define LIBSOFD_H 1 + +#ifdef HAVE_X11 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////// +/* public API */ + +/** open a file select dialog + * @param dpy X Display connection + * @param parent (optional) if not NULL, become transient for given window + * @param x if >0 set explict initial width of the window + * @param y if >0 set explict initial height of the window + * @return 0 on success + */ +int x_fib_show (Display *dpy, Window parent, int x, int y, double scalefactor); + +/** force close the dialog. + * This is normally not needed, the dialog closes itself + * when a file is selected or the user cancels selection. + * @param dpy X Display connection + */ +void x_fib_close (Display *dpy); + +/** non-blocking X11 event handler. + * It is safe to run this function even if the dialog is + * closed or was not initialized. + * + * @param dpy X Display connection + * @param event the XEvent to process + * @return status + * 0: the event was not for this window, or file-dialog still + * active, or the dialog window is not displayed. + * >0: file was selected, dialog closed + * <0: file selection was cancelled. + */ +int x_fib_handle_events (Display *dpy, XEvent *event); + +/** last status of the dialog + * @return >0: file was selected, <0: canceled or inactive. 0: active + */ +int x_fib_status (); + +/** query the selected filename + * @return NULL if none set, or allocated string to be free()ed by the called + */ +char *x_fib_filename (); + +/** customize/configure the dialog before calling \ref x_fib_show + * changes only have any effect if the dialog is not visible. + * @param k key to change + * 0: set current dir to display (must end with slash) + * 1: set title of dialog window + * 2: specify a custom X11 font to use + * 3: specify a custom 'places' file to include + * (following gtk-bookmark convention) + * @param v value + * @return 0 on success. + */ +int x_fib_configure (int k, const char *v); + +/** customize/configure the dialog before calling \ref x_fib_show + * changes only have any effect if the dialog is not visible. + * + * @param k button to change: + * 1: show hidden files + * 2: show places + * 3: show filter/list all (automatically hidden if there is no + * filter function) + * @param v <0 to hide the button >=0 show button, + * 0: set button-state to not-checked + * 1: set button-state to checked + * >1: retain current state + * @return 0 on success. + */ +int x_fib_cfg_buttons (int k, int v); + +/** set custom callback to filter file-names. + * NULL will disable the filter and hide the 'show all' button. + * changes only have any effect if the dialog is not visible. + * + * @param cb callback function to check file + * the callback function is called with the file name (basename only) + * and is expected to return 1 if the file passes the filter + * and 0 if the file should not be listed by default. + * @return 0 on success. + */ +int x_fib_cfg_filter_callback (int (*cb)(const char*)); + +#ifdef __cplusplus +} +#endif + +#endif /* END X11 specific functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* 'recently used' API. x-platform + * NOTE: all functions use a static cache and are not reentrant. + * It is expected that none of these functions are called in + * parallel from different threads. + */ + +/** release static resources of 'recently used files' + */ +void x_fib_free_recent (); + +/** add an entry to the recently used list + * + * The dialog does not add files automatically on open, + * if the application succeeds to open a selected file, + * this function should be called. + * + * @param path complete path to file + * @param atime time of last use, 0: NOW + * @return -1 on error, number of current entries otherwise + */ +int x_fib_add_recent (const char *path, time_t atime); + +/** get a platform specific path to a good location for + * saving the recently used file list. + * (follows XDG_DATA_HOME on Unix, and CSIDL_LOCAL_APPDATA spec) + * + * @param application-name to use to include in file + * @return pointer to static path or NULL + */ +const char *x_fib_recent_file(const char *appname); + +/** save the current list of recently used files to the given filename + * (the format is one file per line, filename URL encoded and space separated + * with last-used timestamp) + * + * This function tries to creates the containing directory if it does + * not exist. + * + * @param fn file to save the list to + * @return 0: on success + */ +int x_fib_save_recent (const char *fn); + +/** load a recently used file list. + * + * @param fn file to load the list from + * @return 0: on success + */ +int x_fib_load_recent (const char *fn); + +/** get number of entries in the current list + * @return number of entries in the recently used list + */ +unsigned int x_fib_recent_count (); + +/** get recently used entry at given position + * + * @param i entry to query + * @return pointer to static string + */ +const char *x_fib_recent_at (unsigned int i); + +#ifdef __cplusplus +} +#endif + +#endif // header guard diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoDefines.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoDefines.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,227 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_DEFINES_H_INCLUDED +#define DISTRHO_DEFINES_H_INCLUDED + +/* Compatibility with non-clang compilers */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif +#ifndef __has_extension +# define __has_extension __has_feature +#endif + +/* Check OS */ +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# define DISTRHO_API +# define DISTRHO_PLUGIN_EXPORT extern "C" __declspec (dllexport) +# define DISTRHO_OS_WINDOWS 1 +# define DISTRHO_DLL_EXTENSION "dll" +#else +# define DISTRHO_API +# define DISTRHO_PLUGIN_EXPORT extern "C" __attribute__ ((visibility("default"))) +# if defined(__APPLE__) +# define DISTRHO_OS_MAC 1 +# define DISTRHO_DLL_EXTENSION "dylib" +# elif defined(__HAIKU__) +# define DISTRHO_OS_HAIKU 1 +# elif defined(__linux__) || defined(__linux) +# define DISTRHO_OS_LINUX 1 +# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# define DISTRHO_OS_BSD 1 +# elif defined(__GNU__) +# define DISTRHO_OS_GNU_HURD 1 +# elif defined(__EMSCRIPTEN__) +# define DISTRHO_OS_WASM 1 +# endif +#endif + +#ifndef DISTRHO_DLL_EXTENSION +# define DISTRHO_DLL_EXTENSION "so" +#endif + +/* Check for C++11 support */ +#if defined(HAVE_CPP11_SUPPORT) +# if HAVE_CPP11_SUPPORT +# define DISTRHO_PROPER_CPP11_SUPPORT +# endif +#elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) || (defined(_MSC_VER) && _MSVC_LANG >= 201103L) +# define DISTRHO_PROPER_CPP11_SUPPORT +# if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407 && ! defined(__clang__)) || (defined(__clang__) && ! __has_extension(cxx_override_control)) +# define override /* gcc4.7+ only */ +# define final /* gcc4.7+ only */ +# endif +#endif + +#ifndef DISTRHO_PROPER_CPP11_SUPPORT +# define constexpr +# define noexcept throw() +# define override +# define final +# define nullptr NULL +#endif + +/* Define unlikely */ +#ifdef __GNUC__ +# define unlikely(x) __builtin_expect(x,0) +#else +# define unlikely(x) x +#endif + +/* Define DISTRHO_DEPRECATED */ +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 480 +# define DISTRHO_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define DISTRHO_DEPRECATED [[deprecated]] /* Note: __declspec(deprecated) it not applicable to enum members */ +#else +# define DISTRHO_DEPRECATED +#endif + +/* Define DISTRHO_DEPRECATED_BY */ +#if defined(__clang__) && (__clang_major__ * 100 + __clang_minor__) >= 502 +# define DISTRHO_DEPRECATED_BY(other) __attribute__((deprecated("", other))) +#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 +# define DISTRHO_DEPRECATED_BY(other) __attribute__((deprecated("Use " other))) +#else +# define DISTRHO_DEPRECATED_BY(other) DISTRHO_DEPRECATED +#endif + +/* Define DISTRHO_SAFE_ASSERT* */ +#define DISTRHO_SAFE_ASSERT(cond) if (unlikely(!(cond))) d_safe_assert (#cond, __FILE__, __LINE__); +#define DISTRHO_SAFE_ASSERT_INT(cond, value) if (unlikely(!(cond))) d_safe_assert_int (#cond, __FILE__, __LINE__, static_cast(value)); +#define DISTRHO_SAFE_ASSERT_INT2(cond, v1, v2) if (unlikely(!(cond))) d_safe_assert_int2 (#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); +#define DISTRHO_SAFE_ASSERT_UINT(cond, value) if (unlikely(!(cond))) d_safe_assert_uint (#cond, __FILE__, __LINE__, static_cast(value)); +#define DISTRHO_SAFE_ASSERT_UINT2(cond, v1, v2) if (unlikely(!(cond))) d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); + +#define DISTRHO_SAFE_ASSERT_BREAK(cond) if (unlikely(!(cond))) { d_safe_assert(#cond, __FILE__, __LINE__); break; } +#define DISTRHO_SAFE_ASSERT_CONTINUE(cond) if (unlikely(!(cond))) { d_safe_assert(#cond, __FILE__, __LINE__); continue; } +#define DISTRHO_SAFE_ASSERT_RETURN(cond, ret) if (unlikely(!(cond))) { d_safe_assert(#cond, __FILE__, __LINE__); return ret; } + +#define DISTRHO_CUSTOM_SAFE_ASSERT(msg, cond) if (unlikely(!(cond))) d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); +#define DISTRHO_CUSTOM_SAFE_ASSERT_BREAK(msg, cond) if (unlikely(!(cond))) { d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); break; } +#define DISTRHO_CUSTOM_SAFE_ASSERT_CONTINUE(msg, cond) if (unlikely(!(cond))) { d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); continue; } +#define DISTRHO_CUSTOM_SAFE_ASSERT_RETURN(msg, cond, ret) if (unlikely(!(cond))) { d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); return ret; } + +#define DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_BREAK(msg, cond) if (unlikely(!(cond))) { static bool _p; if (!_p) { _p = true; d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); } break; } +#define DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_CONTINUE(msg, cond) if (unlikely(!(cond))) { static bool _p; if (!_p) { _p = true; d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); } continue; } +#define DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_RETURN(msg, cond, ret) if (unlikely(!(cond))) { static bool _p; if (!_p) { _p = true; d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); } return ret; } + +#define DISTRHO_SAFE_ASSERT_INT_BREAK(cond, value) if (unlikely(!(cond))) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast(value)); break; } +#define DISTRHO_SAFE_ASSERT_INT_CONTINUE(cond, value) if (unlikely(!(cond))) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast(value)); continue; } +#define DISTRHO_SAFE_ASSERT_INT_RETURN(cond, value, ret) if (unlikely(!(cond))) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast(value)); return ret; } + +#define DISTRHO_SAFE_ASSERT_INT2_BREAK(cond, v1, v2) if (unlikely(!(cond))) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); break; } +#define DISTRHO_SAFE_ASSERT_INT2_CONTINUE(cond, v1, v2) if (unlikely(!(cond))) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); continue; } +#define DISTRHO_SAFE_ASSERT_INT2_RETURN(cond, v1, v2, ret) if (unlikely(!(cond))) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); return ret; } + +#define DISTRHO_SAFE_ASSERT_UINT_BREAK(cond, value) if (unlikely(!(cond))) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast(value)); break; } +#define DISTRHO_SAFE_ASSERT_UINT_CONTINUE(cond, value) if (unlikely(!(cond))) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast(value)); continue; } +#define DISTRHO_SAFE_ASSERT_UINT_RETURN(cond, value, ret) if (unlikely(!(cond))) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast(value)); return ret; } + +#define DISTRHO_SAFE_ASSERT_UINT2_BREAK(cond, v1, v2) if (unlikely(!(cond))) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); break; } +#define DISTRHO_SAFE_ASSERT_UINT2_CONTINUE(cond, v1, v2) if (unlikely(!(cond))) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); continue; } +#define DISTRHO_SAFE_ASSERT_UINT2_RETURN(cond, v1, v2, ret) if (unlikely(!(cond))) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast(v1), static_cast(v2)); return ret; } + +/* Define DISTRHO_SAFE_EXCEPTION */ +#define DISTRHO_SAFE_EXCEPTION(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); } +#define DISTRHO_SAFE_EXCEPTION_BREAK(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); break; } +#define DISTRHO_SAFE_EXCEPTION_CONTINUE(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); continue; } +#define DISTRHO_SAFE_EXCEPTION_RETURN(msg, ret) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); return ret; } + +/* Define DISTRHO_DECLARE_NON_COPYABLE */ +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# define DISTRHO_DECLARE_NON_COPYABLE(ClassName) \ +private: \ + ClassName(ClassName&) = delete; \ + ClassName(const ClassName&) = delete; \ + ClassName& operator=(ClassName&) = delete; \ + ClassName& operator=(const ClassName&) = delete; +#else +# define DISTRHO_DECLARE_NON_COPYABLE(ClassName) \ +private: \ + ClassName(ClassName&); \ + ClassName(const ClassName&); \ + ClassName& operator=(ClassName&); \ + ClassName& operator=(const ClassName&); +#endif + +/* Define DISTRHO_PREVENT_HEAP_ALLOCATION */ +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# define DISTRHO_PREVENT_HEAP_ALLOCATION \ +private: \ + static void* operator new(size_t) = delete; \ + static void operator delete(void*) = delete; +#else +# define DISTRHO_PREVENT_HEAP_ALLOCATION \ +private: \ + static void* operator new(size_t); \ + static void operator delete(void*); +#endif + +/* Define DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION */ +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# define DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION \ +private: \ + static void* operator new(std::size_t) = delete; +#else +# define DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION \ +private: \ + static void* operator new(std::size_t); +#endif + +/* Define namespace */ +#ifndef DISTRHO_NAMESPACE +# define DISTRHO_NAMESPACE DISTRHO +#endif +#define START_NAMESPACE_DISTRHO namespace DISTRHO_NAMESPACE { +#define END_NAMESPACE_DISTRHO } +#define USE_NAMESPACE_DISTRHO using namespace DISTRHO_NAMESPACE; + +/* Define DISTRHO_OS_SEP and DISTRHO_OS_SPLIT */ +#ifdef DISTRHO_OS_WINDOWS +# define DISTRHO_OS_SEP '\\' +# define DISTRHO_OS_SEP_STR "\\" +# define DISTRHO_OS_SPLIT ';' +# define DISTRHO_OS_SPLIT_STR ";" +#else +# define DISTRHO_OS_SEP '/' +# define DISTRHO_OS_SEP_STR "/" +# define DISTRHO_OS_SPLIT ':' +# define DISTRHO_OS_SPLIT_STR ":" +#endif + +/* MSVC warnings */ +#ifdef _MSC_VER +# define strdup _strdup +# pragma warning(disable:4244) /* possible loss of data */ +#endif + +/* Useful macros */ +#define ARRAY_SIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0])) + +/* Useful typedefs */ +typedef unsigned char uchar; +typedef unsigned short int ushort; +typedef unsigned int uint; +typedef unsigned long int ulong; +typedef unsigned long long int ulonglong; + +/* Deprecated macros */ +#define DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) DISTRHO_DECLARE_NON_COPYABLE(ClassName) +#define DISTRHO_DECLARE_NON_COPY_STRUCT(StructName) DISTRHO_DECLARE_NON_COPYABLE(StructName) + +#endif // DISTRHO_DEFINES_H_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPlugin.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,252 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" + +START_NAMESPACE_DISTRHO + +/* ------------------------------------------------------------------------------------------------------------ + * Static data, see DistrhoPluginInternal.hpp */ + +uint32_t d_nextBufferSize = 0; +double d_nextSampleRate = 0.0; +const char* d_nextBundlePath = nullptr; +bool d_nextPluginIsDummy = false; +bool d_nextPluginIsSelfTest = false; +bool d_nextCanRequestParameterValueChanges = false; + +/* ------------------------------------------------------------------------------------------------------------ + * Static fallback data, see DistrhoPluginInternal.hpp */ + +const String PluginExporter::sFallbackString; +/* */ AudioPortWithBusId PluginExporter::sFallbackAudioPort; +const ParameterRanges PluginExporter::sFallbackRanges; +const ParameterEnumerationValues PluginExporter::sFallbackEnumValues; +const PortGroupWithId PluginExporter::sFallbackPortGroup; + +/* ------------------------------------------------------------------------------------------------------------ + * Plugin */ + +Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount) + : pData(new PrivateData()) +{ + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + pData->audioPorts = new AudioPortWithBusId[DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS]; + #endif + + #if defined(DPF_ABORT_ON_ERROR) || defined(DPF_RUNTIME_TESTING) + #define DPF_ABORT abort(); + #else + #define DPF_ABORT + #endif + + if (parameterCount > 0) + { + pData->parameterCount = parameterCount; + pData->parameters = new Parameter[parameterCount]; + } + + if (programCount > 0) + { + #if DISTRHO_PLUGIN_WANT_PROGRAMS + pData->programCount = programCount; + pData->programNames = new String[programCount]; + #else + d_stderr2("DPF warning: Plugins with programs must define `DISTRHO_PLUGIN_WANT_PROGRAMS` to 1"); + DPF_ABORT + #endif + } + + if (stateCount > 0) + { + #if DISTRHO_PLUGIN_WANT_STATE + pData->stateCount = stateCount; + pData->states = new State[stateCount]; + #else + d_stderr2("DPF warning: Plugins with state must define `DISTRHO_PLUGIN_WANT_STATE` to 1"); + DPF_ABORT + #endif + } + + #undef DPF_ABORT +} + +Plugin::~Plugin() +{ + delete pData; +} + +/* ------------------------------------------------------------------------------------------------------------ + * Host state */ + +uint32_t Plugin::getBufferSize() const noexcept +{ + return pData->bufferSize; +} + +double Plugin::getSampleRate() const noexcept +{ + return pData->sampleRate; +} + +const char* Plugin::getBundlePath() const noexcept +{ + return pData->bundlePath; +} + +bool Plugin::isDummyInstance() const noexcept +{ + return pData->isDummy; +} + +bool Plugin::isSelfTestInstance() const noexcept +{ + return pData->isSelfTest; +} + +#if DISTRHO_PLUGIN_WANT_TIMEPOS +const TimePosition& Plugin::getTimePosition() const noexcept +{ + return pData->timePosition; +} +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY +void Plugin::setLatency(const uint32_t frames) noexcept +{ + pData->latency = frames; +} +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +bool Plugin::writeMidiEvent(const MidiEvent& midiEvent) noexcept +{ + return pData->writeMidiCallback(midiEvent); +} +#endif + +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +bool Plugin::canRequestParameterValueChanges() const noexcept +{ + return pData->canRequestParameterValueChanges; +} + +bool Plugin::requestParameterValueChange(const uint32_t index, const float value) noexcept +{ + return pData->requestParameterValueChangeCallback(index, value); +} +#endif + +#if DISTRHO_PLUGIN_WANT_STATE +bool Plugin::updateStateValue(const char* const key, const char* const value) noexcept +{ + return pData->updateStateValueCallback(key, value); +} +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * Init */ + +void Plugin::initAudioPort(bool input, uint32_t index, AudioPort& port) +{ + if (port.hints & kAudioPortIsCV) + { + port.name = input ? "CV Input " : "CV Output "; + port.name += String(index+1); + port.symbol = input ? "cv_in_" : "cv_out_"; + port.symbol += String(index+1); + } + else + { + port.name = input ? "Audio Input " : "Audio Output "; + port.name += String(index+1); + port.symbol = input ? "audio_in_" : "audio_out_"; + port.symbol += String(index+1); + } +} + +void Plugin::initParameter(uint32_t, Parameter&) {} + +void Plugin::initPortGroup(const uint32_t groupId, PortGroup& portGroup) +{ + fillInPredefinedPortGroupData(groupId, portGroup); +} + +#if DISTRHO_PLUGIN_WANT_PROGRAMS +void Plugin::initProgramName(uint32_t, String&) {} +#endif + +#if DISTRHO_PLUGIN_WANT_STATE +void Plugin::initState(const uint32_t index, State& state) +{ + uint hints = 0x0; + String stateKey, defaultStateValue; + + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable:4996) + #elif defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif + initState(index, stateKey, defaultStateValue); + if (isStateFile(index)) + hints = kStateIsFilenamePath; + #if defined(_MSC_VER) + #pragma warning(pop) + #elif defined(__clang__) + #pragma clang diagnostic pop + #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) + #pragma GCC diagnostic pop + #endif + + state.hints = hints; + state.key = stateKey; + state.label = stateKey; + state.defaultValue = defaultStateValue; +} +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * Init */ + +float Plugin::getParameterValue(uint32_t) const { return 0.0f; } +void Plugin::setParameterValue(uint32_t, float) {} + +#if DISTRHO_PLUGIN_WANT_PROGRAMS +void Plugin::loadProgram(uint32_t) {} +#endif + +#if DISTRHO_PLUGIN_WANT_FULL_STATE +String Plugin::getState(const char*) const { return String(); } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE +void Plugin::setState(const char*, const char*) {} +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * Callbacks (optional) */ + +void Plugin::bufferSizeChanged(uint32_t) {} +void Plugin::sampleRateChanged(double) {} + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginCLAP.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginCLAP.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2628 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* TODO items: + * CV: write a specification + * INFO: define url, manual url, support url and string version + * PARAMETERS: test parameter triggers + * States: skip DSP/UI only states as appropriate + * UI: expose external-only UIs + */ + +#include "DistrhoPluginInternal.hpp" +#include "extra/ScopedPointer.hpp" + +#ifndef DISTRHO_PLUGIN_CLAP_ID +# error DISTRHO_PLUGIN_CLAP_ID undefined! +#endif + +#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# undef DISTRHO_PLUGIN_HAS_UI +# define DISTRHO_PLUGIN_HAS_UI 0 +#endif + +#if DISTRHO_PLUGIN_HAS_UI +# include "DistrhoUIInternal.hpp" +# include "../extra/Mutex.hpp" +#endif + +#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT +# include "../extra/RingBuffer.hpp" +#endif + +#include +#include + +#include "clap/entry.h" +#include "clap/plugin-factory.h" +#include "clap/ext/audio-ports.h" +#include "clap/ext/latency.h" +#include "clap/ext/gui.h" +#include "clap/ext/note-ports.h" +#include "clap/ext/params.h" +#include "clap/ext/state.h" +#include "clap/ext/thread-check.h" +#include "clap/ext/timer-support.h" + +#if (defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# define DPF_CLAP_USING_HOST_TIMER 0 +#else +# define DPF_CLAP_USING_HOST_TIMER 1 +#endif + +#ifndef DPF_CLAP_TIMER_INTERVAL +# define DPF_CLAP_TIMER_INTERVAL 16 /* ~60 fps */ +#endif + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +typedef std::map StringMap; + +struct ClapEventQueue +{ + #if DISTRHO_PLUGIN_HAS_UI + enum EventType { + kEventGestureBegin, + kEventGestureEnd, + kEventParamSet + }; + + struct Event { + EventType type; + uint32_t index; + float value; + }; + + struct Queue { + RecursiveMutex lock; + uint allocated; + uint used; + Event* events; + + Queue() + : allocated(0), + used(0), + events(nullptr) {} + + ~Queue() + { + delete[] events; + } + + void addEventFromUI(const Event& event) + { + const RecursiveMutexLocker crml(lock); + + if (events == nullptr) + { + events = static_cast(std::malloc(sizeof(Event) * 8)); + allocated = 8; + } + else if (used + 1 > allocated) + { + allocated = used * 2; + events = static_cast(std::realloc(events, sizeof(Event) * allocated)); + } + + std::memcpy(&events[used++], &event, sizeof(Event)); + } + } fEventQueue; + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + SmallStackBuffer fNotesBuffer; + #endif + #endif + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t fCurrentProgram; + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + StringMap fStateMap; + #if DISTRHO_PLUGIN_HAS_UI + virtual void setStateFromUI(const char* key, const char* value) = 0; + #endif + #endif + + struct CachedParameters { + uint numParams; + bool* changed; + float* values; + + CachedParameters() + : numParams(0), + changed(nullptr), + values(nullptr) {} + + ~CachedParameters() + { + delete[] changed; + delete[] values; + } + + void setup(const uint numParameters) + { + if (numParameters == 0) + return; + + numParams = numParameters; + changed = new bool[numParameters]; + values = new float[numParameters]; + + std::memset(changed, 0, sizeof(bool)*numParameters); + std::memset(values, 0, sizeof(float)*numParameters); + } + } fCachedParameters; + + ClapEventQueue() + #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT + : fNotesBuffer(StackBuffer_INIT) + #endif + { + #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) + std::memset(&fNotesBuffer, 0, sizeof(fNotesBuffer)); + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + fCurrentProgram = 0; + #endif + } + + virtual ~ClapEventQueue() {} +}; + +// -------------------------------------------------------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_HAS_UI + +#if ! DISTRHO_PLUGIN_WANT_STATE +static constexpr const setStateFunc setStateCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static constexpr const sendNoteFunc sendNoteCallback = nullptr; +#endif + +/** + * CLAP UI class. + */ +class ClapUI : public DGL_NAMESPACE::IdleCallback +{ +public: + ClapUI(PluginExporter& plugin, + ClapEventQueue* const eventQueue, + const clap_host_t* const host, + const clap_host_gui_t* const hostGui, + #if DPF_CLAP_USING_HOST_TIMER + const clap_host_timer_support_t* const hostTimer, + #endif + const bool isFloating) + : fPlugin(plugin), + fPluginEventQueue(eventQueue), + fEventQueue(eventQueue->fEventQueue), + fCachedParameters(eventQueue->fCachedParameters), + #if DISTRHO_PLUGIN_WANT_PROGRAMS + fCurrentProgram(eventQueue->fCurrentProgram), + #endif + #if DISTRHO_PLUGIN_WANT_STATE + fStateMap(eventQueue->fStateMap), + #endif + fHost(host), + fHostGui(hostGui), + #if DPF_CLAP_USING_HOST_TIMER + fTimerId(0), + fHostTimer(hostTimer), + #else + fCallbackRegistered(false), + #endif + fIsFloating(isFloating), + fScaleFactor(0.0), + fParentWindow(0), + fTransientWindow(0) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fNotesRingBuffer.setRingBuffer(&eventQueue->fNotesBuffer, false); + #endif + } + + ~ClapUI() override + { + #if DPF_CLAP_USING_HOST_TIMER + if (fTimerId != 0) + fHostTimer->unregister_timer(fHost, fTimerId); + #else + if (fCallbackRegistered && fUI != nullptr) + fUI->removeIdleCallbackForNativeIdle(this); + #endif + } + + #ifndef DISTRHO_OS_MAC + bool setScaleFactor(const double scaleFactor) + { + if (d_isEqual(fScaleFactor, scaleFactor)) + return true; + + fScaleFactor = scaleFactor; + + if (UIExporter* const ui = fUI.get()) + ui->notifyScaleFactorChanged(scaleFactor); + + return true; + } + #endif + + bool getSize(uint32_t* const width, uint32_t* const height) const + { + if (UIExporter* const ui = fUI.get()) + { + *width = ui->getWidth(); + *height = ui->getHeight(); + #ifdef DISTRHO_OS_MAC + const double scaleFactor = ui->getScaleFactor(); + *width /= scaleFactor; + *height /= scaleFactor; + #endif + return true; + } + + double scaleFactor = fScaleFactor; + #if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT) + *width = DISTRHO_UI_DEFAULT_WIDTH; + *height = DISTRHO_UI_DEFAULT_HEIGHT; + if (d_isZero(scaleFactor)) + scaleFactor = 1.0; + #else + UIExporter tmpUI(nullptr, 0, fPlugin.getSampleRate(), + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, d_nextBundlePath, + fPlugin.getInstancePointer(), scaleFactor); + *width = tmpUI.getWidth(); + *height = tmpUI.getHeight(); + scaleFactor = tmpUI.getScaleFactor(); + tmpUI.quit(); + #endif + + #ifdef DISTRHO_OS_MAC + *width /= scaleFactor; + *height /= scaleFactor; + #endif + + return true; + } + + bool canResize() const noexcept + { + #if DISTRHO_UI_USER_RESIZABLE + if (UIExporter* const ui = fUI.get()) + return ui->isResizable(); + #endif + return false; + } + + bool getResizeHints(clap_gui_resize_hints_t* const hints) const + { + if (canResize()) + { + uint minimumWidth, minimumHeight; + bool keepAspectRatio; + fUI->getGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio); + + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI->getScaleFactor(); + minimumWidth /= scaleFactor; + minimumHeight /= scaleFactor; + #endif + + hints->can_resize_horizontally = true; + hints->can_resize_vertically = true; + hints->preserve_aspect_ratio = keepAspectRatio; + hints->aspect_ratio_width = minimumWidth; + hints->aspect_ratio_height = minimumHeight; + + return true; + } + + hints->can_resize_horizontally = false; + hints->can_resize_vertically = false; + hints->preserve_aspect_ratio = false; + hints->aspect_ratio_width = 0; + hints->aspect_ratio_height = 0; + + return false; + } + + bool adjustSize(uint32_t* const width, uint32_t* const height) const + { + if (canResize()) + { + uint minimumWidth, minimumHeight; + bool keepAspectRatio; + fUI->getGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio); + + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI->getScaleFactor(); + minimumWidth /= scaleFactor; + minimumHeight /= scaleFactor; + #endif + + if (keepAspectRatio) + { + if (*width < 1) + *width = 1; + if (*height < 1) + *height = 1; + + const double ratio = static_cast(minimumWidth) / static_cast(minimumHeight); + const double reqRatio = static_cast(*width) / static_cast(*height); + + if (d_isNotEqual(ratio, reqRatio)) + { + // fix width + if (reqRatio > ratio) + *width = static_cast(*height * ratio + 0.5); + // fix height + else + *height = static_cast(static_cast(*width) / ratio + 0.5); + } + } + + if (minimumWidth > *width) + *width = minimumWidth; + if (minimumHeight > *height) + *height = minimumHeight; + + return true; + } + + return false; + } + + bool setSizeFromHost(uint32_t width, uint32_t height) + { + if (UIExporter* const ui = fUI.get()) + { + #ifdef DISTRHO_OS_MAC + const double scaleFactor = ui->getScaleFactor(); + width *= scaleFactor; + height *= scaleFactor; + #endif + ui->setWindowSizeFromHost(width, height); + return true; + } + + return false; + } + + bool setParent(const clap_window_t* const window) + { + if (fIsFloating) + return false; + + fParentWindow = window->uptr; + + if (fUI == nullptr) + { + createUI(); + fHostGui->resize_hints_changed(fHost); + } + + return true; + } + + bool setTransient(const clap_window_t* const window) + { + if (! fIsFloating) + return false; + + fTransientWindow = window->uptr; + + if (UIExporter* const ui = fUI.get()) + ui->setWindowTransientWinId(window->uptr); + + return true; + } + + void suggestTitle(const char* const title) + { + if (! fIsFloating) + return; + + fWindowTitle = title; + + if (UIExporter* const ui = fUI.get()) + ui->setWindowTitle(title); + } + + bool show() + { + if (fUI == nullptr) + { + createUI(); + fHostGui->resize_hints_changed(fHost); + } + + if (fIsFloating) + fUI->setWindowVisible(true); + + #if DPF_CLAP_USING_HOST_TIMER + fHostTimer->register_timer(fHost, DPF_CLAP_TIMER_INTERVAL, &fTimerId); + #else + fCallbackRegistered = true; + fUI->addIdleCallbackForNativeIdle(this, DPF_CLAP_TIMER_INTERVAL); + #endif + return true; + } + + bool hide() + { + if (UIExporter* const ui = fUI.get()) + { + ui->setWindowVisible(false); + #if DPF_CLAP_USING_HOST_TIMER + fHostTimer->unregister_timer(fHost, fTimerId); + fTimerId = 0; + #else + ui->removeIdleCallbackForNativeIdle(this); + fCallbackRegistered = false; + #endif + } + + return true; + } + + // ---------------------------------------------------------------------------------------------------------------- + + void idleCallback() override + { + if (UIExporter* const ui = fUI.get()) + { + #if DPF_CLAP_USING_HOST_TIMER + ui->plugin_idle(); + #else + ui->idleFromNativeIdle(); + #endif + + for (uint i=0; iparameterChanged(i, fCachedParameters.values[i]); + } + } + } + } + + // ---------------------------------------------------------------------------------------------------------------- + + void setParameterValueFromPlugin(const uint index, const float value) + { + if (UIExporter* const ui = fUI.get()) + ui->parameterChanged(index, value); + } + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + void setProgramFromPlugin(const uint index) + { + if (UIExporter* const ui = fUI.get()) + ui->programLoaded(index); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + void setStateFromPlugin(const char* const key, const char* const value) + { + if (UIExporter* const ui = fUI.get()) + ui->stateChanged(key, value); + } + #endif + + // ---------------------------------------------------------------------------------------------------------------- + +private: + // Plugin and UI + PluginExporter& fPlugin; + ClapEventQueue* const fPluginEventQueue; + ClapEventQueue::Queue& fEventQueue; + ClapEventQueue::CachedParameters& fCachedParameters; + #if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t& fCurrentProgram; + #endif + #if DISTRHO_PLUGIN_WANT_STATE + StringMap& fStateMap; + #endif + const clap_host_t* const fHost; + const clap_host_gui_t* const fHostGui; + #if DPF_CLAP_USING_HOST_TIMER + clap_id fTimerId; + const clap_host_timer_support_t* const fHostTimer; + #else + bool fCallbackRegistered; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + RingBufferControl fNotesRingBuffer; + #endif + ScopedPointer fUI; + + const bool fIsFloating; + + // Temporary data + double fScaleFactor; + uintptr_t fParentWindow; + uintptr_t fTransientWindow; + String fWindowTitle; + + // ---------------------------------------------------------------------------------------------------------------- + + void createUI() + { + DISTRHO_SAFE_ASSERT_RETURN(fUI == nullptr,); + + fUI = new UIExporter(this, + fParentWindow, + fPlugin.getSampleRate(), + editParameterCallback, + setParameterCallback, + setStateCallback, + sendNoteCallback, + setSizeCallback, + nullptr, // TODO fileRequestCallback, + d_nextBundlePath, + fPlugin.getInstancePointer(), + fScaleFactor); + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + fUI->programLoaded(fCurrentProgram); + #endif + + #if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update current state from plugin side + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + // Set state + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + const String& value = cit->second; + + // TODO skip DSP only states + + fUI->stateChanged(key, value); + } + #endif + + for (uint32_t i=0; iparameterChanged(i, value); + } + + if (fIsFloating) + { + if (fWindowTitle.isNotEmpty()) + fUI->setWindowTitle(fWindowTitle); + + if (fTransientWindow != 0) + fUI->setWindowTransientWinId(fTransientWindow); + } + } + + // ---------------------------------------------------------------------------------------------------------------- + // DPF callbacks + + void editParameter(const uint32_t rindex, const bool started) const + { + const ClapEventQueue::Event ev = { + started ? ClapEventQueue::kEventGestureBegin : ClapEventQueue::kEventGestureEnd, + rindex, 0.f + }; + fEventQueue.addEventFromUI(ev); + } + + static void editParameterCallback(void* const ptr, const uint32_t rindex, const bool started) + { + static_cast(ptr)->editParameter(rindex, started); + } + + void setParameterValue(const uint32_t rindex, const float value) + { + const ClapEventQueue::Event ev = { + ClapEventQueue::kEventParamSet, + rindex, value + }; + fEventQueue.addEventFromUI(ev); + } + + static void setParameterCallback(void* const ptr, const uint32_t rindex, const float value) + { + static_cast(ptr)->setParameterValue(rindex, value); + } + + void setSizeFromPlugin(const uint width, const uint height) + { + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI->getScaleFactor(); + const uint hostWidth = width / scaleFactor; + const uint hostHeight = height / scaleFactor; + #else + const uint hostWidth = width; + const uint hostHeight = height; + #endif + + if (fHostGui->request_resize(fHost, hostWidth, hostHeight)) + fUI->setWindowSizeFromHost(width, height); + } + + static void setSizeCallback(void* const ptr, const uint width, const uint height) + { + static_cast(ptr)->setSizeFromPlugin(width, height); + } + + #if DISTRHO_PLUGIN_WANT_STATE + void setState(const char* const key, const char* const value) + { + fPluginEventQueue->setStateFromUI(key, value); + } + + static void setStateCallback(void* const ptr, const char* key, const char* value) + { + static_cast(ptr)->setState(key, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + uint8_t midiData[3]; + midiData[0] = (velocity != 0 ? 0x90 : 0x80) | channel; + midiData[1] = note; + midiData[2] = velocity; + fNotesRingBuffer.writeCustomData(midiData, 3); + fNotesRingBuffer.commitWrite(); + } + + static void sendNoteCallback(void* const ptr, const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + static_cast(ptr)->sendNote(channel, note, velocity); + } + #endif + + /* TODO + bool fileRequest(const char*) + { + return true; + } + + static bool fileRequestCallback(void* const ptr, const char* const key) + { + return static_cast(ptr)->fileRequest(key); + } + */ +}; + +// -------------------------------------------------------------------------------------------------------------------- + +#endif // DISTRHO_PLUGIN_HAS_UI + +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static constexpr const writeMidiFunc writeMidiCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +static constexpr const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_STATE +static constexpr const updateStateValueFunc updateStateValueCallback = nullptr; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * CLAP plugin class. + */ +class PluginCLAP : ClapEventQueue +{ +public: + PluginCLAP(const clap_host_t* const host) + : fPlugin(this, + writeMidiCallback, + requestParameterValueChangeCallback, + updateStateValueCallback), + fHost(host), + fOutputEvents(nullptr), + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + fUsingCV(false), + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + fLatencyChanged(false), + fLastKnownLatency(0), + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fMidiEventCount(0), + #endif + fHostExtensions(host) + { + fCachedParameters.setup(fPlugin.getParameterCount()); + + #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT + fNotesRingBuffer.setRingBuffer(&fNotesBuffer, true); + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + for (uint32_t i=0, count=fPlugin.getStateCount(); i(); + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + fillInBusInfoDetails(); + #endif + #if DISTRHO_PLUGIN_NUM_INPUTS != 0 && DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + fillInBusInfoPairs(); + #endif + } + + // ---------------------------------------------------------------------------------------------------------------- + // core + + template + const T* getHostExtension(const char* const extensionId) const + { + return static_cast(fHost->get_extension(fHost, extensionId)); + } + + bool init() + { + if (!clap_version_is_compatible(fHost->clap_version)) + return false; + + return fHostExtensions.init(); + } + + void activate(const double sampleRate, const uint32_t maxFramesCount) + { + fPlugin.setSampleRate(sampleRate, true); + fPlugin.setBufferSize(maxFramesCount, true); + fPlugin.activate(); + } + + void deactivate() + { + fPlugin.deactivate(); + #if DISTRHO_PLUGIN_WANT_LATENCY + checkForLatencyChanges(false, true); + reportLatencyChangeIfNeeded(); + #endif + } + + bool process(const clap_process_t* const process) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fMidiEventCount = 0; + #endif + + #if DISTRHO_PLUGIN_HAS_UI + if (const clap_output_events_t* const outputEvents = process->out_events) + { + const RecursiveMutexTryLocker crmtl(fEventQueue.lock); + + if (crmtl.wasLocked()) + { + // reuse the same struct for gesture and parameters, they are compatible up to where it matters + clap_event_param_value_t clapEvent = { + { 0, 0, 0, 0, CLAP_EVENT_IS_LIVE }, + 0, nullptr, 0, 0, 0, 0, 0.0 + }; + + for (uint32_t i=0; itry_push(outputEvents, &clapEvent.header); + } + + fEventQueue.used = 0; + } + } + #endif + + #if DISTRHO_PLUGIN_WANT_TIMEPOS + if (const clap_event_transport_t* const transport = process->transport) + { + fTimePosition.playing = (transport->flags & CLAP_TRANSPORT_IS_PLAYING) != 0 && + (transport->flags & CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL) == 0; + + fTimePosition.frame = process->steady_time >= 0 ? process->steady_time : 0; + + if (transport->flags & CLAP_TRANSPORT_HAS_TEMPO) + fTimePosition.bbt.beatsPerMinute = transport->tempo; + else + fTimePosition.bbt.beatsPerMinute = 120.0; + + // ticksPerBeat is not possible with CLAP + fTimePosition.bbt.ticksPerBeat = 1920.0; + + if ((transport->flags & (CLAP_TRANSPORT_HAS_BEATS_TIMELINE|CLAP_TRANSPORT_HAS_TIME_SIGNATURE)) == (CLAP_TRANSPORT_HAS_BEATS_TIMELINE|CLAP_TRANSPORT_HAS_TIME_SIGNATURE)) + { + if (transport->song_pos_beats >= 0) + { + const int64_t clapPos = std::abs(transport->song_pos_beats); + const int64_t clapBeats = clapPos >> 31; + const double clapRest = static_cast(clapPos & 0x7fffffff) / CLAP_BEATTIME_FACTOR; + + fTimePosition.bbt.bar = static_cast(clapBeats) / transport->tsig_num + 1; + fTimePosition.bbt.beat = static_cast(clapBeats % transport->tsig_num) + 1; + fTimePosition.bbt.tick = clapRest * fTimePosition.bbt.ticksPerBeat; + } + else + { + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0.0; + } + + fTimePosition.bbt.valid = true; + fTimePosition.bbt.beatsPerBar = transport->tsig_num; + fTimePosition.bbt.beatType = transport->tsig_denom; + } + else + { + fTimePosition.bbt.valid = false; + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0.0; + fTimePosition.bbt.beatsPerBar = 4.0f; + fTimePosition.bbt.beatType = 4.0f; + } + + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat* + fTimePosition.bbt.beatsPerBar* + (fTimePosition.bbt.bar-1); + } + else + { + fTimePosition.playing = false; + fTimePosition.frame = 0; + fTimePosition.bbt.valid = false; + fTimePosition.bbt.beatsPerMinute = 120.0; + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0.0; + fTimePosition.bbt.beatsPerBar = 4.f; + fTimePosition.bbt.beatType = 4.f; + fTimePosition.bbt.barStartTick = 0; + } + + fPlugin.setTimePosition(fTimePosition); + #endif + + if (const clap_input_events_t* const inputEvents = process->in_events) + { + if (const uint32_t len = inputEvents->size(inputEvents)) + { + for (uint32_t i=0; iget(inputEvents, i); + + switch (event->type) + { + case CLAP_EVENT_NOTE_ON: + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + // BUG: even though we only report CLAP_NOTE_DIALECT_MIDI as supported, Bitwig sends us this anyway + addNoteEvent(static_cast(static_cast(event)), true); + #endif + break; + case CLAP_EVENT_NOTE_OFF: + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + // BUG: even though we only report CLAP_NOTE_DIALECT_MIDI as supported, Bitwig sends us this anyway + addNoteEvent(static_cast(static_cast(event)), false); + #endif + break; + case CLAP_EVENT_NOTE_CHOKE: + case CLAP_EVENT_NOTE_END: + case CLAP_EVENT_NOTE_EXPRESSION: + break; + case CLAP_EVENT_PARAM_VALUE: + DISTRHO_SAFE_ASSERT_UINT2_BREAK(event->size == sizeof(clap_event_param_value), + event->size, sizeof(clap_event_param_value)); + setParameterValueFromEvent(static_cast(static_cast(event))); + break; + case CLAP_EVENT_PARAM_MOD: + case CLAP_EVENT_PARAM_GESTURE_BEGIN: + case CLAP_EVENT_PARAM_GESTURE_END: + case CLAP_EVENT_TRANSPORT: + break; + case CLAP_EVENT_MIDI: + DISTRHO_SAFE_ASSERT_UINT2_BREAK(event->size == sizeof(clap_event_midi_t), + event->size, sizeof(clap_event_midi_t)); + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + addMidiEvent(static_cast(static_cast(event))); + #endif + break; + case CLAP_EVENT_MIDI_SYSEX: + case CLAP_EVENT_MIDI2: + break; + } + } + } + } + + #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (fMidiEventCount != kMaxMidiEvents && fNotesRingBuffer.isDataAvailableForReading()) + { + uint8_t midiData[3]; + const uint32_t frame = fMidiEventCount != 0 ? fMidiEvents[fMidiEventCount-1].frame : 0; + + while (fNotesRingBuffer.isDataAvailableForReading()) + { + if (! fNotesRingBuffer.readCustomData(midiData, 3)) + break; + + MidiEvent& midiEvent(fMidiEvents[fMidiEventCount++]); + midiEvent.frame = frame; + midiEvent.size = 3; + std::memcpy(midiEvent.data, midiData, 3); + + if (fMidiEventCount == kMaxMidiEvents) + break; + } + } + #endif + + if (const uint32_t frames = process->frames_count) + { + #if DISTRHO_PLUGIN_NUM_INPUTS != 0 + const float** const audioInputs = fAudioInputs; + + uint32_t in=0; + for (uint32_t i=0; iaudio_inputs_count; ++i) + { + const clap_audio_buffer_t& inputs(process->audio_inputs[i]); + DISTRHO_SAFE_ASSERT_CONTINUE(inputs.channel_count != 0); + + for (uint32_t j=0; j(inputs.data32[j]); + } + + if (fUsingCV) + { + for (; inaudio_inputs_count, false); + } + #else + constexpr const float** const audioInputs = nullptr; + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + float** const audioOutputs = fAudioOutputs; + + uint32_t out=0; + for (uint32_t i=0; iaudio_outputs_count; ++i) + { + const clap_audio_buffer_t& outputs(process->audio_outputs[i]); + DISTRHO_SAFE_ASSERT_CONTINUE(outputs.channel_count != 0); + + for (uint32_t j=0; jout_events; + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fPlugin.run(audioInputs, audioOutputs, frames, fMidiEvents, fMidiEventCount); + #else + fPlugin.run(audioInputs, audioOutputs, frames); + #endif + + flushParameters(nullptr, process->out_events, frames - 1); + + fOutputEvents = nullptr; + } + + #if DISTRHO_PLUGIN_WANT_LATENCY + checkForLatencyChanges(true, false); + #endif + + return true; + } + + void onMainThread() + { + #if DISTRHO_PLUGIN_WANT_LATENCY + reportLatencyChangeIfNeeded(); + #endif + } + + // ---------------------------------------------------------------------------------------------------------------- + // parameters + + uint32_t getParameterCount() const + { + return fPlugin.getParameterCount(); + } + + bool getParameterInfo(const uint32_t index, clap_param_info_t* const info) const + { + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + + if (fPlugin.getParameterDesignation(index) == kParameterDesignationBypass) + { + info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_BYPASS|CLAP_PARAM_IS_AUTOMATABLE; + std::strcpy(info->name, "Bypass"); + std::strcpy(info->module, "dpf_bypass"); + } + else + { + const uint32_t hints = fPlugin.getParameterHints(index); + const uint32_t groupId = fPlugin.getParameterGroupId(index); + + info->flags = 0; + if (hints & kParameterIsOutput) + info->flags |= CLAP_PARAM_IS_READONLY; + else if (hints & kParameterIsAutomatable) + info->flags |= CLAP_PARAM_IS_AUTOMATABLE; + + if (hints & (kParameterIsBoolean|kParameterIsInteger)) + info->flags |= CLAP_PARAM_IS_STEPPED; + + d_strncpy(info->name, fPlugin.getParameterName(index), CLAP_NAME_SIZE); + + uint wrtn; + if (groupId != kPortGroupNone) + { + const PortGroupWithId& portGroup(fPlugin.getPortGroupById(groupId)); + strncpy(info->module, portGroup.symbol, CLAP_PATH_SIZE / 2); + info->module[CLAP_PATH_SIZE / 2] = '\0'; + wrtn = std::strlen(info->module); + info->module[wrtn++] = '/'; + } + else + { + wrtn = 0; + } + + d_strncpy(info->module + wrtn, fPlugin.getParameterSymbol(index), CLAP_PATH_SIZE - wrtn); + } + + info->id = index; + info->cookie = nullptr; + info->min_value = ranges.min; + info->max_value = ranges.max; + info->default_value = ranges.def; + return true; + } + + bool getParameterValue(const clap_id param_id, double* const value) const + { + *value = fPlugin.getParameterValue(param_id); + return true; + } + + bool getParameterStringForValue(const clap_id param_id, double value, char* const display, const uint32_t size) const + { + const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(param_id)); + const ParameterRanges& ranges(fPlugin.getParameterRanges(param_id)); + const uint32_t hints = fPlugin.getParameterHints(param_id); + + if (hints & kParameterIsBoolean) + { + const float midRange = ranges.min + (ranges.max - ranges.min) * 0.5f; + value = value > midRange ? ranges.max : ranges.min; + } + else if (hints & kParameterIsInteger) + { + value = std::round(value); + } + + for (uint32_t i=0; i < enumValues.count; ++i) + { + if (d_isEqual(static_cast(enumValues.values[i].value), value)) + { + d_strncpy(display, enumValues.values[i].label, size); + return true; + } + } + + if (hints & kParameterIsInteger) + snprintf_i32(display, value, size); + else + snprintf_f32(display, value, size); + + return true; + } + + bool getParameterValueForString(const clap_id param_id, const char* const display, double* const value) const + { + const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(param_id)); + const bool isInteger = fPlugin.isParameterInteger(param_id); + + for (uint32_t i=0; i < enumValues.count; ++i) + { + if (std::strcmp(display, enumValues.values[i].label) == 0) + { + *value = enumValues.values[i].value; + return true; + } + } + + if (isInteger) + *value = std::atoi(display); + else + *value = std::atof(display); + + return true; + } + + void flushParameters(const clap_input_events_t* const in, + const clap_output_events_t* const out, + const uint32_t frameOffset) + { + if (const uint32_t len = in != nullptr ? in->size(in) : 0) + { + for (uint32_t i=0; iget(in, i); + + if (event->type != CLAP_EVENT_PARAM_VALUE) + continue; + + DISTRHO_SAFE_ASSERT_UINT2_BREAK(event->size == sizeof(clap_event_param_value), + event->size, sizeof(clap_event_param_value)); + + setParameterValueFromEvent(static_cast(static_cast(event))); + } + } + + if (out != nullptr) + { + clap_event_param_value_t clapEvent = { + { sizeof(clap_event_param_value_t), frameOffset, 0, CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_IS_LIVE }, + 0, nullptr, 0, 0, 0, 0, 0.0 + }; + + float value; + for (uint i=0; itry_push(out, &clapEvent.header); + } + } + } + + #if DISTRHO_PLUGIN_WANT_LATENCY + const bool active = fPlugin.isActive(); + checkForLatencyChanges(active, !active); + #endif + } + + // ---------------------------------------------------------------------------------------------------------------- + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void addNoteEvent(const clap_event_note_t* const event, const bool isOn) noexcept + { + DISTRHO_SAFE_ASSERT_UINT_RETURN(event->port_index == 0, event->port_index,); + + if (fMidiEventCount == kMaxMidiEvents) + return; + + MidiEvent& midiEvent(fMidiEvents[fMidiEventCount++]); + midiEvent.frame = event->header.time; + midiEvent.size = 3; + midiEvent.data[0] = (isOn ? 0x90 : 0x80) | (event->channel & 0x0F); + midiEvent.data[1] = std::max(0, std::min(127, static_cast(event->key))); + midiEvent.data[2] = std::max(0, std::min(127, static_cast(event->velocity * 127 + 0.5))); + } + + void addMidiEvent(const clap_event_midi_t* const event) noexcept + { + DISTRHO_SAFE_ASSERT_UINT_RETURN(event->port_index == 0, event->port_index,); + + if (fMidiEventCount == kMaxMidiEvents) + return; + + MidiEvent& midiEvent(fMidiEvents[fMidiEventCount++]); + midiEvent.frame = event->header.time; + midiEvent.size = 3; + std::memcpy(midiEvent.data, event->data, 3); + } + #endif + + void setParameterValueFromEvent(const clap_event_param_value* const event) + { + fCachedParameters.values[event->param_id] = event->value; + fCachedParameters.changed[event->param_id] = true; + fPlugin.setParameterValue(event->param_id, event->value); + } + + // ---------------------------------------------------------------------------------------------------------------- + // audio ports + + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + template + uint32_t getAudioPortCount() const noexcept + { + return (isInput ? fAudioInputBuses : fAudioOutputBuses).size(); + } + + template + bool getAudioPortInfo(const uint32_t index, clap_audio_port_info_t* const info) const noexcept + { + const std::vector& busInfos(isInput ? fAudioInputBuses : fAudioOutputBuses); + DISTRHO_SAFE_ASSERT_RETURN(index < busInfos.size(), false); + + const BusInfo& busInfo(busInfos[index]); + + info->id = busInfo.groupId; + d_strncpy(info->name, busInfo.name, CLAP_NAME_SIZE); + + info->flags = busInfo.isMain ? CLAP_AUDIO_PORT_IS_MAIN : 0x0; + info->channel_count = busInfo.numChannels; + + switch (busInfo.groupId) + { + case kPortGroupMono: + info->port_type = CLAP_PORT_MONO; + break; + case kPortGroupStereo: + info->port_type = CLAP_PORT_STEREO; + break; + default: + info->port_type = nullptr; + break; + } + + info->in_place_pair = busInfo.hasPair ? busInfo.groupId : CLAP_INVALID_ID; + return true; + } + #endif + + // ---------------------------------------------------------------------------------------------------------------- + // latency + + #if DISTRHO_PLUGIN_WANT_LATENCY + uint32_t getLatency() const noexcept + { + return fPlugin.getLatency(); + } + + void checkForLatencyChanges(const bool isActive, const bool fromMainThread) + { + const uint32_t latency = fPlugin.getLatency(); + + if (fLastKnownLatency == latency) + return; + + fLastKnownLatency = latency; + + if (isActive) + { + fLatencyChanged = true; + fHost->request_restart(fHost); + } + else + { + // if this is main-thread we can report latency change directly + if (fromMainThread || (fHostExtensions.threadCheck != nullptr && fHostExtensions.threadCheck->is_main_thread(fHost))) + { + fLatencyChanged = false; + fHostExtensions.latency->changed(fHost); + } + // otherwise we need to request a main-thread callback + else + { + fLatencyChanged = true; + fHost->request_callback(fHost); + } + } + } + + // called from main thread + void reportLatencyChangeIfNeeded() + { + if (fLatencyChanged) + { + fLatencyChanged = false; + fHostExtensions.latency->changed(fHost); + } + } + #endif + + // ---------------------------------------------------------------------------------------------------------------- + // state + + bool stateSave(const clap_ostream_t* const stream) + { + const uint32_t paramCount = fPlugin.getParameterCount(); + #if DISTRHO_PLUGIN_WANT_STATE + const uint32_t stateCount = fPlugin.getStateCount(); + #else + const uint32_t stateCount = 0; + #endif + + if (stateCount == 0 && paramCount == 0) + { + char buffer = '\0'; + return stream->write(stream, &buffer, 1) == 1; + } + + #if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update current state + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } + #endif + + String state; + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + { + String tmpStr("__dpf_program__\xff"); + tmpStr += String(fCurrentProgram); + tmpStr += "\xff"; + + state += tmpStr; + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + if (stateCount != 0) + { + state += "__dpf_state_begin__\xff"; + + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + const String& value = cit->second; + + // join key and value + String tmpStr; + tmpStr = key; + tmpStr += "\xff"; + tmpStr += value; + tmpStr += "\xff"; + + state += tmpStr; + } + + state += "__dpf_state_end__\xff"; + } + #endif + + if (paramCount != 0) + { + state += "__dpf_parameters_begin__\xff"; + + for (uint32_t i=0; i(std::round(fPlugin.getParameterValue(i)))); + else + tmpStr += String(fPlugin.getParameterValue(i)); + tmpStr += "\xff"; + + state += tmpStr; + } + + state += "__dpf_parameters_end__\xff"; + } + + // terminator + state += "\xfe"; + + state.replace('\xff', '\0'); + + // now saving state, carefully until host written bytes matches full state size + const char* buffer = state.buffer(); + const int32_t size = static_cast(state.length())+1; + + for (int32_t wrtntotal = 0, wrtn; wrtntotal < size; wrtntotal += wrtn) + { + wrtn = stream->write(stream, buffer, size - wrtntotal); + DISTRHO_SAFE_ASSERT_INT_RETURN(wrtn > 0, wrtn, false); + } + + return true; + } + + bool stateLoad(const clap_istream_t* const stream) + { + #if DISTRHO_PLUGIN_HAS_UI + ClapUI* const ui = fUI.get(); + #endif + String key, value; + bool hasValue = false; + bool fillingKey = true; // if filling key or value + char queryingType = 'i'; // can be 'n', 's' or 'p' (none, states, parameters) + + char buffer[512], orig; + buffer[sizeof(buffer)-1] = '\xff'; + + for (int32_t terminated = 0, read; terminated == 0;) + { + read = stream->read(stream, buffer, sizeof(buffer)-1); + DISTRHO_SAFE_ASSERT_INT_RETURN(read >= 0, read, false); + + if (read == 0) + return true; + + for (int32_t i = 0; i < read; ++i) + { + // found terminator, stop here + if (buffer[i] == '\xfe') + { + terminated = 1; + break; + } + + // store character at read position + orig = buffer[read]; + + // place null character to create valid string + buffer[read] = '\0'; + + // append to temporary vars + if (fillingKey) + { + key += buffer + i; + } + else + { + value += buffer + i; + hasValue = true; + } + + // increase buffer offset by length of string + i += std::strlen(buffer + i); + + // restore read character + buffer[read] = orig; + + // if buffer offset points to null, we found the end of a string, lets check + if (buffer[i] == '\0') + { + // special keys + if (key == "__dpf_state_begin__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'i' || queryingType == 'n', + queryingType, false); + queryingType = 's'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + if (key == "__dpf_state_end__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 's', queryingType, false); + queryingType = 'n'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + if (key == "__dpf_parameters_begin__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'i' || queryingType == 'n', + queryingType, false); + queryingType = 'p'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + if (key == "__dpf_parameters_end__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'p', queryingType, false); + queryingType = 'x'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + + // no special key, swap between reading real key and value + fillingKey = !fillingKey; + + // if there is no value yet keep reading until we have one + if (! hasValue) + continue; + + if (key == "__dpf_program__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'i', queryingType, false); + queryingType = 'n'; + + d_debug("found program '%s'", value.buffer()); + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + const int program = std::atoi(value.buffer()); + DISTRHO_SAFE_ASSERT_CONTINUE(program >= 0); + + fCurrentProgram = static_cast(program); + fPlugin.loadProgram(fCurrentProgram); + + #if DISTRHO_PLUGIN_HAS_UI + if (ui != nullptr) + ui->setProgramFromPlugin(fCurrentProgram); + #endif + #endif + } + else if (queryingType == 's') + { + d_debug("found state '%s' '%s'", key.buffer(), value.buffer()); + + #if DISTRHO_PLUGIN_WANT_STATE + if (fPlugin.wantStateKey(key)) + { + fStateMap[key] = value; + fPlugin.setState(key, value); + + #if DISTRHO_PLUGIN_HAS_UI + if (ui != nullptr) + ui->setStateFromPlugin(key, value); + #endif + } + #endif + } + else if (queryingType == 'p') + { + d_debug("found parameter '%s' '%s'", key.buffer(), value.buffer()); + float fvalue; + + // find parameter with this symbol, and set its value + for (uint32_t j=0; jrescan(fHost, CLAP_PARAM_RESCAN_VALUES|CLAP_PARAM_RESCAN_TEXT); + + #if DISTRHO_PLUGIN_WANT_LATENCY + checkForLatencyChanges(fPlugin.isActive(), true); + reportLatencyChangeIfNeeded(); + #endif + + #if DISTRHO_PLUGIN_HAS_UI + if (ui != nullptr) + { + for (uint32_t i=0; isetParameterValueFromPlugin(i, fCachedParameters.values[i]); + } + } + #endif + + return true; + } + + // ---------------------------------------------------------------------------------------------------------------- + // gui + + #if DISTRHO_PLUGIN_HAS_UI + bool createUI(const bool isFloating) + { + const clap_host_gui_t* const hostGui = getHostExtension(CLAP_EXT_GUI); + DISTRHO_SAFE_ASSERT_RETURN(hostGui != nullptr, false); + + #if DPF_CLAP_USING_HOST_TIMER + const clap_host_timer_support_t* const hostTimer = getHostExtension(CLAP_EXT_TIMER_SUPPORT); + DISTRHO_SAFE_ASSERT_RETURN(hostTimer != nullptr, false); + #endif + + fUI = new ClapUI(fPlugin, this, fHost, hostGui, + #if DPF_CLAP_USING_HOST_TIMER + hostTimer, + #endif + isFloating); + return true; + } + + void destroyUI() + { + fUI = nullptr; + } + + ClapUI* getUI() const noexcept + { + return fUI.get(); + } + #endif + + #if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_STATE + void setStateFromUI(const char* const key, const char* const value) override + { + fPlugin.setState(key, value); + + // check if we want to save this key + if (! fPlugin.wantStateKey(key)) + return; + + // check if key already exists + for (StringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it) + { + const String& dkey(it->first); + + if (dkey == key) + { + it->second = value; + return; + } + } + + d_stderr("Failed to find plugin state with key \"%s\"", key); + } + #endif + + // ---------------------------------------------------------------------------------------------------------------- + +private: + // Plugin and UI + PluginExporter fPlugin; + #if DISTRHO_PLUGIN_HAS_UI + ScopedPointer fUI; + #endif + + // CLAP stuff + const clap_host_t* const fHost; + const clap_output_events_t* fOutputEvents; + + #if DISTRHO_PLUGIN_NUM_INPUTS != 0 + const float* fAudioInputs[DISTRHO_PLUGIN_NUM_INPUTS]; + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + float* fAudioOutputs[DISTRHO_PLUGIN_NUM_OUTPUTS]; + #endif + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + bool fUsingCV; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + bool fLatencyChanged; + uint32_t fLastKnownLatency; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + uint32_t fMidiEventCount; + MidiEvent fMidiEvents[kMaxMidiEvents]; + #if DISTRHO_PLUGIN_HAS_UI + RingBufferControl fNotesRingBuffer; + #endif + #endif + #if DISTRHO_PLUGIN_WANT_TIMEPOS + TimePosition fTimePosition; + #endif + + struct HostExtensions { + const clap_host_t* const host; + const clap_host_params_t* params; + #if DISTRHO_PLUGIN_WANT_LATENCY + const clap_host_latency_t* latency; + const clap_host_thread_check_t* threadCheck; + #endif + + HostExtensions(const clap_host_t* const host) + : host(host), + params(nullptr) + #if DISTRHO_PLUGIN_WANT_LATENCY + , latency(nullptr) + , threadCheck(nullptr) + #endif + {} + + bool init() + { + params = static_cast(host->get_extension(host, CLAP_EXT_PARAMS)); + #if DISTRHO_PLUGIN_WANT_LATENCY + DISTRHO_SAFE_ASSERT_RETURN(host->request_restart != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(host->request_callback != nullptr, false); + latency = static_cast(host->get_extension(host, CLAP_EXT_LATENCY)); + threadCheck = static_cast(host->get_extension(host, CLAP_EXT_THREAD_CHECK)); + #endif + return true; + } + } fHostExtensions; + + // ---------------------------------------------------------------------------------------------------------------- + // helper functions for dealing with buses + + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + struct BusInfo { + char name[CLAP_NAME_SIZE]; + uint32_t numChannels; + bool hasPair; + bool isCV; + bool isMain; + uint32_t groupId; + }; + std::vector fAudioInputBuses, fAudioOutputBuses; + + template + void fillInBusInfoDetails() + { + constexpr const uint32_t numPorts = isInput ? DISTRHO_PLUGIN_NUM_INPUTS : DISTRHO_PLUGIN_NUM_OUTPUTS; + std::vector& busInfos(isInput ? fAudioInputBuses : fAudioOutputBuses); + + enum { + kPortTypeNull, + kPortTypeAudio, + kPortTypeSidechain, + kPortTypeCV, + kPortTypeGroup + } lastSeenPortType = kPortTypeNull; + uint32_t lastSeenGroupId = kPortGroupNone; + uint32_t nonGroupAudioId = 0; + uint32_t nonGroupSidechainId = 0x20000000; + + for (uint32_t i=0; i 3) + return true; + + const clap_event_midi clapEvent = { + { sizeof(clap_event_midi), midiEvent.frame, 0, CLAP_EVENT_MIDI, CLAP_EVENT_IS_LIVE }, + 0, { midiEvent.data[0], + static_cast(midiEvent.size >= 2 ? midiEvent.data[1] : 0), + static_cast(midiEvent.size >= 3 ? midiEvent.data[2] : 0) } + }; + return fOutputEvents->try_push(fOutputEvents, &clapEvent.header); + } + + static bool writeMidiCallback(void* const ptr, const MidiEvent& midiEvent) + { + return static_cast(ptr)->writeMidi(midiEvent); + } + #endif + + #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(uint32_t, float) + { + return true; + } + + static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) + { + return static_cast(ptr)->requestParameterValueChange(index, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + bool updateState(const char*, const char*) + { + return true; + } + + static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value) + { + return static_cast(ptr)->updateState(key, value); + } + #endif +}; + +// -------------------------------------------------------------------------------------------------------------------- + +static ScopedPointer sPlugin; + +// -------------------------------------------------------------------------------------------------------------------- +// plugin gui + +#if DISTRHO_PLUGIN_HAS_UI + +static const char* const kSupportedAPIs[] = { +#if defined(DISTRHO_OS_WINDOWS) + CLAP_WINDOW_API_WIN32, +#elif defined(DISTRHO_OS_MAC) + CLAP_WINDOW_API_COCOA, +#else + CLAP_WINDOW_API_X11, +#endif +}; + +// TODO DPF external UI +static bool CLAP_ABI clap_gui_is_api_supported(const clap_plugin_t*, const char* const api, bool) +{ + for (size_t i=0; i(plugin->plugin_data); + return instance->createUI(is_floating); + } + } + + return false; +} + +static void CLAP_ABI clap_gui_destroy(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + instance->destroyUI(); +} + +static bool CLAP_ABI clap_gui_set_scale(const clap_plugin_t* const plugin, const double scale) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + #ifndef DISTRHO_OS_MAC + return gui->setScaleFactor(scale); + #else + return true; + // unused + (void)scale; + #endif +} + +static bool CLAP_ABI clap_gui_get_size(const clap_plugin_t* const plugin, uint32_t* const width, uint32_t* const height) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->getSize(width, height); +} + +static bool CLAP_ABI clap_gui_can_resize(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->canResize(); +} + +static bool CLAP_ABI clap_gui_get_resize_hints(const clap_plugin_t* const plugin, clap_gui_resize_hints_t* const hints) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->getResizeHints(hints); +} + +static bool CLAP_ABI clap_gui_adjust_size(const clap_plugin_t* const plugin, uint32_t* const width, uint32_t* const height) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->adjustSize(width, height); +} + +static bool CLAP_ABI clap_gui_set_size(const clap_plugin_t* const plugin, const uint32_t width, const uint32_t height) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->setSizeFromHost(width, height); +} + +static bool CLAP_ABI clap_gui_set_parent(const clap_plugin_t* const plugin, const clap_window_t* const window) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->setParent(window); +} + +static bool CLAP_ABI clap_gui_set_transient(const clap_plugin_t* const plugin, const clap_window_t* const window) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->setTransient(window); +} + +static void CLAP_ABI clap_gui_suggest_title(const clap_plugin_t* const plugin, const char* const title) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr,); + return gui->suggestTitle(title); +} + +static bool CLAP_ABI clap_gui_show(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->show(); +} + +static bool CLAP_ABI clap_gui_hide(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr, false); + return gui->hide(); +} + +static const clap_plugin_gui_t clap_plugin_gui = { + clap_gui_is_api_supported, + clap_gui_get_preferred_api, + clap_gui_create, + clap_gui_destroy, + clap_gui_set_scale, + clap_gui_get_size, + clap_gui_can_resize, + clap_gui_get_resize_hints, + clap_gui_adjust_size, + clap_gui_set_size, + clap_gui_set_parent, + clap_gui_set_transient, + clap_gui_suggest_title, + clap_gui_show, + clap_gui_hide +}; + +// -------------------------------------------------------------------------------------------------------------------- +// plugin timer + +#if DPF_CLAP_USING_HOST_TIMER +static void CLAP_ABI clap_plugin_on_timer(const clap_plugin_t* const plugin, clap_id) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + ClapUI* const gui = instance->getUI(); + DISTRHO_SAFE_ASSERT_RETURN(gui != nullptr,); + return gui->idleCallback(); +} + +static const clap_plugin_timer_support_t clap_timer = { + clap_plugin_on_timer +}; +#endif + +#endif // DISTRHO_PLUGIN_HAS_UI + +// -------------------------------------------------------------------------------------------------------------------- +// plugin audio ports + +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 +static uint32_t CLAP_ABI clap_plugin_audio_ports_count(const clap_plugin_t* const plugin, const bool is_input) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return is_input ? instance->getAudioPortCount() + : instance->getAudioPortCount(); +} + +static bool CLAP_ABI clap_plugin_audio_ports_get(const clap_plugin_t* const plugin, + const uint32_t index, + const bool is_input, + clap_audio_port_info_t* const info) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return is_input ? instance->getAudioPortInfo(index, info) + : instance->getAudioPortInfo(index, info); +} + +static const clap_plugin_audio_ports_t clap_plugin_audio_ports = { + clap_plugin_audio_ports_count, + clap_plugin_audio_ports_get +}; +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// plugin note ports + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT+DISTRHO_PLUGIN_WANT_MIDI_OUTPUT != 0 +static uint32_t CLAP_ABI clap_plugin_note_ports_count(const clap_plugin_t*, const bool is_input) +{ + return (is_input ? DISTRHO_PLUGIN_WANT_MIDI_INPUT : DISTRHO_PLUGIN_WANT_MIDI_OUTPUT) != 0 ? 1 : 0; +} + +static bool CLAP_ABI clap_plugin_note_ports_get(const clap_plugin_t*, uint32_t, + const bool is_input, clap_note_port_info_t* const info) +{ + if (is_input) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + info->id = 0; + info->supported_dialects = CLAP_NOTE_DIALECT_MIDI; + info->preferred_dialect = CLAP_NOTE_DIALECT_MIDI; + std::strcpy(info->name, "Event/MIDI Input"); + return true; + #endif + } + else + { + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + info->id = 0; + info->supported_dialects = CLAP_NOTE_DIALECT_MIDI; + info->preferred_dialect = CLAP_NOTE_DIALECT_MIDI; + std::strcpy(info->name, "Event/MIDI Output"); + return true; + #endif + } + + return false; +} + +static const clap_plugin_note_ports_t clap_plugin_note_ports = { + clap_plugin_note_ports_count, + clap_plugin_note_ports_get +}; +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// plugin parameters + +static uint32_t CLAP_ABI clap_plugin_params_count(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->getParameterCount(); +} + +static bool CLAP_ABI clap_plugin_params_get_info(const clap_plugin_t* const plugin, const uint32_t index, clap_param_info_t* const info) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->getParameterInfo(index, info); +} + +static bool CLAP_ABI clap_plugin_params_get_value(const clap_plugin_t* const plugin, const clap_id param_id, double* const value) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->getParameterValue(param_id, value); +} + +static bool CLAP_ABI clap_plugin_params_value_to_text(const clap_plugin_t* plugin, const clap_id param_id, const double value, char* const display, const uint32_t size) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->getParameterStringForValue(param_id, value, display, size); +} + +static bool CLAP_ABI clap_plugin_params_text_to_value(const clap_plugin_t* plugin, const clap_id param_id, const char* const display, double* const value) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->getParameterValueForString(param_id, display, value); +} + +static void CLAP_ABI clap_plugin_params_flush(const clap_plugin_t* plugin, const clap_input_events_t* in, const clap_output_events_t* out) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->flushParameters(in, out, 0); +} + +static const clap_plugin_params_t clap_plugin_params = { + clap_plugin_params_count, + clap_plugin_params_get_info, + clap_plugin_params_get_value, + clap_plugin_params_value_to_text, + clap_plugin_params_text_to_value, + clap_plugin_params_flush +}; + +#if DISTRHO_PLUGIN_WANT_LATENCY +// -------------------------------------------------------------------------------------------------------------------- +// plugin latency + +static uint32_t CLAP_ABI clap_plugin_latency_get(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->getLatency(); +} + +static const clap_plugin_latency_t clap_plugin_latency = { + clap_plugin_latency_get +}; +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// plugin state + +static bool CLAP_ABI clap_plugin_state_save(const clap_plugin_t* const plugin, const clap_ostream_t* const stream) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->stateSave(stream); +} + +static bool CLAP_ABI clap_plugin_state_load(const clap_plugin_t* const plugin, const clap_istream_t* const stream) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->stateLoad(stream); +} + +static const clap_plugin_state_t clap_plugin_state = { + clap_plugin_state_save, + clap_plugin_state_load +}; + +// -------------------------------------------------------------------------------------------------------------------- +// plugin + +static bool CLAP_ABI clap_plugin_init(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->init(); +} + +static void CLAP_ABI clap_plugin_destroy(const clap_plugin_t* const plugin) +{ + delete static_cast(plugin->plugin_data); + std::free(const_cast(plugin)); +} + +static bool CLAP_ABI clap_plugin_activate(const clap_plugin_t* const plugin, + const double sample_rate, + uint32_t, + const uint32_t max_frames_count) +{ + d_nextBufferSize = max_frames_count; + d_nextSampleRate = sample_rate; + + PluginCLAP* const instance = static_cast(plugin->plugin_data); + instance->activate(sample_rate, max_frames_count); + return true; +} + +static void CLAP_ABI clap_plugin_deactivate(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + instance->deactivate(); +} + +static bool CLAP_ABI clap_plugin_start_processing(const clap_plugin_t*) +{ + // nothing to do + return true; +} + +static void CLAP_ABI clap_plugin_stop_processing(const clap_plugin_t*) +{ + // nothing to do +} + +static void CLAP_ABI clap_plugin_reset(const clap_plugin_t*) +{ + // nothing to do +} + +static clap_process_status CLAP_ABI clap_plugin_process(const clap_plugin_t* const plugin, const clap_process_t* const process) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + return instance->process(process) ? CLAP_PROCESS_CONTINUE : CLAP_PROCESS_ERROR; +} + +static const void* CLAP_ABI clap_plugin_get_extension(const clap_plugin_t*, const char* const id) +{ + if (std::strcmp(id, CLAP_EXT_PARAMS) == 0) + return &clap_plugin_params; + if (std::strcmp(id, CLAP_EXT_STATE) == 0) + return &clap_plugin_state; + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 + if (std::strcmp(id, CLAP_EXT_AUDIO_PORTS) == 0) + return &clap_plugin_audio_ports; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT+DISTRHO_PLUGIN_WANT_MIDI_OUTPUT != 0 + if (std::strcmp(id, CLAP_EXT_NOTE_PORTS) == 0) + return &clap_plugin_note_ports; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + if (std::strcmp(id, CLAP_EXT_LATENCY) == 0) + return &clap_plugin_latency; + #endif + #if DISTRHO_PLUGIN_HAS_UI + if (std::strcmp(id, CLAP_EXT_GUI) == 0) + return &clap_plugin_gui; + #if DPF_CLAP_USING_HOST_TIMER + if (std::strcmp(id, CLAP_EXT_TIMER_SUPPORT) == 0) + return &clap_timer; + #endif + #endif + return nullptr; +} + +static void CLAP_ABI clap_plugin_on_main_thread(const clap_plugin_t* const plugin) +{ + PluginCLAP* const instance = static_cast(plugin->plugin_data); + instance->onMainThread(); +} + +// -------------------------------------------------------------------------------------------------------------------- +// plugin factory + +static uint32_t CLAP_ABI clap_get_plugin_count(const clap_plugin_factory_t*) +{ + return 1; +} + +static const clap_plugin_descriptor_t* CLAP_ABI clap_get_plugin_descriptor(const clap_plugin_factory_t*, + const uint32_t index) +{ + DISTRHO_SAFE_ASSERT_UINT_RETURN(index == 0, index, nullptr); + + static const char* features[] = { + #ifdef DISTRHO_PLUGIN_CLAP_FEATURES + DISTRHO_PLUGIN_CLAP_FEATURES, + #elif DISTRHO_PLUGIN_IS_SYNTH + "instrument", + #endif + nullptr + }; + + static const clap_plugin_descriptor_t descriptor = { + CLAP_VERSION, + DISTRHO_PLUGIN_CLAP_ID, + sPlugin->getName(), + sPlugin->getMaker(), + // TODO url + "", + // TODO manual url + "", + // TODO support url + "", + // TODO version string + "", + sPlugin->getDescription(), + features + }; + + return &descriptor; +} + +static const clap_plugin_t* CLAP_ABI clap_create_plugin(const clap_plugin_factory_t* const factory, + const clap_host_t* const host, + const char*) +{ + clap_plugin_t* const pluginptr = static_cast(std::malloc(sizeof(clap_plugin_t))); + DISTRHO_SAFE_ASSERT_RETURN(pluginptr != nullptr, nullptr); + + // default early values + if (d_nextBufferSize == 0) + d_nextBufferSize = 1024; + if (d_nextSampleRate <= 0.0) + d_nextSampleRate = 44100.0; + + d_nextCanRequestParameterValueChanges = true; + + const clap_plugin_t plugin = { + clap_get_plugin_descriptor(factory, 0), + new PluginCLAP(host), + clap_plugin_init, + clap_plugin_destroy, + clap_plugin_activate, + clap_plugin_deactivate, + clap_plugin_start_processing, + clap_plugin_stop_processing, + clap_plugin_reset, + clap_plugin_process, + clap_plugin_get_extension, + clap_plugin_on_main_thread + }; + + std::memcpy(pluginptr, &plugin, sizeof(clap_plugin_t)); + return pluginptr; +} + +static const clap_plugin_factory_t clap_plugin_factory = { + clap_get_plugin_count, + clap_get_plugin_descriptor, + clap_create_plugin +}; + +// -------------------------------------------------------------------------------------------------------------------- +// plugin entry + +static bool CLAP_ABI clap_plugin_entry_init(const char* const plugin_path) +{ + static String bundlePath; + bundlePath = plugin_path; + d_nextBundlePath = bundlePath.buffer(); + + // init dummy plugin + if (sPlugin == nullptr) + { + // set valid but dummy values + d_nextBufferSize = 512; + d_nextSampleRate = 44100.0; + d_nextPluginIsDummy = true; + d_nextCanRequestParameterValueChanges = true; + + // Create dummy plugin to get data from + sPlugin = new PluginExporter(nullptr, nullptr, nullptr, nullptr); + + // unset + d_nextBufferSize = 0; + d_nextSampleRate = 0.0; + d_nextPluginIsDummy = false; + d_nextCanRequestParameterValueChanges = false; + } + + return true; +} + +static void CLAP_ABI clap_plugin_entry_deinit(void) +{ + sPlugin = nullptr; +} + +static const void* CLAP_ABI clap_plugin_entry_get_factory(const char* const factory_id) +{ + if (std::strcmp(factory_id, CLAP_PLUGIN_FACTORY_ID) == 0) + return &clap_plugin_factory; + return nullptr; +} + +static const clap_plugin_entry_t clap_plugin_entry = { + CLAP_VERSION, + clap_plugin_entry_init, + clap_plugin_entry_deinit, + clap_plugin_entry_get_factory +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +DISTRHO_PLUGIN_EXPORT +const clap_plugin_entry_t clap_entry = DISTRHO_NAMESPACE::clap_plugin_entry; + +// -------------------------------------------------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginCarla.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginCarla.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,551 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" + +#if DISTRHO_PLUGIN_HAS_UI +# include "DistrhoUIInternal.hpp" +#endif + +#include "CarlaNative.hpp" + +// TODO +#undef DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +#define DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 0 + +// ----------------------------------------------------------------------- + +START_NAMESPACE_DISTRHO + +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static constexpr const writeMidiFunc writeMidiCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +static constexpr const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; +#endif +// TODO +static constexpr const updateStateValueFunc updateStateValueCallback = nullptr; + +#if DISTRHO_PLUGIN_HAS_UI +// ----------------------------------------------------------------------- +// Carla UI + +#if ! DISTRHO_PLUGIN_WANT_STATE +static const setStateFunc setStateCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_IS_SYNTH +static const sendNoteFunc sendNoteCallback = nullptr; +#endif + +class UICarla +{ +public: + UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin) + : fHost(host), + fUI(this, 0, plugin->getSampleRate(), + editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, + nullptr, // window size + nullptr, // TODO file request + nullptr, // bundle path + plugin->getInstancePointer()) + { + fUI.setWindowTitle(host->uiName); + + if (host->uiParentId != 0) + fUI.setWindowTransientWinId(host->uiParentId); + } + + ~UICarla() + { + fUI.quit(); + } + + // --------------------------------------------- + + void carla_show(const bool yesNo) + { + fUI.setWindowVisible(yesNo); + } + + bool carla_idle() + { + return fUI.plugin_idle(); + } + + void carla_setParameterValue(const uint32_t index, const float value) + { + fUI.parameterChanged(index, value); + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + void carla_setMidiProgram(const uint32_t realProgram) + { + fUI.programLoaded(realProgram); + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + void carla_setCustomData(const char* const key, const char* const value) + { + fUI.stateChanged(key, value); + } +#endif + + void carla_setUiTitle(const char* const uiTitle) + { + fUI.setWindowTitle(uiTitle); + } + + // --------------------------------------------- + +protected: + void handleEditParameter(const uint32_t, const bool) + { + // TODO + } + + void handleSetParameterValue(const uint32_t rindex, const float value) + { + fHost->ui_parameter_changed(fHost->handle, rindex, value); + } + +#if DISTRHO_PLUGIN_WANT_STATE + void handleSetState(const char* const key, const char* const value) + { + fHost->ui_custom_data_changed(fHost->handle, key, value); + } +#endif + +#if DISTRHO_PLUGIN_IS_SYNTH + void handleSendNote(const uint8_t, const uint8_t, const uint8_t) + { + // TODO + } +#endif + + // --------------------------------------------- + +private: + // Plugin stuff + const NativeHostDescriptor* const fHost; + + // UI + UIExporter fUI; + + // --------------------------------------------- + // Callbacks + + #define handlePtr ((UICarla*)ptr) + + static void editParameterCallback(void* ptr, uint32_t index, bool started) + { + handlePtr->handleEditParameter(index, started); + } + + static void setParameterCallback(void* ptr, uint32_t rindex, float value) + { + handlePtr->handleSetParameterValue(rindex, value); + } + +#if DISTRHO_PLUGIN_WANT_STATE + static void setStateCallback(void* ptr, const char* key, const char* value) + { + handlePtr->handleSetState(key, value); + } +#endif + +#if DISTRHO_PLUGIN_IS_SYNTH + static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity) + { + handlePtr->handleSendNote(channel, note, velocity); + } +#endif + + #undef handlePtr + + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UICarla) +}; +#endif // DISTRHO_PLUGIN_HAS_UI + +// ----------------------------------------------------------------------- +// Carla Plugin + +class PluginCarla : public NativePluginClass +{ +public: + PluginCarla(const NativeHostDescriptor* const host) + : NativePluginClass(host), + fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback), + fScalePointsCache(nullptr) + { +#if DISTRHO_PLUGIN_HAS_UI + fUiPtr = nullptr; +#endif + } + + ~PluginCarla() override + { +#if DISTRHO_PLUGIN_HAS_UI + if (fUiPtr != nullptr) + { + delete fUiPtr; + fUiPtr = nullptr; + } +#endif + + if (fScalePointsCache != nullptr) + { + delete[] fScalePointsCache; + fScalePointsCache = nullptr; + } + } + +protected: + // ------------------------------------------------------------------- + // Plugin parameter calls + + uint32_t getParameterCount() const override + { + return fPlugin.getParameterCount(); + } + + const NativeParameter* getParameterInfo(const uint32_t index) const override + { + CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr); + + static NativeParameter param; + + param.scalePointCount = 0; + param.scalePoints = nullptr; + + { + int nativeParamHints = ::NATIVE_PARAMETER_IS_ENABLED; + const uint32_t paramHints = fPlugin.getParameterHints(index); + + if (paramHints & kParameterIsAutomatable) + nativeParamHints |= ::NATIVE_PARAMETER_IS_AUTOMABLE; + if (paramHints & kParameterIsBoolean) + nativeParamHints |= ::NATIVE_PARAMETER_IS_BOOLEAN; + if (paramHints & kParameterIsInteger) + nativeParamHints |= ::NATIVE_PARAMETER_IS_INTEGER; + if (paramHints & kParameterIsLogarithmic) + nativeParamHints |= ::NATIVE_PARAMETER_IS_LOGARITHMIC; + if (paramHints & kParameterIsOutput) + nativeParamHints |= ::NATIVE_PARAMETER_IS_OUTPUT; + + param.hints = static_cast(nativeParamHints); + } + + param.name = fPlugin.getParameterName(index); + param.unit = fPlugin.getParameterUnit(index); + + { + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + + param.ranges.def = ranges.def; + param.ranges.min = ranges.min; + param.ranges.max = ranges.max; + } + + { + const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index)); + + if (const uint32_t scalePointCount = enumValues.count) + { + NativeParameterScalePoint* const scalePoints = new NativeParameterScalePoint[scalePointCount]; + + for (uint32_t i=0; i(param.hints|::NATIVE_PARAMETER_USES_SCALEPOINTS); + } + else if (fScalePointsCache != nullptr) + { + delete[] fScalePointsCache; + fScalePointsCache = nullptr; + } + } + + return ¶m; + } + + float getParameterValue(const uint32_t index) const override + { + CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f); + + return fPlugin.getParameterValue(index); + } + + // ------------------------------------------------------------------- + // Plugin midi-program calls + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t getMidiProgramCount() const override + { + return fPlugin.getProgramCount(); + } + + const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const override + { + CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr); + + static NativeMidiProgram midiProgram; + + midiProgram.bank = index / 128; + midiProgram.program = index % 128; + midiProgram.name = fPlugin.getProgramName(index); + + return &midiProgram; + } +#endif + + // ------------------------------------------------------------------- + // Plugin state calls + + void setParameterValue(const uint32_t index, const float value) override + { + CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),); + + fPlugin.setParameterValue(index, value); + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override + { + const uint32_t realProgram(bank * 128 + program); + + CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),); + + fPlugin.loadProgram(realProgram); + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + void setCustomData(const char* const key, const char* const value) override + { + CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(value != nullptr,); + + fPlugin.setState(key, value); + } +#endif + + // ------------------------------------------------------------------- + // Plugin process calls + + void activate() override + { + fPlugin.activate(); + } + + void deactivate() override + { + fPlugin.deactivate(); + } + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames, + const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override + { + MidiEvent realMidiEvents[midiEventCount]; + + for (uint32_t i=0; i < midiEventCount; ++i) + { + const NativeMidiEvent& midiEvent(midiEvents[i]); + MidiEvent& realMidiEvent(realMidiEvents[i]); + + realMidiEvent.frame = midiEvent.time; + realMidiEvent.size = midiEvent.size; + + uint8_t j=0; + for (; j(inBuffer), outBuffer, frames, realMidiEvents, midiEventCount); + } +#else + void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames, + const NativeMidiEvent* const, const uint32_t) override + { + fPlugin.run(const_cast(inBuffer), outBuffer, frames); + } +#endif + + // ------------------------------------------------------------------- + // Plugin UI calls + +#if DISTRHO_PLUGIN_HAS_UI + void uiShow(const bool show) override + { + if (show) + { + createUiIfNeeded(); + CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,); + + fUiPtr->carla_show(show); + } + else if (fUiPtr != nullptr) + { + delete fUiPtr; + fUiPtr = nullptr; + } + } + + void uiIdle() override + { + CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,); + + if (! fUiPtr->carla_idle()) + { + uiClosed(); + + delete fUiPtr; + fUiPtr = nullptr; + } + } + + void uiSetParameterValue(const uint32_t index, const float value) override + { + CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,); + CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),); + + fUiPtr->carla_setParameterValue(index, value); + } + +# if DISTRHO_PLUGIN_WANT_PROGRAMS + void uiSetMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override + { + CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,); + + const uint32_t realProgram(bank * 128 + program); + + CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),); + + fUiPtr->carla_setMidiProgram(realProgram); + } +# endif + +# if DISTRHO_PLUGIN_WANT_STATE + void uiSetCustomData(const char* const key, const char* const value) override + { + CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,); + CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(value != nullptr,); + + fUiPtr->carla_setCustomData(key, value); + } +# endif +#endif + + // ------------------------------------------------------------------- + // Plugin dispatcher calls + + void bufferSizeChanged(const uint32_t bufferSize) override + { + fPlugin.setBufferSize(bufferSize, true); + } + + void sampleRateChanged(const double sampleRate) override + { + fPlugin.setSampleRate(sampleRate, true); + } + +#if DISTRHO_PLUGIN_HAS_UI + void uiNameChanged(const char* const uiName) override + { + CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,); + + fUiPtr->carla_setUiTitle(uiName); + } +#endif + + // ------------------------------------------------------------------- + +private: + PluginExporter fPlugin; + mutable NativeParameterScalePoint* fScalePointsCache; + +#if DISTRHO_PLUGIN_HAS_UI + // UI + UICarla* fUiPtr; + + void createUiIfNeeded() + { + if (fUiPtr == nullptr) + fUiPtr = new UICarla(getHostHandle(), &fPlugin); + } +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent) + { + if (midiEvent.size > 4) + return; + + const NativeMidiEvent event = { + midiEvent.frame, 0, midiEvent.size, midiEvent.data + }; + + return ((PluginCarla*)ptr)->fPlugin.writeMidiEvent(midiEvent); + } +#endif + +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(const uint32_t index, const float value) + { + // TODO implementation + return false; + } + + static bool requestParameterValueChangeCallback(void* ptr, const uint32_t index, const float value) + { + return thisPtr->requestParameterValueChange(index, value); + } +#endif + + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla) + + // ------------------------------------------------------------------- + +public: + static NativePluginHandle _instantiate(const NativeHostDescriptor* host) + { + d_nextBufferSize = host->get_buffer_size(host->handle); + d_nextSampleRate = host->get_sample_rate(host->handle); + return new PluginCarla(host); + } + + static void _cleanup(NativePluginHandle handle) + { + delete (PluginCarla*)handle; + } +}; + +END_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginChecks.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginChecks.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,210 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_CHECKS_H_INCLUDED +#define DISTRHO_PLUGIN_CHECKS_H_INCLUDED + +#ifndef DISTRHO_DETAILS_HPP_INCLUDED +# error wrong include order +#endif + +#include "DistrhoPluginInfo.h" + +// ----------------------------------------------------------------------- +// Check if all required macros are defined + +#ifndef DISTRHO_PLUGIN_NAME +# error DISTRHO_PLUGIN_NAME undefined! +#endif + +#ifndef DISTRHO_PLUGIN_NUM_INPUTS +# error DISTRHO_PLUGIN_NUM_INPUTS undefined! +#endif + +#ifndef DISTRHO_PLUGIN_NUM_OUTPUTS +# error DISTRHO_PLUGIN_NUM_OUTPUTS undefined! +#endif + +#ifndef DISTRHO_PLUGIN_URI +# error DISTRHO_PLUGIN_URI undefined! +#endif + +// ----------------------------------------------------------------------- +// Define optional macros if not done yet + +#ifndef DISTRHO_PLUGIN_HAS_UI +# define DISTRHO_PLUGIN_HAS_UI 0 +#endif + +#ifndef DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# define DISTRHO_PLUGIN_HAS_EXTERNAL_UI 0 +#endif + +#ifndef DISTRHO_PLUGIN_IS_RT_SAFE +# define DISTRHO_PLUGIN_IS_RT_SAFE 0 +#endif + +#ifndef DISTRHO_PLUGIN_IS_SYNTH +# define DISTRHO_PLUGIN_IS_SYNTH 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS +# define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_LATENCY +# define DISTRHO_PLUGIN_WANT_LATENCY 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +# define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +# define DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS +# define DISTRHO_PLUGIN_WANT_PROGRAMS 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_STATE +# define DISTRHO_PLUGIN_WANT_STATE 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_FULL_STATE +# define DISTRHO_PLUGIN_WANT_FULL_STATE 0 +# define DISTRHO_PLUGIN_WANT_FULL_STATE_WAS_NOT_SET +#endif + +#ifndef DISTRHO_PLUGIN_WANT_TIMEPOS +# define DISTRHO_PLUGIN_WANT_TIMEPOS 0 +#endif + +#ifndef DISTRHO_UI_FILE_BROWSER +# if defined(DGL_FILE_BROWSER_DISABLED) || DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# define DISTRHO_UI_FILE_BROWSER 0 +# else +# define DISTRHO_UI_FILE_BROWSER 1 +# endif +#endif + +#ifndef DISTRHO_UI_USER_RESIZABLE +# define DISTRHO_UI_USER_RESIZABLE 0 +#endif + +#ifndef DISTRHO_UI_USE_NANOVG +# define DISTRHO_UI_USE_NANOVG 0 +#endif + +// ----------------------------------------------------------------------- +// Define DISTRHO_PLUGIN_HAS_EMBED_UI if needed + +#ifndef DISTRHO_PLUGIN_HAS_EMBED_UI +# if (defined(DGL_CAIRO) && defined(HAVE_CAIRO)) || (defined(DGL_OPENGL) && defined(HAVE_OPENGL)) +# define DISTRHO_PLUGIN_HAS_EMBED_UI 1 +# else +# define DISTRHO_PLUGIN_HAS_EMBED_UI 0 +# endif +#endif + +// ----------------------------------------------------------------------- +// Define DISTRHO_UI_URI if needed + +#ifndef DISTRHO_UI_URI +# define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#DPF_UI" +#endif + +// ----------------------------------------------------------------------- +// Test if synth has audio outputs + +#if DISTRHO_PLUGIN_IS_SYNTH && DISTRHO_PLUGIN_NUM_OUTPUTS == 0 +# error Synths need audio output to work! +#endif + +// ----------------------------------------------------------------------- +// Enable MIDI input if synth, test if midi-input disabled when synth + +#ifndef DISTRHO_PLUGIN_WANT_MIDI_INPUT +# define DISTRHO_PLUGIN_WANT_MIDI_INPUT DISTRHO_PLUGIN_IS_SYNTH +#elif DISTRHO_PLUGIN_IS_SYNTH && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +# error Synths need MIDI input to work! +#endif + +// ----------------------------------------------------------------------- +// Enable state if plugin wants state files (deprecated) + +#ifdef DISTRHO_PLUGIN_WANT_STATEFILES +# warning DISTRHO_PLUGIN_WANT_STATEFILES is deprecated +# undef DISTRHO_PLUGIN_WANT_STATEFILES +# if ! DISTRHO_PLUGIN_WANT_STATE +# undef DISTRHO_PLUGIN_WANT_STATE +# define DISTRHO_PLUGIN_WANT_STATE 1 +# endif +#endif + +// ----------------------------------------------------------------------- +// Enable full state if plugin exports presets + +#if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE && defined(DISTRHO_PLUGIN_WANT_FULL_STATE_WAS_NOT_SET) +# warning Plugins with programs and state should implement full state API too +# undef DISTRHO_PLUGIN_WANT_FULL_STATE +# define DISTRHO_PLUGIN_WANT_FULL_STATE 1 +#endif + +// ----------------------------------------------------------------------- +// Disable file browser if using external UI + +#if DISTRHO_UI_FILE_BROWSER && DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# warning file browser APIs do not work for external UIs +# undef DISTRHO_UI_FILE_BROWSER 0 +# define DISTRHO_UI_FILE_BROWSER 0 +#endif + +// ----------------------------------------------------------------------- +// Disable UI if DGL or external UI is not available + +#if (defined(DGL_CAIRO) && ! defined(HAVE_CAIRO)) || (defined(DGL_OPENGL) && ! defined(HAVE_OPENGL)) +# undef DISTRHO_PLUGIN_HAS_EMBED_UI +# define DISTRHO_PLUGIN_HAS_EMBED_UI 0 +#endif + +#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# undef DISTRHO_PLUGIN_HAS_UI +# define DISTRHO_PLUGIN_HAS_UI 0 +#endif + +// ----------------------------------------------------------------------- +// Make sure both default width and height are provided + +#if defined(DISTRHO_UI_DEFAULT_WIDTH) && !defined(DISTRHO_UI_DEFAULT_HEIGHT) +# error DISTRHO_UI_DEFAULT_WIDTH is defined but DISTRHO_UI_DEFAULT_HEIGHT is not +#endif + +#if defined(DISTRHO_UI_DEFAULT_HEIGHT) && !defined(DISTRHO_UI_DEFAULT_WIDTH) +# error DISTRHO_UI_DEFAULT_HEIGHT is defined but DISTRHO_UI_DEFAULT_WIDTH is not +#endif + +// ----------------------------------------------------------------------- +// Prevent users from messing about with DPF internals + +#ifdef DISTRHO_UI_IS_STANDALONE +# error DISTRHO_UI_IS_STANDALONE must not be defined +#endif + +// ----------------------------------------------------------------------- + +#endif // DISTRHO_PLUGIN_CHECKS_H_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginInternal.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginInternal.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1061 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED +#define DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED + +#include "../DistrhoPlugin.hpp" + +#ifdef DISTRHO_PLUGIN_TARGET_VST3 +# include "DistrhoPluginVST.hpp" +#endif + +#include + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// Maxmimum values + +static const uint32_t kMaxMidiEvents = 512; + +// ----------------------------------------------------------------------- +// Static data, see DistrhoPlugin.cpp + +extern uint32_t d_nextBufferSize; +extern double d_nextSampleRate; +extern const char* d_nextBundlePath; +extern bool d_nextPluginIsDummy; +extern bool d_nextPluginIsSelfTest; +extern bool d_nextCanRequestParameterValueChanges; + +// ----------------------------------------------------------------------- +// DSP callbacks + +typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent); +typedef bool (*requestParameterValueChangeFunc) (void* ptr, uint32_t index, float value); +typedef bool (*updateStateValueFunc) (void* ptr, const char* key, const char* value); + +// ----------------------------------------------------------------------- +// Helpers + +struct AudioPortWithBusId : AudioPort { + uint32_t busId; + + AudioPortWithBusId() + : AudioPort(), + busId(0) {} +}; + +struct PortGroupWithId : PortGroup { + uint32_t groupId; + + PortGroupWithId() + : PortGroup(), + groupId(kPortGroupNone) {} +}; + +static inline +void fillInPredefinedPortGroupData(const uint32_t groupId, PortGroup& portGroup) +{ + switch (groupId) + { + case kPortGroupNone: + portGroup.name.clear(); + portGroup.symbol.clear(); + break; + case kPortGroupMono: + portGroup.name = "Mono"; + portGroup.symbol = "dpf_mono"; + break; + case kPortGroupStereo: + portGroup.name = "Stereo"; + portGroup.symbol = "dpf_stereo"; + break; + } +} + +static inline +void d_strncpy(char* const dst, const char* const src, const size_t length) +{ + DISTRHO_SAFE_ASSERT_RETURN(length > 0,); + + if (const size_t len = std::min(std::strlen(src), length-1U)) + { + std::memcpy(dst, src, len); + dst[len] = '\0'; + } + else + { + dst[0] = '\0'; + } +} + +template +static inline +void snprintf_t(char* const dst, const T value, const char* const format, const size_t size) +{ + DISTRHO_SAFE_ASSERT_RETURN(size > 0,); + std::snprintf(dst, size-1, format, value); + dst[size-1] = '\0'; +} + +static inline +void snprintf_f32(char* const dst, const float value, const size_t size) +{ + return snprintf_t(dst, value, "%f", size); +} + +static inline +void snprintf_f32(char* const dst, const double value, const size_t size) +{ + return snprintf_t(dst, value, "%f", size); +} + +static inline +void snprintf_i32(char* const dst, const int32_t value, const size_t size) +{ + return snprintf_t(dst, value, "%d", size); +} + +static inline +void snprintf_u32(char* const dst, const uint32_t value, const size_t size) +{ + return snprintf_t(dst, value, "%u", size); +} + +// ----------------------------------------------------------------------- +// Plugin private data + +struct Plugin::PrivateData { + const bool canRequestParameterValueChanges; + const bool isDummy; + const bool isSelfTest; + bool isProcessing; + +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + AudioPortWithBusId* audioPorts; +#endif + + uint32_t parameterCount; + uint32_t parameterOffset; + Parameter* parameters; + + uint32_t portGroupCount; + PortGroupWithId* portGroups; + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t programCount; + String* programNames; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + uint32_t stateCount; + State* states; +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY + uint32_t latency; +#endif + +#if DISTRHO_PLUGIN_WANT_TIMEPOS + TimePosition timePosition; +#endif + + // Callbacks + void* callbacksPtr; + writeMidiFunc writeMidiCallbackFunc; + requestParameterValueChangeFunc requestParameterValueChangeCallbackFunc; + updateStateValueFunc updateStateValueCallbackFunc; + + uint32_t bufferSize; + double sampleRate; + char* bundlePath; + + PrivateData() noexcept + : canRequestParameterValueChanges(d_nextCanRequestParameterValueChanges), + isDummy(d_nextPluginIsDummy), + isSelfTest(d_nextPluginIsSelfTest), + isProcessing(false), +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + audioPorts(nullptr), +#endif + parameterCount(0), + parameterOffset(0), + parameters(nullptr), + portGroupCount(0), + portGroups(nullptr), +#if DISTRHO_PLUGIN_WANT_PROGRAMS + programCount(0), + programNames(nullptr), +#endif +#if DISTRHO_PLUGIN_WANT_STATE + stateCount(0), + states(nullptr), +#endif +#if DISTRHO_PLUGIN_WANT_LATENCY + latency(0), +#endif + callbacksPtr(nullptr), + writeMidiCallbackFunc(nullptr), + requestParameterValueChangeCallbackFunc(nullptr), + updateStateValueCallbackFunc(nullptr), + bufferSize(d_nextBufferSize), + sampleRate(d_nextSampleRate), + bundlePath(d_nextBundlePath != nullptr ? strdup(d_nextBundlePath) : nullptr) + { + DISTRHO_SAFE_ASSERT(bufferSize != 0); + DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); + +#if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2) + parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; +# if DISTRHO_PLUGIN_WANT_LATENCY + parameterOffset += 1; +# endif +#endif + +#ifdef DISTRHO_PLUGIN_TARGET_LV2 +# if (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS) + parameterOffset += 1; +# endif +# if (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE) + parameterOffset += 1; +# endif +#endif + +#ifdef DISTRHO_PLUGIN_TARGET_VST3 + parameterOffset += kVst3InternalParameterCount; +#endif + } + + ~PrivateData() noexcept + { +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (audioPorts != nullptr) + { + delete[] audioPorts; + audioPorts = nullptr; + } +#endif + + if (parameters != nullptr) + { + delete[] parameters; + parameters = nullptr; + } + + if (portGroups != nullptr) + { + delete[] portGroups; + portGroups = nullptr; + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + if (programNames != nullptr) + { + delete[] programNames; + programNames = nullptr; + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + if (states != nullptr) + { + delete[] states; + states = nullptr; + } +#endif + + if (bundlePath != nullptr) + { + std::free(bundlePath); + bundlePath = nullptr; + } + } + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool writeMidiCallback(const MidiEvent& midiEvent) + { + if (writeMidiCallbackFunc != nullptr) + return writeMidiCallbackFunc(callbacksPtr, midiEvent); + + return false; + } +#endif + +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChangeCallback(const uint32_t index, const float value) + { + if (requestParameterValueChangeCallbackFunc != nullptr) + return requestParameterValueChangeCallbackFunc(callbacksPtr, index, value); + + return false; + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + bool updateStateValueCallback(const char* const key, const char* const value) + { + d_stdout("updateStateValueCallback %p", updateStateValueCallbackFunc); + if (updateStateValueCallbackFunc != nullptr) + return updateStateValueCallbackFunc(callbacksPtr, key, value); + + return false; + } +#endif +}; + +// ----------------------------------------------------------------------- +// Plugin exporter class + +class PluginExporter +{ +public: + PluginExporter(void* const callbacksPtr, + const writeMidiFunc writeMidiCall, + const requestParameterValueChangeFunc requestParameterValueChangeCall, + const updateStateValueFunc updateStateValueCall) + : fPlugin(createPlugin()), + fData((fPlugin != nullptr) ? fPlugin->pData : nullptr), + fIsActive(false) + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + +#if defined(DPF_RUNTIME_TESTING) && defined(__GNUC__) && !defined(__clang__) + /* Run-time testing build. + * Verify that virtual functions are overriden if parameters, programs or states are in use. + * This does not work on all compilers, but we use it purely as informational check anyway. */ + if (fData->parameterCount != 0) + { + if ((void*)(fPlugin->*(&Plugin::initParameter)) == (void*)&Plugin::initParameter) + { + d_stderr2("DPF warning: Plugins with parameters must implement `initParameter`"); + abort(); + } + if ((void*)(fPlugin->*(&Plugin::getParameterValue)) == (void*)&Plugin::getParameterValue) + { + d_stderr2("DPF warning: Plugins with parameters must implement `getParameterValue`"); + abort(); + } + if ((void*)(fPlugin->*(&Plugin::setParameterValue)) == (void*)&Plugin::setParameterValue) + { + d_stderr2("DPF warning: Plugins with parameters must implement `setParameterValue`"); + abort(); + } + } + +# if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fData->programCount != 0) + { + if ((void*)(fPlugin->*(&Plugin::initProgramName)) == (void*)&Plugin::initProgramName) + { + d_stderr2("DPF warning: Plugins with programs must implement `initProgramName`"); + abort(); + } + if ((void*)(fPlugin->*(&Plugin::loadProgram)) == (void*)&Plugin::loadProgram) + { + d_stderr2("DPF warning: Plugins with programs must implement `loadProgram`"); + abort(); + } + } +# endif + +# if DISTRHO_PLUGIN_WANT_STATE + if (fData->stateCount != 0) + { + if ((void*)(fPlugin->*(static_cast(&Plugin::initState))) == + (void*)static_cast(&Plugin::initState)) + { + d_stderr2("DPF warning: Plugins with state must implement `initState`"); + abort(); + } + + if ((void*)(fPlugin->*(&Plugin::setState)) == (void*)&Plugin::setState) + { + d_stderr2("DPF warning: Plugins with state must implement `setState`"); + abort(); + } + } +# endif + +# if DISTRHO_PLUGIN_WANT_FULL_STATE + if (fData->stateCount != 0) + { + if ((void*)(fPlugin->*(&Plugin::getState)) == (void*)&Plugin::getState) + { + d_stderr2("DPF warning: Plugins with full state must implement `getState`"); + abort(); + } + } + else + { + d_stderr2("DPF warning: Plugins with full state must have at least 1 state"); + abort(); + } +# endif +#endif + +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + { + uint32_t j=0; +# if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++j) + fPlugin->initAudioPort(true, i, fData->audioPorts[j]); +# endif +# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++j) + fPlugin->initAudioPort(false, i, fData->audioPorts[j]); +# endif + } +#endif // DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + + for (uint32_t i=0, count=fData->parameterCount; i < count; ++i) + fPlugin->initParameter(i, fData->parameters[i]); + + { + std::set portGroupIndices; + +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + portGroupIndices.insert(fData->audioPorts[i].groupId); +#endif + for (uint32_t i=0, count=fData->parameterCount; i < count; ++i) + portGroupIndices.insert(fData->parameters[i].groupId); + + portGroupIndices.erase(kPortGroupNone); + + if (const uint32_t portGroupSize = static_cast(portGroupIndices.size())) + { + fData->portGroups = new PortGroupWithId[portGroupSize]; + fData->portGroupCount = portGroupSize; + + uint32_t index = 0; + for (std::set::iterator it = portGroupIndices.begin(); it != portGroupIndices.end(); ++it, ++index) + { + PortGroupWithId& portGroup(fData->portGroups[index]); + portGroup.groupId = *it; + + if (portGroup.groupId < portGroupSize) + fPlugin->initPortGroup(portGroup.groupId, portGroup); + else + fillInPredefinedPortGroupData(portGroup.groupId, portGroup); + } + } + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + for (uint32_t i=0, count=fData->programCount; i < count; ++i) + fPlugin->initProgramName(i, fData->programNames[i]); +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + for (uint32_t i=0, count=fData->stateCount; i < count; ++i) + fPlugin->initState(i, fData->states[i]); +#endif + + fData->callbacksPtr = callbacksPtr; + fData->writeMidiCallbackFunc = writeMidiCall; + fData->requestParameterValueChangeCallbackFunc = requestParameterValueChangeCall; + fData->updateStateValueCallbackFunc = updateStateValueCall; + } + + ~PluginExporter() + { + delete fPlugin; + } + + // ------------------------------------------------------------------- + + const char* getName() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); + + return fPlugin->getName(); + } + + const char* getLabel() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); + + return fPlugin->getLabel(); + } + + const char* getDescription() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); + + return fPlugin->getDescription(); + } + + const char* getMaker() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); + + return fPlugin->getMaker(); + } + + const char* getHomePage() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); + + return fPlugin->getHomePage(); + } + + const char* getLicense() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); + + return fPlugin->getLicense(); + } + + uint32_t getVersion() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0); + + return fPlugin->getVersion(); + } + + long getUniqueId() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0); + + return fPlugin->getUniqueId(); + } + + void* getInstancePointer() const noexcept + { + return fPlugin; + } + + // ------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_LATENCY + uint32_t getLatency() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + + return fData->latency; + } +#endif + +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + AudioPortWithBusId& getAudioPort(const bool input, const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackAudioPort); + + if (input) + { +# if DISTRHO_PLUGIN_NUM_INPUTS > 0 + DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_INPUTS, sFallbackAudioPort); +# endif + } + else + { +# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + DISTRHO_SAFE_ASSERT_RETURN(index < DISTRHO_PLUGIN_NUM_OUTPUTS, sFallbackAudioPort); +# endif + } + + return fData->audioPorts[index + (input ? 0 : DISTRHO_PLUGIN_NUM_INPUTS)]; + } + + uint32_t getAudioPortHints(const bool input, const uint32_t index) const noexcept + { + return getAudioPort(input, index).hints; + } + + uint32_t getAudioPortCountWithGroupId(const bool input, const uint32_t groupId) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + + uint32_t numPorts = 0; + + if (input) + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; iaudioPorts[i].groupId == groupId) + ++numPorts; + } + #endif + } + else + { + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; iaudioPorts[i + DISTRHO_PLUGIN_NUM_INPUTS].groupId == groupId) + ++numPorts; + } + #endif + } + + return numPorts; + } +#endif + + uint32_t getParameterCount() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + + return fData->parameterCount; + } + + uint32_t getParameterOffset() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + + return fData->parameterOffset; + } + + uint32_t getParameterHints(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0); + + return fData->parameters[index].hints; + } + + ParameterDesignation getParameterDesignation(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kParameterDesignationNull); + + return fData->parameters[index].designation; + } + + bool isParameterInput(const uint32_t index) const noexcept + { + return (getParameterHints(index) & kParameterIsOutput) == 0x0; + } + + bool isParameterOutput(const uint32_t index) const noexcept + { + return (getParameterHints(index) & kParameterIsOutput) != 0x0; + } + + bool isParameterInteger(const uint32_t index) const noexcept + { + return (getParameterHints(index) & kParameterIsInteger) != 0x0; + } + + bool isParameterTrigger(const uint32_t index) const noexcept + { + return (getParameterHints(index) & kParameterIsTrigger) == kParameterIsTrigger; + } + + bool isParameterOutputOrTrigger(const uint32_t index) const noexcept + { + const uint32_t hints = getParameterHints(index); + + if (hints & kParameterIsOutput) + return true; + if ((hints & kParameterIsTrigger) == kParameterIsTrigger) + return true; + + return false; + } + + const String& getParameterName(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); + + return fData->parameters[index].name; + } + + const String& getParameterShortName(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); + + return fData->parameters[index].shortName; + } + + const String& getParameterSymbol(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); + + return fData->parameters[index].symbol; + } + + const String& getParameterUnit(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); + + return fData->parameters[index].unit; + } + + const String& getParameterDescription(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); + + return fData->parameters[index].description; + } + + const ParameterEnumerationValues& getParameterEnumValues(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackEnumValues); + + return fData->parameters[index].enumValues; + } + + const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges); + + return fData->parameters[index].ranges; + } + + uint8_t getParameterMidiCC(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0); + + return fData->parameters[index].midiCC; + } + + uint32_t getParameterGroupId(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kPortGroupNone); + + return fData->parameters[index].groupId; + } + + float getParameterDefault(const uint32_t index) const + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f); + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f); + + return fData->parameters[index].ranges.def; + } + + float getParameterValue(const uint32_t index) const + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f); + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f); + + return fPlugin->getParameterValue(index); + } + + void setParameterValue(const uint32_t index, const float value) + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount,); + + fPlugin->setParameterValue(index, value); + } + + uint32_t getPortGroupCount() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + + return fData->portGroupCount; + } + + const PortGroupWithId& getPortGroupById(const uint32_t groupId) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && fData->portGroupCount != 0, sFallbackPortGroup); + + for (uint32_t i=0; i < fData->portGroupCount; ++i) + { + const PortGroupWithId& portGroup(fData->portGroups[i]); + + if (portGroup.groupId == groupId) + return portGroup; + } + + return sFallbackPortGroup; + } + + const PortGroupWithId& getPortGroupByIndex(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->portGroupCount, sFallbackPortGroup); + + return fData->portGroups[index]; + } + + const String& getPortGroupSymbolForId(const uint32_t groupId) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString); + + return getPortGroupById(groupId).symbol; + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t getProgramCount() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + + return fData->programCount; + } + + const String& getProgramName(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount, sFallbackString); + + return fData->programNames[index]; + } + + void loadProgram(const uint32_t index) + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,); + + fPlugin->loadProgram(index); + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + uint32_t getStateCount() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + + return fData->stateCount; + } + + uint32_t getStateHints(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, 0x0); + + return fData->states[index].hints; + } + + const String& getStateKey(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); + + return fData->states[index].key; + } + + const String& getStateDefaultValue(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); + + return fData->states[index].defaultValue; + } + + const String& getStateLabel(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); + + return fData->states[index].label; + } + + const String& getStateDescription(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); + + return fData->states[index].description; + } + + #ifdef __MOD_DEVICES__ + const String& getStateFileTypes(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); + + return fData->states[index].fileTypes; + } + #endif + +# if DISTRHO_PLUGIN_WANT_FULL_STATE + String getStateValue(const char* const key) const + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString); + DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', sFallbackString); + + return fPlugin->getState(key); + } +# endif + + void setState(const char* const key, const char* const value) + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); + DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,); + + fPlugin->setState(key, value); + } + + bool wantStateKey(const char* const key) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false); + + for (uint32_t i=0; i < fData->stateCount; ++i) + { + if (fData->states[i].key == key) + return true; + } + + return false; + } +#endif + +#if DISTRHO_PLUGIN_WANT_TIMEPOS + void setTimePosition(const TimePosition& timePosition) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + + std::memcpy(&fData->timePosition, &timePosition, sizeof(TimePosition)); + } +#endif + + // ------------------------------------------------------------------- + + bool isActive() const noexcept + { + return fIsActive; + } + + void activate() + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(! fIsActive,); + + fIsActive = true; + fPlugin->activate(); + } + + void deactivate() + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fIsActive,); + + fIsActive = false; + fPlugin->deactivate(); + } + + void deactivateIfNeeded() + { + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + + if (fIsActive) + { + fIsActive = false; + fPlugin->deactivate(); + } + } + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void run(const float** const inputs, float** const outputs, const uint32_t frames, + const MidiEvent* const midiEvents, const uint32_t midiEventCount) + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + + if (! fIsActive) + { + fIsActive = true; + fPlugin->activate(); + } + + fData->isProcessing = true; + fPlugin->run(inputs, outputs, frames, midiEvents, midiEventCount); + fData->isProcessing = false; + } +#else + void run(const float** const inputs, float** const outputs, const uint32_t frames) + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + + if (! fIsActive) + { + fIsActive = true; + fPlugin->activate(); + } + + fData->isProcessing = true; + fPlugin->run(inputs, outputs, frames); + fData->isProcessing = false; + } +#endif + + // ------------------------------------------------------------------- + + uint32_t getBufferSize() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + return fData->bufferSize; + } + + double getSampleRate() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0.0); + return fData->sampleRate; + } + + void setBufferSize(const uint32_t bufferSize, const bool doCallback = false) + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + DISTRHO_SAFE_ASSERT(bufferSize >= 2); + + if (fData->bufferSize == bufferSize) + return; + + fData->bufferSize = bufferSize; + + if (doCallback) + { + if (fIsActive) fPlugin->deactivate(); + fPlugin->bufferSizeChanged(bufferSize); + if (fIsActive) fPlugin->activate(); + } + } + + void setSampleRate(const double sampleRate, const bool doCallback = false) + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + DISTRHO_SAFE_ASSERT(sampleRate > 0.0); + + if (d_isEqual(fData->sampleRate, sampleRate)) + return; + + fData->sampleRate = sampleRate; + + if (doCallback) + { + if (fIsActive) fPlugin->deactivate(); + fPlugin->sampleRateChanged(sampleRate); + if (fIsActive) fPlugin->activate(); + } + } + +private: + // ------------------------------------------------------------------- + // Plugin and DistrhoPlugin data + + Plugin* const fPlugin; + Plugin::PrivateData* const fData; + bool fIsActive; + + // ------------------------------------------------------------------- + // Static fallback data, see DistrhoPlugin.cpp + + static const String sFallbackString; + static /* */ AudioPortWithBusId sFallbackAudioPort; + static const ParameterRanges sFallbackRanges; + static const ParameterEnumerationValues sFallbackEnumValues; + static const PortGroupWithId sFallbackPortGroup; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_PLUGIN_INTERNAL_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginJACK.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginJACK.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1161 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * This program 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. + * + * 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 Lesser General Public License for more details. + * + * For a full copy of the license see the LGPL.txt file + */ + +#include "DistrhoPluginInternal.hpp" + +#ifndef STATIC_BUILD +# include "../DistrhoPluginUtils.hpp" +#endif + +#if DISTRHO_PLUGIN_HAS_UI +# include "DistrhoUIInternal.hpp" +# include "../extra/RingBuffer.hpp" +#else +# include "../extra/Sleep.hpp" +#endif + +#ifdef DPF_RUNTIME_TESTING +# include "../extra/Thread.hpp" +#endif + +#if defined(HAVE_JACK) && defined(STATIC_BUILD) && !defined(DISTRHO_OS_WASM) +# define JACKBRIDGE_DIRECT +#endif + +#include "jackbridge/JackBridge.cpp" +#include "lv2/lv2.h" + +#ifdef DISTRHO_OS_MAC +# define Point CocoaPoint +# include +# undef Point +#endif + +#ifndef DISTRHO_OS_WINDOWS +# include +# include +#endif + +#ifdef __SSE2_MATH__ +# include +#endif + +#ifndef JACK_METADATA_ORDER +# define JACK_METADATA_ORDER "http://jackaudio.org/metadata/order" +#endif + +#ifndef JACK_METADATA_PRETTY_NAME +# define JACK_METADATA_PRETTY_NAME "http://jackaudio.org/metadata/pretty-name" +#endif + +#ifndef JACK_METADATA_PORT_GROUP +# define JACK_METADATA_PORT_GROUP "http://jackaudio.org/metadata/port-group" +#endif + +#ifndef JACK_METADATA_SIGNAL_TYPE +# define JACK_METADATA_SIGNAL_TYPE "http://jackaudio.org/metadata/signal-type" +#endif + +// ----------------------------------------------------------------------- + +START_NAMESPACE_DISTRHO + +#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static const sendNoteFunc sendNoteCallback = nullptr; +#endif +#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_STATE +static const setStateFunc setStateCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static const writeMidiFunc writeMidiCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +static const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; +#endif + +// ----------------------------------------------------------------------- + +static volatile bool gCloseSignalReceived = false; + +#ifdef DISTRHO_OS_WINDOWS +static BOOL WINAPI winSignalHandler(DWORD dwCtrlType) noexcept +{ + if (dwCtrlType == CTRL_C_EVENT) + { + gCloseSignalReceived = true; + return TRUE; + } + return FALSE; +} + +static void initSignalHandler() +{ + SetConsoleCtrlHandler(winSignalHandler, TRUE); +} +#else +static void closeSignalHandler(int) noexcept +{ + gCloseSignalReceived = true; +} + +static void initSignalHandler() +{ + struct sigaction sig; + memset(&sig, 0, sizeof(sig)); + + sig.sa_handler = closeSignalHandler; + sig.sa_flags = SA_RESTART; + sigemptyset(&sig.sa_mask); + sigaction(SIGINT, &sig, nullptr); + sigaction(SIGTERM, &sig, nullptr); +} +#endif + +// ----------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_HAS_UI +class PluginJack : public DGL_NAMESPACE::IdleCallback +#else +class PluginJack +#endif +{ +public: + PluginJack(jack_client_t* const client, const uintptr_t winId) + : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, nullptr), +#if DISTRHO_PLUGIN_HAS_UI + fUI(this, + winId, + d_nextSampleRate, + nullptr, // edit param + setParameterValueCallback, + setStateCallback, + sendNoteCallback, + nullptr, // window size + nullptr, // file request + nullptr, // bundle + fPlugin.getInstancePointer(), + 0.0), +#endif + fClient(client) + { +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 || DISTRHO_PLUGIN_NUM_OUTPUTS > 0 +# if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + { + const AudioPort& port(fPlugin.getAudioPort(true, i)); + ulong hints = JackPortIsInput; + if (port.hints & kAudioPortIsCV) + hints |= JackPortIsControlVoltage; + fPortAudioIns[i] = jackbridge_port_register(fClient, port.symbol, JACK_DEFAULT_AUDIO_TYPE, hints, 0); + setAudioPortMetadata(port, fPortAudioIns[i], i); + } +# endif +# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + { + const AudioPort& port(fPlugin.getAudioPort(false, i)); + ulong hints = JackPortIsOutput; + if (port.hints & kAudioPortIsCV) + hints |= JackPortIsControlVoltage; + fPortAudioOuts[i] = jackbridge_port_register(fClient, port.symbol, JACK_DEFAULT_AUDIO_TYPE, hints, 0); + setAudioPortMetadata(port, fPortAudioOuts[i], DISTRHO_PLUGIN_NUM_INPUTS+i); + } +# endif +#endif + + fPortEventsIn = jackbridge_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + fPortMidiOut = jackbridge_port_register(fClient, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); + fPortMidiOutBuffer = nullptr; +#endif + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fPlugin.getProgramCount() > 0) + { + fPlugin.loadProgram(0); +# if DISTRHO_PLUGIN_HAS_UI + fUI.programLoaded(0); +# endif + } +# if DISTRHO_PLUGIN_HAS_UI + fProgramChanged = -1; +# endif +#endif + + if (const uint32_t count = fPlugin.getParameterCount()) + { + fLastOutputValues = new float[count]; + std::memset(fLastOutputValues, 0, sizeof(float)*count); + +#if DISTRHO_PLUGIN_HAS_UI + fParametersChanged = new bool[count]; + std::memset(fParametersChanged, 0, sizeof(bool)*count); +#endif + + for (uint32_t i=0; i < count; ++i) + { +#if DISTRHO_PLUGIN_HAS_UI + if (! fPlugin.isParameterOutput(i)) + fUI.parameterChanged(i, fPlugin.getParameterValue(i)); +#endif + } + } + else + { + fLastOutputValues = nullptr; +#if DISTRHO_PLUGIN_HAS_UI + fParametersChanged = nullptr; +#endif + } + + jackbridge_set_thread_init_callback(fClient, jackThreadInitCallback, this); + jackbridge_set_buffer_size_callback(fClient, jackBufferSizeCallback, this); + jackbridge_set_sample_rate_callback(fClient, jackSampleRateCallback, this); + jackbridge_set_process_callback(fClient, jackProcessCallback, this); + jackbridge_on_shutdown(fClient, jackShutdownCallback, this); + + fPlugin.activate(); + + jackbridge_activate(fClient); + + std::fflush(stdout); + +#if DISTRHO_PLUGIN_HAS_UI + if (const char* const name = jackbridge_get_client_name(fClient)) + fUI.setWindowTitle(name); + else + fUI.setWindowTitle(fPlugin.getName()); + + fUI.exec(this); +#else + while (! gCloseSignalReceived) + d_sleep(1); + + // unused + (void)winId; +#endif + } + + ~PluginJack() + { + if (fClient != nullptr) + jackbridge_deactivate(fClient); + + if (fLastOutputValues != nullptr) + { + delete[] fLastOutputValues; + fLastOutputValues = nullptr; + } + +#if DISTRHO_PLUGIN_HAS_UI + if (fParametersChanged != nullptr) + { + delete[] fParametersChanged; + fParametersChanged = nullptr; + } +#endif + + fPlugin.deactivate(); + + if (fClient == nullptr) + return; + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + jackbridge_port_unregister(fClient, fPortMidiOut); + fPortMidiOut = nullptr; +#endif + + jackbridge_port_unregister(fClient, fPortEventsIn); + fPortEventsIn = nullptr; + +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + { + jackbridge_port_unregister(fClient, fPortAudioIns[i]); + fPortAudioIns[i] = nullptr; + } +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + { + jackbridge_port_unregister(fClient, fPortAudioOuts[i]); + fPortAudioOuts[i] = nullptr; + } +#endif + + jackbridge_client_close(fClient); + } + + // ------------------------------------------------------------------- + +protected: +#if DISTRHO_PLUGIN_HAS_UI + void idleCallback() override + { + if (gCloseSignalReceived) + return fUI.quit(); + +# if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fProgramChanged >= 0) + { + fUI.programLoaded(fProgramChanged); + fProgramChanged = -1; + } +# endif + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (fPlugin.isParameterOutput(i)) + { + const float value = fPlugin.getParameterValue(i); + + if (d_isEqual(fLastOutputValues[i], value)) + continue; + + fLastOutputValues[i] = value; + fUI.parameterChanged(i, value); + } + else if (fParametersChanged[i]) + { + fParametersChanged[i] = false; + fUI.parameterChanged(i, fPlugin.getParameterValue(i)); + } + } + + fUI.exec_idle(); + } +#endif + + void jackBufferSize(const jack_nframes_t nframes) + { + fPlugin.setBufferSize(nframes, true); + } + + void jackSampleRate(const jack_nframes_t nframes) + { + fPlugin.setSampleRate(nframes, true); + } + + void jackProcess(const jack_nframes_t nframes) + { +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + const float* audioIns[DISTRHO_PLUGIN_NUM_INPUTS]; + + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + audioIns[i] = (const float*)jackbridge_port_get_buffer(fPortAudioIns[i], nframes); +#else + static const float** audioIns = nullptr; +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + float* audioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; + + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + audioOuts[i] = (float*)jackbridge_port_get_buffer(fPortAudioOuts[i], nframes); +#else + static float** audioOuts = nullptr; +#endif + +#if DISTRHO_PLUGIN_WANT_TIMEPOS + jack_position_t pos; + fTimePosition.playing = (jackbridge_transport_query(fClient, &pos) == JackTransportRolling); + + if (pos.unique_1 == pos.unique_2) + { + fTimePosition.frame = pos.frame; + + if (pos.valid & JackPositionBBT) + { + fTimePosition.bbt.valid = true; + + fTimePosition.bbt.bar = pos.bar; + fTimePosition.bbt.beat = pos.beat; + fTimePosition.bbt.tick = pos.tick; +#ifdef JACK_TICK_DOUBLE + if (pos.valid & JackTickDouble) + fTimePosition.bbt.tick = pos.tick_double; + else +#endif + fTimePosition.bbt.tick = pos.tick; + fTimePosition.bbt.barStartTick = pos.bar_start_tick; + + fTimePosition.bbt.beatsPerBar = pos.beats_per_bar; + fTimePosition.bbt.beatType = pos.beat_type; + + fTimePosition.bbt.ticksPerBeat = pos.ticks_per_beat; + fTimePosition.bbt.beatsPerMinute = pos.beats_per_minute; + } + else + fTimePosition.bbt.valid = false; + } + else + { + fTimePosition.bbt.valid = false; + fTimePosition.frame = 0; + } + + fPlugin.setTimePosition(fTimePosition); +#endif + + updateParameterTriggers(); + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + fPortMidiOutBuffer = jackbridge_port_get_buffer(fPortMidiOut, nframes); + jackbridge_midi_clear_buffer(fPortMidiOutBuffer); +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + uint32_t midiEventCount = 0; + MidiEvent midiEvents[512]; + +# if DISTRHO_PLUGIN_HAS_UI + while (fNotesRingBuffer.isDataAvailableForReading()) + { + uint8_t midiData[3]; + if (! fNotesRingBuffer.readCustomData(midiData, 3)) + break; + + MidiEvent& midiEvent(midiEvents[midiEventCount++]); + midiEvent.frame = 0; + midiEvent.size = 3; + std::memcpy(midiEvent.data, midiData, 3); + + if (midiEventCount == 512) + break; + } +# endif +#else + static const uint32_t midiEventCount = 0; +#endif + + void* const midiInBuf = jackbridge_port_get_buffer(fPortEventsIn, nframes); + + if (const uint32_t eventCount = std::min(512u - midiEventCount, jackbridge_midi_get_event_count(midiInBuf))) + { + jack_midi_event_t jevent; + + for (uint32_t i=0; i < eventCount; ++i) + { + if (! jackbridge_midi_event_get(&jevent, midiInBuf, i)) + break; + + // Check if message is control change on channel 1 + if (jevent.buffer[0] == 0xB0 && jevent.size == 3) + { + const uint8_t control = jevent.buffer[1]; + const uint8_t value = jevent.buffer[2]; + + /* NOTE: This is not optimal, we're iterating all parameters on every CC message. + Since the JACK standalone is more of a test tool, this will do for now. */ + for (uint32_t j=0, paramCount=fPlugin.getParameterCount(); j < paramCount; ++j) + { + if (fPlugin.isParameterOutput(j)) + continue; + if (fPlugin.getParameterMidiCC(j) != control) + continue; + + const float scaled = static_cast(value)/127.0f; + const float fvalue = fPlugin.getParameterRanges(j).getUnnormalizedValue(scaled); + fPlugin.setParameterValue(j, fvalue); +#if DISTRHO_PLUGIN_HAS_UI + fParametersChanged[j] = true; +#endif + break; + } + } +#if DISTRHO_PLUGIN_WANT_PROGRAMS + // Check if message is program change on channel 1 + else if (jevent.buffer[0] == 0xC0 && jevent.size == 2) + { + const uint8_t program = jevent.buffer[1]; + + if (program < fPlugin.getProgramCount()) + { + fPlugin.loadProgram(program); +# if DISTRHO_PLUGIN_HAS_UI + fProgramChanged = program; +# endif + } + } +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + MidiEvent& midiEvent(midiEvents[midiEventCount++]); + + midiEvent.frame = jevent.time; + midiEvent.size = static_cast(jevent.size); + + if (midiEvent.size > MidiEvent::kDataSize) + midiEvent.dataExt = jevent.buffer; + else + std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); +#endif + } + } + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); +#else + fPlugin.run(audioIns, audioOuts, nframes); +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + fPortMidiOutBuffer = nullptr; +#endif + } + + void jackShutdown() + { + d_stderr("jack has shutdown, quitting now..."); + fClient = nullptr; +#if DISTRHO_PLUGIN_HAS_UI + fUI.quit(); +#endif + } + + // ------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_HAS_UI + void setParameterValue(const uint32_t index, const float value) + { + fPlugin.setParameterValue(index, value); + } + +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + uint8_t midiData[3]; + midiData[0] = (velocity != 0 ? 0x90 : 0x80) | channel; + midiData[1] = note; + midiData[2] = velocity; + fNotesRingBuffer.writeCustomData(midiData, 3); + fNotesRingBuffer.commitWrite(); + } +# endif + +# if DISTRHO_PLUGIN_WANT_STATE + void setState(const char* const key, const char* const value) + { + fPlugin.setState(key, value); + } +# endif +#endif // DISTRHO_PLUGIN_HAS_UI + + // NOTE: no trigger support for JACK, simulate it here + void updateParameterTriggers() + { + float defValue; + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) != kParameterIsTrigger) + continue; + + defValue = fPlugin.getParameterRanges(i).def; + + if (d_isNotEqual(defValue, fPlugin.getParameterValue(i))) + fPlugin.setParameterValue(i, defValue); + } + } + + // ------------------------------------------------------------------- + +private: + PluginExporter fPlugin; +#if DISTRHO_PLUGIN_HAS_UI + UIExporter fUI; +#endif + + jack_client_t* fClient; + +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + jack_port_t* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; +#endif +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; +#endif + jack_port_t* fPortEventsIn; +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + jack_port_t* fPortMidiOut; + void* fPortMidiOutBuffer; +#endif +#if DISTRHO_PLUGIN_WANT_TIMEPOS + TimePosition fTimePosition; +#endif + + // Temporary data + float* fLastOutputValues; + +#if DISTRHO_PLUGIN_HAS_UI + // Store DSP changes to send to UI + bool* fParametersChanged; +# if DISTRHO_PLUGIN_WANT_PROGRAMS + int fProgramChanged; +# endif +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + SmallStackRingBuffer fNotesRingBuffer; +# endif +#endif + + void setAudioPortMetadata(const AudioPort& port, jack_port_t* const jackport, const uint32_t index) + { + DISTRHO_SAFE_ASSERT_RETURN(jackport != nullptr,); + + const jack_uuid_t uuid = jackbridge_port_uuid(jackport); + + if (uuid == JACK_UUID_EMPTY_INITIALIZER) + return; + + jackbridge_set_property(fClient, uuid, JACK_METADATA_PRETTY_NAME, port.name, "text/plain"); + + { + char strBuf[0xff]; + snprintf(strBuf, 0xff - 2, "%u", index); + strBuf[0xff - 1] = '\0'; + jackbridge_set_property(fClient, uuid, JACK_METADATA_ORDER, strBuf, "http://www.w3.org/2001/XMLSchema#integer"); + } + + if (port.groupId != kPortGroupNone) + { + const PortGroupWithId& portGroup(fPlugin.getPortGroupById(port.groupId)); + jackbridge_set_property(fClient, uuid, JACK_METADATA_PORT_GROUP, portGroup.name, "text/plain"); + } + + if (port.hints & kAudioPortIsCV) + { + jackbridge_set_property(fClient, uuid, JACK_METADATA_SIGNAL_TYPE, "CV", "text/plain"); + } + else + { + jackbridge_set_property(fClient, uuid, JACK_METADATA_SIGNAL_TYPE, "AUDIO", "text/plain"); + return; + } + + // set cv ranges + const bool cvPortScaled = port.hints & kCVPortHasScaledRange; + + if (port.hints & kCVPortHasBipolarRange) + { + if (cvPortScaled) + { + jackbridge_set_property(fClient, uuid, LV2_CORE__minimum, "-5", "http://www.w3.org/2001/XMLSchema#integer"); + jackbridge_set_property(fClient, uuid, LV2_CORE__maximum, "5", "http://www.w3.org/2001/XMLSchema#integer"); + } + else + { + jackbridge_set_property(fClient, uuid, LV2_CORE__minimum, "-1", "http://www.w3.org/2001/XMLSchema#integer"); + jackbridge_set_property(fClient, uuid, LV2_CORE__maximum, "1", "http://www.w3.org/2001/XMLSchema#integer"); + } + } + else if (port.hints & kCVPortHasNegativeUnipolarRange) + { + if (cvPortScaled) + { + jackbridge_set_property(fClient, uuid, LV2_CORE__minimum, "-10", "http://www.w3.org/2001/XMLSchema#integer"); + jackbridge_set_property(fClient, uuid, LV2_CORE__maximum, "0", "http://www.w3.org/2001/XMLSchema#integer"); + } + else + { + jackbridge_set_property(fClient, uuid, LV2_CORE__minimum, "-1", "http://www.w3.org/2001/XMLSchema#integer"); + jackbridge_set_property(fClient, uuid, LV2_CORE__maximum, "0", "http://www.w3.org/2001/XMLSchema#integer"); + } + } + else if (port.hints & kCVPortHasPositiveUnipolarRange) + { + if (cvPortScaled) + { + jackbridge_set_property(fClient, uuid, LV2_CORE__minimum, "0", "http://www.w3.org/2001/XMLSchema#integer"); + jackbridge_set_property(fClient, uuid, LV2_CORE__maximum, "10", "http://www.w3.org/2001/XMLSchema#integer"); + } + else + { + jackbridge_set_property(fClient, uuid, LV2_CORE__minimum, "0", "http://www.w3.org/2001/XMLSchema#integer"); + jackbridge_set_property(fClient, uuid, LV2_CORE__maximum, "1", "http://www.w3.org/2001/XMLSchema#integer"); + } + } + } + + // ------------------------------------------------------------------- + // Callbacks + + #define thisPtr ((PluginJack*)ptr) + + static void jackThreadInitCallback(void*) + { + #if defined(__SSE2_MATH__) + _mm_setcsr(_mm_getcsr() | 0x8040); + #elif defined(__aarch64__) + uint64_t c; + __asm__ __volatile__("mrs %0, fpcr \n" + "orr %0, %0, #0x1000000\n" + "msr fpcr, %0 \n" + "isb \n" + : "=r"(c) :: "memory"); + #elif defined(__arm__) && !defined(__SOFTFP__) + uint32_t c; + __asm__ __volatile__("vmrs %0, fpscr \n" + "orr %0, %0, #0x1000000\n" + "vmsr fpscr, %0 \n" + : "=r"(c) :: "memory"); + #endif + } + + static int jackBufferSizeCallback(jack_nframes_t nframes, void* ptr) + { + thisPtr->jackBufferSize(nframes); + return 0; + } + + static int jackSampleRateCallback(jack_nframes_t nframes, void* ptr) + { + thisPtr->jackSampleRate(nframes); + return 0; + } + + static int jackProcessCallback(jack_nframes_t nframes, void* ptr) + { + thisPtr->jackProcess(nframes); + return 0; + } + + static void jackShutdownCallback(void* ptr) + { + thisPtr->jackShutdown(); + } + +#if DISTRHO_PLUGIN_HAS_UI + static void setParameterValueCallback(void* ptr, uint32_t index, float value) + { + thisPtr->setParameterValue(index, value); + } + +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity) + { + thisPtr->sendNote(channel, note, velocity); + } +# endif + +# if DISTRHO_PLUGIN_WANT_STATE + static void setStateCallback(void* ptr, const char* key, const char* value) + { + thisPtr->setState(key, value); + } +# endif +#endif // DISTRHO_PLUGIN_HAS_UI + +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(const uint32_t index, const float value) + { + DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount(), false); + + fPlugin.setParameterValue(index, value); +# if DISTRHO_PLUGIN_HAS_UI + fParametersChanged[index] = true; +# endif + return true; + } + + static bool requestParameterValueChangeCallback(void* ptr, const uint32_t index, const float value) + { + return thisPtr->requestParameterValueChange(index, value); + } +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool writeMidi(const MidiEvent& midiEvent) + { + DISTRHO_SAFE_ASSERT_RETURN(fPortMidiOutBuffer != nullptr, false); + + return jackbridge_midi_event_write(fPortMidiOutBuffer, + midiEvent.frame, + midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data, + midiEvent.size); + } + + static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent) + { + return thisPtr->writeMidi(midiEvent); + } +#endif + + #undef thisPtr +}; + +// ----------------------------------------------------------------------- + +#ifdef DPF_RUNTIME_TESTING +class PluginProcessTestingThread : public Thread +{ + PluginExporter& plugin; + +public: + PluginProcessTestingThread(PluginExporter& p) : plugin(p) {} + +protected: + void run() override + { + plugin.setBufferSize(256, true); + plugin.activate(); + + float buffer[256]; + const float* inputs[DISTRHO_PLUGIN_NUM_INPUTS > 0 ? DISTRHO_PLUGIN_NUM_INPUTS : 1]; + float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS > 0 ? DISTRHO_PLUGIN_NUM_OUTPUTS : 1]; + for (int i=0; i 0 ? DISTRHO_PLUGIN_NUM_INPUTS : 1]; + float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS > 0 ? DISTRHO_PLUGIN_NUM_OUTPUTS : 1]; + for (int i=0; i= 9) + # pragma GCC diagnostic push + # pragma GCC diagnostic ignored "-Wcast-function-type" + #endif + const SPDA SetProcessDPIAware = (SPDA)GetProcAddress(user32, "SetProcessDPIAware"); + #if defined(__GNUC__) && (__GNUC__ >= 9) + # pragma GCC diagnostic pop + #endif + if (SetProcessDPIAware) + SetProcessDPIAware(); + FreeLibrary(user32); + } + + const String win32error = "Failed to create " STANDALONE_NAME ", reason was:\n" + errorString; + MessageBoxA(nullptr, win32error.buffer(), "", MB_ICONERROR); + #endif + + return 1; + } + + d_nextBufferSize = jackbridge_get_buffer_size(client); + d_nextSampleRate = jackbridge_get_sample_rate(client); + d_nextCanRequestParameterValueChanges = true; + + uintptr_t winId = 0; + #if DISTRHO_PLUGIN_HAS_UI + if (argc == 3 && std::strcmp(argv[1], "embed") == 0) + winId = static_cast(std::atoll(argv[2])); + #endif + + const PluginJack p(client, winId); + + #if defined(DISTRHO_OS_WINDOWS) && DISTRHO_PLUGIN_HAS_UI + /* the code below is based on + * https://www.tillett.info/2013/05/13/how-to-create-a-windows-program-that-works-as-both-as-a-gui-and-console-application/ + */ + + // Send "enter" to release application from the console + // This is a hack, but if not used the console doesn't know the application has + // returned. The "enter" key only sent if the console window is in focus. + if (hasConsole && (GetConsoleWindow() == GetForegroundWindow() || SetFocus(GetConsoleWindow()) != nullptr)) + { + INPUT ip; + // Set up a generic keyboard event. + ip.type = INPUT_KEYBOARD; + ip.ki.wScan = 0; // hardware scan code for key + ip.ki.time = 0; + ip.ki.dwExtraInfo = 0; + + // Send the "Enter" key + ip.ki.wVk = 0x0D; // virtual-key code for the "Enter" key + ip.ki.dwFlags = 0; // 0 for key press + SendInput(1, &ip, sizeof(INPUT)); + + // Release the "Enter" key + ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release + SendInput(1, &ip, sizeof(INPUT)); + } + #endif + + return 0; +} + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,761 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" + +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +# error Cannot use parameter value change request with LADSPA or DSSI +#endif +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +# error Cannot use MIDI Output with LADSPA or DSSI +#endif +#if DISTRHO_PLUGIN_WANT_FULL_STATE && !defined(DISTRHO_PLUGIN_WANT_FULL_STATE_WITH_LADSPA) +# error Cannot use full state with LADSPA or DSSI +#endif + +#if DISTRHO_PLUGIN_WANT_TIMEPOS && !defined(DISTRHO_NO_WARNINGS) +# warning LADSPA/DSSI does not support TimePos +#endif + +#ifdef DISTRHO_PLUGIN_TARGET_DSSI +# include "dssi/dssi.h" +#else +# include "ladspa/ladspa.h" +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT +# error Cannot use MIDI with LADSPA +# endif +# if DISTRHO_PLUGIN_WANT_STATE && !defined(DISTRHO_NO_WARNINGS) +# warning LADSPA cannot handle states +# endif +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +class PluginLadspaDssi +{ +public: + PluginLadspaDssi() + : fPlugin(nullptr, nullptr, nullptr, nullptr), + fPortControls(nullptr), + fLastControlValues(nullptr) + { +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + fPortAudioIns[i] = nullptr; +#else + fPortAudioIns = nullptr; +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + fPortAudioOuts[i] = nullptr; +#else + fPortAudioOuts = nullptr; +#endif + + if (const uint32_t count = fPlugin.getParameterCount()) + { + fPortControls = new LADSPA_Data*[count]; + fLastControlValues = new LADSPA_Data[count]; + + for (uint32_t i=0; i < count; ++i) + { + fPortControls[i] = nullptr; + fLastControlValues[i] = fPlugin.getParameterValue(i); + } + } + else + { + fPortControls = nullptr; + fLastControlValues = nullptr; + } + +#if DISTRHO_PLUGIN_WANT_LATENCY + fPortLatency = nullptr; +#endif + } + + ~PluginLadspaDssi() noexcept + { + if (fPortControls != nullptr) + { + delete[] fPortControls; + fPortControls = nullptr; + } + + if (fLastControlValues != nullptr) + { + delete[] fLastControlValues; + fLastControlValues = nullptr; + } + } + + // ------------------------------------------------------------------- + + void ladspa_activate() + { + fPlugin.activate(); + } + + void ladspa_deactivate() + { + fPlugin.deactivate(); + } + + // ------------------------------------------------------------------- + + void ladspa_connect_port(const ulong port, LADSPA_Data* const dataLocation) noexcept + { + ulong index = 0; + +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + { + if (port == index++) + { + fPortAudioIns[i] = dataLocation; + return; + } + } +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + { + if (port == index++) + { + fPortAudioOuts[i] = dataLocation; + return; + } + } +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY + if (port == index++) + { + fPortLatency = dataLocation; + return; + } +#endif + + for (ulong i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (port == index++) + { + fPortControls[i] = dataLocation; + return; + } + } + } + + // ------------------------------------------------------------------- + +#ifdef DISTRHO_PLUGIN_TARGET_DSSI + void ladspa_run(const ulong sampleCount) + { + dssi_run_synth(sampleCount, nullptr, 0); + } + + void dssi_run_synth(const ulong sampleCount, snd_seq_event_t* const events, const ulong eventCount) +#else + void ladspa_run(const ulong sampleCount) +#endif + { + // pre-roll + if (sampleCount == 0) + return updateParameterOutputsAndTriggers(); + + // Check for updated parameters + float curValue; + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (fPortControls[i] == nullptr) + continue; + + curValue = *fPortControls[i]; + + if (fPlugin.isParameterInput(i) && d_isNotEqual(fLastControlValues[i], curValue)) + { + fLastControlValues[i] = curValue; + fPlugin.setParameterValue(i, curValue); + } + } + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + // Get MIDI Events + uint32_t midiEventCount = 0; + MidiEvent midiEvents[eventCount]; + + for (uint32_t i=0, j; i < eventCount; ++i) + { + const snd_seq_event_t& seqEvent(events[i]); + + // FIXME + if (seqEvent.data.note.channel > 0xF || seqEvent.data.control.channel > 0xF) + continue; + + switch (seqEvent.type) + { + case SND_SEQ_EVENT_NOTEOFF: + j = midiEventCount++; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0x80 + seqEvent.data.note.channel; + midiEvents[j].data[1] = seqEvent.data.note.note; + midiEvents[j].data[2] = 0; + midiEvents[j].data[3] = 0; + break; + case SND_SEQ_EVENT_NOTEON: + j = midiEventCount++; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0x90 + seqEvent.data.note.channel; + midiEvents[j].data[1] = seqEvent.data.note.note; + midiEvents[j].data[2] = seqEvent.data.note.velocity; + midiEvents[j].data[3] = 0; + break; + case SND_SEQ_EVENT_KEYPRESS: + j = midiEventCount++; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0xA0 + seqEvent.data.note.channel; + midiEvents[j].data[1] = seqEvent.data.note.note; + midiEvents[j].data[2] = seqEvent.data.note.velocity; + midiEvents[j].data[3] = 0; + break; + case SND_SEQ_EVENT_CONTROLLER: + j = midiEventCount++; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0xB0 + seqEvent.data.control.channel; + midiEvents[j].data[1] = seqEvent.data.control.param; + midiEvents[j].data[2] = seqEvent.data.control.value; + midiEvents[j].data[3] = 0; + break; + case SND_SEQ_EVENT_CHANPRESS: + j = midiEventCount++; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 2; + midiEvents[j].data[0] = 0xD0 + seqEvent.data.control.channel; + midiEvents[j].data[1] = seqEvent.data.control.value; + midiEvents[j].data[2] = 0; + midiEvents[j].data[3] = 0; + break; + case SND_SEQ_EVENT_PITCHBEND: + j = midiEventCount++; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel; + uint16_t tempvalue = seqEvent.data.control.value + 8192; + midiEvents[j].data[1] = tempvalue & 0x7F; + midiEvents[j].data[2] = tempvalue >> 7; + midiEvents[j].data[3] = 0; + break; + } + } + + fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, midiEvents, midiEventCount); +#else + fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); +#endif + + updateParameterOutputsAndTriggers(); + +#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT + return; // unused + (void)events; (void)eventCount; +#endif + } + + // ------------------------------------------------------------------- + +#ifdef DISTRHO_PLUGIN_TARGET_DSSI +# if DISTRHO_PLUGIN_WANT_STATE + char* dssi_configure(const char* const key, const char* const value) + { + if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX)) == 0) + return nullptr; + if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX)) == 0) + return nullptr; + + fPlugin.setState(key, value); + return nullptr; + } +# endif + +# if DISTRHO_PLUGIN_WANT_PROGRAMS + const DSSI_Program_Descriptor* dssi_get_program(const ulong index) + { + if (index >= fPlugin.getProgramCount()) + return nullptr; + + static DSSI_Program_Descriptor desc; + + desc.Bank = index / 128; + desc.Program = index % 128; + desc.Name = fPlugin.getProgramName(index); + + return &desc; + } + + void dssi_select_program(const ulong bank, const ulong program) + { + const ulong realProgram(bank * 128 + program); + + DISTRHO_SAFE_ASSERT_RETURN(realProgram < fPlugin.getProgramCount(),); + + fPlugin.loadProgram(realProgram); + + // Update control inputs + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (fPlugin.isParameterOutput(i)) + continue; + + fLastControlValues[i] = fPlugin.getParameterValue(i); + + if (fPortControls[i] != nullptr) + *fPortControls[i] = fLastControlValues[i]; + } + } +# endif + + int dssi_get_midi_controller_for_port(const ulong port) noexcept + { + const uint32_t parameterOffset = fPlugin.getParameterOffset(); + + if (port > parameterOffset) + return DSSI_NONE; + + const uint8_t midiCC = fPlugin.getParameterMidiCC(port-parameterOffset); + + if (midiCC == 0 || midiCC == 32 || midiCC >= 0x78) + return DSSI_NONE; + + return DSSI_CC(midiCC); + } +#endif + + // ------------------------------------------------------------------- + +private: + PluginExporter fPlugin; + + // LADSPA ports +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + const LADSPA_Data* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; +#else + const LADSPA_Data** fPortAudioIns; +#endif +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + LADSPA_Data* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; +#else + LADSPA_Data** fPortAudioOuts; +#endif + LADSPA_Data** fPortControls; +#if DISTRHO_PLUGIN_WANT_LATENCY + LADSPA_Data* fPortLatency; +#endif + + // Temporary data + LADSPA_Data* fLastControlValues; + + // ------------------------------------------------------------------- + + void updateParameterOutputsAndTriggers() + { + float value; + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (fPlugin.isParameterOutput(i)) + { + value = fLastControlValues[i] = fPlugin.getParameterValue(i); + + if (fPortControls[i] != nullptr) + *fPortControls[i] = value; + } + else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger) + { + // NOTE: no trigger support in LADSPA control ports, simulate it here + value = fPlugin.getParameterRanges(i).def; + + if (d_isEqual(value, fPlugin.getParameterValue(i))) + continue; + + fLastControlValues[i] = value; + fPlugin.setParameterValue(i, value); + + if (fPortControls[i] != nullptr) + *fPortControls[i] = value; + } + } + +#if DISTRHO_PLUGIN_WANT_LATENCY + if (fPortLatency != nullptr) + *fPortLatency = fPlugin.getLatency(); +#endif + } +}; + +// ----------------------------------------------------------------------- + +static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, ulong sampleRate) +{ + if (d_nextBufferSize == 0) + d_nextBufferSize = 2048; + d_nextSampleRate = sampleRate; + + return new PluginLadspaDssi(); +} + +#define instancePtr ((PluginLadspaDssi*)instance) + +static void ladspa_connect_port(LADSPA_Handle instance, ulong port, LADSPA_Data* dataLocation) +{ + instancePtr->ladspa_connect_port(port, dataLocation); +} + +static void ladspa_activate(LADSPA_Handle instance) +{ + instancePtr->ladspa_activate(); +} + +static void ladspa_run(LADSPA_Handle instance, ulong sampleCount) +{ + instancePtr->ladspa_run(sampleCount); +} + +static void ladspa_deactivate(LADSPA_Handle instance) +{ + instancePtr->ladspa_deactivate(); +} + +static void ladspa_cleanup(LADSPA_Handle instance) +{ + delete instancePtr; +} + +#ifdef DISTRHO_PLUGIN_TARGET_DSSI +# if DISTRHO_PLUGIN_WANT_STATE +static char* dssi_configure(LADSPA_Handle instance, const char* key, const char* value) +{ + return instancePtr->dssi_configure(key, value); +} +# endif + +# if DISTRHO_PLUGIN_WANT_PROGRAMS +static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, ulong index) +{ + return instancePtr->dssi_get_program(index); +} + +static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong program) +{ + instancePtr->dssi_select_program(bank, program); +} +# endif + +static int dssi_get_midi_controller_for_port(LADSPA_Handle instance, ulong port) +{ + return instancePtr->dssi_get_midi_controller_for_port(port); +} + +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT +static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount) +{ + instancePtr->dssi_run_synth(sampleCount, events, eventCount); +} +# endif +#endif + +#undef instancePtr + +// ----------------------------------------------------------------------- + +static LADSPA_Descriptor sLadspaDescriptor = { + /* UniqueID */ 0, + /* Label */ nullptr, +#if DISTRHO_PLUGIN_IS_RT_SAFE + /* Properties */ LADSPA_PROPERTY_HARD_RT_CAPABLE, +#else + /* Properties */ 0x0, +#endif + /* Name */ nullptr, + /* Maker */ nullptr, + /* Copyright */ nullptr, + /* PortCount */ 0, + /* PortDescriptors */ nullptr, + /* PortNames */ nullptr, + /* PortRangeHints */ nullptr, + /* ImplementationData */ nullptr, + ladspa_instantiate, + ladspa_connect_port, + ladspa_activate, + ladspa_run, + /* run_adding */ nullptr, + /* set_run_adding_gain */ nullptr, + ladspa_deactivate, + ladspa_cleanup +}; + +#ifdef DISTRHO_PLUGIN_TARGET_DSSI +static DSSI_Descriptor sDssiDescriptor = { + 1, + &sLadspaDescriptor, +# if DISTRHO_PLUGIN_WANT_STATE + dssi_configure, +# else + /* configure */ nullptr, +# endif +# if DISTRHO_PLUGIN_WANT_PROGRAMS + dssi_get_program, + dssi_select_program, +# else + /* get_program */ nullptr, + /* select_program */ nullptr, +# endif + dssi_get_midi_controller_for_port, +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + dssi_run_synth, +# else + /* run_synth */ nullptr, +# endif + /* run_synth_adding */ nullptr, + /* run_multiple_synths */ nullptr, + /* run_multiple_synths_adding */ nullptr, + nullptr, nullptr +}; +#endif + +// ----------------------------------------------------------------------- + +static const struct DescriptorInitializer +{ + DescriptorInitializer() + { + // Create dummy plugin to get data from + d_nextBufferSize = 512; + d_nextSampleRate = 44100.0; + d_nextPluginIsDummy = true; + const PluginExporter plugin(nullptr, nullptr, nullptr, nullptr); + d_nextBufferSize = 0; + d_nextSampleRate = 0.0; + d_nextPluginIsDummy = false; + + // Get port count, init + ulong port = 0; + ulong portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.getParameterCount(); +#if DISTRHO_PLUGIN_WANT_LATENCY + portCount += 1; +#endif + const char** const portNames = new const char*[portCount]; + LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor[portCount]; + LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount]; + + // Set ports +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port) + { + const AudioPort& aport(plugin.getAudioPort(true, i)); + + portNames[port] = strdup(aport.name); + portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT; + + portRangeHints[port].HintDescriptor = 0x0; + portRangeHints[port].LowerBound = 0.0f; + portRangeHints[port].UpperBound = 1.0f; + } +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port) + { + const AudioPort& aport(plugin.getAudioPort(false, i)); + + portNames[port] = strdup(aport.name); + portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT; + + portRangeHints[port].HintDescriptor = 0x0; + portRangeHints[port].LowerBound = 0.0f; + portRangeHints[port].UpperBound = 1.0f; + } +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY + // Set latency port + portNames[port] = strdup("_latency"); + portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT; + portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE|LADSPA_HINT_INTEGER; + portRangeHints[port].LowerBound = 0.0f; + portRangeHints[port].UpperBound = 1.0f; + ++port; +#endif + + for (ulong i=0, count=plugin.getParameterCount(); i < count; ++i, ++port) + { + portNames[port] = strdup((const char*)plugin.getParameterName(i)); + portDescriptors[port] = LADSPA_PORT_CONTROL; + + if (plugin.isParameterOutput(i)) + portDescriptors[port] |= LADSPA_PORT_OUTPUT; + else + portDescriptors[port] |= LADSPA_PORT_INPUT; + + const uint32_t hints = plugin.getParameterHints(i); + + { + const ParameterRanges& ranges(plugin.getParameterRanges(i)); + const float defValue = ranges.def; + + // LADSPA doesn't allow bounded hints on toggles + portRangeHints[port].HintDescriptor = hints & kParameterIsBoolean + ? 0 + : LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE; + + portRangeHints[port].LowerBound = ranges.min; + portRangeHints[port].UpperBound = ranges.max; + + /**/ if (d_isZero(defValue)) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_0; + else if (d_isEqual(defValue, 1.0f)) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_1; + else if (d_isEqual(defValue, 100.0f)) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_100; + else if (d_isEqual(defValue, 440.0f)) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_440; + else if (d_isEqual(ranges.min, defValue)) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM; + else if (d_isEqual(ranges.max, defValue)) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM; + else + { + const float middleValue = ranges.min/2.0f + ranges.max/2.0f; + const float middleLow = (ranges.min/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f; + const float middleHigh = (ranges.max/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f; + + /**/ if (defValue < middleLow) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW; + else if (defValue > middleHigh) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH; + else + portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE; + } + } + + { + if (hints & kParameterIsBoolean) + { + portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED; + } + else + { + if (hints & kParameterIsInteger) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER; + if (hints & kParameterIsLogarithmic) + portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC; + } + } + } + + // Set data + sLadspaDescriptor.UniqueID = plugin.getUniqueId(); + sLadspaDescriptor.Label = strdup(plugin.getLabel()); + sLadspaDescriptor.Name = strdup(plugin.getName()); + sLadspaDescriptor.Maker = strdup(plugin.getMaker()); + sLadspaDescriptor.Copyright = strdup(plugin.getLicense()); + sLadspaDescriptor.PortCount = portCount; + sLadspaDescriptor.PortNames = portNames; + sLadspaDescriptor.PortDescriptors = portDescriptors; + sLadspaDescriptor.PortRangeHints = portRangeHints; + } + + ~DescriptorInitializer() + { + if (sLadspaDescriptor.Label != nullptr) + { + std::free((void*)sLadspaDescriptor.Label); + sLadspaDescriptor.Label = nullptr; + } + + if (sLadspaDescriptor.Name != nullptr) + { + std::free((void*)sLadspaDescriptor.Name); + sLadspaDescriptor.Name = nullptr; + } + + if (sLadspaDescriptor.Maker != nullptr) + { + std::free((void*)sLadspaDescriptor.Maker); + sLadspaDescriptor.Maker = nullptr; + } + + if (sLadspaDescriptor.Copyright != nullptr) + { + std::free((void*)sLadspaDescriptor.Copyright); + sLadspaDescriptor.Copyright = nullptr; + } + + if (sLadspaDescriptor.PortDescriptors != nullptr) + { + delete[] sLadspaDescriptor.PortDescriptors; + sLadspaDescriptor.PortDescriptors = nullptr; + } + + if (sLadspaDescriptor.PortRangeHints != nullptr) + { + delete[] sLadspaDescriptor.PortRangeHints; + sLadspaDescriptor.PortRangeHints = nullptr; + } + + if (sLadspaDescriptor.PortNames != nullptr) + { + for (ulong i=0; i < sLadspaDescriptor.PortCount; ++i) + { + if (sLadspaDescriptor.PortNames[i] != nullptr) + std::free((void*)sLadspaDescriptor.PortNames[i]); + } + + delete[] sLadspaDescriptor.PortNames; + sLadspaDescriptor.PortNames = nullptr; + } + } +} sDescInit; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +DISTRHO_PLUGIN_EXPORT +const LADSPA_Descriptor* ladspa_descriptor(ulong index) +{ + USE_NAMESPACE_DISTRHO + return (index == 0) ? &sLadspaDescriptor : nullptr; +} + +#ifdef DISTRHO_PLUGIN_TARGET_DSSI +DISTRHO_PLUGIN_EXPORT +const DSSI_Descriptor* dssi_descriptor(ulong index) +{ + USE_NAMESPACE_DISTRHO + return (index == 0) ? &sDssiDescriptor : nullptr; +} +#endif + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLV2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLV2.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1653 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" + +#include "lv2/atom.h" +#include "lv2/atom-forge.h" +#include "lv2/atom-util.h" +#include "lv2/buf-size.h" +#include "lv2/data-access.h" +#include "lv2/instance-access.h" +#include "lv2/midi.h" +#include "lv2/options.h" +#include "lv2/parameters.h" +#include "lv2/patch.h" +#include "lv2/state.h" +#include "lv2/time.h" +#include "lv2/urid.h" +#include "lv2/worker.h" +#include "lv2/lv2_kxstudio_properties.h" +#include "lv2/lv2_programs.h" +#include "lv2/control-input-port-change-request.h" + +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD +# include "libmodla.h" +#endif + +#include + +#ifndef DISTRHO_PLUGIN_URI +# error DISTRHO_PLUGIN_URI undefined! +#endif + +#ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX +# define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:" +#endif + +#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE) +#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE) + +START_NAMESPACE_DISTRHO + +typedef std::map StringToStringMap; +typedef std::map UridToStringMap; + +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static const writeMidiFunc writeMidiCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +static const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_STATE +static const updateStateValueFunc updateStateValueCallback = nullptr; +#endif + +// ----------------------------------------------------------------------- + +class PluginLv2 +{ +public: + PluginLv2(const double sampleRate, + const LV2_URID_Map* const uridMap, + const LV2_Worker_Schedule* const worker, + const LV2_ControlInputPort_Change_Request* const ctrlInPortChangeReq, + const bool usingNominal) + : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback), + fUsingNominal(usingNominal), +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + fRunCount(0), +#endif + fPortControls(nullptr), + fLastControlValues(nullptr), + fSampleRate(sampleRate), + fURIDs(uridMap), +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + fCtrlInPortChangeReq(ctrlInPortChangeReq), +#endif + fUridMap(uridMap), + fWorker(worker) + { +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + fPortAudioIns[i] = nullptr; +#else + fPortAudioIns = nullptr; +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + fPortAudioOuts[i] = nullptr; +#else + fPortAudioOuts = nullptr; +#endif + + if (const uint32_t count = fPlugin.getParameterCount()) + { + fPortControls = new float*[count]; + fLastControlValues = new float[count]; + + for (uint32_t i=0; i < count; ++i) + { + fPortControls[i] = nullptr; + fLastControlValues[i] = fPlugin.getParameterValue(i); + } + } + else + { + fPortControls = nullptr; + fLastControlValues = nullptr; + } + +#if DISTRHO_LV2_USE_EVENTS_IN + fPortEventsIn = nullptr; +#endif +#if DISTRHO_PLUGIN_WANT_LATENCY + fPortLatency = nullptr; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + std::memset(&fAtomForge, 0, sizeof(fAtomForge)); + lv2_atom_forge_init(&fAtomForge, uridMap); + + if (const uint32_t count = fPlugin.getStateCount()) + { + fUrids = new LV2_URID[count]; + fNeededUiSends = new bool[count]; + + for (uint32_t i=0; i < count; ++i) + { + fNeededUiSends[i] = false; + + const String& statekey(fPlugin.getStateKey(i)); + fStateMap[statekey] = fPlugin.getStateDefaultValue(i); + + const String lv2key(DISTRHO_PLUGIN_URI "#" + statekey); + const LV2_URID urid = fUrids[i] = uridMap->map(uridMap->handle, lv2key.buffer()); + fUridStateMap[urid] = statekey; + } + } + else + { + fUrids = nullptr; + fNeededUiSends = nullptr; + } +#else + // unused + (void)fWorker; +#endif + +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + // unused + (void)ctrlInPortChangeReq; +#endif + } + + ~PluginLv2() + { + if (fPortControls != nullptr) + { + delete[] fPortControls; + fPortControls = nullptr; + } + + if (fLastControlValues) + { + delete[] fLastControlValues; + fLastControlValues = nullptr; + } + +#if DISTRHO_PLUGIN_WANT_STATE + if (fNeededUiSends != nullptr) + { + delete[] fNeededUiSends; + fNeededUiSends = nullptr; + } + + if (fUrids != nullptr) + { + delete[] fUrids; + fUrids = nullptr; + } + + fStateMap.clear(); +#endif + } + + // ------------------------------------------------------------------- + + bool getPortControlValue(uint32_t index, float& value) const + { + if (const float* control = fPortControls[index]) + { + switch (fPlugin.getParameterDesignation(index)) + { + default: + value = *control; + break; + case kParameterDesignationBypass: + value = 1.0f - *control; + break; + } + + return true; + } + + return false; + } + + void setPortControlValue(uint32_t index, float value) + { + if (float* control = fPortControls[index]) + { + switch (fPlugin.getParameterDesignation(index)) + { + default: + *control = value; + break; + case kParameterDesignationBypass: + *control = 1.0f - value; + break; + } + } + } + + // ------------------------------------------------------------------- + + void lv2_activate() + { +#if DISTRHO_PLUGIN_WANT_TIMEPOS + fTimePosition.clear(); + + // hosts may not send all values, resulting on some invalid data, let's reset everything + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0.0; + fTimePosition.bbt.barStartTick = 0; + fTimePosition.bbt.beatsPerBar = 4; + fTimePosition.bbt.beatType = 4; + fTimePosition.bbt.ticksPerBeat = 1920.0; + fTimePosition.bbt.beatsPerMinute = 120.0; +#endif + fPlugin.activate(); + } + + void lv2_deactivate() + { + fPlugin.deactivate(); + } + + // ------------------------------------------------------------------- + + void lv2_connect_port(const uint32_t port, void* const dataLocation) + { + uint32_t index = 0; + +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + { + if (port == index++) + { + fPortAudioIns[i] = (const float*)dataLocation; + return; + } + } +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + { + if (port == index++) + { + fPortAudioOuts[i] = (float*)dataLocation; + return; + } + } +#endif + +#if DISTRHO_LV2_USE_EVENTS_IN + if (port == index++) + { + fPortEventsIn = (LV2_Atom_Sequence*)dataLocation; + return; + } +#endif + +#if DISTRHO_LV2_USE_EVENTS_OUT + if (port == index++) + { + fEventsOutData.port = (LV2_Atom_Sequence*)dataLocation; + return; + } +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY + if (port == index++) + { + fPortLatency = (float*)dataLocation; + return; + } +#endif + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (port == index++) + { + fPortControls[i] = (float*)dataLocation; + return; + } + } + } + + // ------------------------------------------------------------------- + + void lv2_run(const uint32_t sampleCount) + { + // cache midi input and time position first +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + uint32_t midiEventCount = 0; +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS + LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) + { + if (event == nullptr) + break; + +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (event->body.type == fURIDs.midiEvent) + { + if (midiEventCount >= kMaxMidiEvents) + continue; + + const uint8_t* const data((const uint8_t*)(event + 1)); + + MidiEvent& midiEvent(fMidiEvents[midiEventCount++]); + + midiEvent.frame = event->time.frames; + midiEvent.size = event->body.size; + + if (midiEvent.size > MidiEvent::kDataSize) + { + midiEvent.dataExt = data; + std::memset(midiEvent.data, 0, MidiEvent::kDataSize); + } + else + { + midiEvent.dataExt = nullptr; + std::memcpy(midiEvent.data, data, midiEvent.size); + } + + continue; + } +# endif +# if DISTRHO_PLUGIN_WANT_TIMEPOS + if (event->body.type == fURIDs.atomBlank || event->body.type == fURIDs.atomObject) + { + const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body); + + if (obj->body.otype != fURIDs.timePosition) + continue; + + LV2_Atom* bar = nullptr; + LV2_Atom* barBeat = nullptr; + LV2_Atom* beatUnit = nullptr; + LV2_Atom* beatsPerBar = nullptr; + LV2_Atom* beatsPerMinute = nullptr; + LV2_Atom* frame = nullptr; + LV2_Atom* speed = nullptr; + LV2_Atom* ticksPerBeat = nullptr; + + lv2_atom_object_get(obj, + fURIDs.timeBar, &bar, + fURIDs.timeBarBeat, &barBeat, + fURIDs.timeBeatUnit, &beatUnit, + fURIDs.timeBeatsPerBar, &beatsPerBar, + fURIDs.timeBeatsPerMinute, &beatsPerMinute, + fURIDs.timeFrame, &frame, + fURIDs.timeSpeed, &speed, + fURIDs.timeTicksPerBeat, &ticksPerBeat, + 0); + + // need to handle this first as other values depend on it + if (ticksPerBeat != nullptr) + { + /**/ if (ticksPerBeat->type == fURIDs.atomDouble) + fLastPositionData.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body; + else if (ticksPerBeat->type == fURIDs.atomFloat) + fLastPositionData.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body; + else if (ticksPerBeat->type == fURIDs.atomInt) + fLastPositionData.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body; + else if (ticksPerBeat->type == fURIDs.atomLong) + fLastPositionData.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body; + else + d_stderr("Unknown lv2 ticksPerBeat value type"); + + if (fLastPositionData.ticksPerBeat > 0.0) + fTimePosition.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat; + } + + // same + if (speed != nullptr) + { + /**/ if (speed->type == fURIDs.atomDouble) + fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body; + else if (speed->type == fURIDs.atomFloat) + fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body; + else if (speed->type == fURIDs.atomInt) + fLastPositionData.speed = ((LV2_Atom_Int*)speed)->body; + else if (speed->type == fURIDs.atomLong) + fLastPositionData.speed = ((LV2_Atom_Long*)speed)->body; + else + d_stderr("Unknown lv2 speed value type"); + + fTimePosition.playing = d_isNotZero(fLastPositionData.speed); + } + + if (bar != nullptr) + { + /**/ if (bar->type == fURIDs.atomDouble) + fLastPositionData.bar = ((LV2_Atom_Double*)bar)->body; + else if (bar->type == fURIDs.atomFloat) + fLastPositionData.bar = ((LV2_Atom_Float*)bar)->body; + else if (bar->type == fURIDs.atomInt) + fLastPositionData.bar = ((LV2_Atom_Int*)bar)->body; + else if (bar->type == fURIDs.atomLong) + fLastPositionData.bar = ((LV2_Atom_Long*)bar)->body; + else + d_stderr("Unknown lv2 bar value type"); + + if (fLastPositionData.bar >= 0) + fTimePosition.bbt.bar = fLastPositionData.bar + 1; + } + + if (barBeat != nullptr) + { + /**/ if (barBeat->type == fURIDs.atomDouble) + fLastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body; + else if (barBeat->type == fURIDs.atomFloat) + fLastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body; + else if (barBeat->type == fURIDs.atomInt) + fLastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body; + else if (barBeat->type == fURIDs.atomLong) + fLastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body; + else + d_stderr("Unknown lv2 barBeat value type"); + + if (fLastPositionData.barBeat >= 0.0f) + { + const double rest = std::fmod(fLastPositionData.barBeat, 1.0f); + fTimePosition.bbt.beat = std::round(fLastPositionData.barBeat - rest + 1.0); + fTimePosition.bbt.tick = rest * fTimePosition.bbt.ticksPerBeat; + } + } + + if (beatUnit != nullptr) + { + /**/ if (beatUnit->type == fURIDs.atomDouble) + fLastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body; + else if (beatUnit->type == fURIDs.atomFloat) + fLastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body; + else if (beatUnit->type == fURIDs.atomInt) + fLastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body; + else if (beatUnit->type == fURIDs.atomLong) + fLastPositionData.beatUnit = ((LV2_Atom_Long*)beatUnit)->body; + else + d_stderr("Unknown lv2 beatUnit value type"); + + if (fLastPositionData.beatUnit > 0) + fTimePosition.bbt.beatType = fLastPositionData.beatUnit; + } + + if (beatsPerBar != nullptr) + { + /**/ if (beatsPerBar->type == fURIDs.atomDouble) + fLastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body; + else if (beatsPerBar->type == fURIDs.atomFloat) + fLastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body; + else if (beatsPerBar->type == fURIDs.atomInt) + fLastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body; + else if (beatsPerBar->type == fURIDs.atomLong) + fLastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body; + else + d_stderr("Unknown lv2 beatsPerBar value type"); + + if (fLastPositionData.beatsPerBar > 0.0f) + fTimePosition.bbt.beatsPerBar = fLastPositionData.beatsPerBar; + } + + if (beatsPerMinute != nullptr) + { + /**/ if (beatsPerMinute->type == fURIDs.atomDouble) + fLastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body; + else if (beatsPerMinute->type == fURIDs.atomFloat) + fLastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body; + else if (beatsPerMinute->type == fURIDs.atomInt) + fLastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body; + else if (beatsPerMinute->type == fURIDs.atomLong) + fLastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body; + else + d_stderr("Unknown lv2 beatsPerMinute value type"); + + if (fLastPositionData.beatsPerMinute > 0.0f) + { + fTimePosition.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute; + + if (d_isNotZero(fLastPositionData.speed)) + fTimePosition.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed); + } + } + + if (frame != nullptr) + { + /**/ if (frame->type == fURIDs.atomDouble) + fLastPositionData.frame = ((LV2_Atom_Double*)frame)->body; + else if (frame->type == fURIDs.atomFloat) + fLastPositionData.frame = ((LV2_Atom_Float*)frame)->body; + else if (frame->type == fURIDs.atomInt) + fLastPositionData.frame = ((LV2_Atom_Int*)frame)->body; + else if (frame->type == fURIDs.atomLong) + fLastPositionData.frame = ((LV2_Atom_Long*)frame)->body; + else + d_stderr("Unknown lv2 frame value type"); + + if (fLastPositionData.frame >= 0) + fTimePosition.frame = fLastPositionData.frame; + } + + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat* + fTimePosition.bbt.beatsPerBar* + (fTimePosition.bbt.bar-1); + + fTimePosition.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 && + fLastPositionData.beatUnit > 0 && + fLastPositionData.beatsPerBar > 0.0f); + + fPlugin.setTimePosition(fTimePosition); + + continue; + } +# endif + } +#endif + + // check for messages from UI or host +#if DISTRHO_PLUGIN_WANT_STATE + LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) + { + if (event == nullptr) + break; + + #if DISTRHO_PLUGIN_HAS_UI + if (event->body.type == fURIDs.dpfKeyValue) + { + const void* const data = (const void*)(event + 1); + + // check if this is our special message + if (std::strcmp((const char*)data, "__dpf_ui_data__") == 0) + { + for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) + { + if (fPlugin.getStateHints(i) & kStateIsOnlyForDSP) + continue; + fNeededUiSends[i] = true; + } + } + // no, send to DSP as usual + else if (fWorker != nullptr) + { + fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body); + } + } + else + #endif + if (event->body.type == fURIDs.atomObject && fWorker != nullptr) + { + const LV2_Atom_Object* const object = (const LV2_Atom_Object*)&event->body; + + const LV2_Atom* property = nullptr; + const LV2_Atom* value = nullptr; + lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr); + + if (property != nullptr && property->type == fURIDs.atomURID && + value != nullptr && (value->type == fURIDs.atomPath || value->type == fURIDs.atomString)) + { + fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body); + } + } + } +#endif + + // Check for updated parameters + float curValue; + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (!getPortControlValue(i, curValue)) + continue; + + if (fPlugin.isParameterInput(i) && d_isNotEqual(fLastControlValues[i], curValue)) + { + fLastControlValues[i] = curValue; + + fPlugin.setParameterValue(i, curValue); + } + } + + // Run plugin + if (sampleCount != 0) + { + #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + fRunCount = mod_license_run_begin(fRunCount, sampleCount); + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount); + #else + fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); + #endif + + #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + for (uint32_t i=0; i 0.0) + { + // playing forwards + fLastPositionData.frame += sampleCount; + } + else + { + // playing backwards + fLastPositionData.frame -= sampleCount; + + if (fLastPositionData.frame < 0) + fLastPositionData.frame = 0; + } + + fTimePosition.frame = fLastPositionData.frame; + + if (fTimePosition.bbt.valid) + { + const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed; + const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute; + const double addedBarBeats = double(sampleCount) / framesPerBeat; + + if (fLastPositionData.barBeat >= 0.0f) + { + fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+addedBarBeats, + (double)fLastPositionData.beatsPerBar); + + const double rest = std::fmod(fLastPositionData.barBeat, 1.0f); + fTimePosition.bbt.beat = std::round(fLastPositionData.barBeat - rest + 1.0); + fTimePosition.bbt.tick = rest * fTimePosition.bbt.ticksPerBeat; + + if (fLastPositionData.bar >= 0) + { + fLastPositionData.bar += std::floor((fLastPositionData.barBeat+addedBarBeats)/ + fLastPositionData.beatsPerBar); + + if (fLastPositionData.bar < 0) + fLastPositionData.bar = 0; + + fTimePosition.bbt.bar = fLastPositionData.bar + 1; + + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat* + fTimePosition.bbt.beatsPerBar* + (fTimePosition.bbt.bar-1); + } + } + + fTimePosition.bbt.beatsPerMinute = std::abs(beatsPerMinute); + } + + fPlugin.setTimePosition(fTimePosition); + } + #endif + } + + updateParameterOutputsAndTriggers(); + + #if DISTRHO_PLUGIN_WANT_STATE + fEventsOutData.initIfNeeded(fURIDs.atomSequence); + + LV2_Atom_Event* aev; + const uint32_t capacity = fEventsOutData.capacity; + + for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) + { + if (! fNeededUiSends[i]) + continue; + + const uint32_t hints = fPlugin.getStateHints(i); + + #if ! DISTRHO_PLUGIN_HAS_UI + if ((hints & kStateIsHostReadable) == 0x0) + { + fNeededUiSends[i] = false; + continue; + } + #endif + + const String& curKey(fPlugin.getStateKey(i)); + + for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key(cit->first); + + if (curKey != key) + continue; + + const String& value(cit->second); + + // set msg size + uint32_t msgSize; + + if (hints & kStateIsHostReadable) + { + // object, prop key, prop urid, value key, value + msgSize = sizeof(LV2_Atom_Object) + + sizeof(LV2_Atom_Property_Body) * 4 + + sizeof(LV2_Atom_URID) * 3 + + sizeof(LV2_Atom_String) + + value.length() + 1; + } + else + { + // key + value + 2x null terminator + separator + msgSize = static_cast(key.length()+value.length())+3U; + } + + if (sizeof(LV2_Atom_Event) + msgSize > capacity - fEventsOutData.offset) + { + d_stdout("Sending key '%s' to UI failed, out of space (needs %u bytes)", + key.buffer(), msgSize); + break; + } + + // put data + aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + fEventsOutData.offset); + aev->time.frames = 0; + + if (hints & kStateIsHostReadable) + { + uint8_t* const msgBuf = (uint8_t*)&aev->body; + LV2_Atom_Forge atomForge = fAtomForge; + lv2_atom_forge_set_buffer(&atomForge, msgBuf, msgSize); + + LV2_Atom_Forge_Frame forgeFrame; + lv2_atom_forge_object(&atomForge, &forgeFrame, 0, fURIDs.patchSet); + + lv2_atom_forge_key(&atomForge, fURIDs.patchProperty); + lv2_atom_forge_urid(&atomForge, fUrids[i]); + + lv2_atom_forge_key(&atomForge, fURIDs.patchValue); + if ((hints & kStateIsFilenamePath) == kStateIsFilenamePath) + lv2_atom_forge_path(&atomForge, value.buffer(), static_cast(value.length()+1)); + else + lv2_atom_forge_string(&atomForge, value.buffer(), static_cast(value.length()+1)); + + lv2_atom_forge_pop(&atomForge, &forgeFrame); + + msgSize = ((LV2_Atom*)msgBuf)->size; + } + else + { + aev->body.type = fURIDs.dpfKeyValue; + aev->body.size = msgSize; + + uint8_t* const msgBuf = LV2_ATOM_BODY(&aev->body); + std::memset(msgBuf, 0, msgSize); + + // write key and value in atom buffer + std::memcpy(msgBuf, key.buffer(), key.length()+1); + std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()+1); + } + + fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize)); + fNeededUiSends[i] = false; + break; + } + } + #endif + + #if DISTRHO_LV2_USE_EVENTS_OUT + fEventsOutData.endRun(); + #endif + } + + // ------------------------------------------------------------------- + + uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) + { + // currently unused + return LV2_OPTIONS_ERR_UNKNOWN; + } + + uint32_t lv2_set_options(const LV2_Options_Option* const options) + { + for (int i=0; options[i].key != 0; ++i) + { + if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__nominalBlockLength)) + { + if (options[i].type == fURIDs.atomInt) + { + const int32_t bufferSize(*(const int32_t*)options[i].value); + fPlugin.setBufferSize(bufferSize, true); + } + else + { + d_stderr("Host changed nominalBlockLength but with wrong value type"); + } + } + else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength) && ! fUsingNominal) + { + if (options[i].type == fURIDs.atomInt) + { + const int32_t bufferSize(*(const int32_t*)options[i].value); + fPlugin.setBufferSize(bufferSize, true); + } + else + { + d_stderr("Host changed maxBlockLength but with wrong value type"); + } + } + else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate)) + { + if (options[i].type == fURIDs.atomFloat) + { + const float sampleRate(*(const float*)options[i].value); + fSampleRate = sampleRate; + fPlugin.setSampleRate(sampleRate, true); + } + else + { + d_stderr("Host changed sampleRate but with wrong value type"); + } + } + } + + return LV2_OPTIONS_SUCCESS; + } + + // ------------------------------------------------------------------- + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + const LV2_Program_Descriptor* lv2_get_program(const uint32_t index) + { + if (index >= fPlugin.getProgramCount()) + return nullptr; + + static LV2_Program_Descriptor desc; + + desc.bank = index / 128; + desc.program = index % 128; + desc.name = fPlugin.getProgramName(index); + + return &desc; + } + + void lv2_select_program(const uint32_t bank, const uint32_t program) + { + const uint32_t realProgram(bank * 128 + program); + + if (realProgram >= fPlugin.getProgramCount()) + return; + + fPlugin.loadProgram(realProgram); + + // Update control inputs + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (fPlugin.isParameterOutput(i)) + continue; + + fLastControlValues[i] = fPlugin.getParameterValue(i); + + setPortControlValue(i, fLastControlValues[i]); + } + + #if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update state + for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } + #endif + } + #endif + + // ------------------------------------------------------------------- + + #if DISTRHO_PLUGIN_WANT_STATE + LV2_State_Status lv2_save(const LV2_State_Store_Function store, const LV2_State_Handle handle) + { + #if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update current state + for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } + #endif + + String lv2key; + LV2_URID urid; + + for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) + { + const String& curKey(fPlugin.getStateKey(i)); + + for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key(cit->first); + + if (curKey != key) + continue; + + const uint32_t hints = fPlugin.getStateHints(i); + + #if ! DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + // do not save UI-only messages if there is no UI available + if (hints & kStateIsOnlyForUI) + break; + #endif + + if (hints & kStateIsHostReadable) + { + lv2key = DISTRHO_PLUGIN_URI "#"; + urid = (hints & kStateIsFilenamePath) == kStateIsFilenamePath + ? fURIDs.atomPath + : fURIDs.atomString; + } + else + { + lv2key = DISTRHO_PLUGIN_LV2_STATE_PREFIX; + urid = fURIDs.atomString; + } + + lv2key += key; + + const String& value(cit->second); + + // some hosts need +1 for the null terminator, even though the type is string + store(handle, + fUridMap->map(fUridMap->handle, lv2key.buffer()), + value.buffer(), + value.length()+1, + urid, + LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); + + break; + } + } + + return LV2_STATE_SUCCESS; + } + + LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function retrieve, const LV2_State_Handle handle) + { + size_t size; + uint32_t type, flags; + + String lv2key; + LV2_URID urid; + + for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) + { + const String& key(fPlugin.getStateKey(i)); + + const uint32_t hints = fPlugin.getStateHints(i); + + if (hints & kStateIsHostReadable) + { + lv2key = DISTRHO_PLUGIN_URI "#"; + urid = (hints & kStateIsFilenamePath) == kStateIsFilenamePath + ? fURIDs.atomPath + : fURIDs.atomString; + } + else + { + lv2key = DISTRHO_PLUGIN_LV2_STATE_PREFIX; + urid = fURIDs.atomString; + } + + lv2key += key; + + size = 0; + type = 0; + flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; + const void* data = retrieve(handle, + fUridMap->map(fUridMap->handle, lv2key.buffer()), + &size, &type, &flags); + + if (data == nullptr || size == 0) + continue; + + DISTRHO_SAFE_ASSERT_CONTINUE(type == urid); + + const char* const value = (const char*)data; + const std::size_t length = std::strlen(value); + DISTRHO_SAFE_ASSERT_CONTINUE(length == size || length+1 == size); + + setState(key, value); + + #if DISTRHO_PLUGIN_WANT_STATE + // signal msg needed for UI + if ((hints & kStateIsOnlyForDSP) == 0x0) + fNeededUiSends[i] = true; + #endif + } + + return LV2_STATE_SUCCESS; + } + + // ------------------------------------------------------------------- + + LV2_Worker_Status lv2_work(const void* const data) + { + const LV2_Atom* const eventBody = (const LV2_Atom*)data; + + if (eventBody->type == fURIDs.dpfKeyValue) + { + const char* const key = (const char*)(eventBody + 1); + const char* const value = key + (std::strlen(key) + 1U); + + setState(key, value); + return LV2_WORKER_SUCCESS; + } + + if (eventBody->type == fURIDs.atomObject) + { + const LV2_Atom_Object* const object = (const LV2_Atom_Object*)eventBody; + + const LV2_Atom* property = nullptr; + const LV2_Atom* value = nullptr; + lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(property != nullptr, LV2_WORKER_ERR_UNKNOWN); + DISTRHO_SAFE_ASSERT_RETURN(property->type == fURIDs.atomURID, LV2_WORKER_ERR_UNKNOWN); + DISTRHO_SAFE_ASSERT_RETURN(value != nullptr, LV2_WORKER_ERR_UNKNOWN); + DISTRHO_SAFE_ASSERT_RETURN(value->type == fURIDs.atomPath || + value->type == fURIDs.atomString, LV2_WORKER_ERR_UNKNOWN); + + const LV2_URID urid = ((const LV2_Atom_URID*)property)->body; + const char* const filename = (const char*)(value + 1); + + String key; + + try { + key = fUridStateMap[urid]; + } DISTRHO_SAFE_EXCEPTION_RETURN("lv2_work fUridStateMap[urid]", LV2_WORKER_ERR_UNKNOWN); + + setState(key, filename); + + /* FIXME host should be responsible for updating UI side, not us + for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) + { + if (fPlugin.getStateKey(i) == key) + { + if ((fPlugin.getStateHints(i) & kStateIsOnlyForDSP) == 0x0) + fNeededUiSends[i] = true; + break; + } + } + */ + + return LV2_WORKER_SUCCESS; + } + + return LV2_WORKER_ERR_UNKNOWN; + } + + LV2_Worker_Status lv2_work_response(uint32_t, const void*) + { + return LV2_WORKER_SUCCESS; + } + #endif + + // ------------------------------------------------------------------- + + #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + void* lv2_get_instance_pointer() + { + return fPlugin.getInstancePointer(); + } + #endif + + // ------------------------------------------------------------------- + +private: + PluginExporter fPlugin; + const bool fUsingNominal; // if false use maxBlockLength + + #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + uint32_t fRunCount; + #endif + + // LV2 ports + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + const float* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; + #else + const float** fPortAudioIns; + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + float* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; + #else + float** fPortAudioOuts; + #endif + float** fPortControls; + #if DISTRHO_LV2_USE_EVENTS_IN + LV2_Atom_Sequence* fPortEventsIn; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + float* fPortLatency; + #endif + + // Temporary data + float* fLastControlValues; + double fSampleRate; + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + MidiEvent fMidiEvents[kMaxMidiEvents]; + #endif + #if DISTRHO_PLUGIN_WANT_TIMEPOS + TimePosition fTimePosition; + + struct Lv2PositionData { + int64_t bar; + float barBeat; + uint32_t beatUnit; + float beatsPerBar; + float beatsPerMinute; + int64_t frame; + double speed; + double ticksPerBeat; + + Lv2PositionData() + : bar(-1), + barBeat(-1.0f), + beatUnit(0), + beatsPerBar(0.0f), + beatsPerMinute(0.0f), + frame(-1), + speed(0.0), + ticksPerBeat(-1.0) {} + + } fLastPositionData; + #endif + + #if DISTRHO_LV2_USE_EVENTS_OUT + struct Lv2EventsOutData { + uint32_t capacity, offset; + LV2_Atom_Sequence* port; + + Lv2EventsOutData() + : capacity(0), + offset(0), + port(nullptr) {} + + void initIfNeeded(const LV2_URID uridAtomSequence) + { + if (capacity != 0) + return; + + capacity = port->atom.size; + + port->atom.size = sizeof(LV2_Atom_Sequence_Body); + port->atom.type = uridAtomSequence; + port->body.unit = 0; + port->body.pad = 0; + } + + void growBy(const uint32_t size) + { + offset += size; + port->atom.size += size; + } + + void endRun() + { + capacity = 0; + offset = 0; + } + + } fEventsOutData; + #endif + + // LV2 URIDs + struct URIDs { + const LV2_URID_Map* _uridMap; + LV2_URID atomBlank; + LV2_URID atomObject; + LV2_URID atomDouble; + LV2_URID atomFloat; + LV2_URID atomInt; + LV2_URID atomLong; + LV2_URID atomPath; + LV2_URID atomSequence; + LV2_URID atomString; + LV2_URID atomURID; + LV2_URID dpfKeyValue; + LV2_URID midiEvent; + LV2_URID patchSet; + LV2_URID patchProperty; + LV2_URID patchValue; + LV2_URID timePosition; + LV2_URID timeBar; + LV2_URID timeBarBeat; + LV2_URID timeBeatUnit; + LV2_URID timeBeatsPerBar; + LV2_URID timeBeatsPerMinute; + LV2_URID timeTicksPerBeat; + LV2_URID timeFrame; + LV2_URID timeSpeed; + + URIDs(const LV2_URID_Map* const uridMap) + : _uridMap(uridMap), + atomBlank(map(LV2_ATOM__Blank)), + atomObject(map(LV2_ATOM__Object)), + atomDouble(map(LV2_ATOM__Double)), + atomFloat(map(LV2_ATOM__Float)), + atomInt(map(LV2_ATOM__Int)), + atomLong(map(LV2_ATOM__Long)), + atomPath(map(LV2_ATOM__Path)), + atomSequence(map(LV2_ATOM__Sequence)), + atomString(map(LV2_ATOM__String)), + atomURID(map(LV2_ATOM__URID)), + dpfKeyValue(map(DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), + midiEvent(map(LV2_MIDI__MidiEvent)), + patchSet(map(LV2_PATCH__Set)), + patchProperty(map(LV2_PATCH__property)), + patchValue(map(LV2_PATCH__value)), + timePosition(map(LV2_TIME__Position)), + timeBar(map(LV2_TIME__bar)), + timeBarBeat(map(LV2_TIME__barBeat)), + timeBeatUnit(map(LV2_TIME__beatUnit)), + timeBeatsPerBar(map(LV2_TIME__beatsPerBar)), + timeBeatsPerMinute(map(LV2_TIME__beatsPerMinute)), + timeTicksPerBeat(map(LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat)), + timeFrame(map(LV2_TIME__frame)), + timeSpeed(map(LV2_TIME__speed)) {} + + inline LV2_URID map(const char* const uri) const + { + return _uridMap->map(_uridMap->handle, uri); + } + } fURIDs; + + // LV2 features + #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + const LV2_ControlInputPort_Change_Request* const fCtrlInPortChangeReq; + #endif + const LV2_URID_Map* const fUridMap; + const LV2_Worker_Schedule* const fWorker; + + #if DISTRHO_PLUGIN_WANT_STATE + LV2_Atom_Forge fAtomForge; + StringToStringMap fStateMap; + UridToStringMap fUridStateMap; + LV2_URID* fUrids; + bool* fNeededUiSends; + + void setState(const char* const key, const char* const newValue) + { + fPlugin.setState(key, newValue); + + // save this key if necessary + if (fPlugin.wantStateKey(key)) + updateInternalState(key, newValue, false); + } + + bool updateState(const char* const key, const char* const newValue) + { + fPlugin.setState(key, newValue); + return updateInternalState(key, newValue, true); + } + + bool updateInternalState(const char* const key, const char* const newValue, const bool sendToUI) + { + // key must already exist + for (StringToStringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it) + { + const String& dkey(it->first); + + if (dkey == key) + { + it->second = newValue; + + if (sendToUI) + { + for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) + { + if (fPlugin.getStateKey(i) == key) + { + if ((fPlugin.getStateHints(i) & kStateIsOnlyForDSP) == 0x0) + fNeededUiSends[i] = true; + break; + } + } + } + + return true; + } + } + + d_stderr("Failed to find plugin state with key \"%s\"", key); + return false; + } + #endif + + void updateParameterOutputsAndTriggers() + { + float curValue; + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (fPlugin.isParameterOutput(i)) + { + curValue = fLastControlValues[i] = fPlugin.getParameterValue(i); + + setPortControlValue(i, curValue); + } + else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger) + { + // NOTE: host is responsible for auto-updating control port buffers + } + } + + #if DISTRHO_PLUGIN_WANT_LATENCY + if (fPortLatency != nullptr) + *fPortLatency = fPlugin.getLatency(); + #endif + } + + #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(const uint32_t index, const float value) + { + if (fCtrlInPortChangeReq == nullptr) + return false; + return fCtrlInPortChangeReq->request_change(fCtrlInPortChangeReq->handle, index, value); + } + + static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) + { + return (((PluginLv2*)ptr)->requestParameterValueChange(index, value) == 0); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value) + { + return ((PluginLv2*)ptr)->updateState(key, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool writeMidi(const MidiEvent& midiEvent) + { + DISTRHO_SAFE_ASSERT_RETURN(fEventsOutData.port != nullptr, false); + + fEventsOutData.initIfNeeded(fURIDs.atomSequence); + + const uint32_t capacity = fEventsOutData.capacity; + const uint32_t offset = fEventsOutData.offset; + + if (sizeof(LV2_Atom_Event) + midiEvent.size > capacity - offset) + return false; + + LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + offset); + aev->time.frames = midiEvent.frame; + aev->body.type = fURIDs.midiEvent; + aev->body.size = midiEvent.size; + std::memcpy(LV2_ATOM_BODY(&aev->body), + midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data, + midiEvent.size); + + fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + midiEvent.size)); + + return true; + } + + static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent) + { + return ((PluginLv2*)ptr)->writeMidi(midiEvent); + } + #endif +}; + +// ----------------------------------------------------------------------- + +static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char* bundlePath, const LV2_Feature* const* features) +{ + const LV2_Options_Option* options = nullptr; + const LV2_URID_Map* uridMap = nullptr; + const LV2_Worker_Schedule* worker = nullptr; + const LV2_ControlInputPort_Change_Request* ctrlInPortChangeReq = nullptr; + + for (int i=0; features[i] != nullptr; ++i) + { + if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) + options = (const LV2_Options_Option*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0) + uridMap = (const LV2_URID_Map*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_WORKER__schedule) == 0) + worker = (const LV2_Worker_Schedule*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI) == 0) + ctrlInPortChangeReq = (const LV2_ControlInputPort_Change_Request*)features[i]->data; + } + + if (options == nullptr) + { + d_stderr("Options feature missing, cannot continue!"); + return nullptr; + } + + if (uridMap == nullptr) + { + d_stderr("URID Map feature missing, cannot continue!"); + return nullptr; + } + +#if DISTRHO_PLUGIN_WANT_STATE + if (worker == nullptr) + { + d_stderr("Worker feature missing, cannot continue!"); + return nullptr; + } +#endif + +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + mod_license_check(features, DISTRHO_PLUGIN_URI); +#endif + + d_nextBufferSize = 0; + bool usingNominal = false; + + for (int i=0; options[i].key != 0; ++i) + { + if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength)) + { + if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int)) + { + d_nextBufferSize = *(const int*)options[i].value; + usingNominal = true; + } + else + { + d_stderr("Host provides nominalBlockLength but has wrong value type"); + } + break; + } + + if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength)) + { + if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int)) + d_nextBufferSize = *(const int*)options[i].value; + else + d_stderr("Host provides maxBlockLength but has wrong value type"); + + // no break, continue in case host supports nominalBlockLength + } + } + + if (d_nextBufferSize == 0) + { + d_stderr("Host does not provide nominalBlockLength or maxBlockLength options"); + d_nextBufferSize = 2048; + } + + d_nextSampleRate = sampleRate; + d_nextBundlePath = bundlePath; + d_nextCanRequestParameterValueChanges = ctrlInPortChangeReq != nullptr; + + if (std::getenv("RUNNING_UNDER_LV2LINT") != nullptr) + d_nextPluginIsDummy = true; + + return new PluginLv2(sampleRate, uridMap, worker, ctrlInPortChangeReq, usingNominal); +} + +#define instancePtr ((PluginLv2*)instance) + +static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation) +{ + instancePtr->lv2_connect_port(port, dataLocation); +} + +static void lv2_activate(LV2_Handle instance) +{ + instancePtr->lv2_activate(); +} + +static void lv2_run(LV2_Handle instance, uint32_t sampleCount) +{ + instancePtr->lv2_run(sampleCount); +} + +static void lv2_deactivate(LV2_Handle instance) +{ + instancePtr->lv2_deactivate(); +} + +static void lv2_cleanup(LV2_Handle instance) +{ + delete instancePtr; +} + +// ----------------------------------------------------------------------- + +static uint32_t lv2_get_options(LV2_Handle instance, LV2_Options_Option* options) +{ + return instancePtr->lv2_get_options(options); +} + +static uint32_t lv2_set_options(LV2_Handle instance, const LV2_Options_Option* options) +{ + return instancePtr->lv2_set_options(options); +} + +// ----------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_PROGRAMS +static const LV2_Program_Descriptor* lv2_get_program(LV2_Handle instance, uint32_t index) +{ + return instancePtr->lv2_get_program(index); +} + +static void lv2_select_program(LV2_Handle instance, uint32_t bank, uint32_t program) +{ + instancePtr->lv2_select_program(bank, program); +} +#endif + +// ----------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_STATE +static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t, const LV2_Feature* const*) +{ + return instancePtr->lv2_save(store, handle); +} + +static LV2_State_Status lv2_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t, const LV2_Feature* const*) +{ + return instancePtr->lv2_restore(retrieve, handle); +} + +LV2_Worker_Status lv2_work(LV2_Handle instance, LV2_Worker_Respond_Function, LV2_Worker_Respond_Handle, uint32_t, const void* data) +{ + return instancePtr->lv2_work(data); +} + +LV2_Worker_Status lv2_work_response(LV2_Handle instance, uint32_t size, const void* body) +{ + return instancePtr->lv2_work_response(size, body); +} +#endif + +// ----------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS +static void* lv2_get_instance_pointer(LV2_Handle instance) +{ + return instancePtr->lv2_get_instance_pointer(); +} +#endif + +// ----------------------------------------------------------------------- + +static const void* lv2_extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; + + if (std::strcmp(uri, LV2_OPTIONS__interface) == 0) + return &options; + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + static const LV2_Programs_Interface programs = { lv2_get_program, lv2_select_program }; + + if (std::strcmp(uri, LV2_PROGRAMS__Interface) == 0) + return &programs; +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + static const LV2_State_Interface state = { lv2_save, lv2_restore }; + static const LV2_Worker_Interface worker = { lv2_work, lv2_work_response, nullptr }; + + if (std::strcmp(uri, LV2_STATE__interface) == 0) + return &state; + if (std::strcmp(uri, LV2_WORKER__interface) == 0) + return &worker; +#endif + +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + struct LV2_DirectAccess_Interface { + void* (*get_instance_pointer)(LV2_Handle handle); + }; + + static const LV2_DirectAccess_Interface directaccess = { lv2_get_instance_pointer }; + + if (std::strcmp(uri, DISTRHO_PLUGIN_LV2_STATE_PREFIX "direct-access") == 0) + return &directaccess; +#endif + +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + return mod_license_interface(uri); +#else + return nullptr; +#endif +} + +#undef instancePtr + +// ----------------------------------------------------------------------- + +static const LV2_Descriptor sLv2Descriptor = { + DISTRHO_PLUGIN_URI, + lv2_instantiate, + lv2_connect_port, + lv2_activate, + lv2_run, + lv2_deactivate, + lv2_cleanup, + lv2_extension_data +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +DISTRHO_PLUGIN_EXPORT +const LV2_Descriptor* lv2_descriptor(uint32_t index) +{ + USE_NAMESPACE_DISTRHO + return (index == 0) ? &sLv2Descriptor : nullptr; +} + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLV2export.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLV2export.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1708 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" +#include "../DistrhoPluginUtils.hpp" + +#include "lv2/atom.h" +#include "lv2/buf-size.h" +#include "lv2/data-access.h" +#include "lv2/instance-access.h" +#include "lv2/midi.h" +#include "lv2/options.h" +#include "lv2/parameters.h" +#include "lv2/patch.h" +#include "lv2/port-groups.h" +#include "lv2/port-props.h" +#include "lv2/presets.h" +#include "lv2/resize-port.h" +#include "lv2/state.h" +#include "lv2/time.h" +#include "lv2/ui.h" +#include "lv2/units.h" +#include "lv2/urid.h" +#include "lv2/worker.h" +#include "lv2/lv2_kxstudio_properties.h" +#include "lv2/lv2_programs.h" + +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD +# include "mod-license.h" +#endif + +#ifdef DISTRHO_OS_WINDOWS +# include +#else +# include +# include +# include +#endif + +#include +#include + +#ifndef DISTRHO_PLUGIN_URI +# error DISTRHO_PLUGIN_URI undefined! +#endif + +#ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX +# define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:" +#endif + +#ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE +# define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048 +#endif + +#ifndef DISTRHO_PLUGIN_USES_MODGUI +# define DISTRHO_PLUGIN_USES_MODGUI 0 +#endif + +#ifndef DISTRHO_PLUGIN_USES_CUSTOM_MODGUI +# define DISTRHO_PLUGIN_USES_CUSTOM_MODGUI 0 +#endif + +#if DISTRHO_PLUGIN_HAS_EMBED_UI +# if DISTRHO_OS_HAIKU +# define DISTRHO_LV2_UI_TYPE "BeUI" +# elif DISTRHO_OS_MAC +# define DISTRHO_LV2_UI_TYPE "CocoaUI" +# elif DISTRHO_OS_WINDOWS +# define DISTRHO_LV2_UI_TYPE "WindowsUI" +# else +# define DISTRHO_LV2_UI_TYPE "X11UI" +# endif +#else +# define DISTRHO_LV2_UI_TYPE "UI" +#endif + +#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE) +#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE) + +#define DISTRHO_BYPASS_PARAMETER_NAME "lv2_enabled" + +// ----------------------------------------------------------------------- +static const char* const lv2ManifestPluginExtensionData[] = +{ + "opts:interface", +#if DISTRHO_PLUGIN_WANT_STATE + LV2_STATE__interface, + LV2_WORKER__interface, +#endif +#if DISTRHO_PLUGIN_WANT_PROGRAMS + LV2_PROGRAMS__Interface, +#endif +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + MOD_LICENSE__interface, +#endif + nullptr +}; + +static const char* const lv2ManifestPluginOptionalFeatures[] = +{ +#if DISTRHO_PLUGIN_IS_RT_SAFE + LV2_CORE__hardRTCapable, +#endif + LV2_BUF_SIZE__boundedBlockLength, + nullptr +}; + +static const char* const lv2ManifestPluginRequiredFeatures[] = +{ + "opts:options", + LV2_URID__map, +#if DISTRHO_PLUGIN_WANT_STATE + LV2_WORKER__schedule, +#endif +#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD + MOD_LICENSE__feature, +#endif + nullptr +}; + +static const char* const lv2ManifestPluginSupportedOptions[] = +{ + LV2_BUF_SIZE__nominalBlockLength, + LV2_BUF_SIZE__maxBlockLength, + LV2_PARAMETERS__sampleRate, + nullptr +}; + +#if DISTRHO_PLUGIN_HAS_UI +static const char* const lv2ManifestUiExtensionData[] = +{ + "opts:interface", + "ui:idleInterface", + "ui:showInterface", +#if DISTRHO_PLUGIN_WANT_PROGRAMS + LV2_PROGRAMS__UIInterface, +#endif + nullptr +}; + +static const char* const lv2ManifestUiOptionalFeatures[] = +{ +#if DISTRHO_PLUGIN_HAS_EMBED_UI +# if !DISTRHO_UI_USER_RESIZABLE + "ui:noUserResize", +# endif + "ui:parent", + "ui:touch", +#endif + "ui:requestValue", + nullptr +}; + +static const char* const lv2ManifestUiRequiredFeatures[] = +{ + "opts:options", + "ui:idleInterface", +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + LV2_DATA_ACCESS_URI, + LV2_INSTANCE_ACCESS_URI, +#endif + LV2_URID__map, + nullptr +}; + +static const char* const lv2ManifestUiSupportedOptions[] = +{ + LV2_PARAMETERS__sampleRate, + nullptr +}; +#endif // DISTRHO_PLUGIN_HAS_UI + +static void addAttribute(DISTRHO_NAMESPACE::String& text, + const char* const attribute, + const char* const values[], + const uint indent, + const bool endInDot = false) +{ + if (values[0] == nullptr) + { + if (endInDot) + { + bool found; + const size_t index = text.rfind(';', &found); + if (found) text[index] = '.'; + } + return; + } + + const size_t attributeLength = std::strlen(attribute); + + for (uint i = 0; values[i] != nullptr; ++i) + { + for (uint j = 0; j < indent; ++j) + text += " "; + + if (i == 0) + { + text += attribute; + } + else + { + for (uint j = 0; j < attributeLength; ++j) + text += " "; + } + + text += " "; + + const bool isUrl = std::strstr(values[i], "://") != nullptr || std::strncmp(values[i], "urn:", 4) == 0; + if (isUrl) text += "<"; + text += values[i]; + if (isUrl) text += ">"; + text += values[i + 1] ? " ,\n" : (endInDot ? " .\n\n" : " ;\n\n"); + } +} + +// ----------------------------------------------------------------------- + +DISTRHO_PLUGIN_EXPORT +void lv2_generate_ttl(const char* const basename) +{ + USE_NAMESPACE_DISTRHO + + String bundlePath(getBinaryFilename()); + if (bundlePath.isNotEmpty()) + { + bundlePath.truncate(bundlePath.rfind(DISTRHO_OS_SEP)); + } +#ifndef DISTRHO_OS_WINDOWS + else if (char* const cwd = ::getcwd(nullptr, 0)) + { + bundlePath = cwd; + std::free(cwd); + } +#endif + d_nextBundlePath = bundlePath.buffer(); + + // Dummy plugin to get data from + d_nextBufferSize = 512; + d_nextSampleRate = 44100.0; + d_nextPluginIsDummy = true; + PluginExporter plugin(nullptr, nullptr, nullptr, nullptr); + d_nextBufferSize = 0; + d_nextSampleRate = 0.0; + d_nextPluginIsDummy = false; + + const String pluginDLL(basename); + const String pluginTTL(pluginDLL + ".ttl"); + +#if DISTRHO_PLUGIN_HAS_UI + String pluginUI(pluginDLL); +# if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + pluginUI.truncate(pluginDLL.rfind("_dsp")); + pluginUI += "_ui"; + const String uiTTL(pluginUI + ".ttl"); +# endif +#endif + + // --------------------------------------------- + + { + std::cout << "Writing manifest.ttl..."; std::cout.flush(); + std::fstream manifestFile("manifest.ttl", std::ios::out); + + String manifestString; + manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; + manifestString += "@prefix rdfs: .\n"; +#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + manifestString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; +#endif +#if DISTRHO_PLUGIN_WANT_PROGRAMS + manifestString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n"; +#endif +#if DISTRHO_PLUGIN_HAS_UI + manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; +#endif + manifestString += "\n"; + + manifestString += "<" DISTRHO_PLUGIN_URI ">\n"; + manifestString += " a lv2:Plugin ;\n"; + manifestString += " lv2:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n"; +#if DISTRHO_PLUGIN_USES_MODGUI + manifestString += " rdfs:seeAlso <" + pluginTTL + "> ,\n"; + manifestString += " .\n"; +#else + manifestString += " rdfs:seeAlso <" + pluginTTL + "> .\n"; +#endif + manifestString += "\n"; + +#if DISTRHO_PLUGIN_HAS_UI + manifestString += "<" DISTRHO_UI_URI ">\n"; + manifestString += " a ui:" DISTRHO_LV2_UI_TYPE " ;\n"; + manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n"; +# if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + addAttribute(manifestString, "lv2:extensionData", lv2ManifestUiExtensionData, 4); + addAttribute(manifestString, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures, 4); + addAttribute(manifestString, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures, 4); + addAttribute(manifestString, "opts:supportedOption", lv2ManifestUiSupportedOptions, 4, true); +# else // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n"; +# endif // DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + manifestString += "\n"; +#endif + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#"); + + char strBuf[0xff+1]; + strBuf[0xff] = '\0'; + + String presetString; + + // Presets + for (uint32_t i = 0; i < plugin.getProgramCount(); ++i) + { + std::snprintf(strBuf, 0xff, "%03i", i+1); + + presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n"; + presetString += " a pset:Preset ;\n"; + presetString += " lv2:appliesTo <" DISTRHO_PLUGIN_URI "> ;\n"; + presetString += " rdfs:label \"" + plugin.getProgramName(i) + "\" ;\n"; + presetString += " rdfs:seeAlso .\n"; + presetString += "\n"; + + manifestString += presetString; + } +#endif + + manifestFile << manifestString; + manifestFile.close(); + std::cout << " done!" << std::endl; + } + + // --------------------------------------------- + + { + std::cout << "Writing " << pluginTTL << "..."; std::cout.flush(); + std::fstream pluginFile(pluginTTL, std::ios::out); + + String pluginString; + + // header +#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT + pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n"; +#endif + pluginString += "@prefix doap: .\n"; + pluginString += "@prefix foaf: .\n"; + pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; + pluginString += "@prefix midi: <" LV2_MIDI_PREFIX "> .\n"; + pluginString += "@prefix mod: .\n"; + pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; + pluginString += "@prefix pg: <" LV2_PORT_GROUPS_PREFIX "> .\n"; + pluginString += "@prefix patch: <" LV2_PATCH_PREFIX "> .\n"; + pluginString += "@prefix rdf: .\n"; + pluginString += "@prefix rdfs: .\n"; +#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT + pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n"; +#endif + pluginString += "@prefix spdx: .\n"; +#if DISTRHO_PLUGIN_HAS_UI + pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; +#endif + pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n"; + pluginString += "\n"; + +#if DISTRHO_PLUGIN_WANT_STATE + bool hasHostVisibleState = false; + + for (uint32_t i=0, count=plugin.getStateCount(); i < count; ++i) + { + const uint32_t hints = plugin.getStateHints(i); + + if ((hints & kStateIsHostReadable) == 0x0) + continue; + + pluginString += "<" DISTRHO_PLUGIN_URI "#" + plugin.getStateKey(i) + ">\n"; + pluginString += " a lv2:Parameter ;\n"; + pluginString += " rdfs:label \"" + plugin.getStateLabel(i) + "\" ;\n"; + + const String& comment(plugin.getStateDescription(i)); + + if (comment.isNotEmpty()) + { + if (comment.contains('"') || comment.contains('\n')) + pluginString += " rdfs:comment \"\"\"" + comment + "\"\"\" ;\n"; + else + pluginString += " rdfs:comment \"" + comment + "\" ;\n"; + } + + if ((hints & kStateIsFilenamePath) == kStateIsFilenamePath) + { + #ifdef __MOD_DEVICES__ + const String& fileTypes(plugin.getStateFileTypes(i)); + if (fileTypes.isNotEmpty()) + pluginString += " mod:fileTypes \"" + fileTypes + "\" ; \n"; + #endif + pluginString += " rdfs:range atom:Path .\n\n"; + } + else + { + pluginString += " rdfs:range atom:String .\n\n"; + } + + hasHostVisibleState = true; + } +#endif + + // plugin + pluginString += "<" DISTRHO_PLUGIN_URI ">\n"; +#ifdef DISTRHO_PLUGIN_LV2_CATEGORY + pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin, doap:Project ;\n"; +#elif DISTRHO_PLUGIN_IS_SYNTH + pluginString += " a lv2:InstrumentPlugin, lv2:Plugin, doap:Project ;\n"; +#else + pluginString += " a lv2:Plugin, doap:Project ;\n"; +#endif + pluginString += "\n"; + + addAttribute(pluginString, "lv2:extensionData", lv2ManifestPluginExtensionData, 4); + addAttribute(pluginString, "lv2:optionalFeature", lv2ManifestPluginOptionalFeatures, 4); + addAttribute(pluginString, "lv2:requiredFeature", lv2ManifestPluginRequiredFeatures, 4); + addAttribute(pluginString, "opts:supportedOption", lv2ManifestPluginSupportedOptions, 4); + +#if DISTRHO_PLUGIN_WANT_STATE + if (hasHostVisibleState) + { + for (uint32_t i=0, count=plugin.getStateCount(); i < count; ++i) + { + const uint32_t hints = plugin.getStateHints(i); + + if ((hints & kStateIsHostReadable) == 0x0) + continue; + + const String& key(plugin.getStateKey(i)); + + if ((hints & kStateIsHostWritable) == kStateIsHostWritable) + pluginString += " patch:writable <" DISTRHO_PLUGIN_URI "#" + key + "> ;\n"; + else + pluginString += " patch:readable <" DISTRHO_PLUGIN_URI "#" + key + "> ;\n"; + } + pluginString += "\n"; + } +#endif + + // UI +#if DISTRHO_PLUGIN_HAS_UI + pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n"; + pluginString += "\n"; +#endif + + { + uint32_t portIndex = 0; + +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex) + { + const AudioPort& port(plugin.getAudioPort(true, i)); + const bool cvPortScaled = port.hints & kCVPortHasScaledRange; + + if (i == 0) + pluginString += " lv2:port [\n"; + else + pluginString += " [\n"; + + if (cvPortScaled) + pluginString += " a lv2:InputPort, lv2:CVPort, mod:CVPort ;\n"; + else if (port.hints & kAudioPortIsCV) + pluginString += " a lv2:InputPort, lv2:CVPort ;\n"; + else + pluginString += " a lv2:InputPort, lv2:AudioPort ;\n"; + + pluginString += " lv2:index " + String(portIndex) + " ;\n"; + pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n"; + pluginString += " lv2:name \"" + port.name + "\" ;\n"; + + if (port.hints & kAudioPortIsSidechain) + pluginString += " lv2:portProperty lv2:isSideChain;\n"; + + if (port.groupId != kPortGroupNone) + { + pluginString += " pg:group <" DISTRHO_PLUGIN_URI "#portGroup_" + + plugin.getPortGroupSymbolForId(port.groupId) + "> ;\n"; + + switch (port.groupId) + { + case kPortGroupMono: + pluginString += " lv2:designation pg:center ;\n"; + break; + case kPortGroupStereo: + if (i == 1) + pluginString += " lv2:designation pg:right ;\n"; + else + pluginString += " lv2:designation pg:left ;\n"; + break; + } + } + + // set ranges + if (port.hints & kCVPortHasBipolarRange) + { + if (cvPortScaled) + { + pluginString += " lv2:minimum -5.0 ;\n"; + pluginString += " lv2:maximum 5.0 ;\n"; + } + else + { + pluginString += " lv2:minimum -1.0 ;\n"; + pluginString += " lv2:maximum 1.0 ;\n"; + } + } + else if (port.hints & kCVPortHasNegativeUnipolarRange) + { + if (cvPortScaled) + { + pluginString += " lv2:minimum -10.0 ;\n"; + pluginString += " lv2:maximum 0.0 ;\n"; + } + else + { + pluginString += " lv2:minimum -1.0 ;\n"; + pluginString += " lv2:maximum 0.0 ;\n"; + } + } + else if (port.hints & kCVPortHasPositiveUnipolarRange) + { + if (cvPortScaled) + { + pluginString += " lv2:minimum 0.0 ;\n"; + pluginString += " lv2:maximum 10.0 ;\n"; + } + else + { + pluginString += " lv2:minimum 0.0 ;\n"; + pluginString += " lv2:maximum 1.0 ;\n"; + } + } + + if ((port.hints & (kAudioPortIsCV|kCVPortIsOptional)) == (kAudioPortIsCV|kCVPortIsOptional)) + pluginString += " lv2:portProperty lv2:connectionOptional;\n"; + + if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS) + pluginString += " ] ;\n"; + else + pluginString += " ] ,\n"; + } + pluginString += "\n"; +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex) + { + const AudioPort& port(plugin.getAudioPort(false, i)); + const bool cvPortScaled = port.hints & kCVPortHasScaledRange; + + if (i == 0) + pluginString += " lv2:port [\n"; + else + pluginString += " [\n"; + + if (cvPortScaled) + pluginString += " a lv2:OutputPort, lv2:CVPort, mod:CVPort ;\n"; + else if (port.hints & kAudioPortIsCV) + pluginString += " a lv2:OutputPort, lv2:CVPort ;\n"; + else + pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n"; + + pluginString += " lv2:index " + String(portIndex) + " ;\n"; + pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n"; + pluginString += " lv2:name \"" + port.name + "\" ;\n"; + + if (port.hints & kAudioPortIsSidechain) + pluginString += " lv2:portProperty lv2:isSideChain;\n"; + + if (port.groupId != kPortGroupNone) + { + pluginString += " pg:group <" DISTRHO_PLUGIN_URI "#portGroup_" + + plugin.getPortGroupSymbolForId(port.groupId) + "> ;\n"; + + switch (port.groupId) + { + case kPortGroupMono: + pluginString += " lv2:designation pg:center ;\n"; + break; + case kPortGroupStereo: + if (i == 1) + pluginString += " lv2:designation pg:right ;\n"; + else + pluginString += " lv2:designation pg:left ;\n"; + break; + } + } + + // set ranges + if (port.hints & kCVPortHasBipolarRange) + { + if (cvPortScaled) + { + pluginString += " lv2:minimum -5.0 ;\n"; + pluginString += " lv2:maximum 5.0 ;\n"; + } + else + { + pluginString += " lv2:minimum -1.0 ;\n"; + pluginString += " lv2:maximum 1.0 ;\n"; + } + } + else if (port.hints & kCVPortHasNegativeUnipolarRange) + { + if (cvPortScaled) + { + pluginString += " lv2:minimum -10.0 ;\n"; + pluginString += " lv2:maximum 0.0 ;\n"; + } + else + { + pluginString += " lv2:minimum -1.0 ;\n"; + pluginString += " lv2:maximum 0.0 ;\n"; + } + } + else if (port.hints & kCVPortHasPositiveUnipolarRange) + { + if (cvPortScaled) + { + pluginString += " lv2:minimum 0.0 ;\n"; + pluginString += " lv2:maximum 10.0 ;\n"; + } + else + { + pluginString += " lv2:minimum 0.0 ;\n"; + pluginString += " lv2:maximum 1.0 ;\n"; + } + } + + if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS) + pluginString += " ] ;\n"; + else + pluginString += " ] ,\n"; + } + pluginString += "\n"; +#endif + +#if DISTRHO_LV2_USE_EVENTS_IN + pluginString += " lv2:port [\n"; + pluginString += " a lv2:InputPort, atom:AtomPort ;\n"; + pluginString += " lv2:index " + String(portIndex) + " ;\n"; + pluginString += " lv2:name \"Events Input\" ;\n"; + pluginString += " lv2:symbol \"lv2_events_in\" ;\n"; + pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n"; + pluginString += " atom:bufferType atom:Sequence ;\n"; +# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) + pluginString += " atom:supports atom:String ;\n"; +# endif +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + pluginString += " atom:supports midi:MidiEvent ;\n"; +# endif +# if DISTRHO_PLUGIN_WANT_TIMEPOS + pluginString += " atom:supports <" LV2_TIME__Position "> ;\n"; +# endif +# if DISTRHO_PLUGIN_WANT_STATE + if (hasHostVisibleState) + { + pluginString += " atom:supports <" LV2_PATCH__Message "> ;\n"; + pluginString += " lv2:designation lv2:control ;\n"; + } +# endif + pluginString += " ] ;\n\n"; + ++portIndex; +#endif + +#if DISTRHO_LV2_USE_EVENTS_OUT + pluginString += " lv2:port [\n"; + pluginString += " a lv2:OutputPort, atom:AtomPort ;\n"; + pluginString += " lv2:index " + String(portIndex) + " ;\n"; + pluginString += " lv2:name \"Events Output\" ;\n"; + pluginString += " lv2:symbol \"lv2_events_out\" ;\n"; + pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n"; + pluginString += " atom:bufferType atom:Sequence ;\n"; +# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) + pluginString += " atom:supports atom:String ;\n"; +# endif +# if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + pluginString += " atom:supports midi:MidiEvent ;\n"; +# endif +# if DISTRHO_PLUGIN_WANT_STATE + if (hasHostVisibleState) + { + pluginString += " atom:supports <" LV2_PATCH__Message "> ;\n"; + pluginString += " lv2:designation lv2:control ;\n"; + } +# endif + pluginString += " ] ;\n\n"; + ++portIndex; +#endif + +#if DISTRHO_PLUGIN_WANT_LATENCY + pluginString += " lv2:port [\n"; + pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n"; + pluginString += " lv2:index " + String(portIndex) + " ;\n"; + pluginString += " lv2:name \"Latency\" ;\n"; + pluginString += " lv2:symbol \"lv2_latency\" ;\n"; + pluginString += " lv2:designation lv2:latency ;\n"; + pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer, <" LV2_PORT_PROPS__notOnGUI "> ;\n"; + pluginString += " ] ;\n\n"; + ++portIndex; +#endif + + for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex) + { + if (i == 0) + pluginString += " lv2:port [\n"; + else + pluginString += " [\n"; + + if (plugin.isParameterOutput(i)) + pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n"; + else + pluginString += " a lv2:InputPort, lv2:ControlPort ;\n"; + + pluginString += " lv2:index " + String(portIndex) + " ;\n"; + + bool designated = false; + + // designation + if (plugin.isParameterInput(i)) + { + switch (plugin.getParameterDesignation(i)) + { + case kParameterDesignationNull: + break; + case kParameterDesignationBypass: + designated = true; + pluginString += " lv2:name \"Enabled\" ;\n"; + pluginString += " lv2:symbol \"" DISTRHO_BYPASS_PARAMETER_NAME "\" ;\n"; + pluginString += " lv2:default 1 ;\n"; + pluginString += " lv2:minimum 0 ;\n"; + pluginString += " lv2:maximum 1 ;\n"; + pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n"; + pluginString += " lv2:designation lv2:enabled ;\n"; + break; + } + } + + if (! designated) + { + const uint32_t hints = plugin.getParameterHints(i); + + // name and symbol + const String& paramName(plugin.getParameterName(i)); + + if (paramName.contains('"')) + pluginString += " lv2:name \"\"\"" + paramName + "\"\"\" ;\n"; + else + pluginString += " lv2:name \"" + paramName + "\" ;\n"; + + String symbol(plugin.getParameterSymbol(i)); + + if (symbol.isEmpty()) + symbol = "lv2_port_" + String(portIndex-1); + + pluginString += " lv2:symbol \"" + symbol + "\" ;\n"; + + // short name + const String& shortName(plugin.getParameterShortName(i)); + + if (shortName.isNotEmpty()) + pluginString += " lv2:shortName \"\"\"" + shortName + "\"\"\" ;\n"; + + // ranges + const ParameterRanges& ranges(plugin.getParameterRanges(i)); + + if (hints & kParameterIsInteger) + { + if (plugin.isParameterInput(i)) + pluginString += " lv2:default " + String(int(ranges.def)) + " ;\n"; + pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n"; + pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n"; + } + else if (hints & kParameterIsLogarithmic) + { + if (plugin.isParameterInput(i)) + { + if (d_isNotZero(ranges.def)) + pluginString += " lv2:default " + String(ranges.def) + " ;\n"; + else if (d_isEqual(ranges.def, ranges.max)) + pluginString += " lv2:default -0.0001 ;\n"; + else + pluginString += " lv2:default 0.0001 ;\n"; + } + + if (d_isNotZero(ranges.min)) + pluginString += " lv2:minimum " + String(ranges.min) + " ;\n"; + else + pluginString += " lv2:minimum 0.0001 ;\n"; + + if (d_isNotZero(ranges.max)) + pluginString += " lv2:maximum " + String(ranges.max) + " ;\n"; + else + pluginString += " lv2:maximum -0.0001 ;\n"; + } + else + { + if (plugin.isParameterInput(i)) + pluginString += " lv2:default " + String(ranges.def) + " ;\n"; + pluginString += " lv2:minimum " + String(ranges.min) + " ;\n"; + pluginString += " lv2:maximum " + String(ranges.max) + " ;\n"; + } + + // enumeration + const ParameterEnumerationValues& enumValues(plugin.getParameterEnumValues(i)); + + if (enumValues.count > 0) + { + if (enumValues.count >= 2 && enumValues.restrictedMode) + pluginString += " lv2:portProperty lv2:enumeration ;\n"; + + for (uint8_t j=0; j < enumValues.count; ++j) + { + const ParameterEnumerationValue& enumValue(enumValues.values[j]); + + if (j == 0) + pluginString += " lv2:scalePoint [\n"; + else + pluginString += " [\n"; + + if (enumValue.label.contains('"')) + pluginString += " rdfs:label \"\"\"" + enumValue.label + "\"\"\" ;\n"; + else + pluginString += " rdfs:label \"" + enumValue.label + "\" ;\n"; + + if (hints & kParameterIsInteger) + { + const int rounded = (int)(enumValue.value + (enumValue.value < 0.0f ? -0.5f : 0.5f)); + pluginString += " rdf:value " + String(rounded) + " ;\n"; + } + else + { + pluginString += " rdf:value " + String(enumValue.value) + " ;\n"; + } + + if (j+1 == enumValues.count) + pluginString += " ] ;\n"; + else + pluginString += " ] ,\n"; + } + } + + // MIDI CC binding + if (const uint8_t midiCC = plugin.getParameterMidiCC(i)) + { + pluginString += " midi:binding [\n"; + pluginString += " a midi:Controller ;\n"; + pluginString += " midi:controllerNumber " + String(midiCC) + " ;\n"; + pluginString += " ] ;\n"; + } + + // unit + const String& unit(plugin.getParameterUnit(i)); + + if (unit.isNotEmpty() && ! unit.contains(' ')) + { + String lunit(unit); + lunit.toLower(); + + /**/ if (lunit == "db") + { + pluginString += " unit:unit unit:db ;\n"; + } + else if (lunit == "hz") + { + pluginString += " unit:unit unit:hz ;\n"; + } + else if (lunit == "khz") + { + pluginString += " unit:unit unit:khz ;\n"; + } + else if (lunit == "mhz") + { + pluginString += " unit:unit unit:mhz ;\n"; + } + else if (lunit == "ms") + { + pluginString += " unit:unit unit:ms ;\n"; + } + else if (lunit == "s") + { + pluginString += " unit:unit unit:s ;\n"; + } + else if (lunit == "%") + { + pluginString += " unit:unit unit:pc ;\n"; + } + else + { + pluginString += " unit:unit [\n"; + pluginString += " a unit:Unit ;\n"; + pluginString += " rdfs:label \"" + unit + "\" ;\n"; + pluginString += " unit:symbol \"" + unit + "\" ;\n"; + if (hints & kParameterIsInteger) + pluginString += " unit:render \"%d " + unit + "\" ;\n"; + else + pluginString += " unit:render \"%f " + unit + "\" ;\n"; + pluginString += " ] ;\n"; + } + } + + // comment + const String& comment(plugin.getParameterDescription(i)); + + if (comment.isNotEmpty()) + { + if (comment.contains('"') || comment.contains('\n')) + pluginString += " rdfs:comment \"\"\"" + comment + "\"\"\" ;\n"; + else + pluginString += " rdfs:comment \"" + comment + "\" ;\n"; + } + + // hints + if (hints & kParameterIsBoolean) + { + if ((hints & kParameterIsTrigger) == kParameterIsTrigger) + pluginString += " lv2:portProperty <" LV2_PORT_PROPS__trigger "> ;\n"; + pluginString += " lv2:portProperty lv2:toggled ;\n"; + } + if (hints & kParameterIsInteger) + pluginString += " lv2:portProperty lv2:integer ;\n"; + if (hints & kParameterIsLogarithmic) + pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n"; + if (hints & kParameterIsHidden) + pluginString += " lv2:portProperty <" LV2_PORT_PROPS__notOnGUI "> ;\n"; + if ((hints & kParameterIsAutomatable) == 0 && plugin.isParameterInput(i)) + { + pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n"; + pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomatable "> ;\n"; + } + + // group + const uint32_t groupId = plugin.getParameterGroupId(i); + + if (groupId != kPortGroupNone) + pluginString += " pg:group <" DISTRHO_PLUGIN_URI "#portGroup_" + + plugin.getPortGroupSymbolForId(groupId) + "> ;\n"; + + } // ! designated + + if (i+1 == count) + pluginString += " ] ;\n\n"; + else + pluginString += " ] ,\n"; + } + } + + // comment + { + const String comment(plugin.getDescription()); + + if (comment.isNotEmpty()) + { + if (comment.contains('"') || comment.contains('\n')) + pluginString += " rdfs:comment \"\"\"" + comment + "\"\"\" ;\n\n"; + else + pluginString += " rdfs:comment \"" + comment + "\" ;\n\n"; + } + } + + #ifdef DISTRHO_PLUGIN_BRAND + // MOD + pluginString += " mod:brand \"" DISTRHO_PLUGIN_BRAND "\" ;\n"; + pluginString += " mod:label \"" DISTRHO_PLUGIN_NAME "\" ;\n\n"; + #endif + + // name + { + const String name(plugin.getName()); + + if (name.contains('"')) + pluginString += " doap:name \"\"\"" + name + "\"\"\" ;\n"; + else + pluginString += " doap:name \"" + name + "\" ;\n"; + } + + // license + { + const String license(plugin.getLicense()); + + // Using URL as license + if (license.contains("://")) + { + pluginString += " doap:license <" + license + "> ;\n\n"; + } + // String contaning quotes, use as-is + else if (license.contains('"')) + { + pluginString += " doap:license \"\"\"" + license + "\"\"\" ;\n\n"; + } + // Regular license string, convert to URL as much as we can + else + { + const String uplicense(license.asUpper()); + + // for reference, see https://spdx.org/licenses/ + + // common licenses + /**/ if (uplicense == "AGPL-1.0-ONLY" || + uplicense == "AGPL1" || + uplicense == "AGPLV1") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "AGPL-1.0-OR-LATER" || + uplicense == "AGPL1+" || + uplicense == "AGPLV1+") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "AGPL-3.0-ONLY" || + uplicense == "AGPL3" || + uplicense == "AGPLV3") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "AGPL-3.0-OR-LATER" || + uplicense == "AGPL3+" || + uplicense == "AGPLV3+") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "APACHE-2.0" || + uplicense == "APACHE2" || + uplicense == "APACHE-2") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "BSD-2-CLAUSE" || + uplicense == "BSD2" || + uplicense == "BSD-2") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "BSD-3-CLAUSE" || + uplicense == "BSD3" || + uplicense == "BSD-3") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "GPL-2.0-ONLY" || + uplicense == "GPL2" || + uplicense == "GPLV2") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "GPL-2.0-OR-LATER" || + uplicense == "GPL2+" || + uplicense == "GPLV2+" || + uplicense == "GPLV2.0+" || + uplicense == "GPL V2+") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "GPL-3.0-ONLY" || + uplicense == "GPL3" || + uplicense == "GPLV3") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "GPL-3.0-OR-LATER" || + uplicense == "GPL3+" || + uplicense == "GPLV3+" || + uplicense == "GPLV3.0+" || + uplicense == "GPL V3+") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "ISC") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "LGPL-2.0-ONLY" || + uplicense == "LGPL2" || + uplicense == "LGPLV2") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "LGPL-2.0-OR-LATER" || + uplicense == "LGPL2+" || + uplicense == "LGPLV2+") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "LGPL-2.1-ONLY" || + uplicense == "LGPL2.1" || + uplicense == "LGPLV2.1") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "LGPL-2.1-OR-LATER" || + uplicense == "LGPL2.1+" || + uplicense == "LGPLV2.1+") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "LGPL-3.0-ONLY" || + uplicense == "LGPL3" || + uplicense == "LGPLV3") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "LGPL-3.0-OR-LATER" || + uplicense == "LGPL3+" || + uplicense == "LGPLV3+") + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense == "MIT") + { + pluginString += " doap:license ;\n\n"; + } + + // generic fallbacks + else if (uplicense.startsWith("GPL")) + { + pluginString += " doap:license ;\n\n"; + } + else if (uplicense.startsWith("LGPL")) + { + pluginString += " doap:license ;\n\n"; + } + + // unknown or not handled yet, log a warning + else + { + d_stderr("Unknown license string '%s'", license.buffer()); + pluginString += " doap:license \"" + license + "\" ;\n\n"; + } + } + } + + // developer + { + const String homepage(plugin.getHomePage()); + const String maker(plugin.getMaker()); + + pluginString += " doap:maintainer [\n"; + + if (maker.contains('"')) + pluginString += " foaf:name \"\"\"" + maker + "\"\"\" ;\n"; + else + pluginString += " foaf:name \"" + maker + "\" ;\n"; + + if (homepage.isNotEmpty()) + pluginString += " foaf:homepage <" + homepage + "> ;\n"; + + pluginString += " ] ;\n\n"; + } + + { + const uint32_t version(plugin.getVersion()); + + const uint32_t majorVersion = (version & 0xFF0000) >> 16; + /* */ uint32_t minorVersion = (version & 0x00FF00) >> 8; + const uint32_t microVersion = (version & 0x0000FF) >> 0; + + // NOTE: LV2 ignores 'major' version and says 0 for minor is pre-release/unstable. + if (majorVersion > 0) + minorVersion += 2; + + pluginString += " lv2:microVersion " + String(microVersion) + " ;\n"; + pluginString += " lv2:minorVersion " + String(minorVersion) + " .\n"; + } + + // port groups + if (const uint32_t portGroupCount = plugin.getPortGroupCount()) + { + bool isInput, isOutput; + + for (uint32_t i = 0; i < portGroupCount; ++i) + { + const PortGroupWithId& portGroup(plugin.getPortGroupByIndex(i)); + DISTRHO_SAFE_ASSERT_CONTINUE(portGroup.groupId != kPortGroupNone); + DISTRHO_SAFE_ASSERT_CONTINUE(portGroup.symbol.isNotEmpty()); + + pluginString += "\n<" DISTRHO_PLUGIN_URI "#portGroup_" + portGroup.symbol + ">\n"; + isInput = isOutput = false; + +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS && !isInput; ++i) + isInput = plugin.getAudioPort(true, i).groupId == portGroup.groupId; +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS && !isOutput; ++i) + isOutput = plugin.getAudioPort(false, i).groupId == portGroup.groupId; +#endif + + for (uint32_t i=0, count=plugin.getParameterCount(); i < count && (!isInput || !isOutput); ++i) + { + if (plugin.getParameterGroupId(i) == portGroup.groupId) + { + isInput = isInput || plugin.isParameterInput(i); + isOutput = isOutput || plugin.isParameterOutput(i); + } + } + + pluginString += " a "; + + if (isInput && !isOutput) + pluginString += "pg:InputGroup"; + else if (isOutput && !isInput) + pluginString += "pg:OutputGroup"; + else + pluginString += "pg:Group"; + + switch (portGroup.groupId) + { + case kPortGroupMono: + pluginString += " , pg:MonoGroup"; + break; + case kPortGroupStereo: + pluginString += " , pg:StereoGroup"; + break; + } + + pluginString += " ;\n"; + + // pluginString += " rdfs:label \"" + portGroup.name + "\" ;\n"; + pluginString += " lv2:name \"" + portGroup.name + "\" ;\n"; + pluginString += " lv2:symbol \"" + portGroup.symbol + "\" .\n"; + } + } + + pluginFile << pluginString; + pluginFile.close(); + std::cout << " done!" << std::endl; + } + + #if DISTRHO_PLUGIN_USES_MODGUI && !DISTRHO_PLUGIN_USES_CUSTOM_MODGUI + { + std::cout << "Writing modgui.ttl..."; std::cout.flush(); + std::fstream modguiFile("modgui.ttl", std::ios::out); + + String modguiString; + modguiString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; + modguiString += "@prefix modgui: .\n"; + modguiString += "\n"; + + modguiString += "<" DISTRHO_PLUGIN_URI ">\n"; + modguiString += " modgui:gui [\n"; + #ifdef DISTRHO_PLUGIN_BRAND + modguiString += " modgui:brand \"" DISTRHO_PLUGIN_BRAND "\" ;\n"; + #endif + modguiString += " modgui:label \"" DISTRHO_PLUGIN_NAME "\" ;\n"; + modguiString += " modgui:resourcesDirectory ;\n"; + modguiString += " modgui:iconTemplate ;\n"; + modguiString += " modgui:javascript ;\n"; + modguiString += " modgui:stylesheet ;\n"; + modguiString += " modgui:screenshot ;\n"; + modguiString += " modgui:thumbnail ;\n"; + + uint32_t numParametersOutputs = 0; + for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i) + { + if (plugin.isParameterOutput(i)) + ++numParametersOutputs; + } + if (numParametersOutputs != 0) + { + modguiString += " modgui:monitoredOutputs [\n"; + for (uint32_t i=0, j=0, count=plugin.getParameterCount(); i < count; ++i) + { + if (!plugin.isParameterOutput(i)) + continue; + modguiString += " lv2:symbol \"" + plugin.getParameterSymbol(i) + "\" ;\n"; + if (++j != numParametersOutputs) + modguiString += " ] , [\n"; + } + modguiString += " ] ;\n"; + } + + modguiString += " ] .\n"; + + modguiFile << modguiString; + modguiFile.close(); + std::cout << " done!" << std::endl; + } + + #ifdef DISTRHO_OS_WINDOWS + ::_mkdir("modgui"); + #else + ::mkdir("modgui", 0755); + #endif + + { + std::cout << "Writing modgui/javascript.js..."; std::cout.flush(); + std::fstream jsFile("modgui/javascript.js", std::ios::out); + + String jsString; + jsString += "function(e,f){\n"; + jsString += "'use strict';\nvar ps=["; + + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) + jsString += "'lv2_" + plugin.getAudioPort(false, i).symbol + "',"; + for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + jsString += "'lv2_" + plugin.getAudioPort(true, i).symbol + "',"; + #if DISTRHO_LV2_USE_EVENTS_IN + jsString += "'lv2_events_in',"; + #endif + #if DISTRHO_LV2_USE_EVENTS_OUT + jsString += "'lv2_events_out',"; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + jsString += "'lv2_latency',"; + #endif + + int32_t enabledIndex = INT32_MAX; + for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i) + { + jsString += "'" + plugin.getParameterSymbol(i) + "',"; + if (plugin.getParameterDesignation(i) == kParameterDesignationBypass) + enabledIndex = i; + } + jsString += "];\n"; + jsString += "var ei=" + String(enabledIndex != INT32_MAX ? enabledIndex : -1) + ";\n\n"; + jsString += "if(e.type==='start'){\n"; + jsString += "e.data.p={p:{},c:{},};\n\n"; + jsString += "var err=[];\n"; + jsString += "if(typeof(WebAssembly)==='undefined'){err.push('WebAssembly unsupported');}\n"; + jsString += "else{\n"; + jsString += "if(!WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,3,1,0,1,10,14,1,12,0,65,0,65,0,65,0,252,10,0,0,11])))"; + jsString += "err.push('Bulk Memory Operations unsupported');\n"; + jsString += "if(!WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,2,8,1,1,97,1,98,3,127,1,6,6,1,127,1,65,0,11,7,5,1,1,97,3,1])))"; + jsString += "err.push('Importable/Exportable mutable globals unsupported');\n"; + jsString += "}\n"; + jsString += "if(err.length!==0){e.icon.find('.canvas_wrapper').html('

'+err.join('
')+'

');return;}\n\n"; + jsString += "var s=document.createElement('script');\n"; + jsString += "s.setAttribute('async',true);\n"; + jsString += "s.setAttribute('src',e.api_version>=3?f.get_custom_resource_filename('module.js'):('/resources/module.js?uri='+escape(\"" DISTRHO_PLUGIN_URI "\")+'&r='+VERSION));\n"; + jsString += "s.setAttribute('type','text/javascript');\n"; + jsString += "s.onload=function(){\n"; + jsString += " Module_" DISTRHO_PLUGIN_MODGUI_CLASS_NAME "({\n"; + jsString += " locateFile: function(p,_){return e.api_version>=3?f.get_custom_resource_filename(p):('/resources/'+p+'?uri='+escape(\"" DISTRHO_PLUGIN_URI "\")+'&r='+VERSION)},\n"; + jsString += " postRun:function(m){\n"; + jsString += " var cn=e.icon.attr('mod-instance').replaceAll('/','_');\n"; + jsString += " var cnl=m.lengthBytesUTF8(cn) + 1;\n"; + jsString += " var cna=m._malloc(cnl);\n"; + jsString += " m.stringToUTF8(cn, cna, cnl);\n"; + jsString += " e.icon.find('canvas')[0].id=cn;\n"; + jsString += " var a=m.addFunction(function(i,v){f.set_port_value(ps[i],v);},'vif');\n"; + jsString += " var b=m.addFunction(function(u,v){f.patch_set(m.UTF8ToString(u),'s',m.UTF8ToString(v));},'vpp');\n"; + jsString += " var h=m._modgui_init(cna,a,b);\n"; + jsString += " m._free(cna);\n"; + jsString += " e.data.h=h;\n"; + jsString += " e.data.m=m;\n"; + jsString += " for(var u in e.data.p.p){\n"; + jsString += " var ul=m.lengthBytesUTF8(u)+1,ua=m._malloc(ul),v=e.data.p.p[u],vl=m.lengthBytesUTF8(v)+1,va=m._malloc(vl);\n"; + jsString += " m.stringToUTF8(u,ua,ul);\n"; + jsString += " m.stringToUTF8(v,va,vl);\n"; + jsString += " m._modgui_patch_set(h, ua, va);\n"; + jsString += " m._free(ua);\n"; + jsString += " m._free(va);\n"; + jsString += " }\n"; + jsString += " for(var symbol in e.data.p.c){m._modgui_param_set(h,ps.indexOf(symbol),e.data.p.c[symbol]);}\n"; + jsString += " delete e.data.p;\n"; + jsString += " window.dispatchEvent(new Event('resize'));\n"; + jsString += " },\n"; + jsString += " canvas:(function(){var c=e.icon.find('canvas')[0];c.addEventListener('webglcontextlost',function(e2){alert('WebGL context lost. You will need to reload the page.');e2.preventDefault();},false);return c;})(),\n"; + jsString += " });\n"; + jsString += "};\n"; + jsString += "document.head.appendChild(s);\n\n"; + jsString += "}else if(e.type==='change'){\n\n"; + jsString += "if(e.data.h && e.data.m){\n"; + jsString += " var m=e.data.m;\n"; + jsString += " if(e.uri){\n"; + jsString += " var ul=m.lengthBytesUTF8(e.uri)+1,ua=m._malloc(ul),vl=m.lengthBytesUTF8(e.value)+1,va=m._malloc(vl);\n"; + jsString += " m.stringToUTF8(e.uri,ua,ul);\n"; + jsString += " m.stringToUTF8(e.value,va,vl);\n"; + jsString += " m._modgui_patch_set(e.data.h,ua,va);\n"; + jsString += " m._free(ua);\n"; + jsString += " m._free(va);\n"; + jsString += " }else if(e.symbol===':bypass'){return;\n"; + jsString += " }else{m._modgui_param_set(e.data.h,ps.indexOf(e.symbol),e.value);}\n"; + jsString += "}else{\n"; + jsString += " if(e.symbol===':bypass')return;\n"; + jsString += " if(e.uri){e.data.p.p[e.uri]=e.value;}else{e.data.p.c[e.symbol]=e.value;}\n"; + jsString += "}\n\n"; + jsString += "}else if(e.type==='end'){\n"; + jsString += " if(e.data.h && e.data.m){\n"; + jsString += " var h = e.data.h;\n"; + jsString += " var m = e.data.m;\n"; + jsString += " e.data.h = e.data.m = null;\n"; + jsString += " m._modgui_cleanup(h);\n"; + jsString += "}\n\n"; + jsString += "}\n}\n"; + jsFile << jsString; + jsFile.close(); + std::cout << " done!" << std::endl; + } + + { + std::cout << "Writing modgui/icon.html..."; std::cout.flush(); + std::fstream iconFile("modgui/icon.html", std::ios::out); + + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "

{{#brand}}{{brand}} | {{/brand}}{{label}}

" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " " << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{#effect.ports.audio.input}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{/effect.ports.audio.input}}" << std::endl; + iconFile << " {{#effect.ports.midi.input}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{/effect.ports.midi.input}}" << std::endl; + iconFile << " {{#effect.ports.cv.input}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{/effect.ports.cv.input}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{#effect.ports.audio.output}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{/effect.ports.audio.output}}" << std::endl; + iconFile << " {{#effect.ports.midi.output}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{/effect.ports.midi.output}}" << std::endl; + iconFile << " {{#effect.ports.cv.output}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + iconFile << " {{/effect.ports.cv.output}}" << std::endl; + iconFile << "
" << std::endl; + iconFile << "
" << std::endl; + + iconFile.close(); + std::cout << " done!" << std::endl; + } + + { + std::cout << "Writing modgui/stylesheet.css..."; std::cout.flush(); + std::fstream stylesheetFile("modgui/stylesheet.css", std::ios::out); + + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal{" << std::endl; + stylesheetFile << " padding:0;" << std::endl; + stylesheetFile << " margin:0;" << std::endl; + stylesheetFile << " width:" + String(DISTRHO_UI_DEFAULT_WIDTH) + "px;" << std::endl; + stylesheetFile << " height:" + String(DISTRHO_UI_DEFAULT_HEIGHT + 50) + "px;" << std::endl; + stylesheetFile << " background:#2a2e32;" << std::endl; + stylesheetFile << " border-radius:20px 20px 0 0;" << std::endl; + stylesheetFile << " color:#fff;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .canvas_wrapper{" << std::endl; + stylesheetFile << " --device-pixel-ratio:1;" << std::endl; + stylesheetFile << " /*image-rendering:pixelated;*/" << std::endl; + stylesheetFile << " /*image-rendering:crisp-edges;*/" << std::endl; + stylesheetFile << " background:#000;" << std::endl; + stylesheetFile << " position:absolute;" << std::endl; + stylesheetFile << " top:50px;" << std::endl; + stylesheetFile << " transform-origin:0 0 0;" << std::endl; + stylesheetFile << " transform:scale(calc(1/var(--device-pixel-ratio)));" << std::endl; + stylesheetFile << " width:" + String(DISTRHO_UI_DEFAULT_WIDTH) + "px;" << std::endl; + stylesheetFile << " height:" + String(DISTRHO_UI_DEFAULT_HEIGHT) + "px;" << std::endl; + stylesheetFile << " text-align:center;" << std::endl; + stylesheetFile << " z-index:21;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "/*" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .canvas_wrapper:focus-within{" << std::endl; + stylesheetFile << " z-index:21;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "*/" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-plugin-title{" << std::endl; + stylesheetFile << " position:absolute;" << std::endl; + stylesheetFile << " text-align:center;" << std::endl; + stylesheetFile << " width:100%;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal h1{" << std::endl; + stylesheetFile << " font-size:20px;" << std::endl; + stylesheetFile << " font-weight:bold;" << std::endl; + stylesheetFile << " line-height:50px;" << std::endl; + stylesheetFile << " margin:0;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-control-group{" << std::endl; + stylesheetFile << " position:absolute;" << std::endl; + stylesheetFile << " left:5px;" << std::endl; + stylesheetFile << " z-index:35;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-pedal-input," << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-pedal-output{" << std::endl; + stylesheetFile << " top:75px;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-audio-input," << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-audio-output{" << std::endl; + stylesheetFile << " margin-bottom:25px;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .jack-disconnected{" << std::endl; + stylesheetFile << " top:0px!important;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-switch-image{" << std::endl; + stylesheetFile << " background-image: url(/img/switch.png);" << std::endl; + stylesheetFile << " background-position: left center;" << std::endl; + stylesheetFile << " background-repeat: no-repeat;" << std::endl; + stylesheetFile << " background-size: auto 50px;" << std::endl; + stylesheetFile << " font-weight: bold;" << std::endl; + stylesheetFile << " width: 100px;" << std::endl; + stylesheetFile << " height: 50px;" << std::endl; + stylesheetFile << " cursor: pointer;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-switch-image.off{" << std::endl; + stylesheetFile << " background-position: right center !important;" << std::endl; + stylesheetFile << "}" << std::endl; + stylesheetFile << "." DISTRHO_PLUGIN_MODGUI_CLASS_NAME ".mod-pedal .mod-switch-image.on{" << std::endl; + stylesheetFile << " background-position: left center !important;" << std::endl; + stylesheetFile << "}" << std::endl; + + stylesheetFile.close(); + std::cout << " done!" << std::endl; + } + #endif // DISTRHO_PLUGIN_USES_MODGUI && !DISTRHO_PLUGIN_USES_CUSTOM_MODGUI + + // --------------------------------------------- + +#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + { + std::cout << "Writing " << uiTTL << "..."; std::cout.flush(); + std::fstream uiFile(uiTTL, std::ios::out); + + String uiString; + uiString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; + uiString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; + uiString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; + uiString += "\n"; + + uiString += "<" DISTRHO_UI_URI ">\n"; + + addAttribute(uiString, "lv2:extensionData", lv2ManifestUiExtensionData, 4); + addAttribute(uiString, "lv2:optionalFeature", lv2ManifestUiOptionalFeatures, 4); + addAttribute(uiString, "lv2:requiredFeature", lv2ManifestUiRequiredFeatures, 4); + addAttribute(uiString, "opts:supportedOption", lv2ManifestUiSupportedOptions, 4, true); + + uiFile << uiString; + uiFile.close(); + std::cout << " done!" << std::endl; + } +#endif + + // --------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + { + std::cout << "Writing presets.ttl..."; std::cout.flush(); + std::fstream presetsFile("presets.ttl", std::ios::out); + + String presetsString; + presetsString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; + presetsString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n"; +# if DISTRHO_PLUGIN_WANT_STATE + presetsString += "@prefix owl: .\n"; + presetsString += "@prefix rdfs: .\n"; + presetsString += "@prefix state: <" LV2_STATE_PREFIX "> .\n"; + presetsString += "@prefix xsd: .\n"; +# endif + presetsString += "\n"; + + const uint32_t numParameters = plugin.getParameterCount(); + const uint32_t numPrograms = plugin.getProgramCount(); +# if DISTRHO_PLUGIN_WANT_FULL_STATE + const uint32_t numStates = plugin.getStateCount(); + const bool valid = numParameters != 0 || numStates != 0; +# else + const bool valid = numParameters != 0; +# endif + + DISTRHO_CUSTOM_SAFE_ASSERT_RETURN("Programs require parameters or full state", valid, presetsFile.close()); + + const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#"); + + char strBuf[0xff+1]; + strBuf[0xff] = '\0'; + + String presetString; + +# if DISTRHO_PLUGIN_WANT_FULL_STATE + for (uint32_t i=0; i\n"; + presetString += " a owl:DatatypeProperty ;\n"; + presetString += " rdfs:label \"Plugin state key-value string pair\" ;\n"; + presetString += " rdfs:domain state:State ;\n"; + presetString += " rdfs:range xsd:string .\n\n"; + presetsString += presetString; + } +# endif + + for (uint32_t i=0; i\n"; + +# if DISTRHO_PLUGIN_WANT_FULL_STATE + presetString += " state:state [\n"; + for (uint32_t j=0; j"; + + if (value.length() < 10) + presetString += " \"" + value + "\" ;\n"; + else + presetString += "\n\"\"\"" + value + "\"\"\" ;\n"; + } + + if (numParameters > 0) + presetString += " ] ;\n\n"; + else + presetString += " ] .\n\n"; +# endif + + bool firstParameter = true; + + for (uint32_t j=0; j + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static constexpr const writeMidiFunc writeMidiCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +static constexpr const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_STATE +static const updateStateValueFunc updateStateValueCallback = nullptr; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * Stub plugin class, does nothing but serving as example code for other implementations. + */ +class PluginStub +{ +public: + PluginStub() + : fPlugin(this, + writeMidiCallback, + requestParameterValueChangeCallback, + updateStateValueCallback) + { + } + + // ---------------------------------------------------------------------------------------------------------------- + +private: + // Plugin + PluginExporter fPlugin; + + // ---------------------------------------------------------------------------------------------------------------- + // DPF callbacks + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool writeMidi(const MidiEvent&) + { + return true; + } + + static bool writeMidiCallback(void* const ptr, const MidiEvent& midiEvent) + { + return ((PluginStub*)ptr)->writeMidi(midiEvent); + } + #endif + + #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(uint32_t, float) + { + return true; + } + + static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) + { + return ((PluginStub*)ptr)->requestParameterValueChange(index, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + bool updateState(const char*, const char*) + { + return true; + } + + static bool updateStateValueCallback(void* const ptr, const char* const key, const char* const value) + { + return ((PluginStub*)ptr)->updateState(key, value); + } + #endif +}; + +END_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginVST.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginVST.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,386 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_VST_HPP_INCLUDED +#define DISTRHO_PLUGIN_VST_HPP_INCLUDED + +#include "DistrhoPluginChecks.h" +#include "../DistrhoUtils.hpp" + +#include +#include + +#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI +# undef DISTRHO_PLUGIN_HAS_UI +# define DISTRHO_PLUGIN_HAS_UI 0 +#endif + +#if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# undef DISTRHO_PLUGIN_HAS_UI +# define DISTRHO_PLUGIN_HAS_UI 0 +#endif + +#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include "Base.hpp" +#endif + +#if DISTRHO_PLUGIN_HAS_UI == 1 && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS == 0 +# define DPF_VST3_USES_SEPARATE_CONTROLLER 1 +#else +# define DPF_VST3_USES_SEPARATE_CONTROLLER 0 +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# include +#else +// quick and dirty std::atomic replacement for the things we need +namespace std { + struct atomic_int { + volatile int value; + explicit atomic_int(volatile int v) noexcept : value(v) {} + int operator++() volatile noexcept { return __atomic_add_fetch(&value, 1, __ATOMIC_RELAXED); } + int operator--() volatile noexcept { return __atomic_sub_fetch(&value, 1, __ATOMIC_RELAXED); } + operator int() volatile noexcept { return __atomic_load_n(&value, __ATOMIC_RELAXED); } + }; +}; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +enum Vst3InternalParameters { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + kVst3InternalParameterBufferSize, + kVst3InternalParameterSampleRate, + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + kVst3InternalParameterLatency, + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + kVst3InternalParameterProgram, + #endif + kVst3InternalParameterBaseCount, + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + kVst3InternalParameterMidiCC_start = kVst3InternalParameterBaseCount, + kVst3InternalParameterMidiCC_end = kVst3InternalParameterMidiCC_start + 130*16, + kVst3InternalParameterCount = kVst3InternalParameterMidiCC_end + #else + kVst3InternalParameterCount = kVst3InternalParameterBaseCount + #endif +}; + +#if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS || DISTRHO_PLUGIN_WANT_MIDI_INPUT +# define DPF_VST3_HAS_INTERNAL_PARAMETERS 1 +#else +# define DPF_VST3_HAS_INTERNAL_PARAMETERS 0 +#endif + +#if DPF_VST3_HAS_INTERNAL_PARAMETERS && DISTRHO_PLUGIN_WANT_MIDI_INPUT && \ + !(DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS) +# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 1 +#else +# define DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS 0 +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +static inline +bool strcmp_utf16(const int16_t* const str16, const char* const str8) +{ + size_t i = 0; + for (; str8[i] != '\0'; ++i) + { + const uint8_t char8 = static_cast(str8[i]); + + // skip non-ascii chars, unsupported + if (char8 >= 0x80) + return false; + + if (str16[i] != char8) + return false; + } + + return str16[i] == str8[i]; +} + +// -------------------------------------------------------------------------------------------------------------------- + +static inline +size_t strlen_utf16(const int16_t* const str) +{ + size_t i = 0; + + while (str[i] != 0) + ++i; + + return i; +} + +// -------------------------------------------------------------------------------------------------------------------- + +static inline +void strncpy_utf8(char* const dst, const int16_t* const src, const size_t length) +{ + DISTRHO_SAFE_ASSERT_RETURN(length > 0,); + + if (const size_t len = std::min(strlen_utf16(src), length-1U)) + { + for (size_t i=0; i= 0x80) + continue; + + dst[i] = src[i]; + } + dst[len] = 0; + } + else + { + dst[0] = 0; + } +} + +static inline +void strncpy_utf16(int16_t* const dst, const char* const src, const size_t length) +{ + DISTRHO_SAFE_ASSERT_RETURN(length > 0,); + + if (const size_t len = std::min(std::strlen(src), length-1U)) + { + for (size_t i=0; i= 0x80) + continue; + + dst[i] = src[i]; + } + dst[len] = 0; + } + else + { + dst[0] = 0; + } +} + +// -------------------------------------------------------------------------------------------------------------------- + +template +static inline +void snprintf_utf16_t(int16_t* const dst, const T value, const char* const format, const size_t size) +{ + DISTRHO_SAFE_ASSERT_RETURN(size > 0,); + + char* const tmpbuf = (char*)std::malloc(size); + DISTRHO_SAFE_ASSERT_RETURN(tmpbuf != nullptr,); + + std::snprintf(tmpbuf, size-1, format, value); + tmpbuf[size-1] = '\0'; + + strncpy_utf16(dst, tmpbuf, size); + std::free(tmpbuf); +} + +static inline +void snprintf_f32_utf16(int16_t* const dst, const float value, const size_t size) +{ + return snprintf_utf16_t(dst, value, "%f", size); +} + +static inline +void snprintf_f32_utf16(int16_t* const dst, const double value, const size_t size) +{ + return snprintf_utf16_t(dst, value, "%f", size); +} + +static inline +void snprintf_i32_utf16(int16_t* const dst, const int32_t value, const size_t size) +{ + return snprintf_utf16_t(dst, value, "%d", size); +} + +static inline +void snprintf_u32_utf16(int16_t* const dst, const uint32_t value, const size_t size) +{ + return snprintf_utf16_t(dst, value, "%u", size); +} + +#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EXTERNAL_UI +// -------------------------------------------------------------------------------------------------------------------- +// translate a vstgui-based key character and code to matching values used by DPF + +static inline +uint translateVstKeyCode(bool& special, const int16_t keychar, const int16_t keycode) noexcept +{ + using namespace DGL_NAMESPACE; + + // special stuff first + special = true; + switch (keycode) + { + case 1: return kKeyBackspace; + // 2 \t (handled below) + // 3 clear + // 4 \r (handled below) + case 6: return kKeyEscape; + // 7 space (handled below) + // 8 next + // 17 select + // 18 print + // 19 \n (handled below) + // 20 snapshot + case 22: return kKeyDelete; + // 23 help + // 57 = (handled below) + // numpad stuff follows + // 24 0 (handled below) + // 25 1 (handled below) + // 26 2 (handled below) + // 27 3 (handled below) + // 28 4 (handled below) + // 29 5 (handled below) + // 30 6 (handled below) + // 31 7 (handled below) + // 32 8 (handled below) + // 33 9 (handled below) + // 34 * (handled below) + // 35 + (handled below) + // 36 separator + // 37 - (handled below) + // 38 . (handled below) + // 39 / (handled below) + // handle rest of special keys + /* these special keys are missing: + - kKeySuper + - kKeyCapsLock + - kKeyPrintScreen + */ + case 40: return kKeyF1; + case 41: return kKeyF2; + case 42: return kKeyF3; + case 43: return kKeyF4; + case 44: return kKeyF5; + case 45: return kKeyF6; + case 46: return kKeyF7; + case 47: return kKeyF8; + case 48: return kKeyF9; + case 49: return kKeyF10; + case 50: return kKeyF11; + case 51: return kKeyF12; + case 11: return kKeyLeft; + case 12: return kKeyUp; + case 13: return kKeyRight; + case 14: return kKeyDown; + case 15: return kKeyPageUp; + case 16: return kKeyPageDown; + case 10: return kKeyHome; + case 9: return kKeyEnd; + case 21: return kKeyInsert; + case 54: return kKeyShift; + case 55: return kKeyControl; + case 56: return kKeyAlt; + case 58: return kKeyMenu; + case 52: return kKeyNumLock; + case 53: return kKeyScrollLock; + case 5: return kKeyPause; + } + + // regular keys next + special = false; + switch (keycode) + { + case 2: return '\t'; + case 4: return '\r'; + case 7: return ' '; + case 19: return '\n'; + case 57: return '='; + case 24: return '0'; + case 25: return '1'; + case 26: return '2'; + case 27: return '3'; + case 28: return '4'; + case 29: return '5'; + case 30: return '6'; + case 31: return '7'; + case 32: return '8'; + case 33: return '9'; + case 34: return '*'; + case 35: return '+'; + case 37: return '-'; + case 38: return '.'; + case 39: return '/'; + } + + // fallback + return keychar; +} +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// handy way to create a utf16 string from a utf8 one on the current function scope, used for message strings + +struct ScopedUTF16String { + int16_t* str; + ScopedUTF16String(const char* const s) noexcept + : str(nullptr) + { + const size_t len = std::strlen(s); + str = static_cast(std::malloc(sizeof(int16_t) * (len + 1))); + DISTRHO_SAFE_ASSERT_RETURN(str != nullptr,); + strncpy_utf16(str, s, len + 1); + } + + ~ScopedUTF16String() noexcept + { + std::free(str); + } + + operator const int16_t*() const noexcept + { + return str; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- +// handy way to create a utf8 string from a utf16 one on the current function scope (limited to 128 chars) + +struct ScopedUTF8String { + char str[128]; + + ScopedUTF8String(const int16_t* const s) noexcept + { + strncpy_utf8(str, s, 128); + } + + operator const char*() const noexcept + { + return str; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +#endif // DISTRHO_PLUGIN_VST_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginVST2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginVST2.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1734 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" +#include "DistrhoPluginVST.hpp" +#include "../DistrhoPluginUtils.hpp" +#include "../extra/ScopedSafeLocale.hpp" +#include "../extra/ScopedPointer.hpp" + +#if DISTRHO_PLUGIN_HAS_UI +# include "DistrhoUIInternal.hpp" +# include "../extra/RingBuffer.hpp" +#endif + +#include +#include +#include +#include + +#ifndef __cdecl +# define __cdecl +#endif + +#include "xaymar-vst2/vst.h" + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +extern "C" { + +// define the midi stuff ourselves +typedef struct _VstMidiEvent { + int32_t type; + int32_t byteSize; + int32_t deltaFrames; + int32_t _ignore1[3]; + char midiData[4]; + char _ignore2[4]; +} VstMidiEvent; + +typedef union _VstEvent { + int32_t type; + VstMidiEvent midi; // type 1 +} VstEvent; + +typedef struct _HostVstEvents { + int32_t numEvents; + void* reserved; + const VstEvent* events[]; +} HostVstEvents; + +typedef struct _PluginVstEvents { + int32_t numEvents; + void* reserved; + VstEvent* events[1]; +} PluginVstEvents; + +// info from online documentation of VST provided by Steinberg +typedef struct _VstTimeInfo { + double samplePos; + double sampleRate; + double nanoSeconds; + double ppqPos; + double tempo; + double barStartPos; + double cycleStartPos; + double cycleEndPos; + int32_t timeSigNumerator; + int32_t timeSigDenominator; + int32_t smpteOffset; + int32_t smpteFrameRate; + int32_t samplesToNextClock; + int32_t flags; +} VstTimeInfo; + +} + +// -------------------------------------------------------------------------------------------------------------------- + +typedef std::map StringMap; + +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static const writeMidiFunc writeMidiCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +static const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +struct ParameterAndNotesHelper +{ + float* parameterValues; +#if DISTRHO_PLUGIN_HAS_UI + bool* parameterChecks; +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + SmallStackBuffer notesRingBuffer; +# endif +#endif + + ParameterAndNotesHelper() + : parameterValues(nullptr) +#if DISTRHO_PLUGIN_HAS_UI + , parameterChecks(nullptr) +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + , notesRingBuffer(StackBuffer_INIT) +# endif +#endif + { +#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) + std::memset(¬esRingBuffer, 0, sizeof(notesRingBuffer)); +#endif + } + + virtual ~ParameterAndNotesHelper() + { + if (parameterValues != nullptr) + { + delete[] parameterValues; + parameterValues = nullptr; + } +#if DISTRHO_PLUGIN_HAS_UI + if (parameterChecks != nullptr) + { + delete[] parameterChecks; + parameterChecks = nullptr; + } +#endif + } + +#if DISTRHO_PLUGIN_WANT_STATE + virtual void setStateFromUI(const char* key, const char* value) = 0; +#endif +}; + +#if DISTRHO_PLUGIN_HAS_UI +// -------------------------------------------------------------------------------------------------------------------- + +#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static const sendNoteFunc sendNoteCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_STATE +static const setStateFunc setStateCallback = nullptr; +#endif + +class UIVst +{ +public: + UIVst(const vst_host_callback audioMaster, + vst_effect* const effect, + ParameterAndNotesHelper* const uiHelper, + PluginExporter* const plugin, + const intptr_t winId, const float scaleFactor) + : fAudioMaster(audioMaster), + fEffect(effect), + fUiHelper(uiHelper), + fPlugin(plugin), + fUI(this, winId, plugin->getSampleRate(), + editParameterCallback, + setParameterCallback, + setStateCallback, + sendNoteCallback, + setSizeCallback, + nullptr, // TODO file request + d_nextBundlePath, + plugin->getInstancePointer(), + scaleFactor) +# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + , fKeyboardModifiers(0) +# endif +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + , fNotesRingBuffer() +# endif + { +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fNotesRingBuffer.setRingBuffer(&uiHelper->notesRingBuffer, false); +# endif + } + + // ------------------------------------------------------------------- + + void idle() + { + for (uint32_t i=0, count = fPlugin->getParameterCount(); i < count; ++i) + { + if (fUiHelper->parameterChecks[i]) + { + fUiHelper->parameterChecks[i] = false; + fUI.parameterChanged(i, fUiHelper->parameterValues[i]); + } + } + + fUI.plugin_idle(); + } + + int16_t getWidth() const + { + return fUI.getWidth(); + } + + int16_t getHeight() const + { + return fUI.getHeight(); + } + + double getScaleFactor() const + { + return fUI.getScaleFactor(); + } + + void setSampleRate(const double newSampleRate) + { + fUI.setSampleRate(newSampleRate, true); + } + + void notifyScaleFactorChanged(const double scaleFactor) + { + fUI.notifyScaleFactorChanged(scaleFactor); + } + + // ------------------------------------------------------------------- + // functions called from the plugin side, may block + + #if DISTRHO_PLUGIN_WANT_STATE + void setStateFromPlugin(const char* const key, const char* const value) + { + fUI.stateChanged(key, value); + } + #endif + +# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + int handlePluginKeyEvent(const bool down, const int32_t index, const intptr_t value) + { + d_stdout("handlePluginKeyEvent %i %i %li\n", down, index, (long int)value); + + using namespace DGL_NAMESPACE; + + bool special; + const uint key = translateVstKeyCode(special, index, static_cast(value)); + + switch (key) + { + case kKeyShift: + if (down) + fKeyboardModifiers |= kModifierShift; + else + fKeyboardModifiers &= ~kModifierShift; + break; + case kKeyControl: + if (down) + fKeyboardModifiers |= kModifierControl; + else + fKeyboardModifiers &= ~kModifierControl; + break; + case kKeyAlt: + if (down) + fKeyboardModifiers |= kModifierAlt; + else + fKeyboardModifiers &= ~kModifierAlt; + break; + } + + return fUI.handlePluginKeyboardVST(down, special, key, + value >= 0 ? static_cast(value) : 0, + fKeyboardModifiers) ? 1 : 0; + } +# endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + + // ------------------------------------------------------------------- + +protected: + inline intptr_t hostCallback(const VST_HOST_OPCODE opcode, + const int32_t index = 0, + const intptr_t value = 0, + void* const ptr = nullptr, + const float opt = 0.0f) const + { + return fAudioMaster(fEffect, opcode, index, value, ptr, opt); + } + + void editParameter(const uint32_t index, const bool started) const + { + hostCallback(started ? VST_HOST_OPCODE_2B : VST_HOST_OPCODE_2C, index); + } + + void setParameterValue(const uint32_t index, const float realValue) + { + const ParameterRanges& ranges(fPlugin->getParameterRanges(index)); + const float perValue(ranges.getNormalizedValue(realValue)); + + fPlugin->setParameterValue(index, realValue); + hostCallback(VST_HOST_OPCODE_00, index, 0, nullptr, perValue); + } + + void setSize(uint width, uint height) + { +# ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI.getScaleFactor(); + width /= scaleFactor; + height /= scaleFactor; +# endif + hostCallback(VST_HOST_OPCODE_0F, width, height); + } + +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + uint8_t midiData[3]; + midiData[0] = (velocity != 0 ? 0x90 : 0x80) | channel; + midiData[1] = note; + midiData[2] = velocity; + fNotesRingBuffer.writeCustomData(midiData, 3); + fNotesRingBuffer.commitWrite(); + } +# endif + +# if DISTRHO_PLUGIN_WANT_STATE + void setState(const char* const key, const char* const value) + { + fUiHelper->setStateFromUI(key, value); + } +# endif + +private: + // Vst stuff + const vst_host_callback fAudioMaster; + vst_effect* const fEffect; + ParameterAndNotesHelper* const fUiHelper; + PluginExporter* const fPlugin; + + // Plugin UI + UIExporter fUI; +# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + uint16_t fKeyboardModifiers; +# endif +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + RingBufferControl fNotesRingBuffer; +# endif + + // ------------------------------------------------------------------- + // Callbacks + + #define handlePtr ((UIVst*)ptr) + + static void editParameterCallback(void* ptr, uint32_t index, bool started) + { + handlePtr->editParameter(index, started); + } + + static void setParameterCallback(void* ptr, uint32_t rindex, float value) + { + handlePtr->setParameterValue(rindex, value); + } + + static void setSizeCallback(void* ptr, uint width, uint height) + { + handlePtr->setSize(width, height); + } + +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity) + { + handlePtr->sendNote(channel, note, velocity); + } +# endif + +# if DISTRHO_PLUGIN_WANT_STATE + static void setStateCallback(void* ptr, const char* key, const char* value) + { + handlePtr->setState(key, value); + } +# endif + + #undef handlePtr +}; +#endif // DISTRHO_PLUGIN_HAS_UI + +// -------------------------------------------------------------------------------------------------------------------- + +class PluginVst : public ParameterAndNotesHelper +{ +public: + PluginVst(const vst_host_callback audioMaster, vst_effect* const effect) + : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, nullptr), + fAudioMaster(audioMaster), + fEffect(effect) + { + std::memset(fProgramName, 0, sizeof(fProgramName)); + std::strcpy(fProgramName, "Default"); + + const uint32_t parameterCount = fPlugin.getParameterCount(); + + if (parameterCount != 0) + { + parameterValues = new float[parameterCount]; + + for (uint32_t i=0; i < parameterCount; ++i) + parameterValues[i] = NAN; + } + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fMidiEventCount = 0; +#endif + +#if DISTRHO_PLUGIN_HAS_UI + fVstUI = nullptr; + fVstRect.top = 0; + fVstRect.left = 0; + fVstRect.bottom = 0; + fVstRect.right = 0; + fLastScaleFactor = 0.0f; + + if (parameterCount != 0) + { + parameterChecks = new bool[parameterCount]; + memset(parameterChecks, 0, sizeof(bool)*parameterCount); + } + +# if DISTRHO_OS_MAC +# ifdef __LP64__ + fUsingNsView = true; +# else +# ifndef DISTRHO_NO_WARNINGS +# warning 32bit VST UIs on OSX only work if the host supports "hasCockosViewAsConfig" +# endif + fUsingNsView = false; +# endif +# endif // DISTRHO_OS_MAC + +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fNotesRingBuffer.setRingBuffer(¬esRingBuffer, true); +# endif +#endif // DISTRHO_PLUGIN_HAS_UI + +#if DISTRHO_PLUGIN_WANT_STATE + fStateChunk = nullptr; + + for (uint32_t i=0, count=fPlugin.getStateCount(); i(fPlugin.getParameterCount())) + { + const uint32_t hints = fPlugin.getParameterHints(index); + float value = fPlugin.getParameterValue(index); + + if (hints & kParameterIsBoolean) + { + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + const float midRange = ranges.min + (ranges.max - ranges.min) / 2.0f; + + value = value > midRange ? ranges.max : ranges.min; + } + else if (hints & kParameterIsInteger) + { + value = std::round(value); + } + + const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index)); + + for (uint8_t i = 0; i < enumValues.count; ++i) + { + if (d_isNotEqual(value, enumValues.values[i].value)) + continue; + + strncpy((char*)ptr, enumValues.values[i].label.buffer(), 24); + return 1; + } + + if (hints & kParameterIsInteger) + snprintf_i32((char*)ptr, (int32_t)value, 24); + else + snprintf_f32((char*)ptr, value, 24); + + return 1; + } + break; + + case VST_EFFECT_OPCODE_SET_SAMPLE_RATE: + fPlugin.setSampleRate(opt, true); + +#if DISTRHO_PLUGIN_HAS_UI + if (fVstUI != nullptr) + fVstUI->setSampleRate(opt); +#endif + break; + + case VST_EFFECT_OPCODE_SET_BLOCK_SIZE: + fPlugin.setBufferSize(value, true); + break; + + case VST_EFFECT_OPCODE_SUSPEND: + if (value != 0) + { +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fMidiEventCount = 0; + + // tell host we want MIDI events + hostCallback(VST_HOST_OPCODE_06); +#endif + + // deactivate for possible changes + fPlugin.deactivateIfNeeded(); + + // check if something changed + const uint32_t bufferSize = static_cast(hostCallback(VST_HOST_OPCODE_11)); + const double sampleRate = static_cast(hostCallback(VST_HOST_OPCODE_10)); + + if (bufferSize != 0) + fPlugin.setBufferSize(bufferSize, true); + + if (sampleRate != 0.0) + fPlugin.setSampleRate(sampleRate, true); + + fPlugin.activate(); + } + else + { + fPlugin.deactivate(); + } + break; + +#if DISTRHO_PLUGIN_HAS_UI + case VST_EFFECT_OPCODE_WINDOW_GETRECT: + if (fVstUI != nullptr) + { + fVstRect.right = fVstUI->getWidth(); + fVstRect.bottom = fVstUI->getHeight(); +# ifdef DISTRHO_OS_MAC + const double scaleFactor = fVstUI->getScaleFactor(); + fVstRect.right /= scaleFactor; + fVstRect.bottom /= scaleFactor; +# endif + } + else + { + double scaleFactor = fLastScaleFactor; + #if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT) + fVstRect.right = DISTRHO_UI_DEFAULT_WIDTH; + fVstRect.bottom = DISTRHO_UI_DEFAULT_HEIGHT; + if (d_isZero(scaleFactor)) + scaleFactor = 1.0; + #else + UIExporter tmpUI(nullptr, 0, fPlugin.getSampleRate(), + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, d_nextBundlePath, + fPlugin.getInstancePointer(), scaleFactor); + fVstRect.right = tmpUI.getWidth(); + fVstRect.bottom = tmpUI.getHeight(); + scaleFactor = tmpUI.getScaleFactor(); + tmpUI.quit(); + #endif + #ifdef DISTRHO_OS_MAC + fVstRect.right /= scaleFactor; + fVstRect.bottom /= scaleFactor; + #endif + } + *(vst_rect**)ptr = &fVstRect; + return 1; + + case VST_EFFECT_OPCODE_WINDOW_CREATE: + delete fVstUI; // for hosts which don't pair create/destroy calls (Minihost Modular) + fVstUI = nullptr; + + { +# if DISTRHO_OS_MAC + if (! fUsingNsView) + { + d_stderr("Host doesn't support hasCockosViewAsConfig, cannot use UI"); + return 0; + } +# endif + fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr, fLastScaleFactor); + + #if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update current state from plugin side + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + // Set state + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + const String& value = cit->second; + + // TODO skip DSP only states + + fVstUI->setStateFromPlugin(key, value); + } + #endif + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + setParameterValueFromPlugin(i, fPlugin.getParameterValue(i)); + + fVstUI->idle(); + return 1; + } + break; + + case VST_EFFECT_OPCODE_WINDOW_DESTROY: + if (fVstUI != nullptr) + { + delete fVstUI; + fVstUI = nullptr; + return 1; + } + break; + + case VST_EFFECT_OPCODE_13: // window idle + if (fVstUI != nullptr) + fVstUI->idle(); + break; + +# if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + case VST_EFFECT_OPCODE_3B: // key down + if (fVstUI != nullptr) + return fVstUI->handlePluginKeyEvent(true, index, value); + break; + + case VST_EFFECT_OPCODE_3C: // key up + if (fVstUI != nullptr) + return fVstUI->handlePluginKeyEvent(false, index, value); + break; +# endif +#endif // DISTRHO_PLUGIN_HAS_UI + +#if DISTRHO_PLUGIN_WANT_STATE + case VST_EFFECT_OPCODE_17: // get chunk + { + if (ptr == nullptr) + return 0; + + if (fStateChunk != nullptr) + { + delete[] fStateChunk; + fStateChunk = nullptr; + } + + const uint32_t paramCount = fPlugin.getParameterCount(); + + if (fPlugin.getStateCount() == 0 && paramCount == 0) + { + fStateChunk = new char[1]; + fStateChunk[0] = '\0'; + ret = 1; + } + else + { +# if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update current state + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } +# endif + + String chunkStr; + + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + const String& value = cit->second; + + // join key and value + String tmpStr; + tmpStr = key; + tmpStr += "\xff"; + tmpStr += value; + tmpStr += "\xff"; + + chunkStr += tmpStr; + } + + if (paramCount != 0) + { + // add another separator + chunkStr += "\xff"; + + for (uint32_t i=0; i(value); + + const char* key = (const char*)ptr; + const char* value = nullptr; + size_t size, bytesRead = 0; + + while (bytesRead < chunkSize) + { + if (key[0] == '\0') + break; + + size = std::strlen(key)+1; + value = key + size; + bytesRead += size; + + setStateFromUI(key, value); + +# if DISTRHO_PLUGIN_HAS_UI + if (fVstUI != nullptr) + { + // TODO skip DSP only states + fVstUI->setStateFromPlugin(key, value); + } +# endif + + // get next key + size = std::strlen(value)+1; + key = value + size; + bytesRead += size; + } + + const uint32_t paramCount = fPlugin.getParameterCount(); + + if (bytesRead+4 < chunkSize && paramCount != 0) + { + ++key; + float fvalue; + + // temporarily set locale to "C" while converting floats + const ScopedSafeLocale ssl; + + while (bytesRead < chunkSize) + { + if (key[0] == '\0') + break; + + size = std::strlen(key)+1; + value = key + size; + bytesRead += size; + + // find parameter with this symbol, and set its value + for (uint32_t i=0; inumEvents == 0) + break; + + for (int i=0, count=events->numEvents; i < count; ++i) + { + const VstEvent* const vstEvent = events->events[i]; + + if (vstEvent == nullptr) + break; + if (vstEvent->type != 1) + continue; + if (fMidiEventCount >= kMaxMidiEvents) + break; + + const VstMidiEvent& vstMidiEvent(events->events[i]->midi); + + MidiEvent& midiEvent(fMidiEvents[fMidiEventCount++]); + midiEvent.frame = vstMidiEvent.deltaFrames; + midiEvent.size = 3; + std::memcpy(midiEvent.data, vstMidiEvent.midiData, sizeof(uint8_t)*3); + } + } + break; +#endif + + case VST_EFFECT_OPCODE_PARAM_ISAUTOMATABLE: + if (index < static_cast(fPlugin.getParameterCount())) + { + const uint32_t hints(fPlugin.getParameterHints(index)); + + // must be automatable, and not output + if ((hints & kParameterIsAutomatable) != 0 && (hints & kParameterIsOutput) == 0) + return 1; + } + break; + + case VST_EFFECT_OPCODE_SUPPORTS: + if (const char* const canDo = (const char*)ptr) + { +#if DISTRHO_OS_MAC && DISTRHO_PLUGIN_HAS_UI + if (std::strcmp(canDo, "hasCockosViewAsConfig") == 0) + { + fUsingNsView = true; + return 0xbeef0000; + } +#endif +#ifndef DISTRHO_OS_MAC + if (std::strcmp(canDo, "supportsViewDpiScaling") == 0) + return 1; +#endif + if (std::strcmp(canDo, "receiveVstEvents") == 0 || + std::strcmp(canDo, "receiveVstMidiEvent") == 0) +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + return 1; +#else + return -1; +#endif + if (std::strcmp(canDo, "sendVstEvents") == 0 || + std::strcmp(canDo, "sendVstMidiEvent") == 0) +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + return 1; +#else + return -1; +#endif + if (std::strcmp(canDo, "receiveVstTimeInfo") == 0) +#if DISTRHO_PLUGIN_WANT_TIMEPOS + return 1; +#else + return -1; +#endif + if (std::strcmp(canDo, "offline") == 0) + return -1; + } + break; + + case VST_EFFECT_OPCODE_CUSTOM: +#if DISTRHO_PLUGIN_HAS_UI && !defined(DISTRHO_OS_MAC) + if (index == d_cconst('P', 'r', 'e', 'S') && value == d_cconst('A', 'e', 'C', 's')) + { + if (d_isEqual(fLastScaleFactor, opt)) + break; + + fLastScaleFactor = opt; + + if (fVstUI != nullptr) + fVstUI->notifyScaleFactorChanged(opt); + } +#endif + break; + + //case effStartProcess: + //case effStopProcess: + // unused + // break; + } + + return 0; + } + + float vst_getParameter(const uint32_t index) + { + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + return ranges.getNormalizedValue(fPlugin.getParameterValue(index)); + } + + void vst_setParameter(const uint32_t index, const float value) + { + const uint32_t hints = fPlugin.getParameterHints(index); + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + + // TODO figure out how to detect kVstParameterUsesIntegerMinMax host support, and skip normalization + float realValue = ranges.getUnnormalizedValue(value); + + if (hints & kParameterIsBoolean) + { + const float midRange = ranges.min + (ranges.max - ranges.min) / 2.0f; + realValue = realValue > midRange ? ranges.max : ranges.min; + } + + if (hints & kParameterIsInteger) + { + realValue = std::round(realValue); + } + + fPlugin.setParameterValue(index, realValue); + +#if DISTRHO_PLUGIN_HAS_UI + if (fVstUI != nullptr) + setParameterValueFromPlugin(index, realValue); +#endif + } + + void vst_processReplacing(const float** const inputs, float** const outputs, const int32_t sampleFrames) + { + if (! fPlugin.isActive()) + { + // host has not activated the plugin yet, nasty! + vst_dispatcher(VST_EFFECT_OPCODE_SUSPEND, 0, 1, nullptr, 0.0f); + } + + if (sampleFrames <= 0) + { + updateParameterOutputsAndTriggers(); + return; + } + +#if DISTRHO_PLUGIN_WANT_TIMEPOS + static constexpr const int kWantVstTimeFlags = 0x2602; + + if (const VstTimeInfo* const vstTimeInfo = (const VstTimeInfo*)hostCallback(VST_HOST_OPCODE_07, 0, kWantVstTimeFlags)) + { + fTimePosition.frame = vstTimeInfo->samplePos; + fTimePosition.playing = vstTimeInfo->flags & 0x2; + + // ticksPerBeat is not possible with VST2 + fTimePosition.bbt.ticksPerBeat = 1920.0; + + if (vstTimeInfo->flags & 0x400) + fTimePosition.bbt.beatsPerMinute = vstTimeInfo->tempo; + else + fTimePosition.bbt.beatsPerMinute = 120.0; + + if ((vstTimeInfo->flags & 0x2200) == 0x2200) + { + const double ppqPos = std::abs(vstTimeInfo->ppqPos); + const int ppqPerBar = vstTimeInfo->timeSigNumerator * 4 / vstTimeInfo->timeSigDenominator; + const double barBeats = (std::fmod(ppqPos, ppqPerBar) / ppqPerBar) * vstTimeInfo->timeSigNumerator; + const double rest = std::fmod(barBeats, 1.0); + + fTimePosition.bbt.valid = true; + fTimePosition.bbt.bar = static_cast(ppqPos) / ppqPerBar + 1; + fTimePosition.bbt.beat = static_cast(barBeats - rest + 0.5) + 1; + fTimePosition.bbt.tick = rest * fTimePosition.bbt.ticksPerBeat; + fTimePosition.bbt.beatsPerBar = vstTimeInfo->timeSigNumerator; + fTimePosition.bbt.beatType = vstTimeInfo->timeSigDenominator; + + if (vstTimeInfo->ppqPos < 0.0) + { + --fTimePosition.bbt.bar; + fTimePosition.bbt.beat = vstTimeInfo->timeSigNumerator - fTimePosition.bbt.beat + 1; + fTimePosition.bbt.tick = fTimePosition.bbt.ticksPerBeat - fTimePosition.bbt.tick - 1; + } + } + else + { + fTimePosition.bbt.valid = false; + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0.0; + fTimePosition.bbt.beatsPerBar = 4.0f; + fTimePosition.bbt.beatType = 4.0f; + } + + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat* + fTimePosition.bbt.beatsPerBar* + (fTimePosition.bbt.bar-1); + + fPlugin.setTimePosition(fTimePosition); + } +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT +# if DISTRHO_PLUGIN_HAS_UI + if (fMidiEventCount != kMaxMidiEvents && fNotesRingBuffer.isDataAvailableForReading()) + { + uint8_t midiData[3]; + uint32_t frame = fMidiEventCount != 0 ? fMidiEvents[fMidiEventCount-1].frame : 0; + + while (fNotesRingBuffer.isDataAvailableForReading()) + { + if (! fNotesRingBuffer.readCustomData(midiData, 3)) + break; + + MidiEvent& midiEvent(fMidiEvents[fMidiEventCount++]); + midiEvent.frame = frame; + midiEvent.size = 3; + std::memcpy(midiEvent.data, midiData, 3); + + if (fMidiEventCount == kMaxMidiEvents) + break; + } + } +# endif + + fPlugin.run(inputs, outputs, sampleFrames, fMidiEvents, fMidiEventCount); + fMidiEventCount = 0; +#else + fPlugin.run(inputs, outputs, sampleFrames); +#endif + + updateParameterOutputsAndTriggers(); + } + + // ------------------------------------------------------------------- + + friend class UIVst; + +private: + // Plugin + PluginExporter fPlugin; + + // VST stuff + const vst_host_callback fAudioMaster; + vst_effect* const fEffect; + + // Temporary data + char fProgramName[32]; + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + uint32_t fMidiEventCount; + MidiEvent fMidiEvents[kMaxMidiEvents]; +#endif + +#if DISTRHO_PLUGIN_WANT_TIMEPOS + TimePosition fTimePosition; +#endif + + // UI stuff +#if DISTRHO_PLUGIN_HAS_UI + UIVst* fVstUI; + vst_rect fVstRect; + float fLastScaleFactor; +# if DISTRHO_OS_MAC + bool fUsingNsView; +# endif +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT + RingBufferControl fNotesRingBuffer; +# endif +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + char* fStateChunk; + StringMap fStateMap; +#endif + + // ------------------------------------------------------------------- + // host callback + + intptr_t hostCallback(const VST_HOST_OPCODE opcode, + const int32_t index = 0, + const intptr_t value = 0, + void* const ptr = nullptr, + const float opt = 0.0f) + { + return fAudioMaster(fEffect, opcode, index, value, ptr, opt); + } + + // ------------------------------------------------------------------- + // functions called from the plugin side, RT no block + + void updateParameterOutputsAndTriggers() + { + float curValue; + + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) + { + if (fPlugin.isParameterOutput(i)) + { + // NOTE: no output parameter support in VST2, simulate it here + curValue = fPlugin.getParameterValue(i); + + if (d_isEqual(curValue, parameterValues[i])) + continue; + +#if DISTRHO_PLUGIN_HAS_UI + if (fVstUI != nullptr) + setParameterValueFromPlugin(i, curValue); + else +#endif + parameterValues[i] = curValue; + +#ifndef DPF_VST_SHOW_PARAMETER_OUTPUTS + // skip automating parameter outputs from plugin if we disable them on VST + continue; +#endif + } + else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger) + { + // NOTE: no trigger support in VST parameters, simulate it here + curValue = fPlugin.getParameterValue(i); + + if (d_isEqual(curValue, fPlugin.getParameterRanges(i).def)) + continue; + +#if DISTRHO_PLUGIN_HAS_UI + if (fVstUI != nullptr) + setParameterValueFromPlugin(i, curValue); +#endif + fPlugin.setParameterValue(i, curValue); + } + else + { + continue; + } + + const ParameterRanges& ranges(fPlugin.getParameterRanges(i)); + hostCallback(VST_HOST_OPCODE_00, i, 0, nullptr, ranges.getNormalizedValue(curValue)); + } + + #if DISTRHO_PLUGIN_WANT_LATENCY + fEffect->delay = fPlugin.getLatency(); + #endif + } + +#if DISTRHO_PLUGIN_HAS_UI + void setParameterValueFromPlugin(const uint32_t index, const float realValue) + { + parameterValues[index] = realValue; + parameterChecks[index] = true; + } +#endif + +#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(const uint32_t index, const float value) + { + hostCallback(VST_HOST_OPCODE_00, index, 0, nullptr, value); + return true; + } + + static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) + { + return ((PluginVst*)ptr)->requestParameterValueChange(index, value); + } +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool writeMidi(const MidiEvent& midiEvent) + { + if (midiEvent.size > 4) + return true; + + PluginVstEvents vstEvents = {}; + VstMidiEvent vstMidiEvent = {}; + + vstEvents.numEvents = 1; + vstEvents.events[0] = (VstEvent*)&vstMidiEvent; + + vstMidiEvent.type = 1; + vstMidiEvent.byteSize = static_cast(sizeof(VstMidiEvent));; + vstMidiEvent.deltaFrames = midiEvent.frame; + + for (uint8_t i=0; iwriteMidi(midiEvent); + } +#endif + +#if DISTRHO_PLUGIN_WANT_STATE + // ------------------------------------------------------------------- + // functions called from the UI side, may block + +# if DISTRHO_PLUGIN_HAS_UI + void setStateFromUI(const char* const key, const char* const value) override +# else + void setStateFromUI(const char* const key, const char* const value) +# endif + { + fPlugin.setState(key, value); + + // check if we want to save this key + if (! fPlugin.wantStateKey(key)) + return; + + // check if key already exists + for (StringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it) + { + const String& dkey(it->first); + + if (dkey == key) + { + it->second = value; + return; + } + } + + d_stderr("Failed to find plugin state with key \"%s\"", key); + } +#endif +}; + +// -------------------------------------------------------------------------------------------------------------------- + +struct ExtendedAEffect : vst_effect { + char _padding[63]; + char valid; + vst_host_callback audioMaster; + PluginVst* pluginPtr; +}; + +static ScopedPointer sPlugin; + +static struct Cleanup { + std::vector effects; + + ~Cleanup() + { + for (std::vector::iterator it = effects.begin(), end = effects.end(); it != end; ++it) + { + ExtendedAEffect* const exteffect = *it; + delete exteffect->pluginPtr; + delete exteffect; + } + + sPlugin = nullptr; + } +} sCleanup; + +// -------------------------------------------------------------------------------------------------------------------- + +static inline +ExtendedAEffect* getExtendedEffect(vst_effect* const effect) +{ + if (effect == nullptr) + return nullptr; + + ExtendedAEffect* const exteffect = static_cast(effect); + DISTRHO_SAFE_ASSERT_RETURN(exteffect->valid == 101, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(exteffect->audioMaster != nullptr, nullptr); + + return exteffect; +} + +static inline +PluginVst* getEffectPlugin(vst_effect* const effect) +{ + if (effect == nullptr) + return nullptr; + + ExtendedAEffect* const exteffect = static_cast(effect); + DISTRHO_SAFE_ASSERT_RETURN(exteffect->valid == 101, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(exteffect->audioMaster != nullptr, nullptr); + + return exteffect->pluginPtr; +} + +// -------------------------------------------------------------------------------------------------------------------- + +static intptr_t VST_FUNCTION_INTERFACE vst_dispatcherCallback(vst_effect* const effect, + const VST_EFFECT_OPCODE opcode, + const int32_t index, + const intptr_t value, + void* const ptr, + const float opt) +{ + // handle base opcodes + switch (opcode) + { + case VST_EFFECT_OPCODE_CREATE: + if (ExtendedAEffect* const exteffect = getExtendedEffect(effect)) + { + // some hosts call open/create twice + if (exteffect->pluginPtr != nullptr) + return 1; + + const vst_host_callback audioMaster = exteffect->audioMaster; + + d_nextBufferSize = audioMaster(effect, VST_HOST_OPCODE_11, 0, 0, nullptr, 0.0f); + d_nextSampleRate = audioMaster(effect, VST_HOST_OPCODE_10, 0, 0, nullptr, 0.0f); + d_nextCanRequestParameterValueChanges = true; + + // some hosts are not ready at this point or return 0 buffersize/samplerate + if (d_nextBufferSize == 0) + d_nextBufferSize = 2048; + if (d_nextSampleRate <= 0.0) + d_nextSampleRate = 44100.0; + + exteffect->pluginPtr = new PluginVst(audioMaster, effect); + return 1; + } + return 0; + + case VST_EFFECT_OPCODE_DESTROY: + if (ExtendedAEffect* const exteffect = getExtendedEffect(effect)) + { + // delete plugin object + if (exteffect->pluginPtr != nullptr) + { + delete exteffect->pluginPtr; + exteffect->pluginPtr = nullptr; + } + + // delete effect too, if it comes from us + const std::vector::iterator it = std::find(sCleanup.effects.begin(), sCleanup.effects.end(), exteffect); + if (it != sCleanup.effects.end()) + { + delete exteffect; + sCleanup.effects.erase(it); + } + + // delete global plugin instance too if this is the last loaded effect + if (sCleanup.effects.empty()) + sPlugin = nullptr; + return 1; + } + return 0; + + case VST_EFFECT_OPCODE_PARAM_GETLABEL: + if (ptr != nullptr && index < static_cast(sPlugin->getParameterCount())) + { + d_strncpy((char*)ptr, sPlugin->getParameterUnit(index), 8); + return 1; + } + return 0; + + case VST_EFFECT_OPCODE_PARAM_GETNAME: + if (ptr != nullptr && index < static_cast(sPlugin->getParameterCount())) + { + const String& shortName(sPlugin->getParameterShortName(index)); + if (shortName.isNotEmpty()) + d_strncpy((char*)ptr, shortName, 16); + else + d_strncpy((char*)ptr, sPlugin->getParameterName(index), 16); + return 1; + } + return 0; + + case VST_EFFECT_OPCODE_38: // FIXME VST_EFFECT_OPCODE_GET_PARAMETER_PROPERTIES is wrong by 1 + if (ptr != nullptr && index < static_cast(sPlugin->getParameterCount())) + { + if (vst_parameter_properties* const properties = (vst_parameter_properties*)ptr) + { + memset(properties, 0, sizeof(vst_parameter_properties)); + + // full name + d_strncpy(properties->name, + sPlugin->getParameterName(index), + sizeof(properties->name)); + + // short name + const String& shortName(sPlugin->getParameterShortName(index)); + + if (shortName.isNotEmpty()) + d_strncpy(properties->label, + sPlugin->getParameterShortName(index), + sizeof(properties->label)); + + // parameter hints + const uint32_t hints = sPlugin->getParameterHints(index); + + if (hints & kParameterIsOutput) + return 1; + + if (hints & kParameterIsBoolean) + { + properties->flags |= VST_PARAMETER_FLAGS_SWITCH; + } + + if (hints & kParameterIsInteger) + { + const ParameterRanges& ranges(sPlugin->getParameterRanges(index)); + properties->flags |= VST_PARAMETER_FLAGS_INTEGER_LIMITS; + properties->min_value_i32 = static_cast(ranges.min); + properties->max_value_i32 = static_cast(ranges.max); + } + + if (hints & kParameterIsLogarithmic) + { + properties->flags |= VST_PARAMETER_FLAGS_UNKNOWN6; // can ramp + } + + // parameter group (category in vst) + const uint32_t groupId = sPlugin->getParameterGroupId(index); + + if (groupId != kPortGroupNone) + { + // we can't use groupId directly, so use the index array where this group is stored in + for (uint32_t i=0, count=sPlugin->getPortGroupCount(); i < count; ++i) + { + const PortGroupWithId& portGroup(sPlugin->getPortGroupByIndex(i)); + + if (portGroup.groupId == groupId) + { + properties->flags |= VST_PARAMETER_FLAGS_CATEGORY; + properties->category = i + 1; + d_strncpy(properties->category_label, + portGroup.name.buffer(), + sizeof(properties->category_label)); + break; + } + } + + if (properties->category != 0) + { + for (uint32_t i=0, count=sPlugin->getParameterCount(); i < count; ++i) + if (sPlugin->getParameterGroupId(i) == groupId) + ++properties->num_parameters_in_category; + } + } + + return 1; + } + } + return 0; + + case VST_EFFECT_OPCODE_EFFECT_CATEGORY: + #if DISTRHO_PLUGIN_IS_SYNTH + return VST_CATEGORY_02; + #else + return VST_CATEGORY_01; + #endif + + case VST_EFFECT_OPCODE_EFFECT_NAME: + if (char* const cptr = (char*)ptr) + { + d_strncpy(cptr, sPlugin->getName(), 32); + return 1; + } + return 0; + + case VST_EFFECT_OPCODE_VENDOR_NAME: + if (char* const cptr = (char*)ptr) + { + d_strncpy(cptr, sPlugin->getMaker(), 32); + return 1; + } + return 0; + + case VST_EFFECT_OPCODE_PRODUCT_NAME: + if (char* const cptr = (char*)ptr) + { + d_strncpy(cptr, sPlugin->getLabel(), 32); + return 1; + } + return 0; + + case VST_EFFECT_OPCODE_VENDOR_VERSION: + return sPlugin->getVersion(); + + case VST_EFFECT_OPCODE_VST_VERSION: + return VST_VERSION_2_4_0_0; + + default: + break; + } + + // handle advanced opcodes + if (PluginVst* const pluginPtr = getEffectPlugin(effect)) + return pluginPtr->vst_dispatcher(opcode, index, value, ptr, opt); + + return 0; +} + +static float VST_FUNCTION_INTERFACE vst_getParameterCallback(vst_effect* const effect, + const uint32_t index) +{ + if (PluginVst* const pluginPtr = getEffectPlugin(effect)) + return pluginPtr->vst_getParameter(index); + return 0.0f; +} + +static void VST_FUNCTION_INTERFACE vst_setParameterCallback(vst_effect* const effect, + const uint32_t index, + const float value) +{ + if (PluginVst* const pluginPtr = getEffectPlugin(effect)) + pluginPtr->vst_setParameter(index, value); +} + +static void VST_FUNCTION_INTERFACE vst_processCallback(vst_effect* const effect, + const float* const* const inputs, + float** const outputs, + const int32_t sampleFrames) +{ + if (PluginVst* const pluginPtr = getEffectPlugin(effect)) + pluginPtr->vst_processReplacing(const_cast(inputs), outputs, sampleFrames); +} + +static void VST_FUNCTION_INTERFACE vst_processReplacingCallback(vst_effect* const effect, + const float* const* const inputs, + float** const outputs, + const int32_t sampleFrames) +{ + if (PluginVst* const pluginPtr = getEffectPlugin(effect)) + pluginPtr->vst_processReplacing(const_cast(inputs), outputs, sampleFrames); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +DISTRHO_PLUGIN_EXPORT +#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WASM) || defined(DISTRHO_OS_WINDOWS) +const vst_effect* VSTPluginMain(vst_host_callback audioMaster); +#else +const vst_effect* VSTPluginMain(vst_host_callback audioMaster) asm ("main"); +#endif + +DISTRHO_PLUGIN_EXPORT +const vst_effect* VSTPluginMain(const vst_host_callback audioMaster) +{ + USE_NAMESPACE_DISTRHO + + // old version + if (audioMaster(nullptr, VST_HOST_OPCODE_01 /* version */, 0, 0, nullptr, 0.0f) == 0) + return nullptr; + + // find plugin bundle + static String bundlePath; + if (bundlePath.isEmpty()) + { + String tmpPath(getBinaryFilename()); + tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP)); + #ifdef DISTRHO_OS_MAC + if (tmpPath.endsWith("/MacOS")) + { + tmpPath.truncate(tmpPath.rfind('/')); + if (tmpPath.endsWith("/Contents")) + { + tmpPath.truncate(tmpPath.rfind('/')); + bundlePath = tmpPath; + d_nextBundlePath = bundlePath.buffer(); + } + } + #else + if (tmpPath.endsWith(".vst")) + { + bundlePath = tmpPath; + d_nextBundlePath = bundlePath.buffer(); + } + #endif + } + + // first internal init + if (sPlugin == nullptr) + { + // set valid but dummy values + d_nextBufferSize = 512; + d_nextSampleRate = 44100.0; + d_nextPluginIsDummy = true; + d_nextCanRequestParameterValueChanges = true; + + // Create dummy plugin to get data from + sPlugin = new PluginExporter(nullptr, nullptr, nullptr, nullptr); + + // unset + d_nextBufferSize = 0; + d_nextSampleRate = 0.0; + d_nextPluginIsDummy = false; + d_nextCanRequestParameterValueChanges = false; + } + + ExtendedAEffect* const effect = new ExtendedAEffect; + std::memset(effect, 0, sizeof(ExtendedAEffect)); + + // vst fields + #ifdef WORDS_BIGENDIAN + effect->magic_number = 0x50747356; + #else + effect->magic_number = 0x56737450; + #endif + effect->unique_id = sPlugin->getUniqueId(); + effect->version = sPlugin->getVersion(); + + // VST doesn't support parameter outputs. we can fake them, but it is a hack. Disabled by default. +#ifdef DPF_VST_SHOW_PARAMETER_OUTPUTS + const int numParams = sPlugin->getParameterCount(); +#else + int numParams = 0; + bool outputsReached = false; + + for (uint32_t i=0, count=sPlugin->getParameterCount(); i < count; ++i) + { + if (sPlugin->isParameterInput(i)) + { + // parameter outputs must be all at the end + DISTRHO_SAFE_ASSERT_BREAK(! outputsReached); + ++numParams; + continue; + } + outputsReached = true; + } +#endif + + // plugin fields + effect->num_params = numParams; + effect->num_programs = 1; + effect->num_inputs = DISTRHO_PLUGIN_NUM_INPUTS; + effect->num_outputs = DISTRHO_PLUGIN_NUM_OUTPUTS; + + // plugin flags + effect->flags |= 1 << 4; // uses process_float + #if DISTRHO_PLUGIN_IS_SYNTH + effect->flags |= 1 << 8; + #endif + #if DISTRHO_PLUGIN_HAS_UI + effect->flags |= 1 << 0; + #endif + #if DISTRHO_PLUGIN_WANT_STATE + effect->flags |= 1 << 5; + #endif + + // static calls + effect->control = vst_dispatcherCallback; + effect->process = vst_processCallback; + effect->get_parameter = vst_getParameterCallback; + effect->set_parameter = vst_setParameterCallback; + effect->process_float = vst_processReplacingCallback; + + // special values + effect->valid = 101; + effect->audioMaster = audioMaster; + effect->pluginPtr = nullptr; + + // done + sCleanup.effects.push_back(effect); + + return effect; +} + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginVST3.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginVST3.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4979 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* TODO items: + * == parameters + * - test parameter triggers + * - have parameter outputs host-provided UI working in at least 1 host + * - parameter groups via unit ids + * - test parameter changes from DSP (aka requestParameterValueChange) + * - implement getParameterNormalized/setParameterNormalized for MIDI CC params ? + * - float to int safe casting + * - verify that latency changes works (with and without DPF_VST3_USES_SEPARATE_CONTROLLER) + * == MIDI + * - MIDI CC changes (need to store value to give to the host?) + * - MIDI program changes + * - MIDI sysex + * == BUSES + * - routing info, do we care? + * == CV + * - cv scaling to -1/+1 + * - test in at least 1 host + * == INFO + * - set factory email (needs new DPF API, useful for LV2 as well) + * - do something with set_io_mode? + */ + +#include "DistrhoPluginInternal.hpp" +#include "../DistrhoPluginUtils.hpp" +#include "../extra/ScopedPointer.hpp" + +#define DPF_VST3_MAX_BUFFER_SIZE 32768 +#define DPF_VST3_MAX_SAMPLE_RATE 384000 +#define DPF_VST3_MAX_LATENCY DPF_VST3_MAX_SAMPLE_RATE * 10 + +#if DISTRHO_PLUGIN_HAS_UI +# include "../extra/RingBuffer.hpp" +#endif + +#include "travesty/audio_processor.h" +#include "travesty/component.h" +#include "travesty/edit_controller.h" +#include "travesty/factory.h" +#include "travesty/host.h" + +#include +#include +#include + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static constexpr const writeMidiFunc writeMidiCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +static constexpr const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr; +#endif + +typedef std::map StringMap; + +// -------------------------------------------------------------------------------------------------------------------- +// custom v3_tuid compatible type + +typedef uint32_t dpf_tuid[4]; +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +static_assert(sizeof(v3_tuid) == sizeof(dpf_tuid), "uid size mismatch"); +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// custom, constant uids related to DPF + +static constexpr const uint32_t dpf_id_entry = d_cconst('D', 'P', 'F', ' '); +static constexpr const uint32_t dpf_id_clas = d_cconst('c', 'l', 'a', 's'); +static constexpr const uint32_t dpf_id_comp = d_cconst('c', 'o', 'm', 'p'); +static constexpr const uint32_t dpf_id_ctrl = d_cconst('c', 't', 'r', 'l'); +static constexpr const uint32_t dpf_id_proc = d_cconst('p', 'r', 'o', 'c'); +static constexpr const uint32_t dpf_id_view = d_cconst('v', 'i', 'e', 'w'); + +// -------------------------------------------------------------------------------------------------------------------- +// plugin specific uids (values are filled in during plugin init) + +static dpf_tuid dpf_tuid_class = { dpf_id_entry, dpf_id_clas, 0, 0 }; +static dpf_tuid dpf_tuid_component = { dpf_id_entry, dpf_id_comp, 0, 0 }; +static dpf_tuid dpf_tuid_controller = { dpf_id_entry, dpf_id_ctrl, 0, 0 }; +static dpf_tuid dpf_tuid_processor = { dpf_id_entry, dpf_id_proc, 0, 0 }; +static dpf_tuid dpf_tuid_view = { dpf_id_entry, dpf_id_view, 0, 0 }; + +// -------------------------------------------------------------------------------------------------------------------- +// Utility functions + +const char* tuid2str(const v3_tuid iid) +{ + static constexpr const struct { + v3_tuid iid; + const char* name; + } extra_known_iids[] = { + { V3_ID(0x00000000,0x00000000,0x00000000,0x00000000), "(nil)" }, + // edit-controller + { V3_ID(0xF040B4B3,0xA36045EC,0xABCDC045,0xB4D5A2CC), "{v3_component_handler2|NOT}" }, + { V3_ID(0x7F4EFE59,0xF3204967,0xAC27A3AE,0xAFB63038), "{v3_edit_controller2|NOT}" }, + { V3_ID(0x067D02C1,0x5B4E274D,0xA92D90FD,0x6EAF7240), "{v3_component_handler_bus_activation|NOT}" }, + { V3_ID(0xC1271208,0x70594098,0xB9DD34B3,0x6BB0195E), "{v3_edit_controller_host_editing|NOT}" }, + { V3_ID(0xB7F8F859,0x41234872,0x91169581,0x4F3721A3), "{v3_edit_controller_note_expression_controller|NOT}" }, + // units + { V3_ID(0x8683B01F,0x7B354F70,0xA2651DEC,0x353AF4FF), "{v3_program_list_data|NOT}" }, + { V3_ID(0x6C389611,0xD391455D,0xB870B833,0x94A0EFDD), "{v3_unit_data|NOT}" }, + { V3_ID(0x4B5147F8,0x4654486B,0x8DAB30BA,0x163A3C56), "{v3_unit_handler|NOT}" }, + { V3_ID(0xF89F8CDF,0x699E4BA5,0x96AAC9A4,0x81452B01), "{v3_unit_handler2|NOT}" }, + { V3_ID(0x3D4BD6B5,0x913A4FD2,0xA886E768,0xA5EB92C1), "{v3_unit_info|NOT}" }, + // misc + { V3_ID(0x309ECE78,0xEB7D4FAE,0x8B2225D9,0x09FD08B6), "{v3_audio_presentation_latency|NOT}" }, + { V3_ID(0xB4E8287F,0x1BB346AA,0x83A46667,0x68937BAB), "{v3_automation_state|NOT}" }, + { V3_ID(0x0F194781,0x8D984ADA,0xBBA0C1EF,0xC011D8D0), "{v3_info_listener|NOT}" }, + { V3_ID(0x6D21E1DC,0x91199D4B,0xA2A02FEF,0x6C1AE55C), "{v3_parameter_function_name|NOT}" }, + { V3_ID(0x8AE54FDA,0xE93046B9,0xA28555BC,0xDC98E21E), "{v3_prefetchable_support|NOT}" }, + { V3_ID(0xA81A0471,0x48C34DC4,0xAC30C9E1,0x3C8393D5), "{v3_xml_representation_stream|NOT}" }, + /* + // seen in the wild but unknown, related to component + { V3_ID(0x6548D671,0x997A4EA5,0x9B336A6F,0xB3E93B50), "{v3_|NOT}" }, + { V3_ID(0xC2B7896B,0x069844D5,0x8F06E937,0x33A35FF7), "{v3_|NOT}" }, + { V3_ID(0xE123DE93,0xE0F642A4,0xAE53867E,0x53F059EE), "{v3_|NOT}" }, + { V3_ID(0x83850D7B,0xC12011D8,0xA143000A,0x959B31C6), "{v3_|NOT}" }, + { V3_ID(0x9598D418,0xA00448AC,0x9C6D8248,0x065B2E5C), "{v3_|NOT}" }, + { V3_ID(0xBD386132,0x45174BAD,0xA324390B,0xFD297506), "{v3_|NOT}" }, + { V3_ID(0xD7296A84,0x23B1419C,0xAAD0FAA3,0x53BB16B7), "{v3_|NOT}" }, + { V3_ID(0x181A0AF6,0xA10947BA,0x8A6F7C7C,0x3FF37129), "{v3_|NOT}" }, + { V3_ID(0xC2B7896B,0x69A844D5,0x8F06E937,0x33A35FF7), "{v3_|NOT}" }, + // seen in the wild but unknown, related to edit controller + { V3_ID(0x1F2F76D3,0xBFFB4B96,0xB99527A5,0x5EBCCEF4), "{v3_|NOT}" }, + { V3_ID(0x6B2449CC,0x419740B5,0xAB3C79DA,0xC5FE5C86), "{v3_|NOT}" }, + { V3_ID(0x67800560,0x5E784D90,0xB97BAB4C,0x8DC5BAA3), "{v3_|NOT}" }, + { V3_ID(0xDB51DA00,0x8FD5416D,0xB84894D8,0x7FDE73E4), "{v3_|NOT}" }, + { V3_ID(0xE90FC54F,0x76F24235,0x8AF8BD15,0x68C663D6), "{v3_|NOT}" }, + { V3_ID(0x07938E89,0xBA0D4CA8,0x8C7286AB,0xA9DDA95B), "{v3_|NOT}" }, + { V3_ID(0x42879094,0xA2F145ED,0xAC90E82A,0x99458870), "{v3_|NOT}" }, + { V3_ID(0xC3B17BC0,0x2C174494,0x80293402,0xFBC4BBF8), "{v3_|NOT}" }, + { V3_ID(0x31E29A7A,0xE55043AD,0x8B95B9B8,0xDA1FBE1E), "{v3_|NOT}" }, + { V3_ID(0x8E3C292C,0x95924F9D,0xB2590B1E,0x100E4198), "{v3_|NOT}" }, + { V3_ID(0x50553FD9,0x1D2C4C24,0xB410F484,0xC5FB9F3F), "{v3_|NOT}" }, + { V3_ID(0xF185556C,0x5EE24FC7,0x92F28754,0xB7759EA8), "{v3_|NOT}" }, + { V3_ID(0xD2CE9317,0xF24942C9,0x9742E82D,0xB10CCC52), "{v3_|NOT}" }, + { V3_ID(0xDA57E6D1,0x1F3242D1,0xAD9C1A82,0xFDB95695), "{v3_|NOT}" }, + { V3_ID(0x3ABDFC3E,0x4B964A66,0xFCD86F10,0x0D554023), "{v3_|NOT}" }, + // seen in the wild but unknown, related to view + { V3_ID(0xAA3E50FF,0xB78840EE,0xADCD48E8,0x094CEDB7), "{v3_|NOT}" }, + { V3_ID(0x2CAE14DB,0x4DE04C6E,0x8BD2E611,0x1B31A9C2), "{v3_|NOT}" }, + { V3_ID(0xD868D61D,0x20F445F4,0x947D069E,0xC811D1E4), "{v3_|NOT}" }, + { V3_ID(0xEE49E3CA,0x6FCB44FB,0xAEBEE6C3,0x48625122), "{v3_|NOT}" }, + */ + }; + + if (v3_tuid_match(iid, v3_audio_processor_iid)) + return "{v3_audio_processor}"; + if (v3_tuid_match(iid, v3_attribute_list_iid)) + return "{v3_attribute_list_iid}"; + if (v3_tuid_match(iid, v3_bstream_iid)) + return "{v3_bstream}"; + if (v3_tuid_match(iid, v3_component_iid)) + return "{v3_component}"; + if (v3_tuid_match(iid, v3_component_handler_iid)) + return "{v3_component_handler}"; + if (v3_tuid_match(iid, v3_connection_point_iid)) + return "{v3_connection_point_iid}"; + if (v3_tuid_match(iid, v3_edit_controller_iid)) + return "{v3_edit_controller}"; + if (v3_tuid_match(iid, v3_event_handler_iid)) + return "{v3_event_handler_iid}"; + if (v3_tuid_match(iid, v3_event_list_iid)) + return "{v3_event_list}"; + if (v3_tuid_match(iid, v3_funknown_iid)) + return "{v3_funknown}"; + if (v3_tuid_match(iid, v3_host_application_iid)) + return "{v3_host_application_iid}"; + if (v3_tuid_match(iid, v3_message_iid)) + return "{v3_message_iid}"; + if (v3_tuid_match(iid, v3_midi_mapping_iid)) + return "{v3_midi_mapping_iid}"; + if (v3_tuid_match(iid, v3_param_value_queue_iid)) + return "{v3_param_value_queue}"; + if (v3_tuid_match(iid, v3_param_changes_iid)) + return "{v3_param_changes}"; + if (v3_tuid_match(iid, v3_plugin_base_iid)) + return "{v3_plugin_base}"; + if (v3_tuid_match(iid, v3_plugin_factory_iid)) + return "{v3_plugin_factory}"; + if (v3_tuid_match(iid, v3_plugin_factory_2_iid)) + return "{v3_plugin_factory_2}"; + if (v3_tuid_match(iid, v3_plugin_factory_3_iid)) + return "{v3_plugin_factory_3}"; + if (v3_tuid_match(iid, v3_plugin_frame_iid)) + return "{v3_plugin_frame}"; + if (v3_tuid_match(iid, v3_plugin_view_iid)) + return "{v3_plugin_view}"; + if (v3_tuid_match(iid, v3_plugin_view_content_scale_iid)) + return "{v3_plugin_view_content_scale_iid}"; + if (v3_tuid_match(iid, v3_plugin_view_parameter_finder_iid)) + return "{v3_plugin_view_parameter_finder}"; + if (v3_tuid_match(iid, v3_process_context_requirements_iid)) + return "{v3_process_context_requirements}"; + if (v3_tuid_match(iid, v3_run_loop_iid)) + return "{v3_run_loop_iid}"; + if (v3_tuid_match(iid, v3_timer_handler_iid)) + return "{v3_timer_handler_iid}"; + + if (std::memcmp(iid, dpf_tuid_class, sizeof(dpf_tuid)) == 0) + return "{dpf_tuid_class}"; + if (std::memcmp(iid, dpf_tuid_component, sizeof(dpf_tuid)) == 0) + return "{dpf_tuid_component}"; + if (std::memcmp(iid, dpf_tuid_controller, sizeof(dpf_tuid)) == 0) + return "{dpf_tuid_controller}"; + if (std::memcmp(iid, dpf_tuid_processor, sizeof(dpf_tuid)) == 0) + return "{dpf_tuid_processor}"; + if (std::memcmp(iid, dpf_tuid_view, sizeof(dpf_tuid)) == 0) + return "{dpf_tuid_view}"; + + for (size_t i=0; inext) + { + MidiEvent& midiEvent(midiEvents[count++]); + midiEvent.frame = event->sampleOffset; + + const InputEventStorage& eventStorage(*event->storage); + + switch (eventStorage.type) + { + case NoteOn: + midiEvent.size = 3; + midiEvent.data[0] = 0x90 | (eventStorage.noteOn.channel & 0xf); + midiEvent.data[1] = eventStorage.noteOn.pitch; + midiEvent.data[2] = std::max(0, std::min(127, (int)(eventStorage.noteOn.velocity * 127))); + midiEvent.data[3] = 0; + break; + case NoteOff: + midiEvent.size = 3; + midiEvent.data[0] = 0x80 | (eventStorage.noteOff.channel & 0xf); + midiEvent.data[1] = eventStorage.noteOff.pitch; + midiEvent.data[2] = std::max(0, std::min(127, (int)(eventStorage.noteOff.velocity * 127))); + midiEvent.data[3] = 0; + break; + /* TODO + case SysexData: + break; + */ + case PolyPressure: + midiEvent.size = 3; + midiEvent.data[0] = 0xA0 | (eventStorage.polyPressure.channel & 0xf); + midiEvent.data[1] = eventStorage.polyPressure.pitch; + midiEvent.data[2] = std::max(0, std::min(127, (int)(eventStorage.polyPressure.pressure * 127))); + midiEvent.data[3] = 0; + break; + case CC_Normal: + midiEvent.size = 3; + midiEvent.data[0] = 0xB0 | (eventStorage.midi[0] & 0xf); + midiEvent.data[1] = eventStorage.midi[1]; + midiEvent.data[2] = eventStorage.midi[2]; + break; + case CC_ChannelPressure: + midiEvent.size = 2; + midiEvent.data[0] = 0xD0 | (eventStorage.midi[0] & 0xf); + midiEvent.data[1] = eventStorage.midi[1]; + midiEvent.data[2] = 0; + break; + case CC_Pitchbend: + midiEvent.size = 3; + midiEvent.data[0] = 0xE0 | (eventStorage.midi[0] & 0xf); + midiEvent.data[1] = eventStorage.midi[1]; + midiEvent.data[2] = eventStorage.midi[2]; + break; + case UI_MIDI: + midiEvent.size = 3; + midiEvent.data[0] = eventStorage.midi[0]; + midiEvent.data[1] = eventStorage.midi[1]; + midiEvent.data[2] = eventStorage.midi[2]; + break; + default: + midiEvent.size = 0; + break; + } + } + + return count; + } + + bool appendEvent(const v3_event& event) noexcept + { + // only save events that can be converted directly into MIDI + switch (event.type) + { + case V3_EVENT_NOTE_ON: + case V3_EVENT_NOTE_OFF: + // case V3_EVENT_DATA: + case V3_EVENT_POLY_PRESSURE: + break; + default: + return false; + } + + InputEventStorage& eventStorage(eventListStorage[numUsed]); + + switch (event.type) + { + case V3_EVENT_NOTE_ON: + eventStorage.type = NoteOn; + eventStorage.noteOn = event.note_on; + break; + case V3_EVENT_NOTE_OFF: + eventStorage.type = NoteOff; + eventStorage.noteOff = event.note_off; + break; + case V3_EVENT_DATA: + eventStorage.type = SysexData; + eventStorage.sysexData = event.data; + break; + case V3_EVENT_POLY_PRESSURE: + eventStorage.type = PolyPressure; + eventStorage.polyPressure = event.poly_pressure; + break; + default: + return false; + } + + eventList[numUsed].sampleOffset = event.sample_offset; + eventList[numUsed].storage = &eventStorage; + + return placeSorted(event.sample_offset); + } + + bool appendCC(const int32_t sampleOffset, v3_param_id paramId, const double normalized) noexcept + { + InputEventStorage& eventStorage(eventListStorage[numUsed]); + + paramId -= kVst3InternalParameterMidiCC_start; + + const uint8_t cc = paramId % 130; + + switch (cc) + { + case 128: + eventStorage.type = CC_ChannelPressure; + eventStorage.midi[1] = std::max(0, std::min(127, (int)(normalized * 127))); + eventStorage.midi[2] = 0; + break; + case 129: + eventStorage.type = CC_Pitchbend; + eventStorage.midi[1] = std::max(0, std::min(16384, (int)(normalized * 16384))) & 0x7f; + eventStorage.midi[2] = std::max(0, std::min(16384, (int)(normalized * 16384))) >> 7; + break; + default: + eventStorage.type = CC_Normal; + eventStorage.midi[1] = cc; + eventStorage.midi[2] = std::max(0, std::min(127, (int)(normalized * 127))); + break; + } + + eventStorage.midi[0] = paramId / 130; + + eventList[numUsed].sampleOffset = sampleOffset; + eventList[numUsed].storage = &eventStorage; + + return placeSorted(sampleOffset); + } + + #if DISTRHO_PLUGIN_HAS_UI + // NOTE always runs first + bool appendFromUI(const uint8_t midiData[3]) + { + InputEventStorage& eventStorage(eventListStorage[numUsed]); + + eventStorage.type = UI_MIDI; + std::memcpy(eventStorage.midi, midiData, sizeof(uint8_t)*3); + + InputEvent* const event = &eventList[numUsed]; + + event->sampleOffset = 0; + event->storage = &eventStorage; + event->next = nullptr; + + if (numUsed == 0) + { + firstEvent = lastEvent = event; + } + else + { + lastEvent->next = event; + lastEvent = event; + } + + return ++numUsed == kMaxMidiEvents; + } + #endif + + private: + bool placeSorted(const int32_t sampleOffset) noexcept + { + InputEvent* const event = &eventList[numUsed]; + + // initialize + if (numUsed == 0) + { + firstSampleOffset = lastSampleOffset = sampleOffset; + firstEvent = lastEvent = event; + event->next = nullptr; + } + // push to the back + else if (sampleOffset >= lastSampleOffset) + { + lastSampleOffset = sampleOffset; + lastEvent->next = event; + lastEvent = event; + event->next = nullptr; + } + // push to the front + else if (sampleOffset < firstSampleOffset) + { + firstSampleOffset = sampleOffset; + event->next = firstEvent; + firstEvent = event; + } + // find place in between events + else + { + // keep reference out of the loop so we can check validity afterwards + InputEvent* event2 = firstEvent; + + // iterate all events + for (; event2 != nullptr; event2 = event2->next) + { + // if offset is higher than iterated event, stop and insert in-between + if (sampleOffset > event2->sampleOffset) + break; + + // if offset matches, find the last event with the same offset so we can push after it + if (sampleOffset == event2->sampleOffset) + { + event2 = event2->next; + for (; event2 != nullptr && sampleOffset == event2->sampleOffset; event2 = event2->next) {} + break; + } + } + + DISTRHO_SAFE_ASSERT_RETURN(event2 != nullptr, true); + + event->next = event2->next; + event2->next = event; + } + + return ++numUsed == kMaxMidiEvents; + } + } inputEventList; + #endif // DISTRHO_PLUGIN_WANT_MIDI_INPUT + +public: + PluginVst3(v3_host_application** const host, const bool isComponent) + : fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, nullptr), + fComponentHandler(nullptr), + #if DISTRHO_PLUGIN_HAS_UI + #if DPF_VST3_USES_SEPARATE_CONTROLLER + fConnectionFromCompToCtrl(nullptr), + #endif + fConnectionFromCtrlToView(nullptr), + fHostApplication(host), + #endif + fParameterCount(fPlugin.getParameterCount()), + fVst3ParameterCount(fParameterCount + kVst3InternalParameterCount), + fCachedParameterValues(nullptr), + fDummyAudioBuffer(nullptr), + fParameterValuesChangedDuringProcessing(nullptr) + #if DPF_VST3_USES_SEPARATE_CONTROLLER + , fIsComponent(isComponent) + #endif + #if DISTRHO_PLUGIN_HAS_UI + , fParameterValueChangesForUI(nullptr) + , fConnectedToUI(false) + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + , fLastKnownLatency(fPlugin.getLatency()) + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + , fHostEventOutputHandle(nullptr) + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + , fCurrentProgram(0) + , fProgramCountMinusOne(fPlugin.getProgramCount()-1) + #endif + { + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + DISTRHO_SAFE_ASSERT(isComponent); + #endif + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + std::memset(fEnabledInputs, 0, sizeof(fEnabledInputs)); + fillInBusInfoDetails(); + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + std::memset(fEnabledOutputs, 0, sizeof(fEnabledOutputs)); + fillInBusInfoDetails(); + #endif + + if (const uint32_t extraParameterCount = fParameterCount + kVst3InternalParameterBaseCount) + { + fCachedParameterValues = new float[extraParameterCount]; + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + fCachedParameterValues[kVst3InternalParameterBufferSize] = fPlugin.getBufferSize(); + fCachedParameterValues[kVst3InternalParameterSampleRate] = fPlugin.getSampleRate(); + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + fCachedParameterValues[kVst3InternalParameterLatency] = fLastKnownLatency; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + fCachedParameterValues[kVst3InternalParameterProgram] = 0.0f; + #endif + + for (uint32_t i=0; i < fParameterCount; ++i) + fCachedParameterValues[kVst3InternalParameterBaseCount + i] = fPlugin.getParameterDefault(i); + + fParameterValuesChangedDuringProcessing = new bool[extraParameterCount]; + std::memset(fParameterValuesChangedDuringProcessing, 0, sizeof(bool)*extraParameterCount); + + #if DISTRHO_PLUGIN_HAS_UI + fParameterValueChangesForUI = new bool[extraParameterCount]; + std::memset(fParameterValueChangesForUI, 0, sizeof(bool)*extraParameterCount); + #endif + } + + #if DISTRHO_PLUGIN_WANT_STATE + for (uint32_t i=0, count=fPlugin.getStateCount(); i midRange; + + if (isHigh == (fCachedParameterValues[kVst3InternalParameterBaseCount + index] > midRange)) + return; + + value = isHigh ? ranges.max : ranges.min; + } + else if (hints & kParameterIsInteger) + { + const int ivalue = static_cast(std::round(value)); + + if (static_cast(fCachedParameterValues[kVst3InternalParameterBaseCount + index]) == ivalue) + return; + + value = ivalue; + } + else + { + // deal with low resolution of some hosts, which convert double to float internally and lose precision + if (std::abs(ranges.getNormalizedValue(static_cast(fCachedParameterValues[kVst3InternalParameterBaseCount + index])) - normalized) < 0.0000001) + return; + } + + fCachedParameterValues[kVst3InternalParameterBaseCount + index] = value; + + #if DISTRHO_PLUGIN_HAS_UI + #if DPF_VST3_USES_SEPARATE_CONTROLLER + if (!fIsComponent) + #endif + { + fParameterValueChangesForUI[kVst3InternalParameterBaseCount + index] = true; + } + #endif + + if (!fPlugin.isParameterOutputOrTrigger(index)) + fPlugin.setParameterValue(index, value); + } + + // ---------------------------------------------------------------------------------------------------------------- + // stuff called for UI creation + + void* getInstancePointer() const noexcept + { + return fPlugin.getInstancePointer(); + } + + double getSampleRate() const noexcept + { + return fPlugin.getSampleRate(); + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_component interface calls + + int32_t getBusCount(const int32_t mediaType, const int32_t busDirection) const noexcept + { + switch (mediaType) + { + case V3_AUDIO: + if (busDirection == V3_INPUT) + return inputBuses.audio + inputBuses.sidechain + inputBuses.groups + inputBuses.cvPorts; + if (busDirection == V3_OUTPUT) + return outputBuses.audio + outputBuses.sidechain + outputBuses.groups + outputBuses.cvPorts; + break; + case V3_EVENT: + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (busDirection == V3_INPUT) + return 1; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if (busDirection == V3_OUTPUT) + return 1; + #endif + break; + } + + return 0; + } + + v3_result getBusInfo(const int32_t mediaType, + const int32_t busDirection, + const int32_t busIndex, + v3_bus_info* const info) const + { + DISTRHO_SAFE_ASSERT_INT_RETURN(mediaType == V3_AUDIO || mediaType == V3_EVENT, mediaType, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_INT_RETURN(busDirection == V3_INPUT || busDirection == V3_OUTPUT, busDirection, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_INT_RETURN(busIndex >= 0, busIndex, V3_INVALID_ARG); + + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 || DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + const uint32_t busId = static_cast(busIndex); + #endif + + if (mediaType == V3_AUDIO) + { + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (busDirection == V3_INPUT) + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return getAudioBusInfo(busId, info); + #else + d_stderr("invalid input bus %d", busId); + return V3_INVALID_ARG; + #endif // DISTRHO_PLUGIN_NUM_INPUTS + } + else + { + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + return getAudioBusInfo(busId, info); + #else + d_stderr("invalid output bus %d", busId); + return V3_INVALID_ARG; + #endif // DISTRHO_PLUGIN_NUM_OUTPUTS + } + #else + d_stderr("invalid bus, line %d", __LINE__); + return V3_INVALID_ARG; + #endif // DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS + } + else + { + if (busDirection == V3_INPUT) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + DISTRHO_SAFE_ASSERT_RETURN(busId == 0, V3_INVALID_ARG); + #else + d_stderr("invalid bus, line %d", __LINE__); + return V3_INVALID_ARG; + #endif + } + else + { + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + DISTRHO_SAFE_ASSERT_RETURN(busId == 0, V3_INVALID_ARG); + #else + d_stderr("invalid bus, line %d", __LINE__); + return V3_INVALID_ARG; + #endif + } + info->media_type = V3_EVENT; + info->direction = busDirection; + info->channel_count = 1; + strncpy_utf16(info->bus_name, busDirection == V3_INPUT ? "Event/MIDI Input" + : "Event/MIDI Output", 128); + info->bus_type = V3_MAIN; + info->flags = V3_DEFAULT_ACTIVE; + return V3_OK; + } + } + + v3_result getRoutingInfo(v3_routing_info*, v3_routing_info*) + { + /* + output->media_type = V3_AUDIO; + output->bus_idx = 0; + output->channel = -1; + d_stdout("getRoutingInfo %s %d %d", + v3_media_type_str(input->media_type), input->bus_idx, input->channel); + */ + return V3_NOT_IMPLEMENTED; + } + + v3_result activateBus(const int32_t mediaType, + const int32_t busDirection, + const int32_t busIndex, + const bool state) noexcept + { + DISTRHO_SAFE_ASSERT_INT_RETURN(busDirection == V3_INPUT || busDirection == V3_OUTPUT, busDirection, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_INT_RETURN(busIndex >= 0, busIndex, V3_INVALID_ARG); + + if (mediaType == V3_AUDIO) + { + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + const uint32_t busId = static_cast(busIndex); + + if (busDirection == V3_INPUT) + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + for (uint32_t i=0; i 0 + for (uint32_t i=0; iread(stream, buffer, sizeof(buffer)-1, &read); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(read > 0, read, V3_INTERNAL_ERR); + + if (read == 0) + return V3_OK; + + for (int32_t i = 0; i < read; ++i) + { + // found terminator, stop here + if (buffer[i] == '\xfe') + { + terminated = 1; + break; + } + + // store character at read position + orig = buffer[read]; + + // place null character to create valid string + buffer[read] = '\0'; + + // append to temporary vars + if (fillingKey) + { + key += buffer + i; + } + else + { + value += buffer + i; + hasValue = true; + } + + // increase buffer offset by length of string + i += std::strlen(buffer + i); + + // restore read character + buffer[read] = orig; + + // if buffer offset points to null, we found the end of a string, lets check + if (buffer[i] == '\0') + { + // special keys + if (key == "__dpf_state_begin__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'i' || queryingType == 'n', + queryingType, V3_INTERNAL_ERR); + queryingType = 's'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + if (key == "__dpf_state_end__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 's', queryingType, V3_INTERNAL_ERR); + queryingType = 'n'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + if (key == "__dpf_parameters_begin__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'i' || queryingType == 'n', + queryingType, V3_INTERNAL_ERR); + queryingType = 'p'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + if (key == "__dpf_parameters_end__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'p', queryingType, V3_INTERNAL_ERR); + queryingType = 'x'; + key.clear(); + value.clear(); + hasValue = false; + continue; + } + + // no special key, swap between reading real key and value + fillingKey = !fillingKey; + + // if there is no value yet keep reading until we have one + if (! hasValue) + continue; + + if (key == "__dpf_program__") + { + DISTRHO_SAFE_ASSERT_INT_RETURN(queryingType == 'i', queryingType, V3_INTERNAL_ERR); + queryingType = 'n'; + + d_debug("found program '%s'", value.buffer()); + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + const int program = std::atoi(value.buffer()); + DISTRHO_SAFE_ASSERT_CONTINUE(program >= 0); + + fCurrentProgram = static_cast(program); + fPlugin.loadProgram(fCurrentProgram); + + #if DISTRHO_PLUGIN_HAS_UI + if (connectedToUI) + { + fParameterValueChangesForUI[kVst3InternalParameterProgram] = false; + sendParameterSetToUI(kVst3InternalParameterProgram, program); + } + #endif + #endif + } + else if (queryingType == 's') + { + d_debug("found state '%s' '%s'", key.buffer(), value.buffer()); + + #if DISTRHO_PLUGIN_WANT_STATE + if (fPlugin.wantStateKey(key)) + { + fStateMap[key] = value; + fPlugin.setState(key, value); + + #if DISTRHO_PLUGIN_HAS_UI + if (connectedToUI) + sendStateSetToUI(key, value); + #endif + } + #endif + } + else if (queryingType == 'p') + { + d_debug("found parameter '%s' '%s'", key.buffer(), value.buffer()); + float fvalue; + + // find parameter with this symbol, and set its value + for (uint32_t j=0; j < fParameterCount; ++j) + { + if (fPlugin.isParameterOutputOrTrigger(j)) + continue; + if (fPlugin.getParameterSymbol(j) != key) + continue; + + if (fPlugin.getParameterHints(j) & kParameterIsInteger) + fvalue = std::atoi(value.buffer()); + else + fvalue = std::atof(value.buffer()); + + fCachedParameterValues[kVst3InternalParameterBaseCount + j] = fvalue; + #if DISTRHO_PLUGIN_HAS_UI + if (connectedToUI) + { + // UI parameter updates are handled outside the read loop (after host param restart) + fParameterValueChangesForUI[kVst3InternalParameterBaseCount + j] = true; + } + #endif + fPlugin.setParameterValue(j, fvalue); + break; + } + } + + key.clear(); + value.clear(); + hasValue = false; + } + } + } + + if (fComponentHandler != nullptr) + v3_cpp_obj(fComponentHandler)->restart_component(fComponentHandler, V3_RESTART_PARAM_VALUES_CHANGED); + + #if DISTRHO_PLUGIN_HAS_UI + if (connectedToUI) + { + for (uint32_t i=0; iwrite(stream, &buffer, 1, &ignored); + } + + #if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update current state + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } + #endif + + String state; + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + { + String tmpStr("__dpf_program__\xff"); + tmpStr += String(fCurrentProgram); + tmpStr += "\xff"; + + state += tmpStr; + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + if (stateCount != 0) + { + state += "__dpf_state_begin__\xff"; + + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + const String& value = cit->second; + + // join key and value + String tmpStr; + tmpStr = key; + tmpStr += "\xff"; + tmpStr += value; + tmpStr += "\xff"; + + state += tmpStr; + } + + state += "__dpf_state_end__\xff"; + } + #endif + + if (paramCount != 0) + { + state += "__dpf_parameters_begin__\xff"; + + for (uint32_t i=0; i(std::round(fPlugin.getParameterValue(i)))); + else + tmpStr += String(fPlugin.getParameterValue(i)); + tmpStr += "\xff"; + + state += tmpStr; + } + + state += "__dpf_parameters_end__\xff"; + } + + // terminator + state += "\xfe"; + + state.replace('\xff', '\0'); + + // now saving state, carefully until host written bytes matches full state size + const char* buffer = state.buffer(); + const int32_t size = static_cast(state.length())+1; + v3_result res; + + for (int32_t wrtntotal = 0, wrtn; wrtntotal < size; wrtntotal += wrtn) + { + wrtn = 0; + res = v3_cpp_obj(stream)->write(stream, const_cast(buffer), size - wrtntotal, &wrtn); + + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(wrtn > 0, wrtn, V3_INTERNAL_ERR); + } + + return V3_OK; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_audio_processor interface calls + + v3_result setBusArrangements(v3_speaker_arrangement* const inputs, const int32_t numInputs, + v3_speaker_arrangement* const outputs, const int32_t numOutputs) + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + DISTRHO_SAFE_ASSERT_RETURN(numInputs >= 0, V3_INVALID_ARG); + if (!setAudioBusArrangement(inputs, static_cast(numInputs))) + return V3_INTERNAL_ERR; + #else + DISTRHO_SAFE_ASSERT_RETURN(numInputs == 0, V3_INVALID_ARG); + // unused + (void)inputs; + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + DISTRHO_SAFE_ASSERT_RETURN(numOutputs >= 0, V3_INVALID_ARG); + if (!setAudioBusArrangement(outputs, static_cast(numOutputs))) + return V3_INTERNAL_ERR; + #else + DISTRHO_SAFE_ASSERT_RETURN(numOutputs == 0, V3_INVALID_ARG); + // unused + (void)outputs; + #endif + + return V3_OK; + } + + v3_result getBusArrangement(const int32_t busDirection, const int32_t busIndex, v3_speaker_arrangement* const speaker) const noexcept + { + DISTRHO_SAFE_ASSERT_INT_RETURN(busDirection == V3_INPUT || busDirection == V3_OUTPUT, busDirection, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_INT_RETURN(busIndex >= 0, busIndex, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_RETURN(speaker != nullptr, V3_INVALID_ARG); + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 || DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + const uint32_t busId = static_cast(busIndex); + #endif + + if (busDirection == V3_INPUT) + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (getAudioBusArrangement(busId, speaker)) + return V3_OK; + #endif + d_stderr("invalid input bus arrangement %d, line %d", busIndex, __LINE__); + return V3_INVALID_ARG; + } + else + { + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (getAudioBusArrangement(busId, speaker)) + return V3_OK; + #endif + d_stderr("invalid output bus arrangement %d, line %d", busIndex, __LINE__); + return V3_INVALID_ARG; + } + } + + uint32_t getLatencySamples() const noexcept + { + #if DISTRHO_PLUGIN_WANT_LATENCY + return fPlugin.getLatency(); + #else + return 0; + #endif + } + + v3_result setupProcessing(v3_process_setup* const setup) + { + DISTRHO_SAFE_ASSERT_RETURN(setup->symbolic_sample_size == V3_SAMPLE_32, V3_INVALID_ARG); + + const bool active = fPlugin.isActive(); + fPlugin.deactivateIfNeeded(); + + // TODO process_mode can be V3_REALTIME, V3_PREFETCH, V3_OFFLINE + + fPlugin.setSampleRate(setup->sample_rate, true); + fPlugin.setBufferSize(setup->max_block_size, true); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + fCachedParameterValues[kVst3InternalParameterBufferSize] = setup->max_block_size; + fParameterValuesChangedDuringProcessing[kVst3InternalParameterBufferSize] = true; + + fCachedParameterValues[kVst3InternalParameterSampleRate] = setup->sample_rate; + fParameterValuesChangedDuringProcessing[kVst3InternalParameterSampleRate] = true; + #if DISTRHO_PLUGIN_HAS_UI + fParameterValueChangesForUI[kVst3InternalParameterSampleRate] = true; + #endif + #endif + + if (active) + fPlugin.activate(); + + delete[] fDummyAudioBuffer; + fDummyAudioBuffer = new float[setup->max_block_size]; + + return V3_OK; + } + + v3_result setProcessing(const bool processing) + { + if (processing) + { + if (! fPlugin.isActive()) + fPlugin.activate(); + } + else + { + fPlugin.deactivateIfNeeded(); + } + + return V3_OK; + } + + v3_result process(v3_process_data* const data) + { + DISTRHO_SAFE_ASSERT_RETURN(data->symbolic_sample_size == V3_SAMPLE_32, V3_INVALID_ARG); + // d_debug("process %i", data->symbolic_sample_size); + + // activate plugin if not done yet + if (! fPlugin.isActive()) + fPlugin.activate(); + + #if DISTRHO_PLUGIN_WANT_TIMEPOS + if (v3_process_context* const ctx = data->ctx) + { + fTimePosition.playing = ctx->state & V3_PROCESS_CTX_PLAYING; + + // ticksPerBeat is not possible with VST3 + fTimePosition.bbt.ticksPerBeat = 1920.0; + + if (ctx->state & V3_PROCESS_CTX_PROJECT_TIME_VALID) + fTimePosition.frame = ctx->project_time_in_samples; + else if (ctx->state & V3_PROCESS_CTX_CONT_TIME_VALID) + fTimePosition.frame = ctx->continuous_time_in_samples; + + if (ctx->state & V3_PROCESS_CTX_TEMPO_VALID) + fTimePosition.bbt.beatsPerMinute = ctx->bpm; + else + fTimePosition.bbt.beatsPerMinute = 120.0; + + if ((ctx->state & (V3_PROCESS_CTX_PROJECT_TIME_VALID|V3_PROCESS_CTX_TIME_SIG_VALID)) == (V3_PROCESS_CTX_PROJECT_TIME_VALID|V3_PROCESS_CTX_TIME_SIG_VALID)) + { + const double ppqPos = std::abs(ctx->project_time_quarters); + const int ppqPerBar = ctx->time_sig_numerator * 4 / ctx->time_sig_denom; + const double barBeats = (std::fmod(ppqPos, ppqPerBar) / ppqPerBar) * ctx->time_sig_numerator; + const double rest = std::fmod(barBeats, 1.0); + + fTimePosition.bbt.valid = true; + fTimePosition.bbt.bar = static_cast(ppqPos) / ppqPerBar + 1; + fTimePosition.bbt.beat = static_cast(barBeats - rest + 0.5) + 1; + fTimePosition.bbt.tick = rest * fTimePosition.bbt.ticksPerBeat; + fTimePosition.bbt.beatsPerBar = ctx->time_sig_numerator; + fTimePosition.bbt.beatType = ctx->time_sig_denom; + + if (ctx->project_time_quarters < 0.0) + { + --fTimePosition.bbt.bar; + fTimePosition.bbt.beat = ctx->time_sig_numerator - fTimePosition.bbt.beat + 1; + fTimePosition.bbt.tick = fTimePosition.bbt.ticksPerBeat - fTimePosition.bbt.tick - 1; + } + } + else + { + fTimePosition.bbt.valid = false; + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0.0; + fTimePosition.bbt.beatsPerBar = 4.0f; + fTimePosition.bbt.beatType = 4.0f; + } + + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat* + fTimePosition.bbt.beatsPerBar* + (fTimePosition.bbt.bar-1); + + fPlugin.setTimePosition(fTimePosition); + } + #endif + + if (data->nframes <= 0) + { + updateParametersFromProcessing(data->output_params, 0); + return V3_OK; + } + + const float* inputs[DISTRHO_PLUGIN_NUM_INPUTS != 0 ? DISTRHO_PLUGIN_NUM_INPUTS : 1]; + /* */ float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS != 0 ? DISTRHO_PLUGIN_NUM_OUTPUTS : 1]; + + std::memset(fDummyAudioBuffer, 0, sizeof(float)*data->nframes); + + { + int32_t i = 0; + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (data->inputs != nullptr) + { + for (int32_t b = 0; b < data->num_input_buses; ++b) { + for (int32_t j = 0; j < data->inputs[b].num_channels; ++j) + { + DISTRHO_SAFE_ASSERT_INT_BREAK(i < DISTRHO_PLUGIN_NUM_INPUTS, i); + if (!fEnabledInputs[i] && i < DISTRHO_PLUGIN_NUM_INPUTS) { + inputs[i++] = fDummyAudioBuffer; + continue; + } + + inputs[i++] = data->inputs[b].channel_buffers_32[j]; + } + } + } + #endif + for (; i < std::max(1, DISTRHO_PLUGIN_NUM_INPUTS); ++i) + inputs[i] = fDummyAudioBuffer; + } + + { + int32_t i = 0; + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (data->outputs != nullptr) + { + for (int32_t b = 0; b < data->num_output_buses; ++b) { + for (int32_t j = 0; j < data->outputs[b].num_channels; ++j) + { + DISTRHO_SAFE_ASSERT_INT_BREAK(i < DISTRHO_PLUGIN_NUM_OUTPUTS, i); + if (!fEnabledOutputs[i] && i < DISTRHO_PLUGIN_NUM_OUTPUTS) { + outputs[i++] = fDummyAudioBuffer; + continue; + } + + outputs[i++] = data->outputs[b].channel_buffers_32[j]; + } + } + } + #endif + for (; i < std::max(1, DISTRHO_PLUGIN_NUM_OUTPUTS); ++i) + outputs[i] = fDummyAudioBuffer; + } + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + fHostEventOutputHandle = data->output_events; + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + bool canAppendMoreEvents = true; + inputEventList.init(); + + #if DISTRHO_PLUGIN_HAS_UI + while (fNotesRingBuffer.isDataAvailableForReading()) + { + uint8_t midiData[3]; + if (! fNotesRingBuffer.readCustomData(midiData, 3)) + break; + + if (inputEventList.appendFromUI(midiData)) + { + canAppendMoreEvents = false; + break; + } + } + #endif + + if (canAppendMoreEvents) + { + if (v3_event_list** const eventptr = data->input_events) + { + v3_event event; + for (uint32_t i = 0, count = v3_cpp_obj(eventptr)->get_event_count(eventptr); i < count; ++i) + { + if (v3_cpp_obj(eventptr)->get_event(eventptr, i, &event) != V3_OK) + break; + + if (inputEventList.appendEvent(event)) + { + canAppendMoreEvents = false; + break; + } + } + } + } + #endif + + if (v3_param_changes** const inparamsptr = data->input_params) + { + int32_t offset; + double normalized; + + for (int32_t i = 0, count = v3_cpp_obj(inparamsptr)->get_param_count(inparamsptr); i < count; ++i) + { + v3_param_value_queue** const queue = v3_cpp_obj(inparamsptr)->get_param_data(inparamsptr, i); + DISTRHO_SAFE_ASSERT_BREAK(queue != nullptr); + + const v3_param_id rindex = v3_cpp_obj(queue)->get_param_id(queue); + DISTRHO_SAFE_ASSERT_UINT_BREAK(rindex < fVst3ParameterCount, rindex); + + #if DPF_VST3_HAS_INTERNAL_PARAMETERS + if (rindex < kVst3InternalParameterCount) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + // if there are any MIDI CC events as parameter changes, handle them here + if (canAppendMoreEvents && rindex >= kVst3InternalParameterMidiCC_start && rindex <= kVst3InternalParameterMidiCC_end) + { + for (int32_t j = 0, pcount = v3_cpp_obj(queue)->get_point_count(queue); j < pcount; ++j) + { + if (v3_cpp_obj(queue)->get_point(queue, j, &offset, &normalized) != V3_OK) + break; + + if (inputEventList.appendCC(offset, rindex, normalized)) + { + canAppendMoreEvents = false; + break; + } + } + } + #endif + continue; + } + #endif + + if (v3_cpp_obj(queue)->get_point_count(queue) <= 0) + continue; + + // if there are any parameter changes at frame 0, handle them here + if (v3_cpp_obj(queue)->get_point(queue, 0, &offset, &normalized) != V3_OK) + break; + + if (offset != 0) + continue; + + const uint32_t index = rindex - kVst3InternalParameterCount; + _setNormalizedPluginParameterValue(index, normalized); + } + } + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + const uint32_t midiEventCount = inputEventList.convert(fMidiEvents); + fPlugin.run(inputs, outputs, data->nframes, fMidiEvents, midiEventCount); + #else + fPlugin.run(inputs, outputs, data->nframes); + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + fHostEventOutputHandle = nullptr; + #endif + + // if there are any parameter changes after frame 0, set them here + if (v3_param_changes** const inparamsptr = data->input_params) + { + int32_t offset; + double normalized; + + for (int32_t i = 0, count = v3_cpp_obj(inparamsptr)->get_param_count(inparamsptr); i < count; ++i) + { + v3_param_value_queue** const queue = v3_cpp_obj(inparamsptr)->get_param_data(inparamsptr, i); + DISTRHO_SAFE_ASSERT_BREAK(queue != nullptr); + + const v3_param_id rindex = v3_cpp_obj(queue)->get_param_id(queue); + DISTRHO_SAFE_ASSERT_UINT_BREAK(rindex < fVst3ParameterCount, rindex); + + #if DPF_VST3_HAS_INTERNAL_PARAMETERS + if (rindex < kVst3InternalParameterCount) + continue; + #endif + + const int32_t pcount = v3_cpp_obj(queue)->get_point_count(queue); + + if (pcount <= 0) + continue; + + if (v3_cpp_obj(queue)->get_point(queue, pcount - 1, &offset, &normalized) != V3_OK) + break; + + if (offset == 0) + continue; + + const uint32_t index = rindex - kVst3InternalParameterCount; + _setNormalizedPluginParameterValue(index, normalized); + } + } + + updateParametersFromProcessing(data->output_params, data->nframes - 1); + return V3_OK; + } + + uint32_t getTailSamples() const noexcept + { + return 0; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_edit_controller interface calls + + int32_t getParameterCount() const noexcept + { + return fVst3ParameterCount; + } + + v3_result getParameterInfo(const int32_t rindex, v3_param_info* const info) const noexcept + { + std::memset(info, 0, sizeof(v3_param_info)); + DISTRHO_SAFE_ASSERT_RETURN(rindex >= 0, V3_INVALID_ARG); + + // TODO hash the parameter symbol + info->param_id = rindex; + + #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterBufferSize: + info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN; + info->step_count = DPF_VST3_MAX_BUFFER_SIZE - 1; + strncpy_utf16(info->title, "Buffer Size", 128); + strncpy_utf16(info->short_title, "Buffer Size", 128); + strncpy_utf16(info->units, "frames", 128); + return V3_OK; + case kVst3InternalParameterSampleRate: + info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN; + strncpy_utf16(info->title, "Sample Rate", 128); + strncpy_utf16(info->short_title, "Sample Rate", 128); + strncpy_utf16(info->units, "frames", 128); + return V3_OK; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + case kVst3InternalParameterLatency: + info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN; + strncpy_utf16(info->title, "Latency", 128); + strncpy_utf16(info->short_title, "Latency", 128); + strncpy_utf16(info->units, "frames", 128); + return V3_OK; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + info->flags = V3_PARAM_CAN_AUTOMATE | V3_PARAM_IS_LIST | V3_PARAM_PROGRAM_CHANGE | V3_PARAM_IS_HIDDEN; + info->step_count = fProgramCountMinusOne; + strncpy_utf16(info->title, "Current Program", 128); + strncpy_utf16(info->short_title, "Program", 128); + return V3_OK; + #endif + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (rindex < kVst3InternalParameterCount) + { + const uint32_t index = static_cast(rindex - kVst3InternalParameterMidiCC_start); + info->flags = V3_PARAM_CAN_AUTOMATE | V3_PARAM_IS_HIDDEN; + info->step_count = 127; + char ccstr[24]; + snprintf(ccstr, sizeof(ccstr), "MIDI Ch. %d CC %d", static_cast(index / 130) + 1, index % 130); + strncpy_utf16(info->title, ccstr, 128); + snprintf(ccstr, sizeof(ccstr), "Ch.%d CC%d", index / 130 + 1, index % 130); + strncpy_utf16(info->short_title, ccstr+5, 128); + return V3_OK; + } + #endif + + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + DISTRHO_SAFE_ASSERT_UINT_RETURN(index < fParameterCount, index, V3_INVALID_ARG); + + // set up flags + int32_t flags = 0; + + const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index)); + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + const uint32_t hints = fPlugin.getParameterHints(index); + + switch (fPlugin.getParameterDesignation(index)) + { + case kParameterDesignationNull: + break; + case kParameterDesignationBypass: + flags |= V3_PARAM_IS_BYPASS; + break; + } + + if (hints & kParameterIsAutomatable) + flags |= V3_PARAM_CAN_AUTOMATE; + if (hints & kParameterIsOutput) + flags |= V3_PARAM_READ_ONLY; + + // set up step_count + int32_t step_count = 0; + + if (hints & kParameterIsBoolean) + step_count = 1; + else if (hints & kParameterIsInteger) + step_count = ranges.max - ranges.min; + + if (enumValues.count >= 2 && enumValues.restrictedMode) + { + flags |= V3_PARAM_IS_LIST; + step_count = enumValues.count - 1; + } + + info->flags = flags; + info->step_count = step_count; + info->default_normalised_value = ranges.getNormalizedValue(ranges.def); + // int32_t unit_id; + strncpy_utf16(info->title, fPlugin.getParameterName(index), 128); + strncpy_utf16(info->short_title, fPlugin.getParameterShortName(index), 128); + strncpy_utf16(info->units, fPlugin.getParameterUnit(index), 128); + return V3_OK; + } + + v3_result getParameterStringForValue(const v3_param_id rindex, const double normalized, v3_str_128 output) + { + DISTRHO_SAFE_ASSERT_RETURN(normalized >= 0.0 && normalized <= 1.0, V3_INVALID_ARG); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterBufferSize: + snprintf_i32_utf16(output, static_cast(normalized * DPF_VST3_MAX_BUFFER_SIZE + 0.5), 128); + return V3_OK; + case kVst3InternalParameterSampleRate: + snprintf_f32_utf16(output, std::round(normalized * DPF_VST3_MAX_SAMPLE_RATE), 128); + return V3_OK; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + case kVst3InternalParameterLatency: + snprintf_f32_utf16(output, std::round(normalized * DPF_VST3_MAX_LATENCY), 128); + return V3_OK; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + const uint32_t program = std::round(normalized * fProgramCountMinusOne); + strncpy_utf16(output, fPlugin.getProgramName(program), 128); + return V3_OK; + #endif + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (rindex < kVst3InternalParameterCount) + { + snprintf_f32_utf16(output, std::round(normalized * 127), 128); + return V3_OK; + } + #endif + + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + DISTRHO_SAFE_ASSERT_UINT_RETURN(index < fParameterCount, index, V3_INVALID_ARG); + + const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index)); + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + const uint32_t hints = fPlugin.getParameterHints(index); + float value = ranges.getUnnormalizedValue(normalized); + + if (hints & kParameterIsBoolean) + { + const float midRange = ranges.min + (ranges.max - ranges.min) * 0.5f; + value = value > midRange ? ranges.max : ranges.min; + } + else if (hints & kParameterIsInteger) + { + value = std::round(value); + } + + for (uint32_t i=0; i < enumValues.count; ++i) + { + if (d_isEqual(enumValues.values[i].value, value)) + { + strncpy_utf16(output, enumValues.values[i].label, 128); + return V3_OK; + } + } + + if (hints & kParameterIsInteger) + snprintf_i32_utf16(output, value, 128); + else + snprintf_f32_utf16(output, value, 128); + + return V3_OK; + } + + v3_result getParameterValueForString(const v3_param_id rindex, int16_t* const input, double* const output) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterBufferSize: + *output = static_cast(std::atoi(ScopedUTF8String(input))) / DPF_VST3_MAX_BUFFER_SIZE; + return V3_OK; + case kVst3InternalParameterSampleRate: + *output = std::atof(ScopedUTF8String(input)) / DPF_VST3_MAX_SAMPLE_RATE; + return V3_OK; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + case kVst3InternalParameterLatency: + *output = std::atof(ScopedUTF8String(input)) / DPF_VST3_MAX_LATENCY; + return V3_OK; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + for (uint32_t i=0, count=fPlugin.getProgramCount(); i < count; ++i) + { + if (strcmp_utf16(input, fPlugin.getProgramName(i))) + { + *output = static_cast(i) / static_cast(fProgramCountMinusOne); + return V3_OK; + } + } + return V3_INVALID_ARG; + #endif + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (rindex < kVst3InternalParameterCount) + { + // TODO find CC/channel based on name + return V3_NOT_IMPLEMENTED; + } + #endif + + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + DISTRHO_SAFE_ASSERT_UINT_RETURN(index < fParameterCount, index, V3_INVALID_ARG); + + const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index)); + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + + for (uint32_t i=0; i < enumValues.count; ++i) + { + if (strcmp_utf16(input, enumValues.values[i].label)) + { + *output = ranges.getNormalizedValue(enumValues.values[i].value); + return V3_OK; + } + } + + const ScopedUTF8String input8(input); + + float value; + if (fPlugin.getParameterHints(index) & kParameterIsInteger) + value = std::atoi(input8); + else + value = std::atof(input8); + + *output = ranges.getNormalizedValue(value); + return V3_OK; + } + + double normalizedParameterToPlain(const v3_param_id rindex, const double normalized) + { + DISTRHO_SAFE_ASSERT_RETURN(normalized >= 0.0 && normalized <= 1.0, 0.0); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterBufferSize: + return std::round(normalized * DPF_VST3_MAX_BUFFER_SIZE); + case kVst3InternalParameterSampleRate: + return normalized * DPF_VST3_MAX_SAMPLE_RATE; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + case kVst3InternalParameterLatency: + return normalized * DPF_VST3_MAX_LATENCY; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + return std::round(normalized * fProgramCountMinusOne); + #endif + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (rindex < kVst3InternalParameterCount) + return std::round(normalized * 127); + #endif + + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, 0.0); + + const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); + const uint32_t hints = fPlugin.getParameterHints(index); + float value = ranges.getUnnormalizedValue(normalized); + + if (hints & kParameterIsBoolean) + { + const float midRange = ranges.min + (ranges.max - ranges.min) / 2.0f; + value = value > midRange ? ranges.max : ranges.min; + } + else if (hints & kParameterIsInteger) + { + value = std::round(value); + } + + return value; + } + + double plainParameterToNormalized(const v3_param_id rindex, const double plain) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterBufferSize: + return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_BUFFER_SIZE)); + case kVst3InternalParameterSampleRate: + return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_SAMPLE_RATE)); + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + case kVst3InternalParameterLatency: + return std::max(0.0, std::min(1.0, plain / DPF_VST3_MAX_LATENCY)); + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + return std::max(0.0, std::min(1.0, plain / fProgramCountMinusOne)); + #endif + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (rindex < kVst3InternalParameterCount) + return std::max(0.0, std::min(1.0, plain / 127)); + #endif + + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, 0.0); + + return _getNormalizedParameterValue(index, plain); + } + + double getParameterNormalized(const v3_param_id rindex) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + // TODO something to do here? + if ( + #if !DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS + rindex >= kVst3InternalParameterMidiCC_start && + #endif + rindex <= kVst3InternalParameterMidiCC_end) + return 0.0; + #endif + + #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterBufferSize: + case kVst3InternalParameterSampleRate: + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + case kVst3InternalParameterLatency: + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + #endif + return plainParameterToNormalized(rindex, fCachedParameterValues[rindex]); + } + #endif + + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, 0.0); + + return _getNormalizedParameterValue(index, fCachedParameterValues[kVst3InternalParameterBaseCount + index]); + } + + v3_result setParameterNormalized(const v3_param_id rindex, const double normalized) + { + DISTRHO_SAFE_ASSERT_RETURN(normalized >= 0.0 && normalized <= 1.0, V3_INVALID_ARG); + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + // TODO something to do here? + if ( + #if !DPF_VST3_PURE_MIDI_INTERNAL_PARAMETERS + rindex >= kVst3InternalParameterMidiCC_start && + #endif + rindex <= kVst3InternalParameterMidiCC_end) + return V3_INVALID_ARG; + #endif + + #if DPF_VST3_USES_SEPARATE_CONTROLLER || DISTRHO_PLUGIN_WANT_LATENCY || DISTRHO_PLUGIN_WANT_PROGRAMS + if (rindex < kVst3InternalParameterBaseCount) + { + fCachedParameterValues[rindex] = normalizedParameterToPlain(rindex, normalized); + int flags = 0; + + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterBufferSize: + fPlugin.setBufferSize(fCachedParameterValues[rindex], true); + break; + case kVst3InternalParameterSampleRate: + fPlugin.setSampleRate(fCachedParameterValues[rindex], true); + break; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + case kVst3InternalParameterLatency: + flags = V3_RESTART_LATENCY_CHANGED; + break; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + flags = V3_RESTART_PARAM_VALUES_CHANGED; + fCurrentProgram = fCachedParameterValues[rindex]; + fPlugin.loadProgram(fCurrentProgram); + + for (uint32_t i=0; irestart_component(fComponentHandler, flags); + + return V3_OK; + } + #endif + + DISTRHO_SAFE_ASSERT_UINT2_RETURN(rindex >= kVst3InternalParameterCount, rindex, kVst3InternalParameterCount, V3_INVALID_ARG); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(index < fParameterCount, index, fParameterCount, V3_INVALID_ARG); + + if (fIsComponent) { + DISTRHO_SAFE_ASSERT_RETURN(!fPlugin.isParameterOutputOrTrigger(index), V3_INVALID_ARG); + } + + _setNormalizedPluginParameterValue(index, normalized); + #endif + + return V3_OK; + } + + v3_result setComponentHandler(v3_component_handler** const handler) noexcept + { + fComponentHandler = handler; + return V3_OK; + } + +#if DISTRHO_PLUGIN_HAS_UI + // ---------------------------------------------------------------------------------------------------------------- + // v3_connection_point interface calls + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + void comp2ctrl_connect(v3_connection_point** const other) + { + fConnectionFromCompToCtrl = other; + } + + void comp2ctrl_disconnect() + { + fConnectionFromCompToCtrl = nullptr; + } + + v3_result comp2ctrl_notify(v3_message** const message) + { + const char* const msgid = v3_cpp_obj(message)->get_message_id(message); + DISTRHO_SAFE_ASSERT_RETURN(msgid != nullptr, V3_INVALID_ARG); + + v3_attribute_list** const attrs = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr, V3_INVALID_ARG); + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (std::strcmp(msgid, "midi") == 0) + return notify_midi(attrs); + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + if (std::strcmp(msgid, "state-set") == 0) + return notify_state(attrs); + #endif + + d_stderr("comp2ctrl_notify received unknown msg '%s'", msgid); + + return V3_NOT_IMPLEMENTED; + } + #endif // DPF_VST3_USES_SEPARATE_CONTROLLER + + // ---------------------------------------------------------------------------------------------------------------- + + void ctrl2view_connect(v3_connection_point** const other) + { + DISTRHO_SAFE_ASSERT(fConnectedToUI == false); + + fConnectionFromCtrlToView = other; + fConnectedToUI = false; + } + + void ctrl2view_disconnect() + { + fConnectedToUI = false; + fConnectionFromCtrlToView = nullptr; + } + + v3_result ctrl2view_notify(v3_message** const message) + { + DISTRHO_SAFE_ASSERT_RETURN(fConnectionFromCtrlToView != nullptr, V3_INTERNAL_ERR); + + const char* const msgid = v3_cpp_obj(message)->get_message_id(message); + DISTRHO_SAFE_ASSERT_RETURN(msgid != nullptr, V3_INVALID_ARG); + + if (std::strcmp(msgid, "init") == 0) + { + fConnectedToUI = true; + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + fParameterValueChangesForUI[kVst3InternalParameterSampleRate] = false; + sendParameterSetToUI(kVst3InternalParameterSampleRate, + fCachedParameterValues[kVst3InternalParameterSampleRate]); + #endif + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + fParameterValueChangesForUI[kVst3InternalParameterProgram] = false; + sendParameterSetToUI(kVst3InternalParameterProgram, fCurrentProgram); + #endif + + #if DISTRHO_PLUGIN_WANT_FULL_STATE + // Update current state from plugin side + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + fStateMap[key] = fPlugin.getStateValue(key); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + // Set state + for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) + { + const String& key = cit->first; + const String& value = cit->second; + + sendStateSetToUI(key, value); + } + #endif + + for (uint32_t i=0; iget_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr, V3_INVALID_ARG); + + if (std::strcmp(msgid, "idle") == 0) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + if (fParameterValueChangesForUI[kVst3InternalParameterSampleRate]) + { + fParameterValueChangesForUI[kVst3InternalParameterSampleRate] = false; + sendParameterSetToUI(kVst3InternalParameterSampleRate, + fCachedParameterValues[kVst3InternalParameterSampleRate]); + } + #endif + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fParameterValueChangesForUI[kVst3InternalParameterProgram]) + { + fParameterValueChangesForUI[kVst3InternalParameterProgram] = false; + sendParameterSetToUI(kVst3InternalParameterProgram, fCurrentProgram); + } + #endif + + for (uint32_t i=0; iget_int(attrs, "rindex", &rindex); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT2_RETURN(rindex >= kVst3InternalParameterCount, + rindex, fParameterCount, V3_INTERNAL_ERR); + DISTRHO_SAFE_ASSERT_INT2_RETURN(rindex < kVst3InternalParameterCount + fParameterCount, + rindex, fParameterCount, V3_INTERNAL_ERR); + + res = v3_cpp_obj(attrs)->get_int(attrs, "started", &started); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(started == 0 || started == 1, started, V3_INTERNAL_ERR); + + return started != 0 ? v3_cpp_obj(fComponentHandler)->begin_edit(fComponentHandler, rindex) + : v3_cpp_obj(fComponentHandler)->end_edit(fComponentHandler, rindex); + } + + if (std::strcmp(msgid, "parameter-set") == 0) + { + DISTRHO_SAFE_ASSERT_RETURN(fComponentHandler != nullptr, V3_INTERNAL_ERR); + + int64_t rindex; + double value; + v3_result res; + + res = v3_cpp_obj(attrs)->get_int(attrs, "rindex", &rindex); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT2_RETURN(rindex >= kVst3InternalParameterCount, + rindex, fParameterCount, V3_INTERNAL_ERR); + DISTRHO_SAFE_ASSERT_INT2_RETURN(rindex < kVst3InternalParameterCount + fParameterCount, + rindex, fParameterCount, V3_INTERNAL_ERR); + + res = v3_cpp_obj(attrs)->get_float(attrs, "value", &value); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + + const uint32_t index = rindex - kVst3InternalParameterCount; + const double normalized = _getNormalizedParameterValue(index, value); + + fCachedParameterValues[kVst3InternalParameterBaseCount + index] = value; + + if (! fPlugin.isParameterOutputOrTrigger(index)) + fPlugin.setParameterValue(index, value); + + return v3_cpp_obj(fComponentHandler)->perform_edit(fComponentHandler, rindex, normalized); + } + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (std::strcmp(msgid, "midi") == 0) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + DISTRHO_SAFE_ASSERT_RETURN(fConnectionFromCompToCtrl != nullptr, V3_INTERNAL_ERR); + return v3_cpp_obj(fConnectionFromCompToCtrl)->notify(fConnectionFromCompToCtrl, message); + #else + return notify_midi(attrs); + #endif + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + if (std::strcmp(msgid, "state-set") == 0) + { + const v3_result res = notify_state(attrs); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + if (res != V3_OK) + return res; + + // notify component of the change + DISTRHO_SAFE_ASSERT_RETURN(fConnectionFromCompToCtrl != nullptr, V3_INTERNAL_ERR); + return v3_cpp_obj(fConnectionFromCompToCtrl)->notify(fConnectionFromCompToCtrl, message); + #else + return res; + #endif + } + #endif + + d_stderr("ctrl2view_notify received unknown msg '%s'", msgid); + + return V3_NOT_IMPLEMENTED; + } + + #if DISTRHO_PLUGIN_WANT_STATE + v3_result notify_state(v3_attribute_list** const attrs) + { + int64_t keyLength = -1; + int64_t valueLength = -1; + v3_result res; + + res = v3_cpp_obj(attrs)->get_int(attrs, "key:length", &keyLength); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(keyLength >= 0, keyLength, V3_INTERNAL_ERR); + + res = v3_cpp_obj(attrs)->get_int(attrs, "value:length", &valueLength); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(valueLength >= 0, valueLength, V3_INTERNAL_ERR); + + int16_t* const key16 = (int16_t*)std::malloc(sizeof(int16_t)*(keyLength + 1)); + DISTRHO_SAFE_ASSERT_RETURN(key16 != nullptr, V3_NOMEM); + + int16_t* const value16 = (int16_t*)std::malloc(sizeof(int16_t)*(valueLength + 1)); + DISTRHO_SAFE_ASSERT_RETURN(value16 != nullptr, V3_NOMEM); + + res = v3_cpp_obj(attrs)->get_string(attrs, "key", key16, sizeof(int16_t)*(keyLength+1)); + DISTRHO_SAFE_ASSERT_INT2_RETURN(res == V3_OK, res, keyLength, res); + + if (valueLength != 0) + { + res = v3_cpp_obj(attrs)->get_string(attrs, "value", value16, sizeof(int16_t)*(valueLength+1)); + DISTRHO_SAFE_ASSERT_INT2_RETURN(res == V3_OK, res, valueLength, res); + } + + // do cheap inline conversion + char* const key = (char*)key16; + char* const value = (char*)value16; + + for (int64_t i=0; ifirst); + + if (dkey == key) + { + it->second = value; + std::free(key16); + std::free(value16); + return V3_OK; + } + } + + d_stderr("Failed to find plugin state with key \"%s\"", key); + } + + std::free(key16); + std::free(value16); + return V3_OK; + } + #endif // DISTRHO_PLUGIN_WANT_STATE + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + v3_result notify_midi(v3_attribute_list** const attrs) + { + uint8_t* data; + uint32_t size; + v3_result res; + + res = v3_cpp_obj(attrs)->get_binary(attrs, "data", (const void**)&data, &size); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + + // known maximum size + DISTRHO_SAFE_ASSERT_UINT_RETURN(size == 3, size, V3_INTERNAL_ERR); + + return fNotesRingBuffer.writeCustomData(data, size) && fNotesRingBuffer.commitWrite() ? V3_OK : V3_NOMEM; + } + #endif // DISTRHO_PLUGIN_WANT_MIDI_INPUT +#endif + + // ---------------------------------------------------------------------------------------------------------------- + +private: + // Plugin + PluginExporter fPlugin; + + // VST3 stuff + v3_component_handler** fComponentHandler; + #if DISTRHO_PLUGIN_HAS_UI + #if DPF_VST3_USES_SEPARATE_CONTROLLER + v3_connection_point** fConnectionFromCompToCtrl; + #endif + v3_connection_point** fConnectionFromCtrlToView; + v3_host_application** const fHostApplication; + #endif + + // Temporary data + const uint32_t fParameterCount; + const uint32_t fVst3ParameterCount; // full offset + real + float* fCachedParameterValues; // basic offset + real + float* fDummyAudioBuffer; + bool* fParameterValuesChangedDuringProcessing; // basic offset + real + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + bool fEnabledInputs[DISTRHO_PLUGIN_NUM_INPUTS]; + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + bool fEnabledOutputs[DISTRHO_PLUGIN_NUM_OUTPUTS]; + #endif + #if DPF_VST3_USES_SEPARATE_CONTROLLER + const bool fIsComponent; + #endif + #if DISTRHO_PLUGIN_HAS_UI + bool* fParameterValueChangesForUI; // basic offset + real + bool fConnectedToUI; + #endif + #if DISTRHO_PLUGIN_WANT_LATENCY + uint32_t fLastKnownLatency; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + MidiEvent fMidiEvents[kMaxMidiEvents]; + #if DISTRHO_PLUGIN_HAS_UI + SmallStackRingBuffer fNotesRingBuffer; + #endif + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + v3_event_list** fHostEventOutputHandle; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + uint32_t fCurrentProgram; + const uint32_t fProgramCountMinusOne; + #endif + #if DISTRHO_PLUGIN_WANT_STATE + StringMap fStateMap; + #endif + #if DISTRHO_PLUGIN_WANT_TIMEPOS + TimePosition fTimePosition; + #endif + + // ---------------------------------------------------------------------------------------------------------------- + // helper functions for dealing with buses + + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + template + void fillInBusInfoDetails() + { + constexpr const uint32_t numPorts = isInput ? DISTRHO_PLUGIN_NUM_INPUTS : DISTRHO_PLUGIN_NUM_OUTPUTS; + BusInfo& busInfo(isInput ? inputBuses : outputBuses); + bool* const enabledPorts = isInput + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + ? fEnabledInputs + #else + ? nullptr + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + : fEnabledOutputs; + #else + : nullptr; + #endif + + std::vector visitedPortGroups; + for (uint32_t i=0; i::iterator end = visitedPortGroups.end(); + if (std::find(visitedPortGroups.begin(), end, port.groupId) == end) + { + visitedPortGroups.push_back(port.groupId); + ++busInfo.groups; + } + ++busInfo.groupPorts; + continue; + } + + if (port.hints & kAudioPortIsCV) + ++busInfo.cvPorts; + else if (port.hints & kAudioPortIsSidechain) + ++busInfo.sidechainPorts; + else + ++busInfo.audioPorts; + } + + if (busInfo.audioPorts != 0) + busInfo.audio = 1; + if (busInfo.sidechainPorts != 0) + busInfo.sidechain = 1; + + uint32_t busIdForCV = 0; + const std::vector::iterator vpgStart = visitedPortGroups.begin(); + const std::vector::iterator vpgEnd = visitedPortGroups.end(); + + for (uint32_t i=0; i + v3_result getAudioBusInfo(const uint32_t busId, v3_bus_info* const info) const + { + constexpr const uint32_t numPorts = isInput ? DISTRHO_PLUGIN_NUM_INPUTS : DISTRHO_PLUGIN_NUM_OUTPUTS; + const BusInfo& busInfo(isInput ? inputBuses : outputBuses); + + int32_t numChannels; + uint32_t flags; + v3_bus_types busType; + v3_str_128 busName = {}; + + if (busId < busInfo.groups) + { + numChannels = 0; + + for (uint32_t i=0; imedia_type = V3_AUDIO; + info->direction = isInput ? V3_INPUT : V3_OUTPUT; + info->channel_count = numChannels; + std::memcpy(info->bus_name, busName, sizeof(busName)); + info->bus_type = busType; + info->flags = flags; + return V3_OK; + } + + // someone please tell me what is up with these.. + static inline v3_speaker_arrangement portCountToSpeaker(const uint32_t portCount) + { + DISTRHO_SAFE_ASSERT_RETURN(portCount != 0, 0); + + switch (portCount) + { + // regular mono + case 1: return V3_SPEAKER_M; + // regular stereo + case 2: return V3_SPEAKER_L | V3_SPEAKER_R; + // stereo with center channel + case 3: return V3_SPEAKER_L | V3_SPEAKER_R | V3_SPEAKER_C; + // stereo with surround (quadro) + case 4: return V3_SPEAKER_L | V3_SPEAKER_R | V3_SPEAKER_LS | V3_SPEAKER_RS; + // regular 5.0 + case 5: return V3_SPEAKER_L | V3_SPEAKER_R | V3_SPEAKER_LS | V3_SPEAKER_RS | V3_SPEAKER_C; + // regular 6.0 + case 6: return V3_SPEAKER_L | V3_SPEAKER_R | V3_SPEAKER_LS | V3_SPEAKER_RS | V3_SPEAKER_SL | V3_SPEAKER_SR; + // regular 7.0 + case 7: return V3_SPEAKER_L | V3_SPEAKER_R | V3_SPEAKER_LS | V3_SPEAKER_RS | V3_SPEAKER_SL | V3_SPEAKER_SR | V3_SPEAKER_C; + // regular 8.0 + case 8: return V3_SPEAKER_L | V3_SPEAKER_R | V3_SPEAKER_LS | V3_SPEAKER_RS | V3_SPEAKER_SL | V3_SPEAKER_SR | V3_SPEAKER_C | V3_SPEAKER_S; + // regular 8.1 + case 9: return V3_SPEAKER_L | V3_SPEAKER_R | V3_SPEAKER_LS | V3_SPEAKER_RS | V3_SPEAKER_SL | V3_SPEAKER_SR | V3_SPEAKER_C | V3_SPEAKER_S | V3_SPEAKER_LFE; + // cinema 10.0 + case 10: return ( + V3_SPEAKER_L | V3_SPEAKER_R | + V3_SPEAKER_LS | V3_SPEAKER_RS | + V3_SPEAKER_SL | V3_SPEAKER_SR | + V3_SPEAKER_LC | V3_SPEAKER_RC | + V3_SPEAKER_C | V3_SPEAKER_S); + // cinema 10.1 + case 11: return ( + V3_SPEAKER_L | V3_SPEAKER_R | + V3_SPEAKER_LS | V3_SPEAKER_RS | + V3_SPEAKER_SL | V3_SPEAKER_SR | + V3_SPEAKER_LC | V3_SPEAKER_RC | + V3_SPEAKER_C | V3_SPEAKER_S | V3_SPEAKER_LFE); + default: + d_stderr("portCountToSpeaker error: got weirdly big number ports %u in a single bus", portCount); + return 0; + } + } + + template + v3_speaker_arrangement getSpeakerArrangementForAudioPort(const BusInfo& busInfo, const uint32_t portGroupId, const uint32_t busId) const noexcept + { + switch (portGroupId) + { + case kPortGroupMono: + return V3_SPEAKER_M; + case kPortGroupStereo: + return V3_SPEAKER_L | V3_SPEAKER_R; + } + + if (busId < busInfo.groups) + return portCountToSpeaker(fPlugin.getAudioPortCountWithGroupId(isInput, portGroupId)); + + if (busInfo.audio != 0 && busId == busInfo.groups) + return portCountToSpeaker(busInfo.audioPorts); + + if (busInfo.sidechain != 0 && busId == busInfo.groups + busInfo.audio) + return portCountToSpeaker(busInfo.sidechainPorts); + + return V3_SPEAKER_M; + } + + template + bool getAudioBusArrangement(uint32_t busId, v3_speaker_arrangement* const speaker) const + { + constexpr const uint32_t numPorts = isInput ? DISTRHO_PLUGIN_NUM_INPUTS : DISTRHO_PLUGIN_NUM_OUTPUTS; + const BusInfo& busInfo(isInput ? inputBuses : outputBuses); + + for (uint32_t i=0; i(busInfo, port.groupId, busId); + // d_debug("getAudioBusArrangement %d enabled by value %lx", busId, *speaker); + return true; + } + + return false; + } + + template + bool setAudioBusArrangement(v3_speaker_arrangement* const speakers, const uint32_t numBuses) + { + constexpr const uint32_t numPorts = isInput ? DISTRHO_PLUGIN_NUM_INPUTS : DISTRHO_PLUGIN_NUM_OUTPUTS; + BusInfo& busInfo(isInput ? inputBuses : outputBuses); + bool* const enabledPorts = isInput + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + ? fEnabledInputs + #else + ? nullptr + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + : fEnabledOutputs; + #else + : nullptr; + #endif + + bool ok = true; + + for (uint32_t busId=0; busId(busInfo, port.groupId, busId); + + // fail if host tries to map it to anything else + // FIXME should we allow to map speaker to zero as a way to disable it? + if (earr != arr /* && arr != 0 */) + { + ok = false; + continue; + } + + enabledPorts[i] = arr != 0; + } + } + + // disable any buses outside of the requested arrangement + const uint32_t totalBuses = busInfo.audio + busInfo.sidechain + busInfo.groups + busInfo.cvPorts; + + for (uint32_t busId=numBuses; busIdadd_param_data(outparamsptr, + ¶mId, &index); + DISTRHO_SAFE_ASSERT_RETURN(queue != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(v3_cpp_obj(queue)->add_point(queue, 0, normalized, &index) == V3_OK, false); + + /* FLStudio gets confused with this one, skip it for now + if (offset != 0) + v3_cpp_obj(queue)->add_point(queue, offset, normalized, &index); + */ + + return true; + + // unused at the moment, buggy VST3 hosts :/ + (void)offset; + } + + #if DISTRHO_PLUGIN_HAS_UI + // ---------------------------------------------------------------------------------------------------------------- + // helper functions called during message passing, can block + + v3_message** createMessage(const char* const id) const + { + DISTRHO_SAFE_ASSERT_RETURN(fHostApplication != nullptr, nullptr); + + v3_tuid iid; + memcpy(iid, v3_message_iid, sizeof(v3_tuid)); + v3_message** msg = nullptr; + const v3_result res = v3_cpp_obj(fHostApplication)->create_instance(fHostApplication, iid, iid, (void**)&msg); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_TRUE, res, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(msg != nullptr, nullptr); + + v3_cpp_obj(msg)->set_message_id(msg, id); + return msg; + } + + void sendParameterSetToUI(const v3_param_id rindex, const double value) const + { + v3_message** const message = createMessage("parameter-set"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 2); + v3_cpp_obj(attrlist)->set_int(attrlist, "rindex", rindex); + v3_cpp_obj(attrlist)->set_float(attrlist, "value", value); + v3_cpp_obj(fConnectionFromCtrlToView)->notify(fConnectionFromCtrlToView, message); + + v3_cpp_obj_unref(message); + } + + void sendStateSetToUI(const char* const key, const char* const value) const + { + v3_message** const message = createMessage("state-set"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 2); + v3_cpp_obj(attrlist)->set_int(attrlist, "key:length", std::strlen(key)); + v3_cpp_obj(attrlist)->set_int(attrlist, "value:length", std::strlen(value)); + v3_cpp_obj(attrlist)->set_string(attrlist, "key", ScopedUTF16String(key)); + v3_cpp_obj(attrlist)->set_string(attrlist, "value", ScopedUTF16String(value)); + v3_cpp_obj(fConnectionFromCtrlToView)->notify(fConnectionFromCtrlToView, message); + + v3_cpp_obj_unref(message); + } + + void sendReadyToUI() const + { + v3_message** const message = createMessage("ready"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 2); + v3_cpp_obj(fConnectionFromCtrlToView)->notify(fConnectionFromCtrlToView, message); + + v3_cpp_obj_unref(message); + } + #endif + + // ---------------------------------------------------------------------------------------------------------------- + // DPF callbacks + + #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST + bool requestParameterValueChange(const uint32_t index, float) + { + fParameterValuesChangedDuringProcessing[kVst3InternalParameterBaseCount + index] = true; + return true; + } + + static bool requestParameterValueChangeCallback(void* const ptr, const uint32_t index, const float value) + { + return ((PluginVst3*)ptr)->requestParameterValueChange(index, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool writeMidi(const MidiEvent& midiEvent) + { + DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_RETURN("MIDI output unsupported", fHostEventOutputHandle != nullptr, false); + + v3_event event; + std::memset(&event, 0, sizeof(event)); + event.sample_offset = midiEvent.frame; + + const uint8_t* const data = midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data; + + switch (data[0] & 0xf0) + { + case 0x80: + event.type = V3_EVENT_NOTE_OFF; + event.note_off.channel = data[0] & 0xf; + event.note_off.pitch = data[1]; + event.note_off.velocity = (float)data[2] / 127.0f; + // int32_t note_id; + // float tuning; + break; + case 0x90: + event.type = V3_EVENT_NOTE_ON; + event.note_on.channel = data[0] & 0xf; + event.note_on.pitch = data[1]; + // float tuning; + event.note_on.velocity = (float)data[2] / 127.0f; + // int32_t length; + // int32_t note_id; + break; + case 0xA0: + event.type = V3_EVENT_POLY_PRESSURE; + event.poly_pressure.channel = data[0] & 0xf; + event.poly_pressure.pitch = data[1]; + event.poly_pressure.pressure = (float)data[2] / 127.0f; + // int32_t note_id; + break; + case 0xB0: + event.type = V3_EVENT_LEGACY_MIDI_CC_OUT; + event.midi_cc_out.channel = data[0] & 0xf; + event.midi_cc_out.cc_number = data[1]; + event.midi_cc_out.value = data[2]; + if (midiEvent.size == 4) + event.midi_cc_out.value2 = midiEvent.size == 4; + break; + /* TODO how do we deal with program changes?? + case 0xC0: + break; + */ + case 0xD0: + event.type = V3_EVENT_LEGACY_MIDI_CC_OUT; + event.midi_cc_out.channel = data[0] & 0xf; + event.midi_cc_out.cc_number = 128; + event.midi_cc_out.value = data[1]; + break; + case 0xE0: + event.type = V3_EVENT_LEGACY_MIDI_CC_OUT; + event.midi_cc_out.channel = data[0] & 0xf; + event.midi_cc_out.cc_number = 129; + event.midi_cc_out.value = data[1]; + event.midi_cc_out.value2 = data[2]; + break; + default: + return true; + } + + return v3_cpp_obj(fHostEventOutputHandle)->add_event(fHostEventOutputHandle, &event) == V3_OK; + } + + static bool writeMidiCallback(void* const ptr, const MidiEvent& midiEvent) + { + return ((PluginVst3*)ptr)->writeMidi(midiEvent); + } + #endif +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * VST3 low-level pointer thingies follow, proceed with care. + */ + +// -------------------------------------------------------------------------------------------------------------------- +// v3_funknown for static instances + +static uint32_t V3_API dpf_static_ref(void*) { return 1; } +static uint32_t V3_API dpf_static_unref(void*) { return 0; } + +// -------------------------------------------------------------------------------------------------------------------- +// v3_funknown for classes with a single instance + +template +static uint32_t V3_API dpf_single_instance_ref(void* const self) +{ + return ++(*static_cast(self))->refcounter; +} + +template +static uint32_t V3_API dpf_single_instance_unref(void* const self) +{ + return --(*static_cast(self))->refcounter; +} + +// -------------------------------------------------------------------------------------------------------------------- +// Store components that we can't delete properly, to be cleaned up on module unload + +struct dpf_component; + +static std::vector gComponentGarbage; + +static uint32_t handleUncleanComponent(dpf_component** const componentptr) +{ + gComponentGarbage.push_back(componentptr); + return 0; +} + +#if DPF_VST3_USES_SEPARATE_CONTROLLER +// -------------------------------------------------------------------------------------------------------------------- +// Store controllers that we can't delete properly, to be cleaned up on module unload + +struct dpf_edit_controller; + +static std::vector gControllerGarbage; + +static uint32_t handleUncleanController(dpf_edit_controller** const controllerptr) +{ + gControllerGarbage.push_back(controllerptr); + return 0; +} + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_comp2ctrl_connection_point + +struct dpf_comp2ctrl_connection_point : v3_connection_point_cpp { + std::atomic_int refcounter; + ScopedPointer& vst3; + v3_connection_point** other; + + dpf_comp2ctrl_connection_point(ScopedPointer& v) + : refcounter(1), + vst3(v), + other(nullptr) + { + // v3_funknown, single instance + query_interface = query_interface_connection_point; + ref = dpf_single_instance_ref; + unref = dpf_single_instance_unref; + + // v3_connection_point + point.connect = connect; + point.disconnect = disconnect; + point.notify = notify; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_connection_point(void* const self, const v3_tuid iid, void** const iface) + { + dpf_comp2ctrl_connection_point* const point = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_connection_point_iid)) + { + d_debug("dpf_comp2ctrl_connection_point => %p %s %p | OK", self, tuid2str(iid), iface); + ++point->refcounter; + *iface = self; + return V3_OK; + } + + d_debug("dpf_comp2ctrl_connection_point => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = nullptr; + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_connection_point + + static v3_result V3_API connect(void* const self, v3_connection_point** const other) + { + d_debug("dpf_comp2ctrl_connection_point::connect => %p %p", self, other); + dpf_comp2ctrl_connection_point* const point = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(point->other == nullptr, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_RETURN(point->other != other, V3_INVALID_ARG); + + point->other = other; + + if (PluginVst3* const vst3 = point->vst3) + vst3->comp2ctrl_connect(other); + + return V3_OK; + } + + static v3_result V3_API disconnect(void* const self, v3_connection_point** const other) + { + d_debug("dpf_comp2ctrl_connection_point => %p %p", self, other); + dpf_comp2ctrl_connection_point* const point = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(point->other != nullptr, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_RETURN(point->other == other, V3_INVALID_ARG); + + if (PluginVst3* const vst3 = point->vst3) + vst3->comp2ctrl_disconnect(); + + point->other = nullptr; + + return V3_OK; + } + + static v3_result V3_API notify(void* const self, v3_message** const message) + { + dpf_comp2ctrl_connection_point* const point = *static_cast(self); + + PluginVst3* const vst3 = point->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + v3_connection_point** const other = point->other; + DISTRHO_SAFE_ASSERT_RETURN(other != nullptr, V3_NOT_INITIALIZED); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr, V3_INVALID_ARG); + + int64_t target = 0; + const v3_result res = v3_cpp_obj(attrlist)->get_int(attrlist, "__dpf_msg_target__", &target); + DISTRHO_SAFE_ASSERT_RETURN(res == V3_OK, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(target == 1, target, V3_INTERNAL_ERR); + + // view -> edit controller -> component + return vst3->comp2ctrl_notify(message); + } +}; +#endif // DPF_VST3_USES_SEPARATE_CONTROLLER + +#if DISTRHO_PLUGIN_HAS_UI +// -------------------------------------------------------------------------------------------------------------------- +// dpf_ctrl2view_connection_point + +struct dpf_ctrl2view_connection_point : v3_connection_point_cpp { + ScopedPointer& vst3; + v3_connection_point** other; + + dpf_ctrl2view_connection_point(ScopedPointer& v) + : vst3(v), + other(nullptr) + { + // v3_funknown, single instance, used internally + query_interface = nullptr; + ref = nullptr; + unref = nullptr; + + // v3_connection_point + point.connect = connect; + point.disconnect = disconnect; + point.notify = notify; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_connection_point + + static v3_result V3_API connect(void* const self, v3_connection_point** const other) + { + d_debug("dpf_ctrl2view_connection_point::connect => %p %p", self, other); + dpf_ctrl2view_connection_point* const point = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(point->other == nullptr, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_RETURN(point->other != other, V3_INVALID_ARG); + + point->other = other; + + if (PluginVst3* const vst3 = point->vst3) + vst3->ctrl2view_connect(other); + + return V3_OK; + } + + static v3_result V3_API disconnect(void* const self, v3_connection_point** const other) + { + d_debug("dpf_ctrl2view_connection_point::disconnect => %p %p", self, other); + dpf_ctrl2view_connection_point* const point = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(point->other != nullptr, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_RETURN(point->other == other, V3_INVALID_ARG); + + if (PluginVst3* const vst3 = point->vst3) + vst3->ctrl2view_disconnect(); + + v3_cpp_obj_unref(point->other); + point->other = nullptr; + + return V3_OK; + } + + static v3_result V3_API notify(void* const self, v3_message** const message) + { + dpf_ctrl2view_connection_point* const point = *static_cast(self); + + PluginVst3* const vst3 = point->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + v3_connection_point** const other = point->other; + DISTRHO_SAFE_ASSERT_RETURN(other != nullptr, V3_NOT_INITIALIZED); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr, V3_INVALID_ARG); + + int64_t target = 0; + const v3_result res = v3_cpp_obj(attrlist)->get_int(attrlist, "__dpf_msg_target__", &target); + DISTRHO_SAFE_ASSERT_RETURN(res == V3_OK, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(target == 1 || target == 2, target, V3_INTERNAL_ERR); + + if (target == 1) + { + // view -> edit controller + return vst3->ctrl2view_notify(message); + } + else + { + // edit controller -> view + return v3_cpp_obj(other)->notify(other, message); + } + } +}; +#endif // DISTRHO_PLUGIN_HAS_UI + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT +// -------------------------------------------------------------------------------------------------------------------- +// dpf_midi_mapping + +struct dpf_midi_mapping : v3_midi_mapping_cpp { + dpf_midi_mapping() + { + // v3_funknown, static + query_interface = query_interface_midi_mapping; + ref = dpf_static_ref; + unref = dpf_static_unref; + + // v3_midi_mapping + map.get_midi_controller_assignment = get_midi_controller_assignment; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_midi_mapping(void* const self, const v3_tuid iid, void** const iface) + { + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_midi_mapping_iid)) + { + d_debug("query_interface_midi_mapping => %p %s %p | OK", self, tuid2str(iid), iface); + *iface = self; + return V3_OK; + } + + d_debug("query_interface_midi_mapping => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = nullptr; + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_midi_mapping + + static v3_result V3_API get_midi_controller_assignment(void*, const int32_t bus, const int16_t channel, const int16_t cc, v3_param_id* const id) + { + DISTRHO_SAFE_ASSERT_INT_RETURN(bus == 0, bus, V3_FALSE); + DISTRHO_SAFE_ASSERT_INT_RETURN(channel >= 0 && channel < 16, channel, V3_FALSE); + DISTRHO_SAFE_ASSERT_INT_RETURN(cc >= 0 && cc < 130, cc, V3_FALSE); + + *id = kVst3InternalParameterMidiCC_start + channel * 130 + cc; + return V3_TRUE; + } + + DISTRHO_PREVENT_HEAP_ALLOCATION +}; +#endif // DISTRHO_PLUGIN_WANT_MIDI_INPUT + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_edit_controller + +struct dpf_edit_controller : v3_edit_controller_cpp { + std::atomic_int refcounter; + #if DISTRHO_PLUGIN_HAS_UI + ScopedPointer connectionCtrl2View; + #endif + #if DPF_VST3_USES_SEPARATE_CONTROLLER + ScopedPointer connectionComp2Ctrl; + ScopedPointer vst3; + #else + ScopedPointer& vst3; + bool initialized; + #endif + // cached values + v3_component_handler** handler; + v3_host_application** const hostApplicationFromFactory; + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + v3_host_application** const hostApplicationFromComponent; + v3_host_application** hostApplicationFromComponentInitialize; + #endif + v3_host_application** hostApplicationFromInitialize; + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + dpf_edit_controller(v3_host_application** const hostApp) + : refcounter(1), + vst3(nullptr), + #else + dpf_edit_controller(ScopedPointer& v, v3_host_application** const hostApp, v3_host_application** const hostComp) + : refcounter(1), + vst3(v), + initialized(false), + #endif + handler(nullptr), + hostApplicationFromFactory(hostApp), + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + hostApplicationFromComponent(hostComp), + hostApplicationFromComponentInitialize(nullptr), + #endif + hostApplicationFromInitialize(nullptr) + { + d_debug("dpf_edit_controller() with hostApplication %p", hostApplicationFromFactory); + + // make sure host application is valid through out this controller lifetime + if (hostApplicationFromFactory != nullptr) + v3_cpp_obj_ref(hostApplicationFromFactory); + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + if (hostApplicationFromComponent != nullptr) + v3_cpp_obj_ref(hostApplicationFromComponent); + #endif + + // v3_funknown, everything custom + query_interface = query_interface_edit_controller; + ref = ref_edit_controller; + unref = unref_edit_controller; + + // v3_plugin_base + base.initialize = initialize; + base.terminate = terminate; + + // v3_edit_controller + ctrl.set_component_state = set_component_state; + ctrl.set_state = set_state; + ctrl.get_state = get_state; + ctrl.get_parameter_count = get_parameter_count; + ctrl.get_parameter_info = get_parameter_info; + ctrl.get_parameter_string_for_value = get_parameter_string_for_value; + ctrl.get_parameter_value_for_string = get_parameter_value_for_string; + ctrl.normalised_parameter_to_plain = normalised_parameter_to_plain; + ctrl.plain_parameter_to_normalised = plain_parameter_to_normalised; + ctrl.get_parameter_normalised = get_parameter_normalised; + ctrl.set_parameter_normalised = set_parameter_normalised; + ctrl.set_component_handler = set_component_handler; + ctrl.create_view = create_view; + } + + ~dpf_edit_controller() + { + d_debug("~dpf_edit_controller()"); + #if DISTRHO_PLUGIN_HAS_UI + connectionCtrl2View = nullptr; + #endif + #if DPF_VST3_USES_SEPARATE_CONTROLLER + connectionComp2Ctrl = nullptr; + vst3 = nullptr; + #endif + + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + if (hostApplicationFromComponent != nullptr) + v3_cpp_obj_unref(hostApplicationFromComponent); + #endif + if (hostApplicationFromFactory != nullptr) + v3_cpp_obj_unref(hostApplicationFromFactory); + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_edit_controller(void* const self, const v3_tuid iid, void** const iface) + { + dpf_edit_controller* const controller = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_plugin_base_iid) || + v3_tuid_match(iid, v3_edit_controller_iid)) + { + d_debug("query_interface_edit_controller => %p %s %p | OK", self, tuid2str(iid), iface); + ++controller->refcounter; + *iface = self; + return V3_OK; + } + + if (v3_tuid_match(iid, v3_midi_mapping_iid)) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + d_debug("query_interface_edit_controller => %p %s %p | OK convert static", self, tuid2str(iid), iface); + static dpf_midi_mapping midi_mapping; + static dpf_midi_mapping* midi_mapping_ptr = &midi_mapping; + *iface = &midi_mapping_ptr; + return V3_OK; + #else + d_debug("query_interface_edit_controller => %p %s %p | reject unused", self, tuid2str(iid), iface); + *iface = nullptr; + return V3_NO_INTERFACE; + #endif + } + + if (v3_tuid_match(iid, v3_connection_point_iid)) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + d_debug("query_interface_edit_controller => %p %s %p | OK convert %p", + self, tuid2str(iid), iface, controller->connectionComp2Ctrl.get()); + + if (controller->connectionComp2Ctrl == nullptr) + controller->connectionComp2Ctrl = new dpf_comp2ctrl_connection_point(controller->vst3); + else + ++controller->connectionComp2Ctrl->refcounter; + *iface = &controller->connectionComp2Ctrl; + return V3_OK; + #else + d_debug("query_interface_edit_controller => %p %s %p | reject unwanted", self, tuid2str(iid), iface); + *iface = nullptr; + return V3_NO_INTERFACE; + #endif + } + + d_debug("query_interface_edit_controller => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + *iface = nullptr; + return V3_NO_INTERFACE; + } + + static uint32_t V3_API ref_edit_controller(void* const self) + { + dpf_edit_controller* const controller = *static_cast(self); + const int refcount = ++controller->refcounter; + d_debug("dpf_edit_controller::ref => %p | refcount %i", self, refcount); + return refcount; + } + + static uint32_t V3_API unref_edit_controller(void* const self) + { + dpf_edit_controller** const controllerptr = static_cast(self); + dpf_edit_controller* const controller = *controllerptr; + + if (const int refcount = --controller->refcounter) + { + d_debug("dpf_edit_controller::unref => %p | refcount %i", self, refcount); + return refcount; + } + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + /** + * Some hosts will have unclean instances of a few of the controller child classes at this point. + * We check for those here, going through the whole possible chain to see if it is safe to delete. + * If not, we add this controller to the `gControllerGarbage` global which will take care of it during unload. + */ + + bool unclean = false; + + if (dpf_comp2ctrl_connection_point* const point = controller->connectionComp2Ctrl) + { + if (const int refcount = point->refcounter) + { + unclean = true; + d_stderr("DPF warning: asked to delete controller while component connection point still active (refcount %d)", refcount); + } + } + + if (unclean) + return handleUncleanController(controllerptr); + + d_debug("dpf_edit_controller::unref => %p | refcount is zero, deleting everything now!", self); + + delete controller; + delete controllerptr; + #else + d_debug("dpf_edit_controller::unref => %p | refcount is zero, deletion will be done by component later", self); + #endif + return 0; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_plugin_base + + static v3_result V3_API initialize(void* const self, v3_funknown** const context) + { + dpf_edit_controller* const controller = *static_cast(self); + + // check if already initialized + #if DPF_VST3_USES_SEPARATE_CONTROLLER + DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 == nullptr, V3_INVALID_ARG); + #else + DISTRHO_SAFE_ASSERT_RETURN(! controller->initialized, V3_INVALID_ARG); + #endif + + // query for host application + v3_host_application** hostApplication = nullptr; + if (context != nullptr) + v3_cpp_obj_query_interface(context, v3_host_application_iid, &hostApplication); + + d_debug("dpf_edit_controller::initialize => %p %p | host %p", self, context, hostApplication); + + // save it for later so we can unref it + controller->hostApplicationFromInitialize = hostApplication; + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + // provide the factory application to the plugin if this new one is missing + if (hostApplication == nullptr) + hostApplication = controller->hostApplicationFromFactory; + + // default early values + if (d_nextBufferSize == 0) + d_nextBufferSize = 1024; + if (d_nextSampleRate <= 0.0) + d_nextSampleRate = 44100.0; + + d_nextCanRequestParameterValueChanges = true; + + // create the actual plugin + controller->vst3 = new PluginVst3(hostApplication, false); + + // set connection point if needed + if (dpf_comp2ctrl_connection_point* const point = controller->connectionComp2Ctrl) + { + if (point->other != nullptr) + controller->vst3->comp2ctrl_connect(point->other); + } + #else + // mark as initialized + controller->initialized = true; + #endif + + return V3_OK; + } + + static v3_result V3_API terminate(void* self) + { + d_debug("dpf_edit_controller::terminate => %p", self); + dpf_edit_controller* const controller = *static_cast(self); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + // check if already terminated + DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_INVALID_ARG); + + // delete actual plugin + controller->vst3 = nullptr; + #else + // check if already terminated + DISTRHO_SAFE_ASSERT_RETURN(controller->initialized, V3_INVALID_ARG); + + // mark as uninitialzed + controller->initialized = false; + #endif + + // unref host application received during initialize + if (controller->hostApplicationFromInitialize != nullptr) + { + v3_cpp_obj_unref(controller->hostApplicationFromInitialize); + controller->hostApplicationFromInitialize = nullptr; + } + + return V3_OK; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_edit_controller + + static v3_result V3_API set_component_state(void* const self, v3_bstream** const stream) + { + d_debug("dpf_edit_controller::set_component_state => %p %p", self, stream); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->setState(stream); + #else + return V3_OK; + + // unused + (void)self; + (void)stream; + #endif + } + + static v3_result V3_API set_state(void* const self, v3_bstream** const stream) + { + d_debug("dpf_edit_controller::set_state => %p %p", self, stream); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + dpf_edit_controller* const controller = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_NOT_INITIALIZED); + #endif + + return V3_NOT_IMPLEMENTED; + + // maybe unused + (void)self; + (void)stream; + } + + static v3_result V3_API get_state(void* const self, v3_bstream** const stream) + { + d_debug("dpf_edit_controller::get_state => %p %p", self, stream); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + dpf_edit_controller* const controller = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(controller->vst3 != nullptr, V3_NOT_INITIALIZED); + #endif + + return V3_NOT_IMPLEMENTED; + + // maybe unused + (void)self; + (void)stream; + } + + static int32_t V3_API get_parameter_count(void* self) + { + // d_debug("dpf_edit_controller::get_parameter_count => %p", self); + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->getParameterCount(); + } + + static v3_result V3_API get_parameter_info(void* self, int32_t param_idx, v3_param_info* param_info) + { + // d_debug("dpf_edit_controller::get_parameter_info => %p %i", self, param_idx); + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->getParameterInfo(param_idx, param_info); + } + + static v3_result V3_API get_parameter_string_for_value(void* self, v3_param_id index, double normalized, v3_str_128 output) + { + // NOTE very noisy, called many times + // d_debug("dpf_edit_controller::get_parameter_string_for_value => %p %u %f %p", self, index, normalized, output); + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->getParameterStringForValue(index, normalized, output); + } + + static v3_result V3_API get_parameter_value_for_string(void* self, v3_param_id index, int16_t* input, double* output) + { + d_debug("dpf_edit_controller::get_parameter_value_for_string => %p %u %p %p", self, index, input, output); + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->getParameterValueForString(index, input, output); + } + + static double V3_API normalised_parameter_to_plain(void* self, v3_param_id index, double normalized) + { + d_debug("dpf_edit_controller::normalised_parameter_to_plain => %p %u %f", self, index, normalized); + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->normalizedParameterToPlain(index, normalized); + } + + static double V3_API plain_parameter_to_normalised(void* self, v3_param_id index, double plain) + { + d_debug("dpf_edit_controller::plain_parameter_to_normalised => %p %u %f", self, index, plain); + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->plainParameterToNormalized(index, plain); + } + + static double V3_API get_parameter_normalised(void* self, v3_param_id index) + { + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, 0.0); + + return vst3->getParameterNormalized(index); + } + + static v3_result V3_API set_parameter_normalised(void* const self, const v3_param_id index, const double normalized) + { + // d_debug("dpf_edit_controller::set_parameter_normalised => %p %u %f", self, index, normalized); + dpf_edit_controller* const controller = *static_cast(self); + + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->setParameterNormalized(index, normalized); + } + + static v3_result V3_API set_component_handler(void* self, v3_component_handler** handler) + { + d_debug("dpf_edit_controller::set_component_handler => %p %p", self, handler); + dpf_edit_controller* const controller = *static_cast(self); + + controller->handler = handler; + + if (PluginVst3* const vst3 = controller->vst3) + return vst3->setComponentHandler(handler); + + return V3_NOT_INITIALIZED; + } + + static v3_plugin_view** V3_API create_view(void* self, const char* name) + { + d_debug("dpf_edit_controller::create_view => %p %s", self, name); + + #if DISTRHO_PLUGIN_HAS_UI + dpf_edit_controller* const controller = *static_cast(self); + + d_debug("create_view has contexts %p %p", + controller->hostApplicationFromFactory, controller->hostApplicationFromInitialize); + + // plugin must be initialized + PluginVst3* const vst3 = controller->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, nullptr); + + d_debug("dpf_edit_controller::create_view => %p %s | edit-ctrl %p, factory %p", + self, name, + controller->hostApplicationFromInitialize, + controller->hostApplicationFromFactory); + + // we require a host application for message creation + v3_host_application** const host = controller->hostApplicationFromInitialize != nullptr + ? controller->hostApplicationFromInitialize + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + : controller->hostApplicationFromComponent != nullptr + ? controller->hostApplicationFromComponent + : controller->hostApplicationFromComponentInitialize != nullptr + ? controller->hostApplicationFromComponentInitialize + #endif + : controller->hostApplicationFromFactory; + DISTRHO_SAFE_ASSERT_RETURN(host != nullptr, nullptr); + + v3_plugin_view** const view = dpf_plugin_view_create(host, + vst3->getInstancePointer(), + vst3->getSampleRate()); + DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, nullptr); + + v3_connection_point** uiconn = nullptr; + if (v3_cpp_obj_query_interface(view, v3_connection_point_iid, &uiconn) == V3_OK) + { + d_debug("view connection query ok %p", uiconn); + controller->connectionCtrl2View = new dpf_ctrl2view_connection_point(controller->vst3); + + v3_connection_point** const ctrlconn = (v3_connection_point**)&controller->connectionCtrl2View; + + v3_cpp_obj(uiconn)->connect(uiconn, ctrlconn); + v3_cpp_obj(ctrlconn)->connect(ctrlconn, uiconn); + } + else + { + controller->connectionCtrl2View = nullptr; + } + + return view; + #else + return nullptr; + #endif + + // maybe unused + (void)self; + (void)name; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_process_context_requirements + +struct dpf_process_context_requirements : v3_process_context_requirements_cpp { + dpf_process_context_requirements() + { + // v3_funknown, static + query_interface = query_interface_process_context_requirements; + ref = dpf_static_ref; + unref = dpf_static_unref; + + // v3_process_context_requirements + req.get_process_context_requirements = get_process_context_requirements; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_process_context_requirements(void* const self, const v3_tuid iid, void** const iface) + { + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_process_context_requirements_iid)) + { + d_debug("query_interface_process_context_requirements => %p %s %p | OK", self, tuid2str(iid), iface); + *iface = self; + return V3_OK; + } + + d_debug("query_interface_process_context_requirements => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = nullptr; + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_process_context_requirements + + static uint32_t V3_API get_process_context_requirements(void*) + { + #if DISTRHO_PLUGIN_WANT_TIMEPOS + return 0x0 + | V3_PROCESS_CTX_NEED_CONTINUOUS_TIME // V3_PROCESS_CTX_CONT_TIME_VALID + | V3_PROCESS_CTX_NEED_PROJECT_TIME // V3_PROCESS_CTX_PROJECT_TIME_VALID + | V3_PROCESS_CTX_NEED_TEMPO // V3_PROCESS_CTX_TEMPO_VALID + | V3_PROCESS_CTX_NEED_TIME_SIG // V3_PROCESS_CTX_TIME_SIG_VALID + | V3_PROCESS_CTX_NEED_TRANSPORT_STATE; // V3_PROCESS_CTX_PLAYING + #else + return 0x0; + #endif + } + + DISTRHO_PREVENT_HEAP_ALLOCATION +}; + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_audio_processor + +struct dpf_audio_processor : v3_audio_processor_cpp { + std::atomic_int refcounter; + ScopedPointer& vst3; + + dpf_audio_processor(ScopedPointer& v) + : refcounter(1), + vst3(v) + { + // v3_funknown, single instance + query_interface = query_interface_audio_processor; + ref = dpf_single_instance_ref; + unref = dpf_single_instance_unref; + + // v3_audio_processor + proc.set_bus_arrangements = set_bus_arrangements; + proc.get_bus_arrangement = get_bus_arrangement; + proc.can_process_sample_size = can_process_sample_size; + proc.get_latency_samples = get_latency_samples; + proc.setup_processing = setup_processing; + proc.set_processing = set_processing; + proc.process = process; + proc.get_tail_samples = get_tail_samples; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_audio_processor(void* const self, const v3_tuid iid, void** const iface) + { + dpf_audio_processor* const processor = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_audio_processor_iid)) + { + d_debug("query_interface_audio_processor => %p %s %p | OK", self, tuid2str(iid), iface); + ++processor->refcounter; + *iface = self; + return V3_OK; + } + + if (v3_tuid_match(iid, v3_process_context_requirements_iid)) + { + d_debug("query_interface_audio_processor => %p %s %p | OK convert static", self, tuid2str(iid), iface); + static dpf_process_context_requirements context_req; + static dpf_process_context_requirements* context_req_ptr = &context_req; + *iface = &context_req_ptr; + return V3_OK; + } + + d_debug("query_interface_audio_processor => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = nullptr; + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_audio_processor + + static v3_result V3_API set_bus_arrangements(void* const self, + v3_speaker_arrangement* const inputs, const int32_t num_inputs, + v3_speaker_arrangement* const outputs, const int32_t num_outputs) + { + // NOTE this is called a bunch of times in JUCE hosts + d_debug("dpf_audio_processor::set_bus_arrangements => %p %p %i %p %i", + self, inputs, num_inputs, outputs, num_outputs); + dpf_audio_processor* const processor = *static_cast(self); + + PluginVst3* const vst3 = processor->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return processor->vst3->setBusArrangements(inputs, num_inputs, outputs, num_outputs); + } + + static v3_result V3_API get_bus_arrangement(void* const self, const int32_t bus_direction, + const int32_t idx, v3_speaker_arrangement* const arr) + { + d_debug("dpf_audio_processor::get_bus_arrangement => %p %s %i %p", + self, v3_bus_direction_str(bus_direction), idx, arr); + dpf_audio_processor* const processor = *static_cast(self); + + PluginVst3* const vst3 = processor->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return processor->vst3->getBusArrangement(bus_direction, idx, arr); + } + + static v3_result V3_API can_process_sample_size(void*, const int32_t symbolic_sample_size) + { + // NOTE runs during RT + // d_debug("dpf_audio_processor::can_process_sample_size => %i", symbolic_sample_size); + return symbolic_sample_size == V3_SAMPLE_32 ? V3_OK : V3_NOT_IMPLEMENTED; + } + + static uint32_t V3_API get_latency_samples(void* const self) + { + d_debug("dpf_audio_processor::get_latency_samples => %p", self); + dpf_audio_processor* const processor = *static_cast(self); + + PluginVst3* const vst3 = processor->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, 0); + + return processor->vst3->getLatencySamples(); + } + + static v3_result V3_API setup_processing(void* const self, v3_process_setup* const setup) + { + d_debug("dpf_audio_processor::setup_processing => %p %p", self, setup); + dpf_audio_processor* const processor = *static_cast(self); + + PluginVst3* const vst3 = processor->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + d_debug("dpf_audio_processor::setup_processing => %p %p | %d %f", self, setup, setup->max_block_size, setup->sample_rate); + + d_nextBufferSize = setup->max_block_size; + d_nextSampleRate = setup->sample_rate; + return processor->vst3->setupProcessing(setup); + } + + static v3_result V3_API set_processing(void* const self, const v3_bool state) + { + d_debug("dpf_audio_processor::set_processing => %p %u", self, state); + dpf_audio_processor* const processor = *static_cast(self); + + PluginVst3* const vst3 = processor->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return processor->vst3->setProcessing(state); + } + + static v3_result V3_API process(void* const self, v3_process_data* const data) + { + // NOTE runs during RT + // d_debug("dpf_audio_processor::process => %p", self); + dpf_audio_processor* const processor = *static_cast(self); + + PluginVst3* const vst3 = processor->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return processor->vst3->process(data); + } + + static uint32_t V3_API get_tail_samples(void* const self) + { + d_debug("dpf_audio_processor::get_tail_samples => %p", self); + dpf_audio_processor* const processor = *static_cast(self); + + PluginVst3* const vst3 = processor->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, 0); + + return processor->vst3->getTailSamples(); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_component + +struct dpf_component : v3_component_cpp { + std::atomic_int refcounter; + ScopedPointer processor; + #if DPF_VST3_USES_SEPARATE_CONTROLLER + ScopedPointer connectionComp2Ctrl; + #else + ScopedPointer controller; + #endif + ScopedPointer vst3; + v3_host_application** const hostApplicationFromFactory; + v3_host_application** hostApplicationFromInitialize; + + dpf_component(v3_host_application** const host) + : refcounter(1), + hostApplicationFromFactory(host), + hostApplicationFromInitialize(nullptr) + { + d_debug("dpf_component() with hostApplication %p", hostApplicationFromFactory); + + // make sure host application is valid through out this component lifetime + if (hostApplicationFromFactory != nullptr) + v3_cpp_obj_ref(hostApplicationFromFactory); + + // v3_funknown, everything custom + query_interface = query_interface_component; + ref = ref_component; + unref = unref_component; + + // v3_plugin_base + base.initialize = initialize; + base.terminate = terminate; + + // v3_component + comp.get_controller_class_id = get_controller_class_id; + comp.set_io_mode = set_io_mode; + comp.get_bus_count = get_bus_count; + comp.get_bus_info = get_bus_info; + comp.get_routing_info = get_routing_info; + comp.activate_bus = activate_bus; + comp.set_active = set_active; + comp.set_state = set_state; + comp.get_state = get_state; + } + + ~dpf_component() + { + d_debug("~dpf_component()"); + processor = nullptr; + #if DPF_VST3_USES_SEPARATE_CONTROLLER + connectionComp2Ctrl = nullptr; + #else + controller = nullptr; + #endif + vst3 = nullptr; + + if (hostApplicationFromFactory != nullptr) + v3_cpp_obj_unref(hostApplicationFromFactory); + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_component(void* const self, const v3_tuid iid, void** const iface) + { + dpf_component* const component = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_plugin_base_iid) || + v3_tuid_match(iid, v3_component_iid)) + { + d_debug("query_interface_component => %p %s %p | OK", self, tuid2str(iid), iface); + ++component->refcounter; + *iface = self; + return V3_OK; + } + + if (v3_tuid_match(iid, v3_midi_mapping_iid)) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + d_debug("query_interface_component => %p %s %p | OK convert static", self, tuid2str(iid), iface); + static dpf_midi_mapping midi_mapping; + static dpf_midi_mapping* midi_mapping_ptr = &midi_mapping; + *iface = &midi_mapping_ptr; + return V3_OK; + #else + d_debug("query_interface_component => %p %s %p | reject unused", self, tuid2str(iid), iface); + *iface = nullptr; + return V3_NO_INTERFACE; + #endif + } + + if (v3_tuid_match(iid, v3_audio_processor_iid)) + { + d_debug("query_interface_component => %p %s %p | OK convert %p", + self, tuid2str(iid), iface, component->processor.get()); + + if (component->processor == nullptr) + component->processor = new dpf_audio_processor(component->vst3); + else + ++component->processor->refcounter; + *iface = &component->processor; + return V3_OK; + } + + if (v3_tuid_match(iid, v3_connection_point_iid)) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + d_debug("query_interface_component => %p %s %p | OK convert %p", + self, tuid2str(iid), iface, component->connectionComp2Ctrl.get()); + + if (component->connectionComp2Ctrl == nullptr) + component->connectionComp2Ctrl = new dpf_comp2ctrl_connection_point(component->vst3); + else + ++component->connectionComp2Ctrl->refcounter; + *iface = &component->connectionComp2Ctrl; + return V3_OK; + #else + d_debug("query_interface_component => %p %s %p | reject unwanted", self, tuid2str(iid), iface); + *iface = nullptr; + return V3_NO_INTERFACE; + #endif + } + + if (v3_tuid_match(iid, v3_edit_controller_iid)) + { + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + d_debug("query_interface_component => %p %s %p | OK convert %p", + self, tuid2str(iid), iface, component->controller.get()); + + if (component->controller == nullptr) + component->controller = new dpf_edit_controller(component->vst3, + component->hostApplicationFromFactory, + component->hostApplicationFromInitialize); + else + ++component->controller->refcounter; + *iface = &component->controller; + return V3_OK; + #else + d_debug("query_interface_component => %p %s %p | reject unwanted", self, tuid2str(iid), iface); + *iface = nullptr; + return V3_NO_INTERFACE; + #endif + } + + d_debug("query_interface_component => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + *iface = nullptr; + return V3_NO_INTERFACE; + } + + static uint32_t V3_API ref_component(void* const self) + { + dpf_component* const component = *static_cast(self); + const int refcount = ++component->refcounter; + d_debug("dpf_component::ref => %p | refcount %i", self, refcount); + return refcount; + } + + static uint32_t V3_API unref_component(void* const self) + { + dpf_component** const componentptr = static_cast(self); + dpf_component* const component = *componentptr; + + if (const int refcount = --component->refcounter) + { + d_debug("dpf_component::unref => %p | refcount %i", self, refcount); + return refcount; + } + + /** + * Some hosts will have unclean instances of a few of the component child classes at this point. + * We check for those here, going through the whole possible chain to see if it is safe to delete. + * If not, we add this component to the `gComponentGarbage` global which will take care of it during unload. + */ + + bool unclean = false; + + if (dpf_audio_processor* const proc = component->processor) + { + if (const int refcount = proc->refcounter) + { + unclean = true; + d_stderr("DPF warning: asked to delete component while audio processor still active (refcount %d)", refcount); + } + } + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + if (dpf_comp2ctrl_connection_point* const point = component->connectionComp2Ctrl) + { + if (const int refcount = point->refcounter) + { + unclean = true; + d_stderr("DPF warning: asked to delete component while connection point still active (refcount %d)", refcount); + } + } + #else + if (dpf_edit_controller* const controller = component->controller) + { + if (const int refcount = controller->refcounter) + { + unclean = true; + d_stderr("DPF warning: asked to delete component while edit controller still active (refcount %d)", refcount); + } + } + #endif + + if (unclean) + return handleUncleanComponent(componentptr); + + d_debug("dpf_component::unref => %p | refcount is zero, deleting everything now!", self); + + delete component; + delete componentptr; + return 0; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_plugin_base + + static v3_result V3_API initialize(void* const self, v3_funknown** const context) + { + dpf_component* const component = *static_cast(self); + + // check if already initialized + DISTRHO_SAFE_ASSERT_RETURN(component->vst3 == nullptr, V3_INVALID_ARG); + + // query for host application + v3_host_application** hostApplication = nullptr; + if (context != nullptr) + v3_cpp_obj_query_interface(context, v3_host_application_iid, &hostApplication); + + d_debug("dpf_component::initialize => %p %p | hostApplication %p", self, context, hostApplication); + + // save it for later so we can unref it + component->hostApplicationFromInitialize = hostApplication; + + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + // save it in edit controller too, needed for some hosts + if (component->controller != nullptr) + component->controller->hostApplicationFromComponentInitialize = hostApplication; + #endif + + // provide the factory application to the plugin if this new one is missing + if (hostApplication == nullptr) + hostApplication = component->hostApplicationFromFactory; + + // default early values + if (d_nextBufferSize == 0) + d_nextBufferSize = 1024; + if (d_nextSampleRate <= 0.0) + d_nextSampleRate = 44100.0; + + d_nextCanRequestParameterValueChanges = true; + + // create the actual plugin + component->vst3 = new PluginVst3(hostApplication, true); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + // set connection point if needed + if (dpf_comp2ctrl_connection_point* const point = component->connectionComp2Ctrl) + { + if (point->other != nullptr) + component->vst3->comp2ctrl_connect(point->other); + } + #endif + + return V3_OK; + } + + static v3_result V3_API terminate(void* const self) + { + d_debug("dpf_component::terminate => %p", self); + dpf_component* const component = *static_cast(self); + + // check if already terminated + DISTRHO_SAFE_ASSERT_RETURN(component->vst3 != nullptr, V3_INVALID_ARG); + + // delete actual plugin + component->vst3 = nullptr; + + #if !DPF_VST3_USES_SEPARATE_CONTROLLER + // remove previous host application saved during initialize + if (component->controller != nullptr) + component->controller->hostApplicationFromComponentInitialize = nullptr; + #endif + + // unref host application received during initialize + if (component->hostApplicationFromInitialize != nullptr) + { + v3_cpp_obj_unref(component->hostApplicationFromInitialize); + component->hostApplicationFromInitialize = nullptr; + } + + return V3_OK; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_component + + static v3_result V3_API get_controller_class_id(void*, v3_tuid class_id) + { + d_debug("dpf_component::get_controller_class_id => %p", class_id); + + std::memcpy(class_id, dpf_tuid_controller, sizeof(v3_tuid)); + return V3_OK; + } + + static v3_result V3_API set_io_mode(void* const self, const int32_t io_mode) + { + d_debug("dpf_component::set_io_mode => %p %i", self, io_mode); + + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + // TODO + return V3_NOT_IMPLEMENTED; + + // unused + (void)io_mode; + } + + static int32_t V3_API get_bus_count(void* const self, const int32_t media_type, const int32_t bus_direction) + { + // NOTE runs during RT + // d_debug("dpf_component::get_bus_count => %p %s %s", + // self, v3_media_type_str(media_type), v3_bus_direction_str(bus_direction)); + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + const int32_t ret = vst3->getBusCount(media_type, bus_direction); + // d_debug("dpf_component::get_bus_count returns %i", ret); + return ret; + } + + static v3_result V3_API get_bus_info(void* const self, const int32_t media_type, const int32_t bus_direction, + const int32_t bus_idx, v3_bus_info* const info) + { + d_debug("dpf_component::get_bus_info => %p %s %s %i %p", + self, v3_media_type_str(media_type), v3_bus_direction_str(bus_direction), bus_idx, info); + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->getBusInfo(media_type, bus_direction, bus_idx, info); + } + + static v3_result V3_API get_routing_info(void* const self, v3_routing_info* const input, v3_routing_info* const output) + { + d_debug("dpf_component::get_routing_info => %p %p %p", self, input, output); + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->getRoutingInfo(input, output); + } + + static v3_result V3_API activate_bus(void* const self, const int32_t media_type, const int32_t bus_direction, + const int32_t bus_idx, const v3_bool state) + { + // NOTE this is called a bunch of times + // d_debug("dpf_component::activate_bus => %p %s %s %i %u", + // self, v3_media_type_str(media_type), v3_bus_direction_str(bus_direction), bus_idx, state); + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->activateBus(media_type, bus_direction, bus_idx, state); + } + + static v3_result V3_API set_active(void* const self, const v3_bool state) + { + d_debug("dpf_component::set_active => %p %u", self, state); + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return component->vst3->setActive(state); + } + + static v3_result V3_API set_state(void* const self, v3_bstream** const stream) + { + d_debug("dpf_component::set_state => %p", self); + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->setState(stream); + } + + static v3_result V3_API get_state(void* const self, v3_bstream** const stream) + { + d_debug("dpf_component::get_state => %p %p", self, stream); + dpf_component* const component = *static_cast(self); + + PluginVst3* const vst3 = component->vst3; + DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALIZED); + + return vst3->getState(stream); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- +// Dummy plugin to get data from + +static ScopedPointer sPlugin; + +static const char* getPluginCategories() +{ + static String categories; + static bool firstInit = true; + + if (firstInit) + { + #ifdef DISTRHO_PLUGIN_VST3_CATEGORIES + categories = DISTRHO_PLUGIN_VST3_CATEGORIES; + #elif DISTRHO_PLUGIN_IS_SYNTH + categories = "Instrument"; + #endif + firstInit = false; + } + + return categories.buffer(); +} + +static const char* getPluginVersion() +{ + static String version; + + if (version.isEmpty()) + { + const uint32_t versionNum = sPlugin->getVersion(); + + char versionBuf[64]; + std::snprintf(versionBuf, sizeof(versionBuf)-1, "%d.%d.%d", + (versionNum >> 16) & 0xff, + (versionNum >> 8) & 0xff, + (versionNum >> 0) & 0xff); + versionBuf[sizeof(versionBuf)-1] = '\0'; + version = versionBuf; + } + + return version.buffer(); +} + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_factory + +struct dpf_factory : v3_plugin_factory_cpp { + std::atomic_int refcounter; + + // cached values + v3_funknown** hostContext; + + dpf_factory() + : refcounter(1), + hostContext(nullptr) + { + // v3_funknown, static + query_interface = query_interface_factory; + ref = ref_factory; + unref = unref_factory; + + // v3_plugin_factory + v1.get_factory_info = get_factory_info; + v1.num_classes = num_classes; + v1.get_class_info = get_class_info; + v1.create_instance = create_instance; + + // v3_plugin_factory_2 + v2.get_class_info_2 = get_class_info_2; + + // v3_plugin_factory_3 + v3.get_class_info_utf16 = get_class_info_utf16; + v3.set_host_context = set_host_context; + } + + ~dpf_factory() + { + // unref old context if there is one + if (hostContext != nullptr) + v3_cpp_obj_unref(hostContext); + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + if (gControllerGarbage.size() != 0) + { + d_debug("DPF notice: cleaning up previously undeleted controllers now"); + + for (std::vector::iterator it = gControllerGarbage.begin(); + it != gControllerGarbage.end(); ++it) + { + dpf_edit_controller** const controllerptr = *it; + dpf_edit_controller* const controller = *controllerptr; + delete controller; + delete controllerptr; + } + + gControllerGarbage.clear(); + } + #endif + + if (gComponentGarbage.size() != 0) + { + d_debug("DPF notice: cleaning up previously undeleted components now"); + + for (std::vector::iterator it = gComponentGarbage.begin(); + it != gComponentGarbage.end(); ++it) + { + dpf_component** const componentptr = *it; + dpf_component* const component = *componentptr; + delete component; + delete componentptr; + } + + gComponentGarbage.clear(); + } + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_factory(void* const self, const v3_tuid iid, void** const iface) + { + dpf_factory* const factory = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_plugin_factory_iid) || + v3_tuid_match(iid, v3_plugin_factory_2_iid) || + v3_tuid_match(iid, v3_plugin_factory_3_iid)) + { + d_debug("query_interface_factory => %p %s %p | OK", self, tuid2str(iid), iface); + ++factory->refcounter; + *iface = self; + return V3_OK; + } + + d_debug("query_interface_factory => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = nullptr; + return V3_NO_INTERFACE; + } + + static uint32_t V3_API ref_factory(void* const self) + { + dpf_factory* const factory = *static_cast(self); + const int refcount = ++factory->refcounter; + d_debug("ref_factory::ref => %p | refcount %i", self, refcount); + return refcount; + } + + static uint32_t V3_API unref_factory(void* const self) + { + dpf_factory** const factoryptr = static_cast(self); + dpf_factory* const factory = *factoryptr; + + if (const int refcount = --factory->refcounter) + { + d_debug("unref_factory::unref => %p | refcount %i", self, refcount); + return refcount; + } + + d_debug("unref_factory::unref => %p | refcount is zero, deleting factory", self); + + delete factory; + delete factoryptr; + return 0; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_plugin_factory + + static v3_result V3_API get_factory_info(void*, v3_factory_info* const info) + { + d_debug("dpf_factory::get_factory_info => %p", info); + std::memset(info, 0, sizeof(*info)); + + info->flags = 0x10; // unicode + d_strncpy(info->vendor, sPlugin->getMaker(), ARRAY_SIZE(info->vendor)); + d_strncpy(info->url, sPlugin->getHomePage(), ARRAY_SIZE(info->url)); + // d_strncpy(info->email, "", ARRAY_SIZE(info->email)); // TODO + return V3_OK; + } + + static int32_t V3_API num_classes(void*) + { + d_debug("dpf_factory::num_classes"); + #if DPF_VST3_USES_SEPARATE_CONTROLLER + return 2; // factory can create component and edit-controller + #else + return 1; // factory can only create component, edit-controller must be casted + #endif + } + + static v3_result V3_API get_class_info(void*, const int32_t idx, v3_class_info* const info) + { + d_debug("dpf_factory::get_class_info => %i %p", idx, info); + std::memset(info, 0, sizeof(*info)); + DISTRHO_SAFE_ASSERT_RETURN(idx <= 2, V3_INVALID_ARG); + + info->cardinality = 0x7FFFFFFF; + d_strncpy(info->name, sPlugin->getName(), ARRAY_SIZE(info->name)); + + if (idx == 0) + { + std::memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid)); + d_strncpy(info->category, "Audio Module Class", ARRAY_SIZE(info->category)); + } + else + { + std::memcpy(info->class_id, dpf_tuid_controller, sizeof(v3_tuid)); + d_strncpy(info->category, "Component Controller Class", ARRAY_SIZE(info->category)); + } + + return V3_OK; + } + + static v3_result V3_API create_instance(void* self, const v3_tuid class_id, const v3_tuid iid, void** const instance) + { + d_debug("dpf_factory::create_instance => %p %s %s %p", self, tuid2str(class_id), tuid2str(iid), instance); + dpf_factory* const factory = *static_cast(self); + + // query for host application + v3_host_application** hostApplication = nullptr; + if (factory->hostContext != nullptr) + v3_cpp_obj_query_interface(factory->hostContext, v3_host_application_iid, &hostApplication); + + // create component + if (v3_tuid_match(class_id, *(const v3_tuid*)&dpf_tuid_class) && (v3_tuid_match(iid, v3_component_iid) || + v3_tuid_match(iid, v3_funknown_iid))) + { + dpf_component** const componentptr = new dpf_component*; + *componentptr = new dpf_component(hostApplication); + *instance = static_cast(componentptr); + return V3_OK; + } + + #if DPF_VST3_USES_SEPARATE_CONTROLLER + // create edit controller + if (v3_tuid_match(class_id, *(const v3_tuid*)&dpf_tuid_controller) && (v3_tuid_match(iid, v3_edit_controller_iid) || + v3_tuid_match(iid, v3_funknown_iid))) + { + dpf_edit_controller** const controllerptr = new dpf_edit_controller*; + *controllerptr = new dpf_edit_controller(hostApplication); + *instance = static_cast(controllerptr); + return V3_OK; + } + #endif + + // unsupported, roll back host application + if (hostApplication != nullptr) + v3_cpp_obj_unref(hostApplication); + + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_plugin_factory_2 + + static v3_result V3_API get_class_info_2(void*, const int32_t idx, v3_class_info_2* const info) + { + d_debug("dpf_factory::get_class_info_2 => %i %p", idx, info); + std::memset(info, 0, sizeof(*info)); + DISTRHO_SAFE_ASSERT_RETURN(idx <= 2, V3_INVALID_ARG); + + info->cardinality = 0x7FFFFFFF; + #if DPF_VST3_USES_SEPARATE_CONTROLLER || !DISTRHO_PLUGIN_HAS_UI + info->class_flags = V3_DISTRIBUTABLE; + #endif + d_strncpy(info->sub_categories, getPluginCategories(), ARRAY_SIZE(info->sub_categories)); + d_strncpy(info->name, sPlugin->getName(), ARRAY_SIZE(info->name)); + d_strncpy(info->vendor, sPlugin->getMaker(), ARRAY_SIZE(info->vendor)); + d_strncpy(info->version, getPluginVersion(), ARRAY_SIZE(info->version)); + d_strncpy(info->sdk_version, "VST 3.7.4", ARRAY_SIZE(info->sdk_version)); + + if (idx == 0) + { + std::memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid)); + d_strncpy(info->category, "Audio Module Class", ARRAY_SIZE(info->category)); + } + else + { + std::memcpy(info->class_id, dpf_tuid_controller, sizeof(v3_tuid)); + d_strncpy(info->category, "Component Controller Class", ARRAY_SIZE(info->category)); + } + + return V3_OK; + } + + // ------------------------------------------------------------------------------------------------------------ + // v3_plugin_factory_3 + + static v3_result V3_API get_class_info_utf16(void*, const int32_t idx, v3_class_info_3* const info) + { + d_debug("dpf_factory::get_class_info_utf16 => %i %p", idx, info); + std::memset(info, 0, sizeof(*info)); + DISTRHO_SAFE_ASSERT_RETURN(idx <= 2, V3_INVALID_ARG); + + info->cardinality = 0x7FFFFFFF; + #if DPF_VST3_USES_SEPARATE_CONTROLLER || !DISTRHO_PLUGIN_HAS_UI + info->class_flags = V3_DISTRIBUTABLE; + #endif + d_strncpy(info->sub_categories, getPluginCategories(), ARRAY_SIZE(info->sub_categories)); + DISTRHO_NAMESPACE::strncpy_utf16(info->name, sPlugin->getName(), ARRAY_SIZE(info->name)); + DISTRHO_NAMESPACE::strncpy_utf16(info->vendor, sPlugin->getMaker(), ARRAY_SIZE(info->vendor)); + DISTRHO_NAMESPACE::strncpy_utf16(info->version, getPluginVersion(), ARRAY_SIZE(info->version)); + DISTRHO_NAMESPACE::strncpy_utf16(info->sdk_version, "Travesty 3.7.4", ARRAY_SIZE(info->sdk_version)); + + if (idx == 0) + { + std::memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid)); + d_strncpy(info->category, "Audio Module Class", ARRAY_SIZE(info->category)); + } + else + { + std::memcpy(info->class_id, dpf_tuid_controller, sizeof(v3_tuid)); + d_strncpy(info->category, "Component Controller Class", ARRAY_SIZE(info->category)); + } + + return V3_OK; + } + + static v3_result V3_API set_host_context(void* const self, v3_funknown** const context) + { + d_debug("dpf_factory::set_host_context => %p %p", self, context); + dpf_factory* const factory = *static_cast(self); + + // unref old context if there is one + if (factory->hostContext != nullptr) + v3_cpp_obj_unref(factory->hostContext); + + // store new context + factory->hostContext = context; + + // make sure the object keeps being valid for a while + if (context != nullptr) + v3_cpp_obj_ref(context); + + return V3_OK; + } +}; + +END_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- +// VST3 entry point + +DISTRHO_PLUGIN_EXPORT +const void* GetPluginFactory(void); + +const void* GetPluginFactory(void) +{ + USE_NAMESPACE_DISTRHO; + dpf_factory** const factoryptr = new dpf_factory*; + *factoryptr = new dpf_factory; + return static_cast(factoryptr); +} + +// -------------------------------------------------------------------------------------------------------------------- +// OS specific module load + +#if defined(DISTRHO_OS_MAC) +# define ENTRYFNNAME bundleEntry +# define ENTRYFNNAMEARGS void* +# define EXITFNNAME bundleExit +#elif defined(DISTRHO_OS_WINDOWS) +# define ENTRYFNNAME InitDll +# define ENTRYFNNAMEARGS void +# define EXITFNNAME ExitDll +#else +# define ENTRYFNNAME ModuleEntry +# define ENTRYFNNAMEARGS void* +# define EXITFNNAME ModuleExit +#endif + +DISTRHO_PLUGIN_EXPORT +bool ENTRYFNNAME(ENTRYFNNAMEARGS); + +bool ENTRYFNNAME(ENTRYFNNAMEARGS) +{ + USE_NAMESPACE_DISTRHO; + + // find plugin bundle + static String bundlePath; + if (bundlePath.isEmpty()) + { + String tmpPath(getBinaryFilename()); + tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP)); + tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP)); + + if (tmpPath.endsWith(DISTRHO_OS_SEP_STR "Contents")) + { + tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP)); + bundlePath = tmpPath; + d_nextBundlePath = bundlePath.buffer(); + } + else + { + bundlePath = "error"; + } + } + + // init dummy plugin and set uniqueId + if (sPlugin == nullptr) + { + // set valid but dummy values + d_nextBufferSize = 512; + d_nextSampleRate = 44100.0; + d_nextPluginIsDummy = true; + d_nextCanRequestParameterValueChanges = true; + + // Create dummy plugin to get data from + sPlugin = new PluginExporter(nullptr, nullptr, nullptr, nullptr); + + // unset + d_nextBufferSize = 0; + d_nextSampleRate = 0.0; + d_nextPluginIsDummy = false; + d_nextCanRequestParameterValueChanges = false; + + dpf_tuid_class[2] = dpf_tuid_component[2] = dpf_tuid_controller[2] + = dpf_tuid_processor[2] = dpf_tuid_view[2] = sPlugin->getUniqueId(); + } + + return true; +} + +DISTRHO_PLUGIN_EXPORT +bool EXITFNNAME(void); + +bool EXITFNNAME(void) +{ + DISTRHO_NAMESPACE::sPlugin = nullptr; + return true; +} + +#undef ENTRYFNNAME +#undef EXITFNNAME + +// -------------------------------------------------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUI.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUI.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,463 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoDetails.hpp" +#include "src/DistrhoPluginChecks.h" +#include "src/DistrhoDefines.h" + +#include + +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# include +#else +# include +#endif + +#if DISTRHO_UI_FILE_BROWSER && !defined(DISTRHO_OS_MAC) +# define DISTRHO_PUGL_NAMESPACE_MACRO_HELPER(NS, SEP, FUNCTION) NS ## SEP ## FUNCTION +# define DISTRHO_PUGL_NAMESPACE_MACRO(NS, FUNCTION) DISTRHO_PUGL_NAMESPACE_MACRO_HELPER(NS, _, FUNCTION) +# define x_fib_add_recent DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_add_recent) +# define x_fib_cfg_buttons DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_cfg_buttons) +# define x_fib_cfg_filter_callback DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_cfg_filter_callback) +# define x_fib_close DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_close) +# define x_fib_configure DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_configure) +# define x_fib_filename DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_filename) +# define x_fib_free_recent DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_free_recent) +# define x_fib_handle_events DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_handle_events) +# define x_fib_load_recent DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_load_recent) +# define x_fib_recent_at DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_recent_at) +# define x_fib_recent_count DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_recent_count) +# define x_fib_recent_file DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_recent_file) +# define x_fib_save_recent DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_save_recent) +# define x_fib_show DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_show) +# define x_fib_status DISTRHO_PUGL_NAMESPACE_MACRO(plugin, x_fib_status) +# define DISTRHO_FILE_BROWSER_DIALOG_HPP_INCLUDED +# define FILE_BROWSER_DIALOG_NAMESPACE DISTRHO_NAMESPACE +# define FILE_BROWSER_DIALOG_DISTRHO_NAMESPACE +START_NAMESPACE_DISTRHO +# include "../extra/FileBrowserDialogImpl.hpp" +END_NAMESPACE_DISTRHO +# include "../extra/FileBrowserDialogImpl.cpp" +#endif + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# if defined(DISTRHO_OS_WINDOWS) +# include +# include +# elif defined(HAVE_X11) +# include +# endif +#else +# include "src/TopLevelWidgetPrivateData.hpp" +# include "src/WindowPrivateData.hpp" +#endif + +#include "DistrhoUIPrivateData.hpp" + +START_NAMESPACE_DISTRHO + +/* ------------------------------------------------------------------------------------------------------------ + * Static data, see DistrhoUIInternal.hpp */ + +const char* g_nextBundlePath = nullptr; +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +uintptr_t g_nextWindowId = 0; +double g_nextScaleFactor = 1.0; +#endif + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +/* ------------------------------------------------------------------------------------------------------------ + * get global scale factor */ + +#ifdef DISTRHO_OS_MAC +double getDesktopScaleFactor(uintptr_t parentWindowHandle); +#else +static double getDesktopScaleFactor(const uintptr_t parentWindowHandle) +{ + // allow custom scale for testing + if (const char* const scale = getenv("DPF_SCALE_FACTOR")) + return std::max(1.0, std::atof(scale)); + +#if defined(DISTRHO_OS_WINDOWS) + if (const HMODULE Shcore = LoadLibraryA("Shcore.dll")) + { + typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*); + typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*); + +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-function-type" +# endif + const PFN_GetProcessDpiAwareness GetProcessDpiAwareness + = (PFN_GetProcessDpiAwareness)GetProcAddress(Shcore, "GetProcessDpiAwareness"); + const PFN_GetScaleFactorForMonitor GetScaleFactorForMonitor + = (PFN_GetScaleFactorForMonitor)GetProcAddress(Shcore, "GetScaleFactorForMonitor"); +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic pop +# endif + + DWORD dpiAware = 0; + DWORD scaleFactor = 100; + if (GetProcessDpiAwareness && GetScaleFactorForMonitor + && GetProcessDpiAwareness(nullptr, &dpiAware) == 0 && dpiAware != 0) + { + const HMONITOR hMon = parentWindowHandle != 0 + ? MonitorFromWindow((HWND)parentWindowHandle, MONITOR_DEFAULTTOPRIMARY) + : MonitorFromPoint(POINT{0,0}, MONITOR_DEFAULTTOPRIMARY); + GetScaleFactorForMonitor(hMon, &scaleFactor); + } + + FreeLibrary(Shcore); + return static_cast(scaleFactor) / 100.0; + } +#elif defined(HAVE_X11) + ::Display* const display = XOpenDisplay(nullptr); + DISTRHO_SAFE_ASSERT_RETURN(display != nullptr, 1.0); + + XrmInitialize(); + + double dpi = 96.0; + if (char* const rms = XResourceManagerString(display)) + { + if (const XrmDatabase db = XrmGetStringDatabase(rms)) + { + char* type = nullptr; + XrmValue value = {}; + + if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) + && type != nullptr + && std::strcmp(type, "String") == 0 + && value.addr != nullptr) + { + char* end = nullptr; + const double xftDpi = std::strtod(value.addr, &end); + if (xftDpi > 0.0 && xftDpi < HUGE_VAL) + dpi = xftDpi; + } + + XrmDestroyDatabase(db); + } + } + + XCloseDisplay(display); + return dpi / 96; +#endif + + return 1.0; + + // might be unused + (void)parentWindowHandle; +} +#endif // !DISTRHO_OS_MAC + +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * UI::PrivateData special handling */ + +UI::PrivateData* UI::PrivateData::s_nextPrivateData = nullptr; + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +ExternalWindow::PrivateData +#else +PluginWindow& +#endif +UI::PrivateData::createNextWindow(UI* const ui, uint width, uint height, const bool adjustForScaleFactor) +{ + UI::PrivateData* const pData = s_nextPrivateData; + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + const double scaleFactor = d_isNotZero(pData->scaleFactor) ? pData->scaleFactor : getDesktopScaleFactor(pData->winId); + + if (adjustForScaleFactor && d_isNotZero(scaleFactor) && d_isNotEqual(scaleFactor, 1.0)) + { + width *= scaleFactor; + height *= scaleFactor; + } + + pData->window = new PluginWindow(ui, pData->app); + ExternalWindow::PrivateData ewData; + ewData.parentWindowHandle = pData->winId; + ewData.width = width; + ewData.height = height; + ewData.scaleFactor = scaleFactor; + ewData.title = DISTRHO_PLUGIN_NAME; + ewData.isStandalone = DISTRHO_UI_IS_STANDALONE; + return ewData; + #else + const double scaleFactor = pData->scaleFactor; + + if (adjustForScaleFactor && d_isNotZero(scaleFactor) && d_isNotEqual(scaleFactor, 1.0)) + { + width *= scaleFactor; + height *= scaleFactor; + } + + pData->window = new PluginWindow(ui, pData->app, pData->winId, width, height, scaleFactor); + + // If there are no callbacks, this is most likely a temporary window, so ignore idle callbacks + if (pData->callbacksPtr == nullptr) + pData->window->setIgnoreIdleCallbacks(); + + return pData->window.getObject(); + #endif +} + +/* ------------------------------------------------------------------------------------------------------------ + * UI */ + +UI::UI(const uint width, const uint height, const bool automaticallyScaleAndSetAsMinimumSize) + : UIWidget(UI::PrivateData::createNextWindow(this, + #ifdef DISTRHO_UI_DEFAULT_WIDTH + width == 0 ? DISTRHO_UI_DEFAULT_WIDTH : + #endif + width, + #ifdef DISTRHO_UI_DEFAULT_HEIGHT + height == 0 ? DISTRHO_UI_DEFAULT_HEIGHT : + #endif + height, + #ifdef DISTRHO_UI_DEFAULT_WIDTH + width == 0 + #else + false + #endif + )), + uiData(UI::PrivateData::s_nextPrivateData) +{ +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + if (width != 0 && height != 0) + { + Widget::setSize(width, height); + + if (automaticallyScaleAndSetAsMinimumSize) + setGeometryConstraints(width, height, true, true, true); + } + #ifdef DISTRHO_UI_DEFAULT_WIDTH + else + { + Widget::setSize(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT); + } + #endif +#else + // unused + (void)automaticallyScaleAndSetAsMinimumSize; +#endif +} + +UI::~UI() +{ +} + +/* ------------------------------------------------------------------------------------------------------------ + * Host state */ + +bool UI::isResizable() const noexcept +{ +#if DISTRHO_UI_USER_RESIZABLE +# if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + return true; +# else + return uiData->window->isResizable(); +# endif +#else + return false; +#endif +} + +uint UI::getBackgroundColor() const noexcept +{ + return uiData->bgColor; +} + +uint UI::getForegroundColor() const noexcept +{ + return uiData->fgColor; +} + +double UI::getSampleRate() const noexcept +{ + return uiData->sampleRate; +} + +const char* UI::getBundlePath() const noexcept +{ + return uiData->bundlePath; +} + +void UI::editParameter(uint32_t index, bool started) +{ + uiData->editParamCallback(index + uiData->parameterOffset, started); +} + +void UI::setParameterValue(uint32_t index, float value) +{ + uiData->setParamCallback(index + uiData->parameterOffset, value); +} + +#if DISTRHO_PLUGIN_WANT_STATE +void UI::setState(const char* key, const char* value) +{ + uiData->setStateCallback(key, value); +} +#endif + +#if DISTRHO_PLUGIN_WANT_STATE +bool UI::requestStateFile(const char* key) +{ + return uiData->fileRequestCallback(key); +} +#endif + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT +void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity) +{ + uiData->sendNoteCallback(channel, note, velocity); +} +#endif + +#if DISTRHO_UI_FILE_BROWSER +bool UI::openFileBrowser(const FileBrowserOptions& options) +{ + return getWindow().openFileBrowser((DGL_NAMESPACE::FileBrowserOptions&)options); +} +#endif + +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS +/* ------------------------------------------------------------------------------------------------------------ + * Direct DSP access */ + +void* UI::getPluginInstancePointer() const noexcept +{ + return uiData->dspPtr; +} +#endif + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +/* ------------------------------------------------------------------------------------------------------------ + * External UI helpers (static calls) */ + +const char* UI::getNextBundlePath() noexcept +{ + return g_nextBundlePath; +} + +double UI::getNextScaleFactor() noexcept +{ + return g_nextScaleFactor; +} + +# if DISTRHO_PLUGIN_HAS_EMBED_UI +uintptr_t UI::getNextWindowId() noexcept +{ + return g_nextWindowId; +} +# endif +#endif // DISTRHO_PLUGIN_HAS_EXTERNAL_UI + +/* ------------------------------------------------------------------------------------------------------------ + * DSP/Plugin Callbacks (optional) */ + +void UI::sampleRateChanged(double) +{ +} + +/* ------------------------------------------------------------------------------------------------------------ + * UI Callbacks (optional) */ + +void UI::uiScaleFactorChanged(double) +{ +} + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI +std::vector UI::getClipboardDataOfferTypes() +{ + return uiData->window->getClipboardDataOfferTypes(); +} + +uint32_t UI::uiClipboardDataOffer() +{ + std::vector offers(uiData->window->getClipboardDataOfferTypes()); + + for (std::vector::iterator it=offers.begin(), end=offers.end(); it != end;++it) + { + const DGL_NAMESPACE::ClipboardDataOffer offer = *it; + if (std::strcmp(offer.type, "text/plain") == 0) + return offer.id; + } + + return 0; +} + +void UI::uiFocus(bool, DGL_NAMESPACE::CrossingMode) +{ +} + +void UI::uiReshape(uint, uint) +{ + // NOTE this must be the same as Window::onReshape + pData->fallbackOnResize(); +} +#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + +#if DISTRHO_UI_FILE_BROWSER +void UI::uiFileBrowserSelected(const char*) +{ +} +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * UI Resize Handling, internal */ + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +void UI::sizeChanged(const uint width, const uint height) +{ + UIWidget::sizeChanged(width, height); + + uiData->setSizeCallback(width, height); +} +#else +void UI::onResize(const ResizeEvent& ev) +{ + UIWidget::onResize(ev); + + #if !(defined(DISTRHO_PLUGIN_TARGET_VST3) || defined(DISTRHO_PLUGIN_TARGET_CLAP)) + if (uiData->initializing) + return; + + const uint width = ev.size.getWidth(); + const uint height = ev.size.getHeight(); + uiData->setSizeCallback(width, height); + #endif +} + +// NOTE: only used for VST3 and CLAP +void UI::requestSizeChange(const uint width, const uint height) +{ + #if defined(DISTRHO_PLUGIN_TARGET_VST3) || defined(DISTRHO_PLUGIN_TARGET_CLAP) + if (uiData->initializing) + uiData->window->setSizeFromHost(width, height); + else + uiData->setSizeCallback(width, height); + #else + // unused + (void)width; + (void)height; + #endif +} +#endif + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIDSSI.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIDSSI.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,517 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoUIInternal.hpp" + +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS +# error DSSI UIs do not support direct access! +#endif + +#include "../extra/Sleep.hpp" + +#include + +START_NAMESPACE_DISTRHO + +#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static constexpr const sendNoteFunc sendNoteCallback = nullptr; +#endif + +// ----------------------------------------------------------------------- + +struct OscData { + lo_address addr; + const char* path; + lo_server server; + + OscData() + : addr(nullptr), + path(nullptr), + server(nullptr) {} + + void idle() const + { + if (server == nullptr) + return; + + while (lo_server_recv_noblock(server, 0) != 0) {} + } + + void send_configure(const char* const key, const char* const value) const + { + char targetPath[std::strlen(path)+11]; + std::strcpy(targetPath, path); + std::strcat(targetPath, "/configure"); + lo_send(addr, targetPath, "ss", key, value); + } + + void send_control(const int32_t index, const float value) const + { + char targetPath[std::strlen(path)+9]; + std::strcpy(targetPath, path); + std::strcat(targetPath, "/control"); + lo_send(addr, targetPath, "if", index, value); + } + + void send_midi(uchar data[4]) const + { + char targetPath[std::strlen(path)+6]; + std::strcpy(targetPath, path); + std::strcat(targetPath, "/midi"); + lo_send(addr, targetPath, "m", data); + } + + void send_update(const char* const url) const + { + char targetPath[std::strlen(path)+8]; + std::strcpy(targetPath, path); + std::strcat(targetPath, "/update"); + lo_send(addr, targetPath, "s", url); + } + + void send_exiting() const + { + char targetPath[std::strlen(path)+9]; + std::strcpy(targetPath, path); + std::strcat(targetPath, "/exiting"); + lo_send(addr, targetPath, ""); + } +}; + +// ----------------------------------------------------------------------- + +class UIDssi : public DGL_NAMESPACE::IdleCallback +{ +public: + UIDssi(const OscData& oscData, const char* const uiTitle, const double sampleRate) + : fUI(this, 0, sampleRate, nullptr, + setParameterCallback, setStateCallback, sendNoteCallback, nullptr, nullptr), + fHostClosed(false), + fOscData(oscData) + { + fUI.setWindowTitle(uiTitle); + } + + ~UIDssi() + { + if (fOscData.server != nullptr && ! fHostClosed) + fOscData.send_exiting(); + } + + void exec_start() + { + fUI.exec(this); + } + + void idleCallback() override + { + fOscData.idle(); + + if (fHostClosed) + return; + + fUI.exec_idle(); + } + + // ------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_STATE + void dssiui_configure(const char* key, const char* value) + { + fUI.stateChanged(key, value); + } +#endif + + void dssiui_control(ulong index, float value) + { + fUI.parameterChanged(index, value); + } + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + void dssiui_program(ulong bank, ulong program) + { + fUI.programLoaded(bank * 128 + program); + } +#endif + + void dssiui_samplerate(const double sampleRate) + { + fUI.setSampleRate(sampleRate, true); + } + + void dssiui_show(const bool focus = false) + { + fUI.setWindowVisible(true); + + if (focus) + fUI.focus(); + } + + void dssiui_hide() + { + fUI.setWindowVisible(false); + } + + void dssiui_quit() + { + fHostClosed = true; + fUI.quit(); + } + + // ------------------------------------------------------------------- + +protected: + void setParameterValue(const uint32_t rindex, const float value) + { + if (fOscData.server == nullptr) + return; + + fOscData.send_control(rindex, value); + } + + void setState(const char* const key, const char* const value) + { + if (fOscData.server == nullptr) + return; + + fOscData.send_configure(key, value); + } + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + if (fOscData.server == nullptr) + return; + if (channel > 0xF) + return; + + uint8_t mdata[4] = { + 0, + static_cast(channel + (velocity != 0 ? 0x90 : 0x80)), + note, + velocity + }; + fOscData.send_midi(mdata); + } +#endif + +private: + UIExporter fUI; + bool fHostClosed; + + const OscData& fOscData; + + // ------------------------------------------------------------------- + // Callbacks + + #define uiPtr ((UIDssi*)ptr) + + static void setParameterCallback(void* ptr, uint32_t rindex, float value) + { + uiPtr->setParameterValue(rindex, value); + } + + static void setStateCallback(void* ptr, const char* key, const char* value) + { + uiPtr->setState(key, value); + } + +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity) + { + uiPtr->sendNote(channel, note, velocity); + } +#endif + + #undef uiPtr +}; + +// ----------------------------------------------------------------------- + +static OscData gOscData; +static const char* gUiTitle = nullptr; +static UIDssi* globalUI = nullptr; +static double sampleRate = 0.0; + +static void initUiIfNeeded() +{ + if (globalUI != nullptr) + return; + + if (sampleRate == 0.0) + sampleRate = 44100.0; + + globalUI = new UIDssi(gOscData, gUiTitle, sampleRate); +} + +// ----------------------------------------------------------------------- + +int osc_debug_handler(const char* path, const char*, lo_arg**, int, lo_message, void*) +{ + d_debug("osc_debug_handler(\"%s\")", path); + return 0; + +#ifndef DEBUG + // unused + (void)path; +#endif +} + +void osc_error_handler(int num, const char* msg, const char* path) +{ + d_stderr("osc_error_handler(%i, \"%s\", \"%s\")", num, msg, path); +} + +#if DISTRHO_PLUGIN_WANT_STATE +int osc_configure_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*) +{ + const char* const key = &argv[0]->s; + const char* const value = &argv[1]->s; + d_debug("osc_configure_handler(\"%s\", \"%s\")", key, value); + + initUiIfNeeded(); + + globalUI->dssiui_configure(key, value); + + return 0; +} +#endif + +int osc_control_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*) +{ + const int32_t rindex = argv[0]->i; + const float value = argv[1]->f; + d_debug("osc_control_handler(%i, %f)", rindex, value); + + int32_t index = rindex - DISTRHO_PLUGIN_NUM_INPUTS - DISTRHO_PLUGIN_NUM_OUTPUTS; + + // latency +#if DISTRHO_PLUGIN_WANT_LATENCY + index -= 1; +#endif + + if (index < 0) + return 0; + + initUiIfNeeded(); + + globalUI->dssiui_control(index, value); + + return 0; +} + +#if DISTRHO_PLUGIN_WANT_PROGRAMS +int osc_program_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*) +{ + const int32_t bank = argv[0]->i; + const int32_t program = argv[1]->f; + d_debug("osc_program_handler(%i, %i)", bank, program); + + initUiIfNeeded(); + + globalUI->dssiui_program(bank, program); + + return 0; +} +#endif + +int osc_sample_rate_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*) +{ + sampleRate = argv[0]->i; + d_debug("osc_sample_rate_handler(%f)", sampleRate); + + if (globalUI != nullptr) + globalUI->dssiui_samplerate(sampleRate); + + return 0; +} + +int osc_show_handler(const char*, const char*, lo_arg**, int, lo_message, void*) +{ + d_debug("osc_show_handler()"); + + initUiIfNeeded(); + + globalUI->dssiui_show(); + + return 0; +} + +int osc_hide_handler(const char*, const char*, lo_arg**, int, lo_message, void*) +{ + d_debug("osc_hide_handler()"); + + if (globalUI != nullptr) + globalUI->dssiui_hide(); + + return 0; +} + +int osc_quit_handler(const char*, const char*, lo_arg**, int, lo_message, void*) +{ + d_debug("osc_quit_handler()"); + + if (globalUI != nullptr) + globalUI->dssiui_quit(); + + return 0; +} + +END_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +int main(int argc, char* argv[]) +{ + USE_NAMESPACE_DISTRHO + + // dummy test mode + if (argc == 1) + { + gUiTitle = "DSSI UI Test"; + + initUiIfNeeded(); + globalUI->dssiui_show(true); + globalUI->exec_start(); + + delete globalUI; + globalUI = nullptr; + + return 0; + } + + if (argc != 5) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + const char* oscUrl = argv[1]; + const char* uiTitle = argv[4]; + + char* const oscHost = lo_url_get_hostname(oscUrl); + char* const oscPort = lo_url_get_port(oscUrl); + char* const oscPath = lo_url_get_path(oscUrl); + size_t oscPathSize = strlen(oscPath); + lo_address oscAddr = lo_address_new(oscHost, oscPort); + lo_server oscServer = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler); + + char* const oscServerPath = lo_server_get_url(oscServer); + + char pluginPath[strlen(oscServerPath)+oscPathSize]; + strcpy(pluginPath, oscServerPath); + strcat(pluginPath, oscPath+1); + +#if DISTRHO_PLUGIN_WANT_STATE + char oscPathConfigure[oscPathSize+11]; + strcpy(oscPathConfigure, oscPath); + strcat(oscPathConfigure, "/configure"); + lo_server_add_method(oscServer, oscPathConfigure, "ss", osc_configure_handler, nullptr); +#endif + + char oscPathControl[oscPathSize+9]; + strcpy(oscPathControl, oscPath); + strcat(oscPathControl, "/control"); + lo_server_add_method(oscServer, oscPathControl, "if", osc_control_handler, nullptr); + + d_stdout("oscServerPath: \"%s\"", oscServerPath); + d_stdout("pluginPath: \"%s\"", pluginPath); + d_stdout("oscPathControl: \"%s\"", oscPathControl); + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + char oscPathProgram[oscPathSize+9]; + strcpy(oscPathProgram, oscPath); + strcat(oscPathProgram, "/program"); + lo_server_add_method(oscServer, oscPathProgram, "ii", osc_program_handler, nullptr); +#endif + + char oscPathSampleRate[oscPathSize+13]; + strcpy(oscPathSampleRate, oscPath); + strcat(oscPathSampleRate, "/sample-rate"); + lo_server_add_method(oscServer, oscPathSampleRate, "i", osc_sample_rate_handler, nullptr); + + char oscPathShow[oscPathSize+6]; + strcpy(oscPathShow, oscPath); + strcat(oscPathShow, "/show"); + lo_server_add_method(oscServer, oscPathShow, "", osc_show_handler, nullptr); + + char oscPathHide[oscPathSize+6]; + strcpy(oscPathHide, oscPath); + strcat(oscPathHide, "/hide"); + lo_server_add_method(oscServer, oscPathHide, "", osc_hide_handler, nullptr); + + char oscPathQuit[oscPathSize+6]; + strcpy(oscPathQuit, oscPath); + strcat(oscPathQuit, "/quit"); + lo_server_add_method(oscServer, oscPathQuit, "", osc_quit_handler, nullptr); + + lo_server_add_method(oscServer, nullptr, nullptr, osc_debug_handler, nullptr); + + gUiTitle = uiTitle; + + gOscData.addr = oscAddr; + gOscData.path = oscPath; + gOscData.server = oscServer; + gOscData.send_update(pluginPath); + + // wait for init + for (int i=0; i < 100; ++i) + { + lo_server_recv(oscServer); + + if (sampleRate != 0.0 || globalUI != nullptr) + break; + + d_msleep(50); + } + + int ret = 1; + + if (sampleRate != 0.0 || globalUI != nullptr) + { + initUiIfNeeded(); + + globalUI->exec_start(); + + delete globalUI; + globalUI = nullptr; + + ret = 0; + } + +#if DISTRHO_PLUGIN_WANT_STATE + lo_server_del_method(oscServer, oscPathConfigure, "ss"); +#endif + lo_server_del_method(oscServer, oscPathControl, "if"); +#if DISTRHO_PLUGIN_WANT_PROGRAMS + lo_server_del_method(oscServer, oscPathProgram, "ii"); +#endif + lo_server_del_method(oscServer, oscPathSampleRate, "i"); + lo_server_del_method(oscServer, oscPathShow, ""); + lo_server_del_method(oscServer, oscPathHide, ""); + lo_server_del_method(oscServer, oscPathQuit, ""); + lo_server_del_method(oscServer, nullptr, nullptr); + + std::free(oscServerPath); + std::free(oscHost); + std::free(oscPort); + std::free(oscPath); + + lo_address_free(oscAddr); + lo_server_free(oscServer); + + return ret; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIInternal.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIInternal.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,414 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_UI_INTERNAL_HPP_INCLUDED +#define DISTRHO_UI_INTERNAL_HPP_INCLUDED + +#include "DistrhoUIPrivateData.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// Static data, see DistrhoUI.cpp + +extern const char* g_nextBundlePath; +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +extern uintptr_t g_nextWindowId; +extern double g_nextScaleFactor; +#endif + +// ----------------------------------------------------------------------- +// UI exporter class + +class UIExporter +{ + // ------------------------------------------------------------------- + // UI Widget and its private data + + UI* ui; + UI::PrivateData* uiData; + + // ------------------------------------------------------------------- + +public: + UIExporter(void* const callbacksPtr, + const uintptr_t winId, + const double sampleRate, + const editParamFunc editParamCall, + const setParamFunc setParamCall, + const setStateFunc setStateCall, + const sendNoteFunc sendNoteCall, + const setSizeFunc setSizeCall, + const fileRequestFunc fileRequestCall, + const char* const bundlePath = nullptr, + void* const dspPtr = nullptr, + const double scaleFactor = 0.0, + const uint32_t bgColor = 0, + const uint32_t fgColor = 0xffffffff, + const char* const appClassName = nullptr) + : ui(nullptr), + uiData(new UI::PrivateData(appClassName)) + { + uiData->sampleRate = sampleRate; + uiData->bundlePath = bundlePath != nullptr ? strdup(bundlePath) : nullptr; + uiData->dspPtr = dspPtr; + + uiData->bgColor = bgColor; + uiData->fgColor = fgColor; + uiData->scaleFactor = scaleFactor; + uiData->winId = winId; + + uiData->callbacksPtr = callbacksPtr; + uiData->editParamCallbackFunc = editParamCall; + uiData->setParamCallbackFunc = setParamCall; + uiData->setStateCallbackFunc = setStateCall; + uiData->sendNoteCallbackFunc = sendNoteCall; + uiData->setSizeCallbackFunc = setSizeCall; + uiData->fileRequestCallbackFunc = fileRequestCall; + + g_nextBundlePath = bundlePath; +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + g_nextWindowId = winId; + g_nextScaleFactor = scaleFactor; +#endif + UI::PrivateData::s_nextPrivateData = uiData; + + UI* const uiPtr = createUI(); + + g_nextBundlePath = nullptr; +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + g_nextWindowId = 0; + g_nextScaleFactor = 0.0; +#else + // enter context called in the PluginWindow constructor, see DistrhoUIPrivateData.hpp + uiData->window->leaveContext(); +#endif + UI::PrivateData::s_nextPrivateData = nullptr; + + DISTRHO_SAFE_ASSERT_RETURN(uiPtr != nullptr,); + ui = uiPtr; + uiData->initializing = false; + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + // unused + (void)bundlePath; +#endif + } + + ~UIExporter() + { + quit(); +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + uiData->window->enterContextForDeletion(); +#endif + delete ui; + delete uiData; + } + + // ------------------------------------------------------------------- + + uint getWidth() const noexcept + { + return uiData->window->getWidth(); + } + + uint getHeight() const noexcept + { + return uiData->window->getHeight(); + } + + double getScaleFactor() const noexcept + { + return uiData->window->getScaleFactor(); + } + + bool getGeometryConstraints(uint& minimumWidth, uint& minimumHeight, bool& keepAspectRatio) const noexcept + { +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + uiData->window->getGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio); +#else + const DGL_NAMESPACE::Size size(uiData->window->getGeometryConstraints(keepAspectRatio)); + minimumWidth = size.getWidth(); + minimumHeight = size.getHeight(); +#endif + return true; + } + + bool isResizable() const noexcept + { + return uiData->window->isResizable(); + } + + bool isVisible() const noexcept + { + return uiData->window->isVisible(); + } + + uintptr_t getNativeWindowHandle() const noexcept + { + return uiData->window->getNativeWindowHandle(); + } + + uint getBackgroundColor() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0); + + return uiData->bgColor; + } + + uint getForegroundColor() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0xffffffff); + + return uiData->fgColor; + } + + // ------------------------------------------------------------------- + + uint32_t getParameterOffset() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0); + + return uiData->parameterOffset; + } + + // ------------------------------------------------------------------- + + void parameterChanged(const uint32_t index, const float value) + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + ui->parameterChanged(index, value); + } + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + void programLoaded(const uint32_t index) + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + ui->programLoaded(index); + } + #endif + + #if DISTRHO_PLUGIN_WANT_STATE + void stateChanged(const char* const key, const char* const value) + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); + DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,); + + ui->stateChanged(key, value); + } + #endif + + // ------------------------------------------------------------------- + + #if DISTRHO_UI_IS_STANDALONE + void exec(DGL_NAMESPACE::IdleCallback* const cb) + { + DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); + + uiData->window->show(); + uiData->window->focus(); + uiData->app.addIdleCallback(cb); + uiData->app.exec(); + } + + void exec_idle() + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, ); + + ui->uiIdle(); + } + + void showAndFocus() + { + uiData->window->show(); + uiData->window->focus(); + } + #endif + + bool plugin_idle() + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, false); + + uiData->app.idle(); + ui->uiIdle(); + return ! uiData->app.isQuitting(); + } + + void focus() + { + uiData->window->focus(); + } + + void quit() + { + uiData->window->close(); + uiData->app.quit(); + } + + #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + void repaint() + { + uiData->window->repaint(); + } + #endif + + // ------------------------------------------------------------------- + + #if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS) + void idleFromNativeIdle() + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + uiData->app.triggerIdleCallbacks(); + ui->uiIdle(); + } + + #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + void addIdleCallbackForNativeIdle(IdleCallback* const cb, const uint timerFrequencyInMs) + { + uiData->window->addIdleCallback(cb, timerFrequencyInMs); + } + + void removeIdleCallbackForNativeIdle(IdleCallback* const cb) + { + uiData->window->removeIdleCallback(cb); + } + #endif + #endif + + // ------------------------------------------------------------------- + + void setWindowOffset(const int x, const int y) + { + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + // TODO + (void)x; (void)y; + #else + uiData->window->setOffset(x, y); + #endif + } + + #if defined(DISTRHO_PLUGIN_TARGET_VST3) || defined(DISTRHO_PLUGIN_TARGET_CLAP) + void setWindowSizeFromHost(const uint width, const uint height) + { + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + ui->setSize(width, height); + #else + uiData->window->setSizeFromHost(width, height); + #endif + } + #endif + + void setWindowTitle(const char* const uiTitle) + { + uiData->window->setTitle(uiTitle); + } + + void setWindowTransientWinId(const uintptr_t transientParentWindowHandle) + { +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + ui->setTransientWindowId(transientParentWindowHandle); +#else + uiData->window->setTransientParent(transientParentWindowHandle); +#endif + } + + bool setWindowVisible(const bool yesNo) + { + uiData->window->setVisible(yesNo); + + return ! uiData->app.isQuitting(); + } + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + bool handlePluginKeyboardVST(const bool press, const bool special, const uint keychar, const uint keycode, const uint16_t mods) + { + using namespace DGL_NAMESPACE; + + Widget::KeyboardEvent ev; + ev.mod = mods; + ev.press = press; + ev.key = keychar; + ev.keycode = keycode; + + // keyboard events must always be lowercase + if (ev.key >= 'A' && ev.key <= 'Z') + ev.key += 'a' - 'A'; // A-Z -> a-z + + const bool ret = ui->onKeyboard(ev); + + if (press && !special && (mods & (kModifierControl|kModifierAlt|kModifierSuper)) == 0) + { + Widget::CharacterInputEvent cev; + cev.mod = mods; + cev.character = keychar; + cev.keycode = keycode; + + // if shift modifier is on, convert a-z -> A-Z for character input + if (cev.character >= 'a' && cev.character <= 'z' && (mods & kModifierShift) != 0) + cev.character -= 'a' - 'A'; + + ui->onCharacterInput(cev); + } + + return ret; + } +#endif + + // ------------------------------------------------------------------- + + void notifyScaleFactorChanged(const double scaleFactor) + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + ui->uiScaleFactorChanged(scaleFactor); + } + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + void notifyFocusChanged(const bool focus) + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + ui->uiFocus(focus, DGL_NAMESPACE::kCrossingNormal); + } +#endif + + void setSampleRate(const double sampleRate, const bool doCallback = false) + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr,); + DISTRHO_SAFE_ASSERT(sampleRate > 0.0); + + if (d_isEqual(uiData->sampleRate, sampleRate)) + return; + + uiData->sampleRate = sampleRate; + + if (doCallback) + ui->sampleRateChanged(sampleRate); + } + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_UI_INTERNAL_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUILV2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUILV2.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,929 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoUIInternal.hpp" + +#include "../extra/String.hpp" + +#include "lv2/atom.h" +#include "lv2/atom-util.h" +#include "lv2/data-access.h" +#include "lv2/instance-access.h" +#include "lv2/midi.h" +#include "lv2/options.h" +#include "lv2/parameters.h" +#include "lv2/patch.h" +#include "lv2/ui.h" +#include "lv2/urid.h" +#include "lv2/lv2_kxstudio_properties.h" +#include "lv2/lv2_programs.h" + +#ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX +# define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:" +#endif + +START_NAMESPACE_DISTRHO + +typedef struct _LV2_Atom_MidiEvent { + LV2_Atom atom; /**< Atom header. */ + uint8_t data[3]; /**< MIDI data (body). */ +} LV2_Atom_MidiEvent; + +#if ! DISTRHO_PLUGIN_WANT_STATE +static constexpr const setStateFunc setStateCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static constexpr const sendNoteFunc sendNoteCallback = nullptr; +#endif + +// ----------------------------------------------------------------------- + +template +static const LV2F* getLv2Feature(const LV2_Feature* const* features, const char* const uri) +{ + for (int i=0; features[i] != nullptr; ++i) + { + if (std::strcmp(features[i]->URI, uri) == 0) + return (const LV2F*)features[i]->data; + } + + return nullptr; +} + +class UiLv2 +{ +public: + UiLv2(const char* const bundlePath, + const intptr_t winId, + const LV2_Options_Option* options, + const LV2_URID_Map* const uridMap, + const LV2_Feature* const* const features, + const LV2UI_Controller controller, + const LV2UI_Write_Function writeFunc, + LV2UI_Widget* const widget, + void* const dspPtr, + const float sampleRate, + const float scaleFactor, + const uint32_t bgColor, + const uint32_t fgColor, + const char* const appClassName) + : fUridMap(uridMap), + fUridUnmap(getLv2Feature(features, LV2_URID__unmap)), + fUiPortMap(getLv2Feature(features, LV2_UI__portMap)), + fUiRequestValue(getLv2Feature(features, LV2_UI__requestValue)), + fUiTouch(getLv2Feature(features, LV2_UI__touch)), + fController(controller), + fWriteFunction(writeFunc), + fURIDs(uridMap), + fBypassParameterIndex(fUiPortMap != nullptr ? fUiPortMap->port_index(fUiPortMap->handle, "lv2_enabled") + : LV2UI_INVALID_PORT_INDEX), + fWinIdWasNull(winId == 0), + fUI(this, winId, sampleRate, + editParameterCallback, + setParameterCallback, + setStateCallback, + sendNoteCallback, + nullptr, // resize is very messy, hosts can do it without extensions + fileRequestCallback, + bundlePath, dspPtr, scaleFactor, bgColor, fgColor, appClassName) + { + if (widget != nullptr) + *widget = (LV2UI_Widget)fUI.getNativeWindowHandle(); + + #if DISTRHO_PLUGIN_WANT_STATE + // tell the DSP we're ready to receive msgs + setState("__dpf_ui_data__", ""); + #endif + + if (winId != 0) + return; + + // if winId == 0 then options must not be null + DISTRHO_SAFE_ASSERT_RETURN(options != nullptr,); + + #ifndef __EMSCRIPTEN__ + const LV2_URID uridWindowTitle = uridMap->map(uridMap->handle, LV2_UI__windowTitle); + const LV2_URID uridTransientWinId = uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TransientWindowId); + + const char* windowTitle = nullptr; + + for (int i=0; options[i].key != 0; ++i) + { + if (options[i].key == uridTransientWinId) + { + if (options[i].type == fURIDs.atomLong) + { + if (const int64_t transientWinId = *(const int64_t*)options[i].value) + fUI.setWindowTransientWinId(static_cast(transientWinId)); + } + else + d_stderr("Host provides transientWinId but has wrong value type"); + } + else if (options[i].key == uridWindowTitle) + { + if (options[i].type == fURIDs.atomString) + { + windowTitle = (const char*)options[i].value; + } + else + d_stderr("Host provides windowTitle but has wrong value type"); + } + } + + if (windowTitle == nullptr) + windowTitle = DISTRHO_PLUGIN_NAME; + + fUI.setWindowTitle(windowTitle); + #endif + } + + // ------------------------------------------------------------------- + + void lv2ui_port_event(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer) + { + if (format == 0) + { + const uint32_t parameterOffset = fUI.getParameterOffset(); + + if (rindex < parameterOffset) + return; + + DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),) + + float value = *(const float*)buffer; + + if (rindex == fBypassParameterIndex) + value = 1.0f - value; + + fUI.parameterChanged(rindex-parameterOffset, value); + } + #if DISTRHO_PLUGIN_WANT_STATE + else if (format == fURIDs.atomEventTransfer) + { + const LV2_Atom* const atom = (const LV2_Atom*)buffer; + + if (atom->type == fURIDs.dpfKeyValue) + { + const char* const key = (const char*)LV2_ATOM_BODY_CONST(atom); + const char* const value = key+(std::strlen(key)+1); + + fUI.stateChanged(key, value); + } + else if (atom->type == fURIDs.atomObject && fUridUnmap != nullptr) + { + const LV2_Atom_Object* const obj = (const LV2_Atom_Object*)atom; + + const LV2_Atom* property = nullptr; + const LV2_Atom* atomvalue = nullptr; + lv2_atom_object_get(obj, fURIDs.patchProperty, &property, fURIDs.patchValue, &atomvalue, 0); + + DISTRHO_SAFE_ASSERT_RETURN(property != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(atomvalue != nullptr,); + + DISTRHO_SAFE_ASSERT_RETURN(property->type == fURIDs.atomURID,); + DISTRHO_SAFE_ASSERT_RETURN(atomvalue->type == fURIDs.atomPath || atomvalue->type == fURIDs.atomString,); + + if (property != nullptr && property->type == fURIDs.atomURID && + atomvalue != nullptr && (atomvalue->type == fURIDs.atomPath || atomvalue->type == fURIDs.atomString)) + { + const LV2_URID dpf_lv2_urid = ((const LV2_Atom_URID*)property)->body; + DISTRHO_SAFE_ASSERT_RETURN(dpf_lv2_urid != 0,); + + const char* const dpf_lv2_key = fUridUnmap->unmap(fUridUnmap->handle, dpf_lv2_urid); + DISTRHO_SAFE_ASSERT_RETURN(dpf_lv2_key != nullptr,); + + /*constexpr*/ const size_t reqLen = std::strlen(DISTRHO_PLUGIN_URI "#"); + DISTRHO_SAFE_ASSERT_RETURN(std::strlen(dpf_lv2_key) > reqLen,); + + const char* const key = dpf_lv2_key + reqLen; + const char* const value = (const char*)LV2_ATOM_BODY_CONST(atomvalue); + + fUI.stateChanged(key, value); + } + } + else if (atom->type == fURIDs.midiEvent) + { + // ignore + } + else + { + d_stdout("DPF :: received atom not handled :: %s", + fUridUnmap != nullptr ? fUridUnmap->unmap(fUridUnmap->handle, atom->type) : "(null)"); + } + } + #endif + } + + // ------------------------------------------------------------------- + + int lv2ui_idle() + { + if (fWinIdWasNull) + return (fUI.plugin_idle() && fUI.isVisible()) ? 0 : 1; + + return fUI.plugin_idle() ? 0 : 1; + } + + int lv2ui_show() + { + return fUI.setWindowVisible(true) ? 0 : 1; + } + + int lv2ui_hide() + { + return fUI.setWindowVisible(false) ? 0 : 1; + } + + // ------------------------------------------------------------------- + + uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) + { + // currently unused + return LV2_OPTIONS_ERR_UNKNOWN; + } + + uint32_t lv2_set_options(const LV2_Options_Option* const options) + { + for (int i=0; options[i].key != 0; ++i) + { + if (options[i].key == fURIDs.paramSampleRate) + { + if (options[i].type == fURIDs.atomFloat) + { + const float sampleRate = *(const float*)options[i].value; + fUI.setSampleRate(sampleRate, true); + continue; + } + else + { + d_stderr("Host changed UI sample-rate but with wrong value type"); + continue; + } + } + } + + return LV2_OPTIONS_SUCCESS; + } + + // ------------------------------------------------------------------- + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + void lv2ui_select_program(const uint32_t bank, const uint32_t program) + { + const uint32_t realProgram = bank * 128 + program; + + fUI.programLoaded(realProgram); + } + #endif + + // ------------------------------------------------------------------- + +private: + // LV2 features + const LV2_URID_Map* const fUridMap; + const LV2_URID_Unmap* const fUridUnmap; + const LV2UI_Port_Map* const fUiPortMap; + const LV2UI_Request_Value* const fUiRequestValue; + const LV2UI_Touch* const fUiTouch; + + // LV2 UI stuff + const LV2UI_Controller fController; + const LV2UI_Write_Function fWriteFunction; + + // LV2 URIDs + const struct URIDs { + const LV2_URID_Map* _uridMap; + const LV2_URID dpfKeyValue; + const LV2_URID atomEventTransfer; + const LV2_URID atomFloat; + const LV2_URID atomLong; + const LV2_URID atomObject; + const LV2_URID atomPath; + const LV2_URID atomString; + const LV2_URID atomURID; + const LV2_URID midiEvent; + const LV2_URID paramSampleRate; + const LV2_URID patchProperty; + const LV2_URID patchSet; + const LV2_URID patchValue; + + URIDs(const LV2_URID_Map* const uridMap) + : _uridMap(uridMap), + dpfKeyValue(map(DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), + atomEventTransfer(map(LV2_ATOM__eventTransfer)), + atomFloat(map(LV2_ATOM__Float)), + atomLong(map(LV2_ATOM__Long)), + atomObject(map(LV2_ATOM__Object)), + atomPath(map(LV2_ATOM__Path)), + atomString(map(LV2_ATOM__String)), + atomURID(map(LV2_ATOM__URID)), + midiEvent(map(LV2_MIDI__MidiEvent)), + paramSampleRate(map(LV2_PARAMETERS__sampleRate)), + patchProperty(map(LV2_PATCH__property)), + patchSet(map(LV2_PATCH__Set)), + patchValue(map(LV2_PATCH__value)) {} + + inline LV2_URID map(const char* const uri) const + { + return _uridMap->map(_uridMap->handle, uri); + } + } fURIDs; + + // index of bypass parameter, if present + const uint32_t fBypassParameterIndex; + + // using ui:showInterface if true + const bool fWinIdWasNull; + + // Plugin UI (after LV2 stuff so the UI can call into us during its constructor) + UIExporter fUI; + + // ---------------------------------------------------------------------------------------------------------------- + // DPF callbacks + + void editParameterValue(const uint32_t rindex, const bool started) + { + if (fUiTouch != nullptr && fUiTouch->touch != nullptr) + fUiTouch->touch(fUiTouch->handle, rindex, started); + } + + static void editParameterCallback(void* const ptr, const uint32_t rindex, const bool started) + { + static_cast(ptr)->editParameterValue(rindex, started); + } + + void setParameterValue(const uint32_t rindex, float value) + { + DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,); + + if (rindex == fBypassParameterIndex) + value = 1.0f - value; + + fWriteFunction(fController, rindex, sizeof(float), 0, &value); + } + + static void setParameterCallback(void* const ptr, const uint32_t rindex, const float value) + { + static_cast(ptr)->setParameterValue(rindex, value); + } + + #if DISTRHO_PLUGIN_WANT_STATE + void setState(const char* const key, const char* const value) + { + DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,); + + const uint32_t eventInPortIndex = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; + + // join key and value + String tmpStr; + tmpStr += key; + tmpStr += "\xff"; + tmpStr += value; + + tmpStr[std::strlen(key)] = '\0'; + + // set msg size (key + separator + value + null terminator) + const uint32_t msgSize = static_cast(tmpStr.length()) + 1U; + + // reserve atom space + const uint32_t atomSize = sizeof(LV2_Atom) + msgSize; + char* const atomBuf = (char*)malloc(atomSize); + DISTRHO_SAFE_ASSERT_RETURN(atomBuf != nullptr,); + + std::memset(atomBuf, 0, atomSize); + + // set atom info + LV2_Atom* const atom = (LV2_Atom*)atomBuf; + atom->size = msgSize; + atom->type = fURIDs.dpfKeyValue; + + // set atom data + std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.buffer(), msgSize); + + // send to DSP side + fWriteFunction(fController, eventInPortIndex, atomSize, fURIDs.atomEventTransfer, atom); + + // free atom space + free(atomBuf); + } + + static void setStateCallback(void* const ptr, const char* const key, const char* const value) + { + static_cast(ptr)->setState(key, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,); + + if (channel > 0xF) + return; + + const uint32_t eventInPortIndex = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; + + LV2_Atom_MidiEvent atomMidiEvent; + atomMidiEvent.atom.size = 3; + atomMidiEvent.atom.type = fURIDs.midiEvent; + + atomMidiEvent.data[0] = channel + (velocity != 0 ? 0x90 : 0x80); + atomMidiEvent.data[1] = note; + atomMidiEvent.data[2] = velocity; + + // send to DSP side + fWriteFunction(fController, eventInPortIndex, lv2_atom_total_size(&atomMidiEvent.atom), + fURIDs.atomEventTransfer, &atomMidiEvent); + } + + static void sendNoteCallback(void* const ptr, const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + static_cast(ptr)->sendNote(channel, note, velocity); + } + #endif + + bool fileRequest(const char* const key) + { + d_stdout("UI file request %s %p", key, fUiRequestValue); + + if (fUiRequestValue == nullptr) + return false; + + String dpf_lv2_key(DISTRHO_PLUGIN_URI "#"); + dpf_lv2_key += key; + + const int r = fUiRequestValue->request(fUiRequestValue->handle, + fUridMap->map(fUridMap->handle, dpf_lv2_key.buffer()), + fURIDs.atomPath, + nullptr); + + d_stdout("UI file request %s %p => %s %i", key, fUiRequestValue, dpf_lv2_key.buffer(), r); + return r == LV2UI_REQUEST_VALUE_SUCCESS; + } + + static bool fileRequestCallback(void* ptr, const char* key) + { + return static_cast(ptr)->fileRequest(key); + } +}; + +// ----------------------------------------------------------------------- + +static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, + const char* const uri, + const char* const bundlePath, + const LV2UI_Write_Function writeFunction, + const LV2UI_Controller controller, + LV2UI_Widget* const widget, + const LV2_Feature* const* const features) +{ + if (uri == nullptr || std::strcmp(uri, DISTRHO_PLUGIN_URI) != 0) + { + d_stderr("Invalid plugin URI"); + return nullptr; + } + + const LV2_Options_Option* options = nullptr; + const LV2_URID_Map* uridMap = nullptr; + void* parentId = nullptr; + void* instance = nullptr; + +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + struct LV2_DirectAccess_Interface { + void* (*get_instance_pointer)(LV2_Handle handle); + }; + const LV2_Extension_Data_Feature* extData = nullptr; +#endif + + for (int i=0; features[i] != nullptr; ++i) + { + /**/ if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) + options = (const LV2_Options_Option*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0) + uridMap = (const LV2_URID_Map*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0) + parentId = features[i]->data; +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + else if (std::strcmp(features[i]->URI, LV2_DATA_ACCESS_URI) == 0) + extData = (const LV2_Extension_Data_Feature*)features[i]->data; + else if (std::strcmp(features[i]->URI, LV2_INSTANCE_ACCESS_URI) == 0) + instance = features[i]->data; +#endif + } + + if (options == nullptr && parentId == nullptr) + { + d_stderr("Options feature missing (needed for show-interface), cannot continue!"); + return nullptr; + } + + if (uridMap == nullptr) + { + d_stderr("URID Map feature missing, cannot continue!"); + return nullptr; + } + + if (parentId == nullptr) + { + d_stdout("Parent Window Id missing, host should be using ui:showInterface..."); + } + +#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + if (extData == nullptr || instance == nullptr) + { + d_stderr("Data or instance access missing, cannot continue!"); + return nullptr; + } + + if (const LV2_DirectAccess_Interface* const directAccess = (const LV2_DirectAccess_Interface*)extData->data_access(DISTRHO_PLUGIN_LV2_STATE_PREFIX "direct-access")) + instance = directAccess->get_instance_pointer(instance); + else + instance = nullptr; + + if (instance == nullptr) + { + d_stderr("Failed to get direct access, cannot continue!"); + return nullptr; + } +#endif + + const intptr_t winId = (intptr_t)parentId; + float sampleRate = 0.0f; + float scaleFactor = 0.0f; + uint32_t bgColor = 0; + uint32_t fgColor = 0xffffffff; + const char* appClassName = nullptr; + + if (options != nullptr) + { + const LV2_URID uridAtomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int); + const LV2_URID uridAtomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float); + const LV2_URID uridAtomString = uridMap->map(uridMap->handle, LV2_ATOM__String); + const LV2_URID uridSampleRate = uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate); + const LV2_URID uridBgColor = uridMap->map(uridMap->handle, LV2_UI__backgroundColor); + const LV2_URID uridFgColor = uridMap->map(uridMap->handle, LV2_UI__foregroundColor); + #ifndef DISTRHO_OS_MAC + const LV2_URID uridScaleFactor = uridMap->map(uridMap->handle, LV2_UI__scaleFactor); + #endif + const LV2_URID uridClassName = uridMap->map(uridMap->handle, "urn:distrho:className"); + + for (int i=0; options[i].key != 0; ++i) + { + /**/ if (options[i].key == uridSampleRate) + { + if (options[i].type == uridAtomFloat) + sampleRate = *(const float*)options[i].value; + else + d_stderr("Host provides UI sample-rate but has wrong value type"); + } + else if (options[i].key == uridBgColor) + { + if (options[i].type == uridAtomInt) + bgColor = (uint32_t)*(const int32_t*)options[i].value; + else + d_stderr("Host provides UI background color but has wrong value type"); + } + else if (options[i].key == uridFgColor) + { + if (options[i].type == uridAtomInt) + fgColor = (uint32_t)*(const int32_t*)options[i].value; + else + d_stderr("Host provides UI foreground color but has wrong value type"); + } + #ifndef DISTRHO_OS_MAC + else if (options[i].key == uridScaleFactor) + { + if (options[i].type == uridAtomFloat) + scaleFactor = *(const float*)options[i].value; + else + d_stderr("Host provides UI scale factor but has wrong value type"); + } + #endif + else if (options[i].key == uridClassName) + { + if (options[i].type == uridAtomString) + appClassName = (const char*)options[i].value; + else + d_stderr("Host provides UI scale factor but has wrong value type"); + } + } + } + + if (sampleRate < 1.0) + { + d_stdout("WARNING: this host does not send sample-rate information for LV2 UIs, using 44100 as fallback (this could be wrong)"); + sampleRate = 44100.0; + } + + return new UiLv2(bundlePath, winId, options, uridMap, features, + controller, writeFunction, widget, instance, + sampleRate, scaleFactor, bgColor, fgColor, appClassName); +} + +#define uiPtr ((UiLv2*)ui) + +static void lv2ui_cleanup(LV2UI_Handle ui) +{ + delete uiPtr; +} + +static void lv2ui_port_event(LV2UI_Handle ui, uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer) +{ + uiPtr->lv2ui_port_event(portIndex, bufferSize, format, buffer); +} + +// ----------------------------------------------------------------------- + +static int lv2ui_idle(LV2UI_Handle ui) +{ + return uiPtr->lv2ui_idle(); +} + +static int lv2ui_show(LV2UI_Handle ui) +{ + return uiPtr->lv2ui_show(); +} + +static int lv2ui_hide(LV2UI_Handle ui) +{ + return uiPtr->lv2ui_hide(); +} + +// ----------------------------------------------------------------------- + +static uint32_t lv2_get_options(LV2UI_Handle ui, LV2_Options_Option* options) +{ + return uiPtr->lv2_get_options(options); +} + +static uint32_t lv2_set_options(LV2UI_Handle ui, const LV2_Options_Option* options) +{ + return uiPtr->lv2_set_options(options); +} + +// ----------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_WANT_PROGRAMS +static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t program) +{ + uiPtr->lv2ui_select_program(bank, program); +} +#endif + +// ----------------------------------------------------------------------- + +static const void* lv2ui_extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; + static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle }; + static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide }; + + if (std::strcmp(uri, LV2_OPTIONS__interface) == 0) + return &options; + if (std::strcmp(uri, LV2_UI__idleInterface) == 0) + return &uiIdle; + if (std::strcmp(uri, LV2_UI__showInterface) == 0) + return &uiShow; + +#if DISTRHO_PLUGIN_WANT_PROGRAMS + static const LV2_Programs_UI_Interface uiPrograms = { lv2ui_select_program }; + + if (std::strcmp(uri, LV2_PROGRAMS__UIInterface) == 0) + return &uiPrograms; +#endif + + return nullptr; +} + +#undef instancePtr + +// ----------------------------------------------------------------------- + +static const LV2UI_Descriptor sLv2UiDescriptor = { + DISTRHO_UI_URI, + lv2ui_instantiate, + lv2ui_cleanup, + lv2ui_port_event, + lv2ui_extension_data +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +DISTRHO_PLUGIN_EXPORT +const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index) +{ + USE_NAMESPACE_DISTRHO + return (index == 0) ? &sLv2UiDescriptor : nullptr; +} + +#if defined(__MOD_DEVICES__) && defined(__EMSCRIPTEN__) +#include +#include + +typedef void (*_custom_param_set)(uint32_t port_index, float value); +typedef void (*_custom_patch_set)(const char* uri, const char* value); + +struct ModguiHandle { + LV2UI_Handle handle; + long loop_id; + _custom_param_set param_set; + _custom_patch_set patch_set; +}; + +enum URIs { + kUriNull, + kUriAtomEventTransfer, + kUriDpfKeyValue, +}; + +static std::vector kURIs; + +static LV2_URID lv2_urid_map(LV2_URID_Map_Handle, const char* const uri) +{ + for (size_t i=0, size=kURIs.size(); i= 1,); + + // d_stdout("lv2ui_write_function %p %u %u %u %p", controller, port_index, buffer_size, port_protocol, buffer); + ModguiHandle* const mhandle = static_cast(controller); + + switch (port_protocol) + { + case kUriNull: + mhandle->param_set(port_index, *static_cast(buffer)); + break; + case kUriAtomEventTransfer: + if (const LV2_Atom* const atom = static_cast(buffer)) + { + // d_stdout("lv2ui_write_function %u %u:%s", atom->size, atom->type, kURIs[atom->type].c_str()); + + // if (kURIs[atom->type] == "urn:distrho:KeyValueState") + { + const char* const key = (const char*)(atom + 1); + const char* const value = key + (std::strlen(key) + 1U); + // d_stdout("lv2ui_write_function %s %s", key, value); + + String urikey; + urikey = DISTRHO_PLUGIN_URI "#"; + urikey += key; + + mhandle->patch_set(urikey, value); + } + } + break; + } +} + +static void app_idle(void* const handle) +{ + static_cast(handle)->lv2ui_idle(); +} + +DISTRHO_PLUGIN_EXPORT +LV2UI_Handle modgui_init(const char* const className, _custom_param_set param_set, _custom_patch_set patch_set) +{ + d_stdout("init \"%s\"", className); + DISTRHO_SAFE_ASSERT_RETURN(className != nullptr, nullptr); + + static LV2_URID_Map uridMap = { nullptr, lv2_urid_map }; + static LV2_URID_Unmap uridUnmap = { nullptr, lv2_urid_unmap }; + + // known first URIDs, matching URIs + if (kURIs.empty()) + { + kURIs.push_back(""); + kURIs.push_back("http://lv2plug.in/ns/ext/atom#eventTransfer"); + kURIs.push_back(DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState"); + } + + static float sampleRateValue = 48000.f; + static LV2_Options_Option options[3] = { + { + LV2_OPTIONS_INSTANCE, + 0, + uridMap.map(uridMap.handle, LV2_PARAMETERS__sampleRate), + sizeof(float), + uridMap.map(uridMap.handle, LV2_ATOM__Float), + &sampleRateValue + }, + { + LV2_OPTIONS_INSTANCE, + 0, + uridMap.map(uridMap.handle, "urn:distrho:className"), + std::strlen(className) + 1, + uridMap.map(uridMap.handle, LV2_ATOM__String), + className + }, + {} + }; + + static const LV2_Feature optionsFt = { LV2_OPTIONS__options, static_cast(options) }; + static const LV2_Feature uridMapFt = { LV2_URID__map, static_cast(&uridMap) }; + static const LV2_Feature uridUnmapFt = { LV2_URID__unmap, static_cast(&uridUnmap) }; + + static const LV2_Feature* features[] = { + &optionsFt, + &uridMapFt, + &uridUnmapFt, + nullptr + }; + + ModguiHandle* const mhandle = new ModguiHandle; + mhandle->handle = nullptr; + mhandle->loop_id = 0; + mhandle->param_set = param_set; + mhandle->patch_set = patch_set; + + LV2UI_Widget widget; + const LV2UI_Handle handle = lv2ui_instantiate(&sLv2UiDescriptor, + DISTRHO_PLUGIN_URI, + "", // bundlePath + lv2ui_write_function, + mhandle, + &widget, + features); + mhandle->handle = handle; + + static_cast(handle)->lv2ui_show(); + mhandle->loop_id = emscripten_set_interval(app_idle, 1000.0/60, handle); + + return mhandle; +} + +DISTRHO_PLUGIN_EXPORT +void modgui_param_set(const LV2UI_Handle handle, const uint32_t index, const float value) +{ + lv2ui_port_event(static_cast(handle)->handle, index, sizeof(float), kUriNull, &value); +} + +DISTRHO_PLUGIN_EXPORT +void modgui_patch_set(const LV2UI_Handle handle, const char* const uri, const char* const value) +{ + static const constexpr uint32_t URI_PREFIX_LEN = sizeof(DISTRHO_PLUGIN_URI); + DISTRHO_SAFE_ASSERT_RETURN(std::strncmp(uri, DISTRHO_PLUGIN_URI "#", URI_PREFIX_LEN) == 0,); + + const uint32_t keySize = std::strlen(uri + URI_PREFIX_LEN) + 1; + const uint32_t valueSize = std::strlen(value) + 1; + const uint32_t atomSize = sizeof(LV2_Atom) + keySize + valueSize; + + LV2_Atom* const atom = static_cast(std::malloc(atomSize)); + atom->size = atomSize; + atom->type = kUriDpfKeyValue; + + std::memcpy(static_cast(static_cast(atom + 1)), uri + URI_PREFIX_LEN, keySize); + std::memcpy(static_cast(static_cast(atom + 1)) + keySize, value, valueSize); + + lv2ui_port_event(static_cast(handle)->handle, + DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS, // events input port + atomSize, kUriAtomEventTransfer, atom); + + std::free(atom); +} + +DISTRHO_PLUGIN_EXPORT +void modgui_cleanup(const LV2UI_Handle handle) +{ + d_stdout("cleanup"); + ModguiHandle* const mhandle = static_cast(handle); + if (mhandle->loop_id != 0) + emscripten_clear_interval(mhandle->loop_id); + lv2ui_cleanup(mhandle->handle); + delete mhandle; +} +#endif + +// ----------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIPrivateData.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIPrivateData.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,514 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_UI_PRIVATE_DATA_HPP_INCLUDED +#define DISTRHO_UI_PRIVATE_DATA_HPP_INCLUDED + +#include "../DistrhoUI.hpp" + +#ifdef DISTRHO_PLUGIN_TARGET_VST3 +# include "DistrhoPluginVST.hpp" +#endif + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include "../extra/Sleep.hpp" +// TODO import and use file browser here +#else +# include "../../dgl/src/ApplicationPrivateData.hpp" +# include "../../dgl/src/WindowPrivateData.hpp" +# include "../../dgl/src/pugl.hpp" +#endif + +#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_UI_FILE_BROWSER && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# include +# include +#endif + +#if defined(DISTRHO_PLUGIN_TARGET_JACK) || defined(DISTRHO_PLUGIN_TARGET_DSSI) +# define DISTRHO_UI_IS_STANDALONE 1 +#else +# define DISTRHO_UI_IS_STANDALONE 0 +#endif + +#if defined(DISTRHO_PLUGIN_TARGET_VST3) || defined(DISTRHO_PLUGIN_TARGET_CLAP) +# define DISTRHO_UI_USES_SIZE_REQUEST true +#else +# define DISTRHO_UI_USES_SIZE_REQUEST false +#endif + +#ifdef DISTRHO_PLUGIN_TARGET_VST2 +# undef DISTRHO_UI_USER_RESIZABLE +# define DISTRHO_UI_USER_RESIZABLE 0 +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// Plugin Application, will set class name based on plugin details + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +struct PluginApplication +{ + DGL_NAMESPACE::IdleCallback* idleCallback; + UI* ui; + + explicit PluginApplication(const char*) + : idleCallback(nullptr), + ui(nullptr) {} + + void addIdleCallback(DGL_NAMESPACE::IdleCallback* const cb) + { + DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(idleCallback == nullptr,); + + idleCallback = cb; + } + + bool isQuitting() const noexcept + { + return ui->isQuitting(); + } + + bool isStandalone() const noexcept + { + return DISTRHO_UI_IS_STANDALONE; + } + + void exec() + { + while (ui->isRunning()) + { + d_msleep(30); + idleCallback->idleCallback(); + } + + if (! ui->isQuitting()) + ui->close(); + } + + // these are not needed + void idle() {} + void quit() {} + void triggerIdleCallbacks() {} + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication) +}; +#else +class PluginApplication : public DGL_NAMESPACE::Application +{ +public: + explicit PluginApplication(const char* className) + : DGL_NAMESPACE::Application(DISTRHO_UI_IS_STANDALONE) + { + #if defined(__MOD_DEVICES__) || !defined(__EMSCRIPTEN__) + if (className == nullptr) + { + className = ( + #ifdef DISTRHO_PLUGIN_BRAND + DISTRHO_PLUGIN_BRAND + #else + DISTRHO_MACRO_AS_STRING(DISTRHO_NAMESPACE) + #endif + "-" DISTRHO_PLUGIN_NAME + ); + } + setClassName(className); + #else + // unused + (void)className; + #endif + } + + void triggerIdleCallbacks() + { + pData->triggerIdleCallbacks(); + } + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication) +}; +#endif + +// ----------------------------------------------------------------------- +// Plugin Window, will pass some Window events to UI + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +class PluginWindow +{ + UI* const ui; + +public: + explicit PluginWindow(UI* const uiPtr, PluginApplication& app) + : ui(uiPtr) + { + app.ui = ui; + } + + // fetch cached data + uint getWidth() const noexcept { return ui->pData.width; } + uint getHeight() const noexcept { return ui->pData.height; } + double getScaleFactor() const noexcept { return ui->pData.scaleFactor; } + + // direct mappings + void close() { ui->close(); } + void focus() { ui->focus(); } + void show() { ui->show(); } + bool isResizable() const noexcept { return ui->isResizable(); } + bool isVisible() const noexcept { return ui->isVisible(); } + void setTitle(const char* const title) { ui->setTitle(title); } + void setVisible(const bool visible) { ui->setVisible(visible); } + uintptr_t getNativeWindowHandle() const noexcept { return ui->getNativeWindowHandle(); } + void getGeometryConstraints(uint& minimumWidth, uint& minimumHeight, bool& keepAspectRatio) const noexcept + { + minimumWidth = ui->pData.minWidth; + minimumHeight = ui->pData.minHeight; + keepAspectRatio = ui->pData.keepAspectRatio; + } + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow) +}; +#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI +class PluginWindow : public DGL_NAMESPACE::Window +{ + UI* const ui; + bool initializing; + bool receivedReshapeDuringInit; + +public: + explicit PluginWindow(UI* const uiPtr, + PluginApplication& app, + const uintptr_t parentWindowHandle, + const uint width, + const uint height, + const double scaleFactor) + : Window(app, parentWindowHandle, width, height, scaleFactor, + DISTRHO_UI_USER_RESIZABLE, DISTRHO_UI_USES_SIZE_REQUEST, false), + ui(uiPtr), + initializing(true), + receivedReshapeDuringInit(false) + { + if (pData->view == nullptr) + return; + + // this is called just before creating UI, ensuring proper context to it + if (pData->initPost()) + puglBackendEnter(pData->view); + } + + ~PluginWindow() override + { + if (pData->view != nullptr) + puglBackendLeave(pData->view); + } + + // called after creating UI, restoring proper context + void leaveContext() + { + if (pData->view == nullptr) + return; + + if (receivedReshapeDuringInit) + ui->uiReshape(getWidth(), getHeight()); + + initializing = false; + puglBackendLeave(pData->view); + } + + // used for temporary windows (VST/CLAP get size without active/visible view) + void setIgnoreIdleCallbacks(const bool ignore = true) + { + pData->ignoreIdleCallbacks = ignore; + } + + // called right before deleting UI, ensuring correct context + void enterContextForDeletion() + { + if (pData->view != nullptr) + puglBackendEnter(pData->view); + } + + #if defined(DISTRHO_PLUGIN_TARGET_VST3) || defined(DISTRHO_PLUGIN_TARGET_CLAP) + void setSizeFromHost(const uint width, const uint height) + { + puglSetSizeAndDefault(pData->view, width, height); + } + #endif + + std::vector getClipboardDataOfferTypes() + { + return Window::getClipboardDataOfferTypes(); + } + +protected: + uint32_t onClipboardDataOffer() override + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, 0); + + if (initializing) + return 0; + + return ui->uiClipboardDataOffer(); + } + + void onFocus(const bool focus, const DGL_NAMESPACE::CrossingMode mode) override + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + if (initializing) + return; + + ui->uiFocus(focus, mode); + } + + void onReshape(const uint width, const uint height) override + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + if (initializing) + { + receivedReshapeDuringInit = true; + return; + } + + ui->uiReshape(width, height); + } + + void onScaleFactorChanged(const double scaleFactor) override + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + if (initializing) + return; + + ui->uiScaleFactorChanged(scaleFactor); + } + +# if DISTRHO_UI_FILE_BROWSER + void onFileSelected(const char* filename) override; +# endif + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow) +}; +#endif // DISTRHO_PLUGIN_HAS_EXTERNAL_UI + +// ----------------------------------------------------------------------- +// UI callbacks + +typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started); +typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value); +typedef void (*setStateFunc) (void* ptr, const char* key, const char* value); +typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo); +typedef void (*setSizeFunc) (void* ptr, uint width, uint height); +typedef bool (*fileRequestFunc) (void* ptr, const char* key); + +// ----------------------------------------------------------------------- +// UI private data + +struct UI::PrivateData { + // DGL + PluginApplication app; + ScopedPointer window; + + // DSP + double sampleRate; + uint32_t parameterOffset; + void* dspPtr; + + // UI + uint bgColor; + uint fgColor; + double scaleFactor; + uintptr_t winId; + #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_UI_FILE_BROWSER && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + char* uiStateFileKeyRequest; + std::map lastUsedDirnames; + #endif + char* bundlePath; + + // Ignore initial resize events while initializing + bool initializing; + + // Callbacks + void* callbacksPtr; + editParamFunc editParamCallbackFunc; + setParamFunc setParamCallbackFunc; + setStateFunc setStateCallbackFunc; + sendNoteFunc sendNoteCallbackFunc; + setSizeFunc setSizeCallbackFunc; + fileRequestFunc fileRequestCallbackFunc; + + PrivateData(const char* const appClassName) noexcept + : app(appClassName), + window(nullptr), + sampleRate(0), + parameterOffset(0), + dspPtr(nullptr), + bgColor(0), + fgColor(0xffffffff), + scaleFactor(1.0), + winId(0), + #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_UI_FILE_BROWSER && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + uiStateFileKeyRequest(nullptr), + #endif + bundlePath(nullptr), + initializing(true), + callbacksPtr(nullptr), + editParamCallbackFunc(nullptr), + setParamCallbackFunc(nullptr), + setStateCallbackFunc(nullptr), + sendNoteCallbackFunc(nullptr), + setSizeCallbackFunc(nullptr), + fileRequestCallbackFunc(nullptr) + { + #if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2) + parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; + #if DISTRHO_PLUGIN_WANT_LATENCY + parameterOffset += 1; + #endif + #endif + + #ifdef DISTRHO_PLUGIN_TARGET_LV2 + #if (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE) + parameterOffset += 1; + #endif + #if (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE) + parameterOffset += 1; + #endif + #endif + + #ifdef DISTRHO_PLUGIN_TARGET_VST3 + parameterOffset += kVst3InternalParameterCount; + #endif + } + + ~PrivateData() noexcept + { + #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_UI_FILE_BROWSER && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + std::free(uiStateFileKeyRequest); + #endif + std::free(bundlePath); + } + + void editParamCallback(const uint32_t rindex, const bool started) + { + if (editParamCallbackFunc != nullptr) + editParamCallbackFunc(callbacksPtr, rindex, started); + } + + void setParamCallback(const uint32_t rindex, const float value) + { + if (setParamCallbackFunc != nullptr) + setParamCallbackFunc(callbacksPtr, rindex, value); + } + + void setStateCallback(const char* const key, const char* const value) + { + if (setStateCallbackFunc != nullptr) + setStateCallbackFunc(callbacksPtr, key, value); + } + + void sendNoteCallback(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + if (sendNoteCallbackFunc != nullptr) + sendNoteCallbackFunc(callbacksPtr, channel, note, velocity); + } + + void setSizeCallback(const uint width, const uint height) + { + if (setSizeCallbackFunc != nullptr) + setSizeCallbackFunc(callbacksPtr, width, height); + } + + // implemented below, after PluginWindow + bool fileRequestCallback(const char* const key); + + static UI::PrivateData* s_nextPrivateData; +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + static ExternalWindow::PrivateData createNextWindow(UI* ui, uint width, uint height, bool adjustForScaleFactor); +#else + static PluginWindow& createNextWindow(UI* ui, uint width, uint height, bool adjustForScaleFactor); +#endif +}; + +// ----------------------------------------------------------------------- +// UI private data fileRequestCallback, which requires PluginWindow definitions + +inline bool UI::PrivateData::fileRequestCallback(const char* const key) +{ + if (fileRequestCallbackFunc != nullptr) + return fileRequestCallbackFunc(callbacksPtr, key); + + #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_UI_FILE_BROWSER && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + std::free(uiStateFileKeyRequest); + uiStateFileKeyRequest = strdup(key); + DISTRHO_SAFE_ASSERT_RETURN(uiStateFileKeyRequest != nullptr, false); + + char title[0xff]; + snprintf(title, sizeof(title)-1u, DISTRHO_PLUGIN_NAME ": %s", key); + title[sizeof(title)-1u] = '\0'; + + DGL_NAMESPACE::FileBrowserOptions opts; + opts.title = title; + if (lastUsedDirnames.count(key)) + opts.startDir = lastUsedDirnames[key].c_str(); + return window->openFileBrowser(opts); + #endif + + return false; +} + +// ----------------------------------------------------------------------- +// PluginWindow onFileSelected that require UI::PrivateData definitions + +#if DISTRHO_UI_FILE_BROWSER && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI +inline void PluginWindow::onFileSelected(const char* const filename) +{ + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + if (initializing) + return; + + #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_UI_FILE_BROWSER && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + if (char* const key = ui->uiData->uiStateFileKeyRequest) + { + ui->uiData->uiStateFileKeyRequest = nullptr; + if (filename != nullptr) + { + // notify DSP + ui->setState(key, filename); + + // notify UI + ui->stateChanged(key, filename); + + // save dirname for next time + if (const char* const lastsep = std::strrchr(filename, DISTRHO_OS_SEP)) + ui->uiData->lastUsedDirnames[key] = std::string(filename, lastsep-filename); + } + std::free(key); + return; + } + #endif + + puglBackendEnter(pData->view); + ui->uiFileBrowserSelected(filename); + puglBackendLeave(pData->view); +} +#endif + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_UI_PRIVATE_DATA_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIStub.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIStub.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,127 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoUIInternal.hpp" + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +#if ! DISTRHO_PLUGIN_WANT_STATE +static constexpr const setStateFunc setStateCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static constexpr const sendNoteFunc sendNoteCallback = nullptr; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * Stub UI class, does nothing but serving as example code for other implementations. + */ +class UIStub +{ +public: + UIStub(const intptr_t winId, + const double sampleRate, + const char* const bundlePath, + void* const dspPtr, + const float scaleFactor) + : fUI(this, winId, sampleRate, + editParameterCallback, + setParameterCallback, + setStateCallback, + sendNoteCallback, + setSizeCallback, + fileRequestCallback, + bundlePath, dspPtr, scaleFactor) + { + } + + // ---------------------------------------------------------------------------------------------------------------- + +private: + // Stub stuff here + + // Plugin UI (after Stub stuff so the UI can call into us during its constructor) + UIExporter fUI; + + // ---------------------------------------------------------------------------------------------------------------- + // DPF callbacks + + void editParameter(uint32_t, bool) const + { + } + + static void editParameterCallback(void* const ptr, const uint32_t rindex, const bool started) + { + static_cast(ptr)->editParameter(rindex, started); + } + + void setParameterValue(uint32_t, float) + { + } + + static void setParameterCallback(void* const ptr, const uint32_t rindex, const float value) + { + static_cast(ptr)->setParameterValue(rindex, value); + } + + void setSize(uint, uint) + { + } + + static void setSizeCallback(void* const ptr, const uint width, const uint height) + { + static_cast(ptr)->setSize(width, height); + } + + #if DISTRHO_PLUGIN_WANT_STATE + void setState(const char*, const char*) + { + } + + static void setStateCallback(void* const ptr, const char* key, const char* value) + { + static_cast(ptr)->setState(key, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + } + + static void sendNoteCallback(void* const ptr, const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + static_cast(ptr)->sendNote(channel, note, velocity); + } + #endif + + bool fileRequest(const char*) + { + return true; + } + + static bool fileRequestCallback(void* const ptr, const char* const key) + { + return static_cast(ptr)->fileRequest(key); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIVST3.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIVST3.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1644 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoUIInternal.hpp" + +#include "travesty/base.h" +#include "travesty/edit_controller.h" +#include "travesty/host.h" +#include "travesty/view.h" + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI +# if defined(DISTRHO_OS_MAC) +# include +# elif defined(DISTRHO_OS_WINDOWS) +# include +# define DPF_VST3_WIN32_TIMER_ID 1 +# endif +#endif + +/* TODO items: + * - mousewheel event + * - file request? + */ + +#if !(defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)) +# define DPF_VST3_USING_HOST_RUN_LOOP 1 +#else +# define DPF_VST3_USING_HOST_RUN_LOOP 0 +#endif + +#ifndef DPF_VST3_TIMER_INTERVAL +# define DPF_VST3_TIMER_INTERVAL 16 /* ~60 fps */ +#endif + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +#if ! DISTRHO_PLUGIN_WANT_STATE +static constexpr const setStateFunc setStateCallback = nullptr; +#endif +#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static constexpr const sendNoteFunc sendNoteCallback = nullptr; +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// Static data, see DistrhoPlugin.cpp + +extern const char* d_nextBundlePath; + +// -------------------------------------------------------------------------------------------------------------------- +// Utility functions (defined on plugin side) + +const char* tuid2str(const v3_tuid iid); + +// -------------------------------------------------------------------------------------------------------------------- + +static void applyGeometryConstraints(const uint minimumWidth, + const uint minimumHeight, + const bool keepAspectRatio, + v3_view_rect* const rect) +{ + d_debug("applyGeometryConstraints %u %u %d {%d,%d,%d,%d} | BEFORE", + minimumWidth, minimumHeight, keepAspectRatio, rect->top, rect->left, rect->right, rect->bottom); + const int32_t minWidth = static_cast(minimumWidth); + const int32_t minHeight = static_cast(minimumHeight); + + if (keepAspectRatio) + { + if (rect->right < 1) + rect->right = 1; + if (rect->bottom < 1) + rect->bottom = 1; + + const double ratio = static_cast(minWidth) / static_cast(minHeight); + const double reqRatio = static_cast(rect->right) / static_cast(rect->bottom); + + if (d_isNotEqual(ratio, reqRatio)) + { + // fix width + if (reqRatio > ratio) + rect->right = static_cast(rect->bottom * ratio + 0.5); + // fix height + else + rect->bottom = static_cast(static_cast(rect->right) / ratio + 0.5); + } + } + + if (minWidth > rect->right) + rect->right = minWidth; + if (minHeight > rect->bottom) + rect->bottom = minHeight; + + d_debug("applyGeometryConstraints %u %u %d {%d,%d,%d,%d} | AFTER", + minimumWidth, minimumHeight, keepAspectRatio, rect->top, rect->left, rect->right, rect->bottom); +} + +// -------------------------------------------------------------------------------------------------------------------- + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI +static uint translateVST3Modifiers(const int64_t modifiers) noexcept +{ + using namespace DGL_NAMESPACE; + + uint dglmods = 0; + if (modifiers & (1 << 0)) + dglmods |= kModifierShift; + if (modifiers & (1 << 1)) + dglmods |= kModifierAlt; + #ifdef DISTRHO_OS_MAC + if (modifiers & (1 << 2)) + dglmods |= kModifierSuper; + if (modifiers & (1 << 3)) + dglmods |= kModifierControl; + #else + if (modifiers & (1 << 2)) + dglmods |= kModifierControl; + if (modifiers & (1 << 3)) + dglmods |= kModifierSuper; + #endif + + return dglmods; +} +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI && !DPF_VST3_USING_HOST_RUN_LOOP +/** + * Helper class for getting a native idle timer via native APIs. + */ +class NativeIdleHelper +{ +public: + NativeIdleHelper(IdleCallback* const callback) + : fCallback(callback), + #ifdef DISTRHO_OS_MAC + fTimerRef(nullptr) + #else + fTimerWindow(nullptr), + fTimerWindowClassName() + #endif + { + } + + void registerNativeIdleCallback() + { + #ifdef DISTRHO_OS_MAC + constexpr const CFTimeInterval interval = DPF_VST3_TIMER_INTERVAL * 0.0001; + + CFRunLoopTimerContext context = {}; + context.info = this; + fTimerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + interval, interval, 0, 0, + platformIdleTimerCallback, &context); + DISTRHO_SAFE_ASSERT_RETURN(fTimerRef != nullptr,); + + CFRunLoopAddTimer(CFRunLoopGetCurrent(), fTimerRef, kCFRunLoopCommonModes); + #else + /* + * Create an invisible window to handle a timer. + * There is no need for implementing a window proc because DefWindowProc already calls the + * callback function when processing WM_TIMER messages. + */ + fTimerWindowClassName = ( + #ifdef DISTRHO_PLUGIN_BRAND + DISTRHO_PLUGIN_BRAND + #else + DISTRHO_MACRO_AS_STRING(DISTRHO_NAMESPACE) + #endif + "-" DISTRHO_PLUGIN_NAME "-" + ); + + char suffix[9]; + std::snprintf(suffix, sizeof(suffix), "%08x", std::rand()); + suffix[sizeof(suffix)-1] = '\0'; + fTimerWindowClassName += suffix; + + WNDCLASSEX cls; + ZeroMemory(&cls, sizeof(cls)); + cls.cbSize = sizeof(WNDCLASSEX); + cls.cbWndExtra = sizeof(LONG_PTR); + cls.lpszClassName = fTimerWindowClassName.buffer(); + cls.lpfnWndProc = DefWindowProc; + RegisterClassEx(&cls); + + fTimerWindow = CreateWindowEx(0, cls.lpszClassName, "DPF Timer Helper", + 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(fTimerWindow != nullptr,); + + SetWindowLongPtr(fTimerWindow, GWLP_USERDATA, reinterpret_cast(static_cast(this))); + SetTimer(fTimerWindow, DPF_VST3_WIN32_TIMER_ID, DPF_VST3_TIMER_INTERVAL, + static_cast(platformIdleTimerCallback)); + #endif + } + + void unregisterNativeIdleCallback() + { + #ifdef DISTRHO_OS_MAC + CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), fTimerRef, kCFRunLoopCommonModes); + CFRelease(fTimerRef); + #else + DISTRHO_SAFE_ASSERT_RETURN(fTimerWindow != nullptr,); + KillTimer(fTimerWindow, DPF_VST3_WIN32_TIMER_ID); + DestroyWindow(fTimerWindow); + UnregisterClass(fTimerWindowClassName, nullptr); + #endif + } + +private: + IdleCallback* const fCallback; + + #ifdef DISTRHO_OS_MAC + CFRunLoopTimerRef fTimerRef; + + static void platformIdleTimerCallback(CFRunLoopTimerRef, void* const info) + { + static_cast(info)->fCallback->idleCallback(); + } + #else + HWND fTimerWindow; + String fTimerWindowClassName; + + static void WINAPI platformIdleTimerCallback(const HWND hwnd, UINT, UINT_PTR, DWORD) + { + reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA))->fCallback->idleCallback(); + } + #endif +}; +#endif + +/** + * Helper class for getting a native idle timer, either through pugl or via native APIs. + */ +#if !DPF_VST3_USING_HOST_RUN_LOOP +class NativeIdleCallback : public IdleCallback +{ +public: + NativeIdleCallback(UIExporter& ui) + : fCallbackRegistered(false), + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + fIdleHelper(this) + #else + fUI(ui) + #endif + { + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + // unused + (void)ui; + #endif + } + + void registerNativeIdleCallback() + { + DISTRHO_SAFE_ASSERT_RETURN(!fCallbackRegistered,); + fCallbackRegistered = true; + + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + fIdleHelper.registerNativeIdleCallback(); + #else + fUI.addIdleCallbackForNativeIdle(this, DPF_VST3_TIMER_INTERVAL); + #endif + } + + void unregisterNativeIdleCallback() + { + DISTRHO_SAFE_ASSERT_RETURN(fCallbackRegistered,); + fCallbackRegistered = false; + + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + fIdleHelper.unregisterNativeIdleCallback(); + #else + fUI.removeIdleCallbackForNativeIdle(this); + #endif + } + +private: + bool fCallbackRegistered; + #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI + NativeIdleHelper fIdleHelper; + #else + UIExporter& fUI; + #endif +}; +#endif + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * VST3 UI class. + * + * All the dynamic things from VST3 get implemented here, free of complex low-level VST3 pointer things. + * The UI is created during the "attach" view event, and destroyed during "removed". + * + * The low-level VST3 stuff comes after. + */ +class UIVst3 +#if !DPF_VST3_USING_HOST_RUN_LOOP + : public NativeIdleCallback +#endif +{ +public: + UIVst3(v3_plugin_view** const view, + v3_host_application** const host, + v3_connection_point** const connection, + v3_plugin_frame** const frame, + const intptr_t winId, + const float scaleFactor, + const double sampleRate, + void* const instancePointer, + const bool willResizeFromHost, + const bool needsResizeFromPlugin) + : +#if !DPF_VST3_USING_HOST_RUN_LOOP + NativeIdleCallback(fUI), +#endif + fView(view), + fHostApplication(host), + fConnection(connection), + fFrame(frame), + fScaleFactor(scaleFactor), + fReadyForPluginData(false), + fIsResizingFromPlugin(false), + fIsResizingFromHost(willResizeFromHost), + fNeedsResizeFromPlugin(needsResizeFromPlugin), + fNextPluginRect(), + fUI(this, winId, sampleRate, + editParameterCallback, + setParameterCallback, + setStateCallback, + sendNoteCallback, + setSizeCallback, + nullptr, // TODO file request + d_nextBundlePath, + instancePointer, + scaleFactor) + { + } + + ~UIVst3() + { + #if !DPF_VST3_USING_HOST_RUN_LOOP + unregisterNativeIdleCallback(); + #endif + + if (fConnection != nullptr) + disconnect(); + } + + void postInit(uint32_t nextWidth, uint32_t nextHeight) + { + if (fIsResizingFromHost && nextWidth > 0 && nextHeight > 0) + { + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI.getScaleFactor(); + nextWidth *= scaleFactor; + nextHeight *= scaleFactor; + #endif + + if (fUI.getWidth() != nextWidth || fUI.getHeight() != nextHeight) + { + d_debug("postInit sets new size as %u %u", nextWidth, nextHeight); + fUI.setWindowSizeFromHost(nextWidth, nextHeight); + } + } + else if (fNeedsResizeFromPlugin) + { + d_debug("postInit forcely sets size from plugin as %u %u", fUI.getWidth(), fUI.getHeight()); + setSize(fUI.getWidth(), fUI.getHeight()); + } + + if (fConnection != nullptr) + connect(fConnection); + + #if !DPF_VST3_USING_HOST_RUN_LOOP + registerNativeIdleCallback(); + #endif + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_plugin_view interface calls + +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + v3_result onWheel(float /*distance*/) + { + // TODO + return V3_NOT_IMPLEMENTED; + } + + v3_result onKeyDown(const int16_t keychar, const int16_t keycode, const int16_t modifiers) + { + DISTRHO_SAFE_ASSERT_INT_RETURN(keychar >= 0 && keychar < 0x7f, keychar, V3_FALSE); + + bool special; + const uint key = translateVstKeyCode(special, keychar, keycode); + d_debug("onKeyDown %d %d %x -> %d %d", keychar, keycode, modifiers, special, key); + + return fUI.handlePluginKeyboardVST(true, special, key, + keycode >= 0 ? static_cast(keycode) : 0, + translateVST3Modifiers(modifiers)) ? V3_TRUE : V3_FALSE; + } + + v3_result onKeyUp(const int16_t keychar, const int16_t keycode, const int16_t modifiers) + { + DISTRHO_SAFE_ASSERT_INT_RETURN(keychar >= 0 && keychar < 0x7f, keychar, V3_FALSE); + + bool special; + const uint key = translateVstKeyCode(special, keychar, keycode); + d_debug("onKeyUp %d %d %x -> %d %d", keychar, keycode, modifiers, special, key); + + return fUI.handlePluginKeyboardVST(false, special, key, + keycode >= 0 ? static_cast(keycode) : 0, + translateVST3Modifiers(modifiers)) ? V3_TRUE : V3_FALSE; + } + + v3_result onFocus(const bool state) + { + if (state) + fUI.focus(); + fUI.notifyFocusChanged(state); + return V3_OK; + } +#endif + + v3_result getSize(v3_view_rect* const rect) const noexcept + { + if (fIsResizingFromPlugin) + { + *rect = fNextPluginRect; + } + else + { + rect->left = rect->top = 0; + rect->right = fUI.getWidth(); + rect->bottom = fUI.getHeight(); + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI.getScaleFactor(); + rect->right /= scaleFactor; + rect->bottom /= scaleFactor; + #endif + } + + d_debug("getSize request returning %i %i", rect->right, rect->bottom); + return V3_OK; + } + + v3_result onSize(v3_view_rect* const orect) + { + v3_view_rect rect = *orect; + + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI.getScaleFactor(); + rect.top *= scaleFactor; + rect.left *= scaleFactor; + rect.right *= scaleFactor; + rect.bottom *= scaleFactor; + #endif + + if (fIsResizingFromPlugin) + { + d_debug("host->plugin onSize request %i %i (plugin resize was active, unsetting now)", + rect.right - rect.left, rect.bottom - rect.top); + fIsResizingFromPlugin = false; + } + else + { + d_debug("host->plugin onSize request %i %i (OK)", rect.right - rect.left, rect.bottom - rect.top); + } + + fIsResizingFromHost = true; + fUI.setWindowSizeFromHost(rect.right - rect.left, rect.bottom - rect.top); + return V3_OK; + } + + v3_result setFrame(v3_plugin_frame** const frame) noexcept + { + fFrame = frame; + return V3_OK; + } + + v3_result canResize() noexcept + { + return fUI.isResizable() ? V3_TRUE : V3_FALSE; + } + + v3_result checkSizeConstraint(v3_view_rect* const rect) + { + uint minimumWidth, minimumHeight; + bool keepAspectRatio; + fUI.getGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio); + + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI.getScaleFactor(); + minimumWidth /= scaleFactor; + minimumHeight /= scaleFactor; + #endif + + applyGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio, rect); + return V3_TRUE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_connection_point interface calls + + void connect(v3_connection_point** const point) noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(point != nullptr,); + + fConnection = point; + + d_debug("requesting current plugin state"); + + v3_message** const message = createMessage("init"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); + v3_cpp_obj(fConnection)->notify(fConnection, message); + + v3_cpp_obj_unref(message); + } + + void disconnect() noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fConnection != nullptr,); + + d_debug("reporting UI closed"); + fReadyForPluginData = false; + + v3_message** const message = createMessage("close"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); + v3_cpp_obj(fConnection)->notify(fConnection, message); + + v3_cpp_obj_unref(message); + + fConnection = nullptr; + } + + v3_result notify(v3_message** const message) + { + const char* const msgid = v3_cpp_obj(message)->get_message_id(message); + DISTRHO_SAFE_ASSERT_RETURN(msgid != nullptr, V3_INVALID_ARG); + + v3_attribute_list** const attrs = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr, V3_INVALID_ARG); + + if (std::strcmp(msgid, "ready") == 0) + { + DISTRHO_SAFE_ASSERT_RETURN(! fReadyForPluginData, V3_INTERNAL_ERR); + fReadyForPluginData = true; + return V3_OK; + } + + if (std::strcmp(msgid, "parameter-set") == 0) + { + int64_t rindex; + double value; + v3_result res; + + res = v3_cpp_obj(attrs)->get_int(attrs, "rindex", &rindex); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + + res = v3_cpp_obj(attrs)->get_float(attrs, "value", &value); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + + if (rindex < kVst3InternalParameterBaseCount) + { + switch (rindex) + { + #if DPF_VST3_USES_SEPARATE_CONTROLLER + case kVst3InternalParameterSampleRate: + DISTRHO_SAFE_ASSERT_RETURN(value >= 0.0, V3_INVALID_ARG); + fUI.setSampleRate(value, true); + break; + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kVst3InternalParameterProgram: + DISTRHO_SAFE_ASSERT_RETURN(value >= 0.0, V3_INVALID_ARG); + fUI.programLoaded(static_cast(value + 0.5)); + break; + #endif + } + + // others like latency and buffer-size do not matter on UI side + return V3_OK; + } + + DISTRHO_SAFE_ASSERT_UINT2_RETURN(rindex >= kVst3InternalParameterCount, rindex, kVst3InternalParameterCount, V3_INVALID_ARG); + const uint32_t index = static_cast(rindex - kVst3InternalParameterCount); + + fUI.parameterChanged(index, value); + return V3_OK; + } + + #if DISTRHO_PLUGIN_WANT_STATE + if (std::strcmp(msgid, "state-set") == 0) + { + int64_t keyLength = -1; + int64_t valueLength = -1; + v3_result res; + + res = v3_cpp_obj(attrs)->get_int(attrs, "key:length", &keyLength); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(keyLength >= 0, keyLength, V3_INTERNAL_ERR); + + res = v3_cpp_obj(attrs)->get_int(attrs, "value:length", &valueLength); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); + DISTRHO_SAFE_ASSERT_INT_RETURN(valueLength >= 0, valueLength, V3_INTERNAL_ERR); + + int16_t* const key16 = (int16_t*)std::malloc(sizeof(int16_t)*(keyLength + 1)); + DISTRHO_SAFE_ASSERT_RETURN(key16 != nullptr, V3_NOMEM); + + int16_t* const value16 = (int16_t*)std::malloc(sizeof(int16_t)*(valueLength + 1)); + DISTRHO_SAFE_ASSERT_RETURN(value16 != nullptr, V3_NOMEM); + + res = v3_cpp_obj(attrs)->get_string(attrs, "key", key16, sizeof(int16_t)*(keyLength+1)); + DISTRHO_SAFE_ASSERT_INT2_RETURN(res == V3_OK, res, keyLength, res); + + if (valueLength != 0) + { + res = v3_cpp_obj(attrs)->get_string(attrs, "value", value16, sizeof(int16_t)*(valueLength+1)); + DISTRHO_SAFE_ASSERT_INT2_RETURN(res == V3_OK, res, valueLength, res); + } + + // do cheap inline conversion + char* const key = (char*)key16; + char* const value = (char*)value16; + + for (int64_t i=0; icreate_instance(fHostApplication, iid, iid, (void**)&msg); + DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_TRUE, res, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(msg != nullptr, nullptr); + + v3_cpp_obj(msg)->set_message_id(msg, id); + return msg; + } + + void requestMorePluginData() const + { + DISTRHO_SAFE_ASSERT_RETURN(fConnection != nullptr,); + + v3_message** const message = createMessage("idle"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); + v3_cpp_obj(fConnection)->notify(fConnection, message); + + v3_cpp_obj_unref(message); + } + + // ---------------------------------------------------------------------------------------------------------------- + // DPF callbacks + + void editParameter(const uint32_t rindex, const bool started) const + { + DISTRHO_SAFE_ASSERT_RETURN(fConnection != nullptr,); + + v3_message** const message = createMessage("parameter-edit"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); + v3_cpp_obj(attrlist)->set_int(attrlist, "rindex", rindex); + v3_cpp_obj(attrlist)->set_int(attrlist, "started", started ? 1 : 0); + v3_cpp_obj(fConnection)->notify(fConnection, message); + + v3_cpp_obj_unref(message); + } + + static void editParameterCallback(void* const ptr, const uint32_t rindex, const bool started) + { + static_cast(ptr)->editParameter(rindex, started); + } + + void setParameterValue(const uint32_t rindex, const float realValue) + { + DISTRHO_SAFE_ASSERT_RETURN(fConnection != nullptr,); + + v3_message** const message = createMessage("parameter-set"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); + v3_cpp_obj(attrlist)->set_int(attrlist, "rindex", rindex); + v3_cpp_obj(attrlist)->set_float(attrlist, "value", realValue); + v3_cpp_obj(fConnection)->notify(fConnection, message); + + v3_cpp_obj_unref(message); + } + + static void setParameterCallback(void* const ptr, const uint32_t rindex, const float value) + { + static_cast(ptr)->setParameterValue(rindex, value); + } + + #if DISTRHO_PLUGIN_WANT_STATE + void setState(const char* const key, const char* const value) + { + DISTRHO_SAFE_ASSERT_RETURN(fConnection != nullptr,); + + v3_message** const message = createMessage("state-set"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); + v3_cpp_obj(attrlist)->set_int(attrlist, "key:length", std::strlen(key)); + v3_cpp_obj(attrlist)->set_int(attrlist, "value:length", std::strlen(value)); + v3_cpp_obj(attrlist)->set_string(attrlist, "key", ScopedUTF16String(key)); + v3_cpp_obj(attrlist)->set_string(attrlist, "value", ScopedUTF16String(value)); + v3_cpp_obj(fConnection)->notify(fConnection, message); + + v3_cpp_obj_unref(message); + } + + static void setStateCallback(void* const ptr, const char* const key, const char* const value) + { + static_cast(ptr)->setState(key, value); + } + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + DISTRHO_SAFE_ASSERT_RETURN(fConnection != nullptr,); + + v3_message** const message = createMessage("midi"); + DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); + + v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message); + DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); + + uint8_t midiData[3]; + midiData[0] = (velocity != 0 ? 0x90 : 0x80) | channel; + midiData[1] = note; + midiData[2] = velocity; + + v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); + v3_cpp_obj(attrlist)->set_binary(attrlist, "data", midiData, sizeof(midiData)); + v3_cpp_obj(fConnection)->notify(fConnection, message); + + v3_cpp_obj_unref(message); + } + + static void sendNoteCallback(void* const ptr, const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + static_cast(ptr)->sendNote(channel, note, velocity); + } + #endif + + void setSize(uint width, uint height) + { + DISTRHO_SAFE_ASSERT_RETURN(fView != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fFrame != nullptr,); + + #ifdef DISTRHO_OS_MAC + const double scaleFactor = fUI.getScaleFactor(); + width /= scaleFactor; + height /= scaleFactor; + #endif + + if (fIsResizingFromHost) + { + if (fNeedsResizeFromPlugin) + { + d_debug("plugin->host setSize %u %u (FORCED, exception for first resize)", width, height); + } + else + { + d_debug("plugin->host setSize %u %u (IGNORED, host resize active)", width, height); + return; + } + } + else + { + d_debug("plugin->host setSize %u %u (OK)", width, height); + } + + fIsResizingFromPlugin = true; + + v3_view_rect rect; + rect.left = rect.top = 0; + rect.right = width; + rect.bottom = height; + fNextPluginRect = rect; + v3_cpp_obj(fFrame)->resize_view(fFrame, fView, &rect); + } + + static void setSizeCallback(void* const ptr, const uint width, const uint height) + { + static_cast(ptr)->setSize(width, height); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +/** + * VST3 low-level pointer thingies follow, proceed with care. + */ + +// -------------------------------------------------------------------------------------------------------------------- +// v3_funknown for classes with a single instance + +template +static uint32_t V3_API dpf_single_instance_ref(void* const self) +{ + return ++(*static_cast(self))->refcounter; +} + +template +static uint32_t V3_API dpf_single_instance_unref(void* const self) +{ + return --(*static_cast(self))->refcounter; +} + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_ui_connection_point + +struct dpf_ui_connection_point : v3_connection_point_cpp { + std::atomic_int refcounter; + ScopedPointer& uivst3; + v3_connection_point** other; + + dpf_ui_connection_point(ScopedPointer& v) + : refcounter(1), + uivst3(v), + other(nullptr) + { + // v3_funknown, single instance + query_interface = query_interface_connection_point; + ref = dpf_single_instance_ref; + unref = dpf_single_instance_unref; + + // v3_connection_point + point.connect = connect; + point.disconnect = disconnect; + point.notify = notify; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_connection_point(void* const self, const v3_tuid iid, void** const iface) + { + dpf_ui_connection_point* const point = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_connection_point_iid)) + { + d_debug("UI|query_interface_connection_point => %p %s %p | OK", self, tuid2str(iid), iface); + ++point->refcounter; + *iface = self; + return V3_OK; + } + + d_debug("DSP|query_interface_connection_point => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = NULL; + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_connection_point + + static v3_result V3_API connect(void* const self, v3_connection_point** const other) + { + dpf_ui_connection_point* const point = *static_cast(self); + d_debug("UI|dpf_ui_connection_point::connect => %p %p", self, other); + + DISTRHO_SAFE_ASSERT_RETURN(point->other == nullptr, V3_INVALID_ARG); + + point->other = other; + + if (UIVst3* const uivst3 = point->uivst3) + uivst3->connect(other); + + return V3_OK; + }; + + static v3_result V3_API disconnect(void* const self, v3_connection_point** const other) + { + d_debug("UI|dpf_ui_connection_point::disconnect => %p %p", self, other); + dpf_ui_connection_point* const point = *static_cast(self); + + DISTRHO_SAFE_ASSERT_RETURN(point->other != nullptr, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT(point->other == other); + + point->other = nullptr; + + if (UIVst3* const uivst3 = point->uivst3) + uivst3->disconnect(); + + return V3_OK; + }; + + static v3_result V3_API notify(void* const self, v3_message** const message) + { + dpf_ui_connection_point* const point = *static_cast(self); + + UIVst3* const uivst3 = point->uivst3; + DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); + + return uivst3->notify(message); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_plugin_view_content_scale + +struct dpf_plugin_view_content_scale : v3_plugin_view_content_scale_cpp { + std::atomic_int refcounter; + ScopedPointer& uivst3; + // cached values + float scaleFactor; + + dpf_plugin_view_content_scale(ScopedPointer& v) + : refcounter(1), + uivst3(v), + scaleFactor(0.0f) + { + // v3_funknown, single instance + query_interface = query_interface_view_content_scale; + ref = dpf_single_instance_ref; + unref = dpf_single_instance_unref; + + // v3_plugin_view_content_scale + scale.set_content_scale_factor = set_content_scale_factor; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_view_content_scale(void* const self, const v3_tuid iid, void** const iface) + { + dpf_plugin_view_content_scale* const scale = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_plugin_view_content_scale_iid)) + { + d_debug("query_interface_view_content_scale => %p %s %p | OK", self, tuid2str(iid), iface); + ++scale->refcounter; + *iface = self; + return V3_OK; + } + + d_debug("query_interface_view_content_scale => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = NULL; + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_plugin_view_content_scale + + static v3_result V3_API set_content_scale_factor(void* const self, const float factor) + { + dpf_plugin_view_content_scale* const scale = *static_cast(self); + d_debug("dpf_plugin_view::set_content_scale_factor => %p %f", self, factor); + + scale->scaleFactor = factor; + + if (UIVst3* const uivst3 = scale->uivst3) + return uivst3->setContentScaleFactor(factor); + + return V3_NOT_INITIALIZED; + } +}; + +#if DPF_VST3_USING_HOST_RUN_LOOP +// -------------------------------------------------------------------------------------------------------------------- +// dpf_timer_handler + +struct dpf_timer_handler : v3_timer_handler_cpp { + std::atomic_int refcounter; + ScopedPointer& uivst3; + bool valid; + + dpf_timer_handler(ScopedPointer& v) + : refcounter(1), + uivst3(v), + valid(true) + { + // v3_funknown, single instance + query_interface = query_interface_timer_handler; + ref = dpf_single_instance_ref; + unref = dpf_single_instance_unref; + + // v3_timer_handler + timer.on_timer = on_timer; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_timer_handler(void* self, const v3_tuid iid, void** iface) + { + dpf_timer_handler* const timer = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_timer_handler_iid)) + { + d_debug("query_interface_timer_handler => %p %s %p | OK", self, tuid2str(iid), iface); + ++timer->refcounter; + *iface = self; + return V3_OK; + } + + d_debug("query_interface_timer_handler => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = NULL; + return V3_NO_INTERFACE; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_timer_handler + + static void V3_API on_timer(void* self) + { + dpf_timer_handler* const timer = *static_cast(self); + + DISTRHO_SAFE_ASSERT_RETURN(timer->valid,); + + timer->uivst3->onTimer(); + } +}; +#endif + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_plugin_view + +static const char* const kSupportedPlatforms[] = { +#if defined(DISTRHO_OS_WINDOWS) + V3_VIEW_PLATFORM_TYPE_HWND, +#elif defined(DISTRHO_OS_MAC) + V3_VIEW_PLATFORM_TYPE_NSVIEW, +#else + V3_VIEW_PLATFORM_TYPE_X11, +#endif +}; + +struct dpf_plugin_view : v3_plugin_view_cpp { + std::atomic_int refcounter; + ScopedPointer connection; + ScopedPointer scale; + #if DPF_VST3_USING_HOST_RUN_LOOP + ScopedPointer timer; + #endif + ScopedPointer uivst3; + // cached values + v3_host_application** const hostApplication; + void* const instancePointer; + double sampleRate; + v3_plugin_frame** frame; + v3_run_loop** runloop; + uint32_t nextWidth, nextHeight; + bool sizeRequestedBeforeBeingAttached; + + dpf_plugin_view(v3_host_application** const host, void* const instance, const double sr) + : refcounter(1), + hostApplication(host), + instancePointer(instance), + sampleRate(sr), + frame(nullptr), + runloop(nullptr), + nextWidth(0), + nextHeight(0), + sizeRequestedBeforeBeingAttached(false) + { + d_debug("dpf_plugin_view() with hostApplication %p", hostApplication); + + // make sure host application is valid through out this view lifetime + if (hostApplication != nullptr) + v3_cpp_obj_ref(hostApplication); + + // v3_funknown, everything custom + query_interface = query_interface_view; + ref = ref_view; + unref = unref_view; + + // v3_plugin_view + view.is_platform_type_supported = is_platform_type_supported; + view.attached = attached; + view.removed = removed; + view.on_wheel = on_wheel; + view.on_key_down = on_key_down; + view.on_key_up = on_key_up; + view.get_size = get_size; + view.on_size = on_size; + view.on_focus = on_focus; + view.set_frame = set_frame; + view.can_resize = can_resize; + view.check_size_constraint = check_size_constraint; + } + + ~dpf_plugin_view() + { + d_debug("~dpf_plugin_view()"); + + connection = nullptr; + scale = nullptr; + #if DPF_VST3_USING_HOST_RUN_LOOP + timer = nullptr; + #endif + uivst3 = nullptr; + + if (hostApplication != nullptr) + v3_cpp_obj_unref(hostApplication); + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_funknown + + static v3_result V3_API query_interface_view(void* self, const v3_tuid iid, void** iface) + { + dpf_plugin_view* const view = *static_cast(self); + + if (v3_tuid_match(iid, v3_funknown_iid) || + v3_tuid_match(iid, v3_plugin_view_iid)) + { + d_debug("query_interface_view => %p %s %p | OK", self, tuid2str(iid), iface); + ++view->refcounter; + *iface = self; + return V3_OK; + } + + if (v3_tuid_match(v3_connection_point_iid, iid)) + { + d_debug("query_interface_view => %p %s %p | OK convert %p", + self, tuid2str(iid), iface, view->connection.get()); + + if (view->connection == nullptr) + view->connection = new dpf_ui_connection_point(view->uivst3); + else + ++view->connection->refcounter; + *iface = &view->connection; + return V3_OK; + } + + #ifndef DISTRHO_OS_MAC + if (v3_tuid_match(v3_plugin_view_content_scale_iid, iid)) + { + d_debug("query_interface_view => %p %s %p | OK convert %p", + self, tuid2str(iid), iface, view->scale.get()); + + if (view->scale == nullptr) + view->scale = new dpf_plugin_view_content_scale(view->uivst3); + else + ++view->scale->refcounter; + *iface = &view->scale; + return V3_OK; + } + #endif + + d_debug("query_interface_view => %p %s %p | WARNING UNSUPPORTED", self, tuid2str(iid), iface); + + *iface = nullptr; + return V3_NO_INTERFACE; + } + + static uint32_t V3_API ref_view(void* self) + { + dpf_plugin_view* const view = *static_cast(self); + const int refcount = ++view->refcounter; + d_debug("dpf_plugin_view::ref => %p | refcount %i", self, refcount); + return refcount; + } + + static uint32_t V3_API unref_view(void* self) + { + dpf_plugin_view** const viewptr = static_cast(self); + dpf_plugin_view* const view = *viewptr; + + if (const int refcount = --view->refcounter) + { + d_debug("dpf_plugin_view::unref => %p | refcount %i", self, refcount); + return refcount; + } + + if (view->connection != nullptr && view->connection->other) + v3_cpp_obj(view->connection->other)->disconnect(view->connection->other, + (v3_connection_point**)&view->connection); + + /** + * Some hosts will have unclean instances of a few of the view child classes at this point. + * We check for those here, going through the whole possible chain to see if it is safe to delete. + * TODO cleanup. + */ + + bool unclean = false; + + if (dpf_ui_connection_point* const conn = view->connection) + { + if (const int refcount = conn->refcounter) + { + unclean = true; + d_stderr("DPF warning: asked to delete view while connection point still active (refcount %d)", refcount); + } + } + + #ifndef DISTRHO_OS_MAC + if (dpf_plugin_view_content_scale* const scale = view->scale) + { + if (const int refcount = scale->refcounter) + { + unclean = true; + d_stderr("DPF warning: asked to delete view while content scale still active (refcount %d)", refcount); + } + } + #endif + + if (unclean) + return 0; + + d_debug("dpf_plugin_view::unref => %p | refcount is zero, deleting everything now!", self); + + delete view; + delete viewptr; + return 0; + } + + // ---------------------------------------------------------------------------------------------------------------- + // v3_plugin_view + + static v3_result V3_API is_platform_type_supported(void* const self, const char* const platform_type) + { + d_debug("dpf_plugin_view::is_platform_type_supported => %p %s", self, platform_type); + + for (size_t i=0; i %p %p %s", self, parent, platform_type); + dpf_plugin_view* const view = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(view->uivst3 == nullptr, V3_INVALID_ARG); + + for (size_t i=0; iframe != nullptr, V3_INVALID_ARG); + + v3_run_loop** runloop = nullptr; + v3_cpp_obj_query_interface(view->frame, v3_run_loop_iid, &runloop); + DISTRHO_SAFE_ASSERT_RETURN(runloop != nullptr, V3_INVALID_ARG); + + view->runloop = runloop; + #endif + + const float lastScaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f; + view->uivst3 = new UIVst3((v3_plugin_view**)self, + view->hostApplication, + view->connection != nullptr ? view->connection->other : nullptr, + view->frame, + (uintptr_t)parent, + lastScaleFactor, + view->sampleRate, + view->instancePointer, + view->nextWidth > 0 && view->nextHeight > 0, + view->sizeRequestedBeforeBeingAttached); + + view->uivst3->postInit(view->nextWidth, view->nextHeight); + view->nextWidth = 0; + view->nextHeight = 0; + view->sizeRequestedBeforeBeingAttached = false; + + #if DPF_VST3_USING_HOST_RUN_LOOP + // register a timer host run loop stuff + view->timer = new dpf_timer_handler(view->uivst3); + v3_cpp_obj(runloop)->register_timer(runloop, + (v3_timer_handler**)&view->timer, + DPF_VST3_TIMER_INTERVAL); + #endif + + return V3_OK; + } + } + + return V3_NOT_IMPLEMENTED; + } + + static v3_result V3_API removed(void* const self) + { + d_debug("dpf_plugin_view::removed => %p", self); + dpf_plugin_view* const view = *static_cast(self); + DISTRHO_SAFE_ASSERT_RETURN(view->uivst3 != nullptr, V3_INVALID_ARG); + + #if DPF_VST3_USING_HOST_RUN_LOOP + // unregister our timer as needed + if (v3_run_loop** const runloop = view->runloop) + { + if (view->timer != nullptr && view->timer->valid) + { + v3_cpp_obj(runloop)->unregister_timer(runloop, (v3_timer_handler**)&view->timer); + + if (const int refcount = --view->timer->refcounter) + { + view->timer->valid = false; + d_stderr("VST3 warning: Host run loop did not give away timer (refcount %d)", refcount); + } + else + { + view->timer = nullptr; + } + } + + v3_cpp_obj_unref(runloop); + view->runloop = nullptr; + } + #endif + + view->uivst3 = nullptr; + return V3_OK; + } + + static v3_result V3_API on_wheel(void* const self, const float distance) + { +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + d_debug("dpf_plugin_view::on_wheel => %p %f", self, distance); + dpf_plugin_view* const view = *static_cast(self); + + UIVst3* const uivst3 = view->uivst3; + DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); + + return uivst3->onWheel(distance); +#else + return V3_NOT_IMPLEMENTED; + // unused + (void)self; (void)distance; +#endif + } + + static v3_result V3_API on_key_down(void* const self, const int16_t key_char, const int16_t key_code, const int16_t modifiers) + { +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + d_debug("dpf_plugin_view::on_key_down => %p %i %i %i", self, key_char, key_code, modifiers); + dpf_plugin_view* const view = *static_cast(self); + + UIVst3* const uivst3 = view->uivst3; + DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); + + return uivst3->onKeyDown(key_char, key_code, modifiers); +#else + return V3_NOT_IMPLEMENTED; + // unused + (void)self; (void)key_char; (void)key_code; (void)modifiers; +#endif + } + + static v3_result V3_API on_key_up(void* const self, const int16_t key_char, const int16_t key_code, const int16_t modifiers) + { +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + d_debug("dpf_plugin_view::on_key_up => %p %i %i %i", self, key_char, key_code, modifiers); + dpf_plugin_view* const view = *static_cast(self); + + UIVst3* const uivst3 = view->uivst3; + DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); + + return uivst3->onKeyUp(key_char, key_code, modifiers); +#else + return V3_NOT_IMPLEMENTED; + // unused + (void)self; (void)key_char; (void)key_code; (void)modifiers; +#endif + } + + static v3_result V3_API get_size(void* const self, v3_view_rect* const rect) + { + d_debug("dpf_plugin_view::get_size => %p", self); + dpf_plugin_view* const view = *static_cast(self); + + if (UIVst3* const uivst3 = view->uivst3) + return uivst3->getSize(rect); + + d_debug("dpf_plugin_view::get_size => %p | NOTE: size request before attach", self); + + view->sizeRequestedBeforeBeingAttached = true; + + double scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0; + #if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT) + rect->right = DISTRHO_UI_DEFAULT_WIDTH; + rect->bottom = DISTRHO_UI_DEFAULT_HEIGHT; + if (d_isZero(scaleFactor)) + scaleFactor = 1.0; + #else + UIExporter tmpUI(nullptr, 0, view->sampleRate, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, d_nextBundlePath, + view->instancePointer, scaleFactor); + rect->right = tmpUI.getWidth(); + rect->bottom = tmpUI.getHeight(); + scaleFactor = tmpUI.getScaleFactor(); + tmpUI.quit(); + #endif + rect->left = rect->top = 0; + #ifdef DISTRHO_OS_MAC + rect->right /= scaleFactor; + rect->bottom /= scaleFactor; + #endif + + return V3_OK; + } + + static v3_result V3_API on_size(void* const self, v3_view_rect* const rect) + { + d_debug("dpf_plugin_view::on_size => %p {%d,%d,%d,%d}", + self, rect->top, rect->left, rect->right, rect->bottom); + DISTRHO_SAFE_ASSERT_INT2_RETURN(rect->right > rect->left, rect->right, rect->left, V3_INVALID_ARG); + DISTRHO_SAFE_ASSERT_INT2_RETURN(rect->bottom > rect->top, rect->bottom, rect->top, V3_INVALID_ARG); + + dpf_plugin_view* const view = *static_cast(self); + + if (UIVst3* const uivst3 = view->uivst3) + return uivst3->onSize(rect); + + view->nextWidth = static_cast(rect->right - rect->left); + view->nextHeight = static_cast(rect->bottom - rect->top); + return V3_OK; + } + + static v3_result V3_API on_focus(void* const self, const v3_bool state) + { +#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI + d_debug("dpf_plugin_view::on_focus => %p %u", self, state); + dpf_plugin_view* const view = *static_cast(self); + + UIVst3* const uivst3 = view->uivst3; + DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); + + return uivst3->onFocus(state); +#else + return V3_NOT_IMPLEMENTED; + // unused + (void)self; (void)state; +#endif + } + + static v3_result V3_API set_frame(void* const self, v3_plugin_frame** const frame) + { + d_debug("dpf_plugin_view::set_frame => %p %p", self, frame); + dpf_plugin_view* const view = *static_cast(self); + + view->frame = frame; + + if (UIVst3* const uivst3 = view->uivst3) + return uivst3->setFrame(frame); + + return V3_OK; + } + + static v3_result V3_API can_resize(void* const self) + { +#if DISTRHO_UI_USER_RESIZABLE + dpf_plugin_view* const view = *static_cast(self); + + if (UIVst3* const uivst3 = view->uivst3) + return uivst3->canResize(); + + return V3_TRUE; +#else + return V3_FALSE; + + // unused + (void)self; +#endif + } + + static v3_result V3_API check_size_constraint(void* const self, v3_view_rect* const rect) + { + d_debug("dpf_plugin_view::check_size_constraint => %p {%d,%d,%d,%d}", + self, rect->top, rect->left, rect->right, rect->bottom); + dpf_plugin_view* const view = *static_cast(self); + + if (UIVst3* const uivst3 = view->uivst3) + return uivst3->checkSizeConstraint(rect); + + return V3_NOT_INITIALIZED; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- +// dpf_plugin_view_create (called from plugin side) + +v3_plugin_view** dpf_plugin_view_create(v3_host_application** host, void* instancePointer, double sampleRate); + +v3_plugin_view** dpf_plugin_view_create(v3_host_application** const host, + void* const instancePointer, + const double sampleRate) +{ + dpf_plugin_view** const viewptr = new dpf_plugin_view*; + *viewptr = new dpf_plugin_view(host, instancePointer, sampleRate); + return static_cast(static_cast(viewptr)); +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUtils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUtils.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,168 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_IS_STANDALONE +# error Wrong build configuration +#endif + +#include "../extra/String.hpp" +#include "../DistrhoStandaloneUtils.hpp" + +#ifdef DISTRHO_OS_WINDOWS +# include +#else +# ifndef STATIC_BUILD +# include +# endif +# include +# include +#endif + +#ifdef DISTRHO_OS_WINDOWS +# if DISTRHO_IS_STANDALONE || defined(STATIC_BUILD) +static constexpr const HINSTANCE hInstance = nullptr; +# else +static HINSTANCE hInstance = nullptr; + +DISTRHO_PLUGIN_EXPORT +BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID) +{ + if (reason == DLL_PROCESS_ATTACH) + hInstance = hInst; + return 1; +} +# endif +#endif + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +const char* getBinaryFilename() +{ + static String filename; + + #ifndef STATIC_BUILD + if (filename.isNotEmpty()) + return filename; + + #ifdef DISTRHO_OS_WINDOWS + CHAR filenameBuf[MAX_PATH]; + filenameBuf[0] = '\0'; + GetModuleFileNameA(hInstance, filenameBuf, sizeof(filenameBuf)); + filename = filenameBuf; + #else + Dl_info info; + dladdr((void*)getBinaryFilename, &info); + char filenameBuf[PATH_MAX]; + filename = realpath(info.dli_fname, filenameBuf); + #endif + #endif + + return filename; +} + +const char* getPluginFormatName() noexcept +{ +#if defined(DISTRHO_PLUGIN_TARGET_CARLA) + return "Carla"; +#elif defined(DISTRHO_PLUGIN_TARGET_JACK) + #if defined(DISTRHO_OS_WASM) + return "Wasm/Standalone"; + #elif defined(HAVE_JACK) + return "JACK/Standalone"; + #else + return "Standalone"; + #endif +#elif defined(DISTRHO_PLUGIN_TARGET_LADSPA) + return "LADSPA"; +#elif defined(DISTRHO_PLUGIN_TARGET_DSSI) + return "DSSI"; +#elif defined(DISTRHO_PLUGIN_TARGET_LV2) + return "LV2"; +#elif defined(DISTRHO_PLUGIN_TARGET_VST2) + return "VST2"; +#elif defined(DISTRHO_PLUGIN_TARGET_VST3) + return "VST3"; +#elif defined(DISTRHO_PLUGIN_TARGET_CLAP) + return "CLAP"; +#elif defined(DISTRHO_PLUGIN_TARGET_STATIC) && defined(DISTRHO_PLUGIN_TARGET_STATIC_NAME) + return DISTRHO_PLUGIN_TARGET_STATIC_NAME; +#else + return "Unknown"; +#endif +} + +const char* getResourcePath(const char* const bundlePath) noexcept +{ + DISTRHO_SAFE_ASSERT_RETURN(bundlePath != nullptr, nullptr); + + #if defined(DISTRHO_PLUGIN_TARGET_JACK) || defined(DISTRHO_PLUGIN_TARGET_VST2) || defined(DISTRHO_PLUGIN_TARGET_CLAP) + static String resourcePath; + + if (resourcePath.isEmpty()) + { + resourcePath = bundlePath; + #ifdef DISTRHO_OS_MAC + resourcePath += "/Contents/Resources"; + #else + resourcePath += DISTRHO_OS_SEP_STR "resources"; + #endif + } + + return resourcePath.buffer(); + #elif defined(DISTRHO_PLUGIN_TARGET_LV2) + static String resourcePath; + + if (resourcePath.isEmpty()) + { + resourcePath = bundlePath; + resourcePath += DISTRHO_OS_SEP_STR "resources"; + } + + return resourcePath.buffer(); + #elif defined(DISTRHO_PLUGIN_TARGET_VST3) + static String resourcePath; + + if (resourcePath.isEmpty()) + { + resourcePath = bundlePath; + resourcePath += "/Contents/Resources"; + } + + return resourcePath.buffer(); + #endif + + return nullptr; +} + +#ifndef DISTRHO_PLUGIN_TARGET_JACK +// all these are null for non-standalone targets +bool isUsingNativeAudio() noexcept { return false; } +bool supportsAudioInput() { return false; } +bool supportsBufferSizeChanges() { return false; } +bool supportsMIDI() { return false; } +bool isAudioInputEnabled() { return false; } +bool isMIDIEnabled() { return false; } +uint getBufferSize() { return 0; } +bool requestAudioInput() { return false; } +bool requestBufferSizeChange(uint) { return false; } +bool requestMIDI() { return false; } +#endif + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/audio-buffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/audio-buffer.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,37 @@ +#pragma once + +#include "private/std.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Sample code for reading a stereo buffer: +// +// bool isLeftConstant = (buffer->constant_mask & (1 << 0)) != 0; +// bool isRightConstant = (buffer->constant_mask & (1 << 1)) != 0; +// +// for (int i = 0; i < N; ++i) { +// float l = data32[0][isLeftConstant ? 0 : i]; +// float r = data32[1][isRightConstant ? 0 : i]; +// } +// +// Note: checking the constant mask is optional, and this implies that +// the buffer must be filled with the constant value. +// Rationale: if a buffer reader doesn't check the constant mask, then it may +// process garbage samples and in result, garbage samples may be transmitted +// to the audio interface with all the bad consequences it can have. +// +// The constant mask is a hint. +typedef struct clap_audio_buffer { + // Either data32 or data64 pointer will be set. + float **data32; + double **data64; + uint32_t channel_count; + uint32_t latency; // latency from/to the audio interface + uint64_t constant_mask; +} clap_audio_buffer_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/entry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/entry.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,68 @@ +#pragma once + +#include "version.h" +#include "private/macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// This interface is the entry point of the dynamic library. +// +// CLAP plugins standard search path: +// +// Linux +// - ~/.clap +// - /usr/lib/clap +// +// Windows +// - %CommonFilesFolder%/CLAP/ +// - %LOCALAPPDATA%/Programs/Common/CLAP/ +// +// MacOS +// - /Library/Audio/Plug-Ins/CLAP +// - ~/Library/Audio/Plug-Ins/CLAP +// +// In addition to the OS-specific default locations above, a CLAP host must query the environment +// for a CLAP_PATH variable, which is a list of directories formatted in the same manner as the host +// OS binary search path (PATH on Unix, separated by `:` and Path on Windows, separated by ';', as +// of this writing). +// +// Each directory should be recursively searched for files and/or bundles as appropriate in your OS +// ending with the extension `.clap`. +// +// Every method must be thread-safe. +typedef struct clap_plugin_entry { + clap_version_t clap_version; // initialized to CLAP_VERSION + + // This function must be called first, and can only be called once. + // + // It should be as fast as possible, in order to perform a very quick scan of the plugin + // descriptors. + // + // It is forbidden to display graphical user interface in this call. + // It is forbidden to perform user interaction in this call. + // + // If the initialization depends upon expensive computation, maybe try to do them ahead of time + // and cache the result. + // + // If init() returns false, then the host must not call deinit() nor any other clap + // related symbols from the DSO. + bool(CLAP_ABI *init)(const char *plugin_path); + + // No more calls into the DSO must be made after calling deinit(). + void(CLAP_ABI *deinit)(void); + + // Get the pointer to a factory. See plugin-factory.h for an example. + // + // Returns null if the factory is not provided. + // The returned pointer must *not* be freed by the caller. + const void *(CLAP_ABI *get_factory)(const char *factory_id); +} clap_plugin_entry_t; + +/* Entry point */ +CLAP_EXPORT extern const clap_plugin_entry_t clap_entry; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/events.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/events.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,285 @@ +#pragma once + +#include "private/std.h" +#include "fixedpoint.h" +#include "id.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// event header +// must be the first attribute of the event +typedef struct clap_event_header { + uint32_t size; // event size including this header, eg: sizeof (clap_event_note) + uint32_t time; // sample offset within the buffer for this event + uint16_t space_id; // event space, see clap_host_event_registry + uint16_t type; // event type + uint32_t flags; // see clap_event_flags +} clap_event_header_t; + +// The clap core event space +static const CLAP_CONSTEXPR uint16_t CLAP_CORE_EVENT_SPACE_ID = 0; + +enum clap_event_flags { + // Indicate a live user event, for example a user turning a physical knob + // or playing a physical key. + CLAP_EVENT_IS_LIVE = 1 << 0, + + // Indicate that the event should not be recorded. + // For example this is useful when a parameter changes because of a MIDI CC, + // because if the host records both the MIDI CC automation and the parameter + // automation there will be a conflict. + CLAP_EVENT_DONT_RECORD = 1 << 1, +}; + +// Some of the following events overlap, a note on can be expressed with: +// - CLAP_EVENT_NOTE_ON +// - CLAP_EVENT_MIDI +// - CLAP_EVENT_MIDI2 +// +// The preferred way of sending a note event is to use CLAP_EVENT_NOTE_*. +// +// The same event must not be sent twice: it is forbidden to send a the same note on +// encoded with both CLAP_EVENT_NOTE_ON and CLAP_EVENT_MIDI. +// +// The plugins are encouraged to be able to handle note events encoded as raw midi or midi2, +// or implement clap_plugin_event_filter and reject raw midi and midi2 events. +enum { + // NOTE_ON and NOTE_OFF represent a key pressed and key released event, respectively. + // A NOTE_ON with a velocity of 0 is valid and should not be interpreted as a NOTE_OFF. + // + // NOTE_CHOKE is meant to choke the voice(s), like in a drum machine when a closed hihat + // chokes an open hihat. This event can be sent by the host to the plugin. Here are two use cases: + // - a plugin is inside a drum pad in Bitwig Studio's drum machine, and this pad is choked by + // another one + // - the user double clicks the DAW's stop button in the transport which then stops the sound on + // every tracks + // + // NOTE_END is sent by the plugin to the host. The port, channel, key and note_id are those given + // by the host in the NOTE_ON event. In other words, this event is matched against the + // plugin's note input port. + // NOTE_END is useful to help the host to match the plugin's voice life time. + // + // When using polyphonic modulations, the host has to allocate and release voices for its + // polyphonic modulator. Yet only the plugin effectively knows when the host should terminate + // a voice. NOTE_END solves that issue in a non-intrusive and cooperative way. + // + // CLAP assumes that the host will allocate a unique voice on NOTE_ON event for a given port, + // channel and key. This voice will run until the plugin will instruct the host to terminate + // it by sending a NOTE_END event. + // + // Consider the following sequence: + // - process() + // Host->Plugin NoteOn(port:0, channel:0, key:16, time:t0) + // Host->Plugin NoteOn(port:0, channel:0, key:64, time:t0) + // Host->Plugin NoteOff(port:0, channel:0, key:16, t1) + // Host->Plugin NoteOff(port:0, channel:0, key:64, t1) + // # on t2, both notes did terminate + // Host->Plugin NoteOn(port:0, channel:0, key:64, t3) + // # Here the plugin finished processing all the frames and will tell the host + // # to terminate the voice on key 16 but not 64, because a note has been started at t3 + // Plugin->Host NoteEnd(port:0, channel:0, key:16, time:ignored) + // + // These four events use clap_event_note. + CLAP_EVENT_NOTE_ON, + CLAP_EVENT_NOTE_OFF, + CLAP_EVENT_NOTE_CHOKE, + CLAP_EVENT_NOTE_END, + + // Represents a note expression. + // Uses clap_event_note_expression. + CLAP_EVENT_NOTE_EXPRESSION, + + // PARAM_VALUE sets the parameter's value; uses clap_event_param_value. + // PARAM_MOD sets the parameter's modulation amount; uses clap_event_param_mod. + // + // The value heard is: param_value + param_mod. + // + // In case of a concurrent global value/modulation versus a polyphonic one, + // the voice should only use the polyphonic one and the polyphonic modulation + // amount will already include the monophonic signal. + CLAP_EVENT_PARAM_VALUE, + CLAP_EVENT_PARAM_MOD, + + // Indicates that the user started or finished adjusting a knob. + // This is not mandatory to wrap parameter changes with gesture events, but this improves + // the user experience a lot when recording automation or overriding automation playback. + // Uses clap_event_param_gesture. + CLAP_EVENT_PARAM_GESTURE_BEGIN, + CLAP_EVENT_PARAM_GESTURE_END, + + CLAP_EVENT_TRANSPORT, // update the transport info; clap_event_transport + CLAP_EVENT_MIDI, // raw midi event; clap_event_midi + CLAP_EVENT_MIDI_SYSEX, // raw midi sysex event; clap_event_midi_sysex + CLAP_EVENT_MIDI2, // raw midi 2 event; clap_event_midi2 +}; + +// Note on, off, end and choke events. +// In the case of note choke or end events: +// - the velocity is ignored. +// - key and channel are used to match active notes, a value of -1 matches all. +typedef struct clap_event_note { + clap_event_header_t header; + + int32_t note_id; // -1 if unspecified, otherwise >=0 + int16_t port_index; + int16_t channel; // 0..15 + int16_t key; // 0..127 + double velocity; // 0..1 +} clap_event_note_t; + +enum { + // with 0 < x <= 4, plain = 20 * log(x) + CLAP_NOTE_EXPRESSION_VOLUME, + + // pan, 0 left, 0.5 center, 1 right + CLAP_NOTE_EXPRESSION_PAN, + + // relative tuning in semitone, from -120 to +120 + CLAP_NOTE_EXPRESSION_TUNING, + + // 0..1 + CLAP_NOTE_EXPRESSION_VIBRATO, + CLAP_NOTE_EXPRESSION_EXPRESSION, + CLAP_NOTE_EXPRESSION_BRIGHTNESS, + CLAP_NOTE_EXPRESSION_PRESSURE, +}; +typedef int32_t clap_note_expression; + +typedef struct clap_event_note_expression { + clap_event_header_t header; + + clap_note_expression expression_id; + + // target a specific note_id, port, key and channel, -1 for global + int32_t note_id; + int16_t port_index; + int16_t channel; + int16_t key; + + double value; // see expression for the range +} clap_event_note_expression_t; + +typedef struct clap_event_param_value { + clap_event_header_t header; + + // target parameter + clap_id param_id; // @ref clap_param_info.id + void *cookie; // @ref clap_param_info.cookie + + // target a specific note_id, port, key and channel, -1 for global + int32_t note_id; + int16_t port_index; + int16_t channel; + int16_t key; + + double value; +} clap_event_param_value_t; + +typedef struct clap_event_param_mod { + clap_event_header_t header; + + // target parameter + clap_id param_id; // @ref clap_param_info.id + void *cookie; // @ref clap_param_info.cookie + + // target a specific note_id, port, key and channel, -1 for global + int32_t note_id; + int16_t port_index; + int16_t channel; + int16_t key; + + double amount; // modulation amount +} clap_event_param_mod_t; + +typedef struct clap_event_param_gesture { + clap_event_header_t header; + + // target parameter + clap_id param_id; // @ref clap_param_info.id +} clap_event_param_gesture_t; + +enum clap_transport_flags { + CLAP_TRANSPORT_HAS_TEMPO = 1 << 0, + CLAP_TRANSPORT_HAS_BEATS_TIMELINE = 1 << 1, + CLAP_TRANSPORT_HAS_SECONDS_TIMELINE = 1 << 2, + CLAP_TRANSPORT_HAS_TIME_SIGNATURE = 1 << 3, + CLAP_TRANSPORT_IS_PLAYING = 1 << 4, + CLAP_TRANSPORT_IS_RECORDING = 1 << 5, + CLAP_TRANSPORT_IS_LOOP_ACTIVE = 1 << 6, + CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL = 1 << 7, +}; + +typedef struct clap_event_transport { + clap_event_header_t header; + + uint32_t flags; // see clap_transport_flags + + clap_beattime song_pos_beats; // position in beats + clap_sectime song_pos_seconds; // position in seconds + + double tempo; // in bpm + double tempo_inc; // tempo increment for each samples and until the next + // time info event + + clap_beattime loop_start_beats; + clap_beattime loop_end_beats; + clap_sectime loop_start_seconds; + clap_sectime loop_end_seconds; + + clap_beattime bar_start; // start pos of the current bar + int32_t bar_number; // bar at song pos 0 has the number 0 + + uint16_t tsig_num; // time signature numerator + uint16_t tsig_denom; // time signature denominator +} clap_event_transport_t; + +typedef struct clap_event_midi { + clap_event_header_t header; + + uint16_t port_index; + uint8_t data[3]; +} clap_event_midi_t; + +typedef struct clap_event_midi_sysex { + clap_event_header_t header; + + uint16_t port_index; + const uint8_t *buffer; // midi buffer + uint32_t size; +} clap_event_midi_sysex_t; + +// While it is possible to use a series of midi2 event to send a sysex, +// prefer clap_event_midi_sysex if possible for efficiency. +typedef struct clap_event_midi2 { + clap_event_header_t header; + + uint16_t port_index; + uint32_t data[4]; +} clap_event_midi2_t; + +// Input event list, events must be sorted by time. +typedef struct clap_input_events { + void *ctx; // reserved pointer for the list + + // returns the number of events in the list + uint32_t(CLAP_ABI *size)(const struct clap_input_events *list); + + // Don't free the returned event, it belongs to the list + const clap_event_header_t *(CLAP_ABI *get)(const struct clap_input_events *list, uint32_t index); +} clap_input_events_t; + +// Output event list, events must be sorted by time. +typedef struct clap_output_events { + void *ctx; // reserved pointer for the list + + // Pushes a copy of the event + // returns false if the event could not be pushed to the queue (out of memory?) + bool(CLAP_ABI *try_push)(const struct clap_output_events *list, + const clap_event_header_t *event); +} clap_output_events_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/audio-ports.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/audio-ports.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,116 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +/// @page Audio Ports +/// +/// This extension provides a way for the plugin to describe its current audio ports. +/// +/// If the plugin does not implement this extension, it won't have audio ports. +/// +/// 32 bits support is required for both host and plugins. 64 bits audio is optional. +/// +/// The plugin is only allowed to change its ports configuration while it is deactivated. + +static CLAP_CONSTEXPR const char CLAP_EXT_AUDIO_PORTS[] = "clap.audio-ports"; +static CLAP_CONSTEXPR const char CLAP_PORT_MONO[] = "mono"; +static CLAP_CONSTEXPR const char CLAP_PORT_STEREO[] = "stereo"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // This port is the main audio input or output. + // There can be only one main input and main output. + // Main port must be at index 0. + CLAP_AUDIO_PORT_IS_MAIN = 1 << 0, + + // This port can be used with 64 bits audio + CLAP_AUDIO_PORT_SUPPORTS_64BITS = 1 << 1, + + // 64 bits audio is preferred with this port + CLAP_AUDIO_PORT_PREFERS_64BITS = 1 << 2, + + // This port must be used with the same sample size as all the other ports which have this flag. + // In other words if all ports have this flag then the plugin may either be used entirely with + // 64 bits audio or 32 bits audio, but it can't be mixed. + CLAP_AUDIO_PORT_REQUIRES_COMMON_SAMPLE_SIZE = 1 << 3, +}; + +typedef struct clap_audio_port_info { + // id identifies a port and must be stable. + // id may overlap between input and output ports. + clap_id id; + char name[CLAP_NAME_SIZE]; // displayable name + + uint32_t flags; + uint32_t channel_count; + + // If null or empty then it is unspecified (arbitrary audio). + // This filed can be compared against: + // - CLAP_PORT_MONO + // - CLAP_PORT_STEREO + // - CLAP_PORT_SURROUND (defined in the surround extension) + // - CLAP_PORT_AMBISONIC (defined in the ambisonic extension) + // - CLAP_PORT_CV (defined in the cv extension) + // + // An extension can provide its own port type and way to inspect the channels. + const char *port_type; + + // in-place processing: allow the host to use the same buffer for input and output + // if supported set the pair port id. + // if not supported set to CLAP_INVALID_ID + clap_id in_place_pair; +} clap_audio_port_info_t; + +// The audio ports scan has to be done while the plugin is deactivated. +typedef struct clap_plugin_audio_ports { + // number of ports, for either input or output + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input); + + // get info about about an audio port. + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, + uint32_t index, + bool is_input, + clap_audio_port_info_t *info); +} clap_plugin_audio_ports_t; + +enum { + // The ports name did change, the host can scan them right away. + CLAP_AUDIO_PORTS_RESCAN_NAMES = 1 << 0, + + // [!active] The flags did change + CLAP_AUDIO_PORTS_RESCAN_FLAGS = 1 << 1, + + // [!active] The channel_count did change + CLAP_AUDIO_PORTS_RESCAN_CHANNEL_COUNT = 1 << 2, + + // [!active] The port type did change + CLAP_AUDIO_PORTS_RESCAN_PORT_TYPE = 1 << 3, + + // [!active] The in-place pair did change, this requires. + CLAP_AUDIO_PORTS_RESCAN_IN_PLACE_PAIR = 1 << 4, + + // [!active] The list of ports have changed: entries have been removed/added. + CLAP_AUDIO_PORTS_RESCAN_LIST = 1 << 5, +}; + +typedef struct clap_host_audio_ports { + // Checks if the host allows a plugin to change a given aspect of the audio ports definition. + // [main-thread] + bool(CLAP_ABI *is_rescan_flag_supported)(const clap_host_t *host, uint32_t flag); + + // Rescan the full list of audio ports according to the flags. + // It is illegal to ask the host to rescan with a flag that is not supported. + // Certain flags require the plugin to be de-activated. + // [main-thread] + void(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags); +} clap_host_audio_ports_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/gui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/gui.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,223 @@ +#pragma once + +#include "../plugin.h" + +/// @page GUI +/// +/// This extension defines how the plugin will present its GUI. +/// +/// There are two approaches: +/// 1. the plugin creates a window and embeds it into the host's window +/// 2. the plugin creates a floating window +/// +/// Embedding the window gives more control to the host, and feels more integrated. +/// Floating window are sometimes the only option due to technical limitations. +/// +/// Showing the GUI works as follow: +/// 1. clap_plugin_gui->is_api_supported(), check what can work +/// 2. clap_plugin_gui->create(), allocates gui resources +/// 3. if the plugin window is floating +/// 4. -> clap_plugin_gui->set_transient() +/// 5. -> clap_plugin_gui->suggest_title() +/// 6. else +/// 7. -> clap_plugin_gui->set_scale() +/// 8. -> clap_plugin_gui->can_resize() +/// 9. -> if resizable and has known size from previous session, clap_plugin_gui->set_size() +/// 10. -> else clap_plugin_gui->get_size(), gets initial size +/// 11. -> clap_plugin_gui->set_parent() +/// 12. clap_plugin_gui->show() +/// 13. clap_plugin_gui->hide()/show() ... +/// 14. clap_plugin_gui->destroy() when done with the gui +/// +/// Resizing the window (initiated by the plugin, if embedded): +/// 1. Plugins calls clap_host_gui->request_resize() +/// 2. If the host returns true the new size is accepted, +/// the host doesn't have to call clap_plugin_gui->set_size(). +/// If the host returns false, the new size is rejected. +/// +/// Resizing the window (drag, if embedded)): +/// 1. Only possible if clap_plugin_gui->can_resize() returns true +/// 2. Mouse drag -> new_size +/// 3. clap_plugin_gui->adjust_size(new_size) -> working_size +/// 4. clap_plugin_gui->set_size(working_size) + +static CLAP_CONSTEXPR const char CLAP_EXT_GUI[] = "clap.gui"; + +// If your windowing API is not listed here, please open an issue and we'll figure it out. +// https://github.com/free-audio/clap/issues/new + +// uses physical size +// embed using https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WIN32[] = "win32"; + +// uses logical size, don't call clap_plugin_gui->set_scale() +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_COCOA[] = "cocoa"; + +// uses physical size +// embed using https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_X11[] = "x11"; + +// uses physical size +// embed is currently not supported, use floating windows +static const CLAP_CONSTEXPR char CLAP_WINDOW_API_WAYLAND[] = "wayland"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *clap_hwnd; +typedef void *clap_nsview; +typedef unsigned long clap_xwnd; + +// Represent a window reference. +typedef struct clap_window { + const char *api; // one of CLAP_WINDOW_API_XXX + union { + clap_nsview cocoa; + clap_xwnd x11; + clap_hwnd win32; + void *ptr; // for anything defined outside of clap + uintptr_t uptr; + }; +} clap_window_t; + +// Information to improve window resizing when initiated by the host or window manager. +typedef struct clap_gui_resize_hints { + bool can_resize_horizontally; + bool can_resize_vertically; + + // only if can resize horizontally and vertically + bool preserve_aspect_ratio; + uint32_t aspect_ratio_width; + uint32_t aspect_ratio_height; +} clap_gui_resize_hints_t; + +// Size (width, height) is in pixels; the corresponding windowing system extension is +// responsible for defining if it is physical pixels or logical pixels. +typedef struct clap_plugin_gui { + // Returns true if the requested gui api is supported + // [main-thread] + bool(CLAP_ABI *is_api_supported)(const clap_plugin_t *plugin, const char *api, bool is_floating); + + // Returns true if the plugin has a preferred api. + // The host has no obligation to honor the plugin preferrence, this is just a hint. + // The const char **api variable should be explicitly assigned as a pointer to + // one of the CLAP_WINDOW_API_ constants defined above, not strcopied. + // [main-thread] + bool(CLAP_ABI *get_preferred_api)(const clap_plugin_t *plugin, + const char **api, + bool *is_floating); + + // Create and allocate all resources necessary for the gui. + // + // If is_floating is true, then the window will not be managed by the host. The plugin + // can set its window to stays above the parent window, see set_transient(). + // api may be null or blank for floating window. + // + // If is_floating is false, then the plugin has to embbed its window into the parent window, see + // set_parent(). + // + // After this call, the GUI may not be visible yet; don't forget to call show(). + // [main-thread] + bool(CLAP_ABI *create)(const clap_plugin_t *plugin, const char *api, bool is_floating); + + // Free all resources associated with the gui. + // [main-thread] + void(CLAP_ABI *destroy)(const clap_plugin_t *plugin); + + // Set the absolute GUI scaling factor, and override any OS info. + // Should not be used if the windowing api relies upon logical pixels. + // + // If the plugin prefers to work out the scaling factor itself by querying the OS directly, + // then ignore the call. + // + // Returns true if the scaling could be applied + // Returns false if the call was ignored, or the scaling could not be applied. + // [main-thread] + bool(CLAP_ABI *set_scale)(const clap_plugin_t *plugin, double scale); + + // Get the current size of the plugin UI. + // clap_plugin_gui->create() must have been called prior to asking the size. + // [main-thread] + bool(CLAP_ABI *get_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); + + // Returns true if the window is resizeable (mouse drag). + // Only for embedded windows. + // [main-thread] + bool(CLAP_ABI *can_resize)(const clap_plugin_t *plugin); + + // Returns true if the plugin can provide hints on how to resize the window. + // [main-thread] + bool(CLAP_ABI *get_resize_hints)(const clap_plugin_t *plugin, clap_gui_resize_hints_t *hints); + + // If the plugin gui is resizable, then the plugin will calculate the closest + // usable size which fits in the given size. + // This method does not change the size. + // + // Only for embedded windows. + // [main-thread] + bool(CLAP_ABI *adjust_size)(const clap_plugin_t *plugin, uint32_t *width, uint32_t *height); + + // Sets the window size. Only for embedded windows. + // [main-thread] + bool(CLAP_ABI *set_size)(const clap_plugin_t *plugin, uint32_t width, uint32_t height); + + // Embbeds the plugin window into the given window. + // [main-thread & !floating] + bool(CLAP_ABI *set_parent)(const clap_plugin_t *plugin, const clap_window_t *window); + + // Set the plugin floating window to stay above the given window. + // [main-thread & floating] + bool(CLAP_ABI *set_transient)(const clap_plugin_t *plugin, const clap_window_t *window); + + // Suggests a window title. Only for floating windows. + // [main-thread & floating] + void(CLAP_ABI *suggest_title)(const clap_plugin_t *plugin, const char *title); + + // Show the window. + // [main-thread] + bool(CLAP_ABI *show)(const clap_plugin_t *plugin); + + // Hide the window, this method does not free the resources, it just hides + // the window content. Yet it may be a good idea to stop painting timers. + // [main-thread] + bool(CLAP_ABI *hide)(const clap_plugin_t *plugin); +} clap_plugin_gui_t; + +typedef struct clap_host_gui { + // The host should call get_resize_hints() again. + // [thread-safe] + void(CLAP_ABI *resize_hints_changed)(const clap_host_t *host); + + /* Request the host to resize the client area to width, height. + * Return true if the new size is accepted, false otherwise. + * The host doesn't have to call set_size(). + * + * Note: if not called from the main thread, then a return value simply means that the host + * acknowledged the request and will process it asynchronously. If the request then can't be + * satisfied then the host will call set_size() to revert the operation. + * + * [thread-safe] */ + bool(CLAP_ABI *request_resize)(const clap_host_t *host, uint32_t width, uint32_t height); + + /* Request the host to show the plugin gui. + * Return true on success, false otherwise. + * [thread-safe] */ + bool(CLAP_ABI *request_show)(const clap_host_t *host); + + /* Request the host to hide the plugin gui. + * Return true on success, false otherwise. + * [thread-safe] */ + bool(CLAP_ABI *request_hide)(const clap_host_t *host); + + // The floating window has been closed, or the connection to the gui has been lost. + // + // If was_destroyed is true, then the host must call clap_plugin_gui->destroy() to acknowledge + // the gui destruction. + // [thread-safe] + void(CLAP_ABI *closed)(const clap_host_t *host, bool was_destroyed); +} clap_host_gui_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/latency.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/latency.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,28 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_LATENCY[] = "clap.latency"; + +#ifdef __cplusplus +extern "C" { +#endif + +// The audio ports scan has to be done while the plugin is deactivated. +typedef struct clap_plugin_latency { + // Returns the plugin latency. + // [main-thread] + uint32_t(CLAP_ABI *get)(const clap_plugin_t *plugin); +} clap_plugin_latency_t; + +typedef struct clap_host_latency { + // Tell the host that the latency changed. + // The latency is only allowed to change if the plugin is deactivated. + // If the plugin is activated, call host->request_restart() + // [main-thread] + void(CLAP_ABI *changed)(const clap_host_t *host); +} clap_host_latency_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/note-ports.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/note-ports.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,78 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +/// @page Note Ports +/// +/// This extension provides a way for the plugin to describe its current note ports. +/// If the plugin does not implement this extension, it won't have note input or output. +/// The plugin is only allowed to change its note ports configuration while it is deactivated. + +static CLAP_CONSTEXPR const char CLAP_EXT_NOTE_PORTS[] = "clap.note-ports"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum clap_note_dialect { + // Uses clap_event_note and clap_event_note_expression. + CLAP_NOTE_DIALECT_CLAP = 1 << 0, + + // Uses clap_event_midi, no polyphonic expression + CLAP_NOTE_DIALECT_MIDI = 1 << 1, + + // Uses clap_event_midi, with polyphonic expression (MPE) + CLAP_NOTE_DIALECT_MIDI_MPE = 1 << 2, + + // Uses clap_event_midi2 + CLAP_NOTE_DIALECT_MIDI2 = 1 << 3, +}; + +typedef struct clap_note_port_info { + // id identifies a port and must be stable. + // id may overlap between input and output ports. + clap_id id; + uint32_t supported_dialects; // bitfield, see clap_note_dialect + uint32_t preferred_dialect; // one value of clap_note_dialect + char name[CLAP_NAME_SIZE]; // displayable name, i18n? +} clap_note_port_info_t; + +// The note ports scan has to be done while the plugin is deactivated. +typedef struct clap_plugin_note_ports { + // number of ports, for either input or output + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin, bool is_input); + + // get info about about a note port. + // [main-thread] + bool(CLAP_ABI *get)(const clap_plugin_t *plugin, + uint32_t index, + bool is_input, + clap_note_port_info_t *info); +} clap_plugin_note_ports_t; + +enum { + // The ports have changed, the host shall perform a full scan of the ports. + // This flag can only be used if the plugin is not active. + // If the plugin active, call host->request_restart() and then call rescan() + // when the host calls deactivate() + CLAP_NOTE_PORTS_RESCAN_ALL = 1 << 0, + + // The ports name did change, the host can scan them right away. + CLAP_NOTE_PORTS_RESCAN_NAMES = 1 << 1, +}; + +typedef struct clap_host_note_ports { + // Query which dialects the host supports + // [main-thread] + uint32_t(CLAP_ABI *supported_dialects)(const clap_host_t *host); + + // Rescan the full list of note ports according to the flags. + // [main-thread] + void(CLAP_ABI *rescan)(const clap_host_t *host, uint32_t flags); +} clap_host_note_ports_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/params.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/params.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,328 @@ +#pragma once + +#include "../plugin.h" +#include "../string-sizes.h" + +/// @page Parameters +/// @brief parameters management +/// +/// Main idea: +/// +/// The host sees the plugin as an atomic entity; and acts as a controller on top of its parameters. +/// The plugin is responsible for keeping its audio processor and its GUI in sync. +/// +/// The host can at any time read parameters' value on the [main-thread] using +/// @ref clap_plugin_params.value(). +/// +/// There are two options to communicate parameter value changes, and they are not concurrent. +/// - send automation points during clap_plugin.process() +/// - send automation points during clap_plugin_params.flush(), for parameter changes +/// without processing audio +/// +/// When the plugin changes a parameter value, it must inform the host. +/// It will send @ref CLAP_EVENT_PARAM_VALUE event during process() or flush(). +/// If the user is adjusting the value, don't forget to mark the begining and end +/// of the gesture by sending CLAP_EVENT_PARAM_GESTURE_BEGIN and CLAP_EVENT_PARAM_GESTURE_END +/// events. +/// +/// @note MIDI CCs are tricky because you may not know when the parameter adjustment ends. +/// Also if the host records incoming MIDI CC and parameter change automation at the same time, +/// there will be a conflict at playback: MIDI CC vs Automation. +/// The parameter automation will always target the same parameter because the param_id is stable. +/// The MIDI CC may have a different mapping in the future and may result in a different playback. +/// +/// When a MIDI CC changes a parameter's value, set the flag CLAP_EVENT_DONT_RECORD in +/// clap_event_param.header.flags. That way the host may record the MIDI CC automation, but not the +/// parameter change and there won't be conflict at playback. +/// +/// Scenarios: +/// +/// I. Loading a preset +/// - load the preset in a temporary state +/// - call @ref clap_host_params.rescan() if anything changed +/// - call @ref clap_host_latency.changed() if latency changed +/// - invalidate any other info that may be cached by the host +/// - if the plugin is activated and the preset will introduce breaking changes +/// (latency, audio ports, new parameters, ...) be sure to wait for the host +/// to deactivate the plugin to apply those changes. +/// If there are no breaking changes, the plugin can apply them them right away. +/// The plugin is resonsible for updating both its audio processor and its gui. +/// +/// II. Turning a knob on the DAW interface +/// - the host will send an automation event to the plugin via a process() or flush() +/// +/// III. Turning a knob on the Plugin interface +/// - the plugin is responsible for sending the parameter value to its audio processor +/// - call clap_host_params->request_flush() or clap_host->request_process(). +/// - when the host calls either clap_plugin->process() or clap_plugin_params->flush(), +/// send an automation event and don't forget to set begin_adjust, +/// end_adjust and should_record flags +/// +/// IV. Turning a knob via automation +/// - host sends an automation point during clap_plugin->process() or clap_plugin_params->flush(). +/// - the plugin is responsible for updating its GUI +/// +/// V. Turning a knob via plugin's internal MIDI mapping +/// - the plugin sends a CLAP_EVENT_PARAM_SET output event, set should_record to false +/// - the plugin is responsible to update its GUI +/// +/// VI. Adding or removing parameters +/// - if the plugin is activated call clap_host->restart() +/// - once the plugin isn't active: +/// - apply the new state +/// - if a parameter is gone or is created with an id that may have been used before, +/// call clap_host_params.clear(host, param_id, CLAP_PARAM_CLEAR_ALL) +/// - call clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) + +static CLAP_CONSTEXPR const char CLAP_EXT_PARAMS[] = "clap.params"; + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // Is this param stepped? (integer values only) + // if so the double value is converted to integer using a cast (equivalent to trunc). + CLAP_PARAM_IS_STEPPED = 1 << 0, + + // Useful for for periodic parameters like a phase + CLAP_PARAM_IS_PERIODIC = 1 << 1, + + // The parameter should not be shown to the user, because it is currently not used. + // It is not necessary to process automation for this parameter. + CLAP_PARAM_IS_HIDDEN = 1 << 2, + + // The parameter can't be changed by the host. + CLAP_PARAM_IS_READONLY = 1 << 3, + + // This parameter is used to merge the plugin and host bypass button. + // It implies that the parameter is stepped. + // min: 0 -> bypass off + // max: 1 -> bypass on + CLAP_PARAM_IS_BYPASS = 1 << 4, + + // When set: + // - automation can be recorded + // - automation can be played back + // + // The host can send live user changes for this parameter regardless of this flag. + // + // If this parameters affect the internal processing structure of the plugin, ie: max delay, fft + // size, ... and the plugins needs to re-allocate its working buffers, then it should call + // host->request_restart(), and perform the change once the plugin is re-activated. + CLAP_PARAM_IS_AUTOMATABLE = 1 << 5, + + // Does this parameter support per note automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_NOTE_ID = 1 << 6, + + // Does this parameter support per key automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_KEY = 1 << 7, + + // Does this parameter support per channel automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_CHANNEL = 1 << 8, + + // Does this parameter support per port automations? + CLAP_PARAM_IS_AUTOMATABLE_PER_PORT = 1 << 9, + + // Does this parameter support the modulation signal? + CLAP_PARAM_IS_MODULATABLE = 1 << 10, + + // Does this parameter support per note modulations? + CLAP_PARAM_IS_MODULATABLE_PER_NOTE_ID = 1 << 11, + + // Does this parameter support per key modulations? + CLAP_PARAM_IS_MODULATABLE_PER_KEY = 1 << 12, + + // Does this parameter support per channel modulations? + CLAP_PARAM_IS_MODULATABLE_PER_CHANNEL = 1 << 13, + + // Does this parameter support per port modulations? + CLAP_PARAM_IS_MODULATABLE_PER_PORT = 1 << 14, + + // Any change to this parameter will affect the plugin output and requires to be done via + // process() if the plugin is active. + // + // A simple example would be a DC Offset, changing it will change the output signal and must be + // processed. + CLAP_PARAM_REQUIRES_PROCESS = 1 << 15, +}; +typedef uint32_t clap_param_info_flags; + +/* This describes a parameter */ +typedef struct clap_param_info { + // stable parameter identifier, it must never change. + clap_id id; + + clap_param_info_flags flags; + + // This value is optional and set by the plugin. The host will + // set it on all subsequent events regarding this param_id + // or set the cookie to nullptr if the host chooses to + // not implement cookies. + // + // The plugin must gracefully handle the case of a cookie + // which is nullptr, but can safely assume any cookie + // which is not nullptr is the value it issued. + // + // It is very strongly recommended that the host implement + // cookies. Some plugins may have noticably reduced + // performance when addressing params in hosts without cookies. + // + // The cookie's purpose is to provide a fast access to the + // plugin parameter objects. For instance: + // + // in clap_plugin_params.get_info + // Parameter *p = findParameter(param_id); + // param_info->cookie = p; + // + // later, in clap_plugin.process: + // + // Parameter *p{nullptr}; + // if (evt->cookie) [[likely]] + // p = (Parameter *)evt->cookie; + // else + // p = -- alternate mechanism -- + // + // where "alternate mechanism" is a mechanism the plugin implements + // to map parameter ids to internal objects. + // + // The host should make no assumption about the + // value of the cookie other than passing it back to the plugin or + // replacing it with nullptr. + // + // Once set, the cookie is valid until invalidated by a call to + // clap_host_params->rescan(CLAP_PARAM_RESCAN_ALL) or when the plugin is + // destroyed. + void *cookie; + + // the display name + char name[CLAP_NAME_SIZE]; + + // the module path containing the param, eg:"oscillators/wt1" + // '/' will be used as a separator to show a tree like structure. + char module[CLAP_PATH_SIZE]; + + double min_value; // minimum plain value + double max_value; // maximum plain value + double default_value; // default plain value +} clap_param_info_t; + +typedef struct clap_plugin_params { + // Returns the number of parameters. + // [main-thread] + uint32_t(CLAP_ABI *count)(const clap_plugin_t *plugin); + + // Copies the parameter's info to param_info and returns true on success. + // [main-thread] + bool(CLAP_ABI *get_info)(const clap_plugin_t *plugin, + uint32_t param_index, + clap_param_info_t *param_info); + + // Gets the parameter plain value. + // [main-thread] + bool(CLAP_ABI *get_value)(const clap_plugin_t *plugin, clap_id param_id, double *value); + + // Formats the display text for the given parameter value. + // The host should always format the parameter value to text using this function + // before displaying it to the user. + // [main-thread] + bool(CLAP_ABI *value_to_text)( + const clap_plugin_t *plugin, clap_id param_id, double value, char *display, uint32_t size); + + // Converts the display text to a parameter value. + // [main-thread] + bool(CLAP_ABI *text_to_value)(const clap_plugin_t *plugin, + clap_id param_id, + const char *display, + double *value); + + // Flushes a set of parameter changes. + // This method must not be called concurrently to clap_plugin->process(). + // + // Note: if the plugin is processing, then the process() call will already achieve the + // parameter update (bi-directionnal), so a call to flush isn't required, also be aware + // that the plugin may use the sample offset in process(), while this information would be + // lost within flush(). + // + // [active ? audio-thread : main-thread] + void(CLAP_ABI *flush)(const clap_plugin_t *plugin, + const clap_input_events_t *in, + const clap_output_events_t *out); +} clap_plugin_params_t; + +enum { + // The parameter values did change, eg. after loading a preset. + // The host will scan all the parameters value. + // The host will not record those changes as automation points. + // New values takes effect immediately. + CLAP_PARAM_RESCAN_VALUES = 1 << 0, + + // The value to text conversion changed, and the text needs to be rendered again. + CLAP_PARAM_RESCAN_TEXT = 1 << 1, + + // The parameter info did change, use this flag for: + // - name change + // - module change + // - is_periodic (flag) + // - is_hidden (flag) + // New info takes effect immediately. + CLAP_PARAM_RESCAN_INFO = 1 << 2, + + // Invalidates everything the host knows about parameters. + // It can only be used while the plugin is deactivated. + // If the plugin is activated use clap_host->restart() and delay any change until the host calls + // clap_plugin->deactivate(). + // + // You must use this flag if: + // - some parameters were added or removed. + // - some parameters had critical changes: + // - is_per_note (flag) + // - is_per_channel (flag) + // - is_readonly (flag) + // - is_bypass (flag) + // - is_stepped (flag) + // - is_modulatable (flag) + // - min_value + // - max_value + // - cookie + CLAP_PARAM_RESCAN_ALL = 1 << 3, +}; +typedef uint32_t clap_param_rescan_flags; + +enum { + // Clears all possible references to a parameter + CLAP_PARAM_CLEAR_ALL = 1 << 0, + + // Clears all automations to a parameter + CLAP_PARAM_CLEAR_AUTOMATIONS = 1 << 1, + + // Clears all modulations to a parameter + CLAP_PARAM_CLEAR_MODULATIONS = 1 << 2, +}; +typedef uint32_t clap_param_clear_flags; + +typedef struct clap_host_params { + // Rescan the full list of parameters according to the flags. + // [main-thread] + void(CLAP_ABI *rescan)(const clap_host_t *host, clap_param_rescan_flags flags); + + // Clears references to a parameter. + // [main-thread] + void(CLAP_ABI *clear)(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags); + + // Request a parameter flush. + // + // The host will then schedule a call to either: + // - clap_plugin.process() + // - clap_plugin_params.flush() + // + // This function is always safe to use and should not be called from an [audio-thread] as the + // plugin would already be within process() or flush(). + // + // [thread-safe,!audio-thread] + void(CLAP_ABI *request_flush)(const clap_host_t *host); +} clap_host_params_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/state.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/state.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,33 @@ +#pragma once + +#include "../plugin.h" +#include "../stream.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_STATE[] = "clap.state"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_state { + // Saves the plugin state into stream. + // Returns true if the state was correctly saved. + // [main-thread] + bool(CLAP_ABI *save)(const clap_plugin_t *plugin, const clap_ostream_t *stream); + + // Loads the plugin state from stream. + // Returns true if the state was correctly restored. + // [main-thread] + bool(CLAP_ABI *load)(const clap_plugin_t *plugin, const clap_istream_t *stream); +} clap_plugin_state_t; + +typedef struct clap_host_state { + // Tell the host that the plugin state has changed and should be saved again. + // If a parameter value changes, then it is implicit that the state is dirty. + // [main-thread] + void(CLAP_ABI *mark_dirty)(const clap_host_t *host); +} clap_host_state_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/thread-check.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/thread-check.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,51 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_THREAD_CHECK[] = "clap.thread-check"; + +#ifdef __cplusplus +extern "C" { +#endif + +/// @page thread-check +/// +/// CLAP defines two symbolic threads: +/// +/// main-thread: +/// This is the thread in which most of the interaction between the plugin and host happens. +/// It is usually the thread on which the GUI receives its events. +/// It isn't a realtime thread, yet this thread needs to respond fast enough to user interaction, +/// so it is recommended to run long and expensive tasks such as preset indexing or asset loading +/// in dedicated background threads. +/// +/// audio-thread: +/// This thread is used for realtime audio processing. Its execution should be as deterministic +/// as possible to meet the audio interface's deadline (can be <1ms). In other words, there is a +/// known set of operations that should be avoided: malloc() and free(), mutexes (spin mutexes +/// are worse), I/O, waiting, ... +/// The audio-thread is something symbolic, there isn't one OS thread that remains the +/// audio-thread for the plugin lifetime. As you may guess, the host is likely to have a +/// thread pool and the plugin.process() call may be scheduled on different OS threads over time. +/// The most important thing is that there can't be two audio-threads at the same time. All the +/// functions marked with [audio-thread] **ARE NOT CONCURRENT**. The host may mark any OS thread, +/// including the main-thread as the audio-thread, as long as it can guarentee that only one OS +/// thread is the audio-thread at a time. The audio-thread can be seen as a concurrency guard for +/// all functions marked with [audio-thread]. + +// This interface is useful to do runtime checks and make +// sure that the functions are called on the correct threads. +// It is highly recommended that hosts implement this extension. +typedef struct clap_host_thread_check { + // Returns true if "this" thread is the main thread. + // [thread-safe] + bool(CLAP_ABI *is_main_thread)(const clap_host_t *host); + + // Returns true if "this" thread is one of the audio threads. + // [thread-safe] + bool(CLAP_ABI *is_audio_thread)(const clap_host_t *host); +} clap_host_thread_check_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/timer-support.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/ext/timer-support.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,29 @@ +#pragma once + +#include "../plugin.h" + +static CLAP_CONSTEXPR const char CLAP_EXT_TIMER_SUPPORT[] = "clap.timer-support"; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_timer_support { + // [main-thread] + void(CLAP_ABI *on_timer)(const clap_plugin_t *plugin, clap_id timer_id); +} clap_plugin_timer_support_t; + +typedef struct clap_host_timer_support { + // Registers a periodic timer. + // The host may adjust the period if it is under a certain threshold. + // 30 Hz should be allowed. + // [main-thread] + bool(CLAP_ABI *register_timer)(const clap_host_t *host, uint32_t period_ms, clap_id *timer_id); + + // [main-thread] + bool(CLAP_ABI *unregister_timer)(const clap_host_t *host, clap_id timer_id); +} clap_host_timer_support_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/fixedpoint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/fixedpoint.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,16 @@ +#pragma once + +#include "private/std.h" +#include "private/macros.h" + +/// We use fixed point representation of beat time and seconds time +/// Usage: +/// double x = ...; // in beats +/// clap_beattime y = round(CLAP_BEATTIME_FACTOR * x); + +// This will never change +static const CLAP_CONSTEXPR int64_t CLAP_BEATTIME_FACTOR = 1LL << 31; +static const CLAP_CONSTEXPR int64_t CLAP_SECTIME_FACTOR = 1LL << 31; + +typedef int64_t clap_beattime; +typedef int64_t clap_sectime; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/host.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/host.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,41 @@ +#pragma once + +#include "version.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_host { + clap_version_t clap_version; // initialized to CLAP_VERSION + + void *host_data; // reserved pointer for the host + + // name and version are mandatory. + const char *name; // eg: "Bitwig Studio" + const char *vendor; // eg: "Bitwig GmbH" + const char *url; // eg: "https://bitwig.com" + const char *version; // eg: "4.3" + + // Query an extension. + // [thread-safe] + const void *(CLAP_ABI *get_extension)(const struct clap_host *host, const char *extension_id); + + // Request the host to deactivate and then reactivate the plugin. + // The operation may be delayed by the host. + // [thread-safe] + void(CLAP_ABI *request_restart)(const struct clap_host *host); + + // Request the host to activate and start processing the plugin. + // This is useful if you have external IO and need to wake up the plugin from "sleep". + // [thread-safe] + void(CLAP_ABI *request_process)(const struct clap_host *host); + + // Request the host to schedule a call to plugin->on_main_thread(plugin) on the main thread. + // [thread-safe] + void(CLAP_ABI *request_callback)(const struct clap_host *host); +} clap_host_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/id.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/id.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,8 @@ +#pragma once + +#include "private/std.h" +#include "private/macros.h" + +typedef uint32_t clap_id; + +static const CLAP_CONSTEXPR clap_id CLAP_INVALID_ID = UINT32_MAX; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/plugin-factory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/plugin-factory.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,40 @@ +#pragma once + +#include "plugin.h" + +static const CLAP_CONSTEXPR char CLAP_PLUGIN_FACTORY_ID[] = "clap.plugin-factory"; + +#ifdef __cplusplus +extern "C" { +#endif + +// Every method must be thread-safe. +// It is very important to be able to scan the plugin as quickly as possible. +// +// The host may use clap_plugin_invalidation_factory to detect filesystem changes +// which may change the factory's content. +typedef struct clap_plugin_factory { + // Get the number of plugins available. + // [thread-safe] + uint32_t(CLAP_ABI *get_plugin_count)(const struct clap_plugin_factory *factory); + + // Retrieves a plugin descriptor by its index. + // Returns null in case of error. + // The descriptor must not be freed. + // [thread-safe] + const clap_plugin_descriptor_t *(CLAP_ABI *get_plugin_descriptor)( + const struct clap_plugin_factory *factory, uint32_t index); + + // Create a clap_plugin by its plugin_id. + // The returned pointer must be freed by calling plugin->destroy(plugin); + // The plugin is not allowed to use the host callbacks in the create method. + // Returns null in case of error. + // [thread-safe] + const clap_plugin_t *(CLAP_ABI *create_plugin)(const struct clap_plugin_factory *factory, + const clap_host_t *host, + const char *plugin_id); +} clap_plugin_factory_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/plugin-features.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/plugin-features.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,76 @@ +#pragma once + +#include "private/macros.h" + +// This file provides a set of standard plugin features meant to be used +// within clap_plugin_descriptor.features. +// +// For practical reasons we'll avoid spaces and use `-` instead to facilitate +// scripts that generate the feature array. +// +// Non-standard features should be formated as follow: "$namespace:$feature" + +///////////////////// +// Plugin category // +///////////////////// + +// Add this feature if your plugin can process note events and then produce audio +#define CLAP_PLUGIN_FEATURE_INSTRUMENT "instrument" + +// Add this feature if your plugin is an audio effect +#define CLAP_PLUGIN_FEATURE_AUDIO_EFFECT "audio-effect" + +// Add this feature if your plugin is a note effect or a note generator/sequencer +#define CLAP_PLUGIN_FEATURE_NOTE_EFFECT "note-effect" + +// Add this feature if your plugin is an analyzer +#define CLAP_PLUGIN_FEATURE_ANALYZER "analyzer" + +///////////////////////// +// Plugin sub-category // +///////////////////////// + +#define CLAP_PLUGIN_FEATURE_SYNTHESIZER "synthesizer" +#define CLAP_PLUGIN_FEATURE_SAMPLER "sampler" +#define CLAP_PLUGIN_FEATURE_DRUM "drum" // For single drum +#define CLAP_PLUGIN_FEATURE_DRUM_MACHINE "drum-machine" + +#define CLAP_PLUGIN_FEATURE_FILTER "filter" +#define CLAP_PLUGIN_FEATURE_PHASER "phaser" +#define CLAP_PLUGIN_FEATURE_EQUALIZER "equalizer" +#define CLAP_PLUGIN_FEATURE_DEESSER "de-esser" +#define CLAP_PLUGIN_FEATURE_PHASE_VOCODER "phase-vocoder" +#define CLAP_PLUGIN_FEATURE_GRANULAR "granular" +#define CLAP_PLUGIN_FEATURE_FREQUENCY_SHIFTER "frequency-shifter" +#define CLAP_PLUGIN_FEATURE_PITCH_SHIFTER "pitch-shifter" + +#define CLAP_PLUGIN_FEATURE_DISTORTION "distortion" +#define CLAP_PLUGIN_FEATURE_TRANSIENT_SHAPER "transient-shaper" +#define CLAP_PLUGIN_FEATURE_COMPRESSOR "compressor" +#define CLAP_PLUGIN_FEATURE_LIMITER "limiter" + +#define CLAP_PLUGIN_FEATURE_FLANGER "flanger" +#define CLAP_PLUGIN_FEATURE_CHORUS "chorus" +#define CLAP_PLUGIN_FEATURE_DELAY "delay" +#define CLAP_PLUGIN_FEATURE_REVERB "reverb" + +#define CLAP_PLUGIN_FEATURE_TREMOLO "tremolo" +#define CLAP_PLUGIN_FEATURE_GLITCH "glitch" + +#define CLAP_PLUGIN_FEATURE_UTILITY "utility" +#define CLAP_PLUGIN_FEATURE_PITCH_CORRECTION "pitch-correction" +#define CLAP_PLUGIN_FEATURE_RESTORATION "restoration" // repair the sound + +#define CLAP_PLUGIN_FEATURE_MULTI_EFFECTS "multi-effects" + +#define CLAP_PLUGIN_FEATURE_MIXING "mixing" +#define CLAP_PLUGIN_FEATURE_MASTERING "mastering" + +//////////////////////// +// Audio Capabilities // +//////////////////////// + +#define CLAP_PLUGIN_FEATURE_MONO "mono" +#define CLAP_PLUGIN_FEATURE_STEREO "stereo" +#define CLAP_PLUGIN_FEATURE_SURROUND "surround" +#define CLAP_PLUGIN_FEATURE_AMBISONIC "ambisonic" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/plugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/plugin.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,96 @@ +#pragma once + +#include "private/macros.h" +#include "host.h" +#include "process.h" +#include "plugin-features.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_plugin_descriptor { + clap_version_t clap_version; // initialized to CLAP_VERSION + + // Mandatory fields must be set and must not be blank. + // Otherwise the fields can be null or blank, though it is safer to make them blank. + const char *id; // eg: "com.u-he.diva", mandatory + const char *name; // eg: "Diva", mandatory + const char *vendor; // eg: "u-he" + const char *url; // eg: "https://u-he.com/products/diva/" + const char *manual_url; // eg: "https://dl.u-he.com/manuals/plugins/diva/Diva-user-guide.pdf" + const char *support_url; // eg: "https://u-he.com/support/" + const char *version; // eg: "1.4.4" + const char *description; // eg: "The spirit of analogue" + + // Arbitrary list of keywords. + // They can be matched by the host indexer and used to classify the plugin. + // The array of pointers must be null terminated. + // For some standard features see plugin-features.h + const char **features; +} clap_plugin_descriptor_t; + +typedef struct clap_plugin { + const clap_plugin_descriptor_t *desc; + + void *plugin_data; // reserved pointer for the plugin + + // Must be called after creating the plugin. + // If init returns false, the host must destroy the plugin instance. + // [main-thread] + bool(CLAP_ABI *init)(const struct clap_plugin *plugin); + + // Free the plugin and its resources. + // It is required to deactivate the plugin prior to this call. + // [main-thread & !active] + void(CLAP_ABI *destroy)(const struct clap_plugin *plugin); + + // Activate and deactivate the plugin. + // In this call the plugin may allocate memory and prepare everything needed for the process + // call. The process's sample rate will be constant and process's frame count will included in + // the [min, max] range, which is bounded by [1, INT32_MAX]. + // Once activated the latency and port configuration must remain constant, until deactivation. + // + // [main-thread & !active_state] + bool(CLAP_ABI *activate)(const struct clap_plugin *plugin, + double sample_rate, + uint32_t min_frames_count, + uint32_t max_frames_count); + // [main-thread & active_state] + void(CLAP_ABI *deactivate)(const struct clap_plugin *plugin); + + // Call start processing before processing. + // [audio-thread & active_state & !processing_state] + bool(CLAP_ABI *start_processing)(const struct clap_plugin *plugin); + + // Call stop processing before sending the plugin to sleep. + // [audio-thread & active_state & processing_state] + void(CLAP_ABI *stop_processing)(const struct clap_plugin *plugin); + + // - Clears all buffers, performs a full reset of the processing state (filters, oscillators, + // enveloppes, lfo, ...) and kills all voices. + // - The parameter's value remain unchanged. + // - clap_process.steady_time may jump backward. + // + // [audio-thread & active_state] + void(CLAP_ABI *reset)(const struct clap_plugin *plugin); + + // process audio, events, ... + // [audio-thread & active_state & processing_state] + clap_process_status(CLAP_ABI *process)(const struct clap_plugin *plugin, + const clap_process_t *process); + + // Query an extension. + // The returned pointer is owned by the plugin. + // [thread-safe] + const void *(CLAP_ABI *get_extension)(const struct clap_plugin *plugin, const char *id); + + // Called by the host on the main thread in response to a previous call to: + // host->request_callback(host); + // [main-thread] + void(CLAP_ABI *on_main_thread)(const struct clap_plugin *plugin); +} clap_plugin_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/private/macros.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/private/macros.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,44 @@ +#pragma once + +// Define CLAP_EXPORT +#if !defined(CLAP_EXPORT) +# if defined _WIN32 || defined __CYGWIN__ +# ifdef __GNUC__ +# define CLAP_EXPORT __attribute__((dllexport)) +# else +# define CLAP_EXPORT __declspec(dllexport) +# endif +# else +# if __GNUC__ >= 4 || defined(__clang__) +# define CLAP_EXPORT __attribute__((visibility("default"))) +# else +# define CLAP_EXPORT +# endif +# endif +#endif + +#if !defined(CLAP_ABI) +# if defined _WIN32 || defined __CYGWIN__ +# define CLAP_ABI __cdecl +# else +# define CLAP_ABI +# endif +#endif + +#if defined(__cplusplus) && __cplusplus >= 201103L +# define CLAP_HAS_CXX11 +# define CLAP_CONSTEXPR constexpr +#else +# define CLAP_CONSTEXPR +#endif + +#if defined(__cplusplus) && __cplusplus >= 201703L +# define CLAP_HAS_CXX17 +# define CLAP_NODISCARD [[nodiscard]] +#else +# define CLAP_NODISCARD +#endif + +#if defined(__cplusplus) && __cplusplus >= 202002L +# define CLAP_HAS_CXX20 +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/private/std.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/private/std.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,16 @@ +#pragma once + +#include "macros.h" + +#ifdef CLAP_HAS_CXX11 +# include +#else +# include +#endif + +#ifdef __cplusplus +# include +#else +# include +# include +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/process.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/process.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,66 @@ +#pragma once + +#include "events.h" +#include "audio-buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // Processing failed. The output buffer must be discarded. + CLAP_PROCESS_ERROR = 0, + + // Processing succeeded, keep processing. + CLAP_PROCESS_CONTINUE = 1, + + // Processing succeeded, keep processing if the output is not quiet. + CLAP_PROCESS_CONTINUE_IF_NOT_QUIET = 2, + + // Rely upon the plugin's tail to determine if the plugin should continue to process. + // see clap_plugin_tail + CLAP_PROCESS_TAIL = 3, + + // Processing succeeded, but no more processing is required, + // until the next event or variation in audio input. + CLAP_PROCESS_SLEEP = 4, +}; +typedef int32_t clap_process_status; + +typedef struct clap_process { + // A steady sample time counter. + // This field can be used to calculate the sleep duration between two process calls. + // This value may be specific to this plugin instance and have no relation to what + // other plugin instances may receive. + // + // Set to -1 if not available, otherwise the value must be greater or equal to 0, + // and must be increased by at least `frames_count` for the next call to process. + int64_t steady_time; + + // Number of frames to process + uint32_t frames_count; + + // time info at sample 0 + // If null, then this is a free running host, no transport events will be provided + const clap_event_transport_t *transport; + + // Audio buffers, they must have the same count as specified + // by clap_plugin_audio_ports->count(). + // The index maps to clap_plugin_audio_ports->get(). + // Input buffer and its contents are read-only. + const clap_audio_buffer_t *audio_inputs; + clap_audio_buffer_t *audio_outputs; + uint32_t audio_inputs_count; + uint32_t audio_outputs_count; + + // Input and output events. + // + // Events must be sorted by time. + // The input event list can't be modified. + const clap_input_events_t *in_events; + const clap_output_events_t *out_events; +} clap_process_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/stream.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/stream.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,26 @@ +#pragma once + +#include "private/std.h" +#include "private/macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_istream { + void *ctx; // reserved pointer for the stream + + // returns the number of bytes read; 0 indicates end of file and -1 a read error + int64_t(CLAP_ABI *read)(const struct clap_istream *stream, void *buffer, uint64_t size); +} clap_istream_t; + +typedef struct clap_ostream { + void *ctx; // reserved pointer for the stream + + // returns the number of bytes written; -1 on write error + int64_t(CLAP_ABI *write)(const struct clap_ostream *stream, const void *buffer, uint64_t size); +} clap_ostream_t; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/string-sizes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/string-sizes.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,21 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + // String capacity for names that can be displayed to the user. + CLAP_NAME_SIZE = 256, + + // String capacity for describing a path, like a parameter in a module hierarchy or path within a + // set of nested track groups. + // + // This is not suited for describing a file path on the disk, as NTFS allows up to 32K long + // paths. + CLAP_PATH_SIZE = 1024, +}; + +#ifdef __cplusplus +} +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/clap/version.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/clap/version.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,34 @@ +#pragma once + +#include "private/macros.h" +#include "private/std.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clap_version { + // This is the major ABI and API design + // Version 0.X.Y correspond to the development stage, API and ABI are not stable + // Version 1.X.Y correspont to the release stage, API and ABI are stable + uint32_t major; + uint32_t minor; + uint32_t revision; +} clap_version_t; + +#ifdef __cplusplus +} +#endif + +#define CLAP_VERSION_MAJOR ((uint32_t)1) +#define CLAP_VERSION_MINOR ((uint32_t)1) +#define CLAP_VERSION_REVISION ((uint32_t)1) +#define CLAP_VERSION_INIT {CLAP_VERSION_MAJOR, CLAP_VERSION_MINOR, CLAP_VERSION_REVISION} + +static const CLAP_CONSTEXPR clap_version_t CLAP_VERSION = CLAP_VERSION_INIT; + +CLAP_NODISCARD static inline CLAP_CONSTEXPR bool +clap_version_is_compatible(const clap_version_t v) { + // versions 0.x.y were used during development stage and aren't compatible + return v.major >= 1; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/dssi/dssi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/dssi/dssi.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,445 @@ +/* -*- c-basic-offset: 4 -*- */ + +/* dssi.h + + DSSI version 1.0 + Copyright (c) 2004, 2009 Chris Cannam, Steve Harris and Sean Bolton + + 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.1 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., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA +*/ + +#ifndef DSSI_INCLUDED +#define DSSI_INCLUDED + +#include "../ladspa/ladspa.h" +#include "seq_event-compat.h" + +#define DSSI_VERSION "1.0" +#define DSSI_VERSION_MAJOR 1 +#define DSSI_VERSION_MINOR 0 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DSSI_PLUGIN_EXPORT +# define DSSI_PLUGIN_EXPORT LADSPA_PLUGIN_EXPORT +#endif + +/* + There is a need for an API that supports hosted MIDI soft synths + with GUIs in Linux audio applications. In time the GMPI initiative + should comprehensively address this need, but the requirement for + Linux applications to be able to support simple hosted synths is + here now, and GMPI is not. This proposal (the "DSSI Soft Synth + Interface" or DSSI, pronounced "dizzy") aims to provide a simple + solution in a way that we hope will prove complete and compelling + enough to support now, yet not so compelling as to supplant GMPI or + any other comprehensive future proposal. + + For simplicity and familiarity, this API is based as far as + possible on existing work -- the LADSPA plugin API for control + values and audio processing, and the ALSA sequencer event types for + MIDI event communication. The GUI part of the proposal is quite + new, but may also be applicable retroactively to LADSPA plugins + that do not otherwise support this synth interface. +*/ + +typedef struct _DSSI_Program_Descriptor { + + /** Bank number for this program. Note that DSSI does not support + MIDI-style separation of bank LSB and MSB values. There is no + restriction on the set of available banks: the numbers do not + need to be contiguous, there does not need to be a bank 0, etc. */ + unsigned long Bank; + + /** Program number (unique within its bank) for this program. + There is no restriction on the set of available programs: the + numbers do not need to be contiguous, there does not need to + be a program 0, etc. */ + unsigned long Program; + + /** Name of the program. */ + const char * Name; + +} DSSI_Program_Descriptor; + + +typedef struct _DSSI_Descriptor { + + /** + * DSSI_API_Version + * + * This member indicates the DSSI API level used by this plugin. + * If we're lucky, this will never be needed. For now all plugins + * must set it to 1. + */ + int DSSI_API_Version; + + /** + * LADSPA_Plugin + * + * A DSSI synth plugin consists of a LADSPA plugin plus an + * additional framework for controlling program settings and + * transmitting MIDI events. A plugin must fully implement the + * LADSPA descriptor fields as well as the required LADSPA + * functions including instantiate() and (de)activate(). It + * should also implement run(), with the same behaviour as if + * run_synth() (below) were called with no synth events. + * + * In order to instantiate a synth the host calls the LADSPA + * instantiate function, passing in this LADSPA_Descriptor + * pointer. The returned LADSPA_Handle is used as the argument + * for the DSSI functions below as well as for the LADSPA ones. + */ + const LADSPA_Descriptor *LADSPA_Plugin; + + /** + * configure() + * + * This member is a function pointer that sends a piece of + * configuration data to the plugin. The key argument specifies + * some aspect of the synth's configuration that is to be changed, + * and the value argument specifies a new value for it. A plugin + * that does not require this facility at all may set this member + * to NULL. + * + * This call is intended to set some session-scoped aspect of a + * plugin's behaviour, for example to tell the plugin to load + * sample data from a particular file. The plugin should act + * immediately on the request. The call should return NULL on + * success, or an error string that may be shown to the user. The + * host will free the returned value after use if it is non-NULL. + * + * Calls to configure() are not automated as timed events. + * Instead, a host should remember the last value associated with + * each key passed to configure() during a given session for a + * given plugin instance, and should call configure() with the + * correct value for each key the next time it instantiates the + * "same" plugin instance, for example on reloading a project in + * which the plugin was used before. Plugins should note that a + * host may typically instantiate a plugin multiple times with the + * same configuration values, and should share data between + * instances where practical. + * + * Calling configure() completely invalidates the program and bank + * information last obtained from the plugin. + * + * Reserved and special key prefixes + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * The DSSI: prefix + * ---------------- + * Configure keys starting with DSSI: are reserved for particular + * purposes documented in the DSSI specification. At the moment, + * there is one such key: DSSI:PROJECT_DIRECTORY. A host may call + * configure() passing this key and a directory path value. This + * indicates to the plugin and its UI that a directory at that + * path exists and may be used for project-local data. Plugins + * may wish to use the project directory as a fallback location + * when looking for other file data, or as a base for relative + * paths in other configuration values. + * + * The GLOBAL: prefix + * ------------------ + * Configure keys starting with GLOBAL: may be used by the plugin + * and its UI for any purpose, but are treated specially by the + * host. When one of these keys is used in a configure OSC call + * from the plugin UI, the host makes the corresponding configure + * call (preserving the GLOBAL: prefix) not only to the target + * plugin but also to all other plugins in the same instance + * group, as well as their UIs. Note that if any instance + * returns non-NULL from configure to indicate error, the host + * may stop there (and the set of plugins on which configure has + * been called will thus depend on the host implementation). + * See also the configure OSC call documentation in RFC.txt. + */ + char *(*configure)(LADSPA_Handle Instance, + const char *Key, + const char *Value); + + #define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:" + #define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:" + #define DSSI_PROJECT_DIRECTORY_KEY \ + DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY" + + /** + * get_program() + * + * This member is a function pointer that provides a description + * of a program (named preset sound) available on this synth. A + * plugin that does not support programs at all should set this + * member to NULL. + * + * The Index argument is an index into the plugin's list of + * programs, not a program number as represented by the Program + * field of the DSSI_Program_Descriptor. (This distinction is + * needed to support synths that use non-contiguous program or + * bank numbers.) + * + * This function returns a DSSI_Program_Descriptor pointer that is + * guaranteed to be valid only until the next call to get_program, + * deactivate, or configure, on the same plugin instance. This + * function must return NULL if passed an Index argument out of + * range, so that the host can use it to query the number of + * programs as well as their properties. + */ + const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance, + unsigned long Index); + + /** + * select_program() + * + * This member is a function pointer that selects a new program + * for this synth. The program change should take effect + * immediately at the start of the next run_synth() call. (This + * means that a host providing the capability of changing programs + * between any two notes on a track must vary the block size so as + * to place the program change at the right place. A host that + * wanted to avoid this would probably just instantiate a plugin + * for each program.) + * + * A plugin that does not support programs at all should set this + * member NULL. Plugins should ignore a select_program() call + * with an invalid bank or program. + * + * A plugin is not required to select any particular default + * program on activate(): it's the host's duty to set a program + * explicitly. The current program is invalidated by any call to + * configure(). + * + * A plugin is permitted to re-write the values of its input + * control ports when select_program is called. The host should + * re-read the input control port values and update its own + * records appropriately. (This is the only circumstance in + * which a DSSI plugin is allowed to modify its own input ports.) + */ + void (*select_program)(LADSPA_Handle Instance, + unsigned long Bank, + unsigned long Program); + + /** + * get_midi_controller_for_port() + * + * This member is a function pointer that returns the MIDI + * controller number or NRPN that should be mapped to the given + * input control port. If the given port should not have any MIDI + * controller mapped to it, the function should return DSSI_NONE. + * The behaviour of this function is undefined if the given port + * number does not correspond to an input control port. A plugin + * that does not want MIDI controllers mapped to ports at all may + * set this member NULL. + * + * Correct values can be got using the macros DSSI_CC(num) and + * DSSI_NRPN(num) as appropriate, and values can be combined using + * bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port + * should respond to CC #23 and NRPN #1069. + * + * The host is responsible for doing proper scaling from MIDI + * controller and NRPN value ranges to port ranges according to + * the plugin's LADSPA port hints. Hosts should not deliver + * through run_synth any MIDI controller events that have already + * been mapped to control port values. + * + * A plugin should not attempt to request mappings from + * controllers 0 or 32 (MIDI Bank Select MSB and LSB). + */ + int (*get_midi_controller_for_port)(LADSPA_Handle Instance, + unsigned long Port); + + /** + * run_synth() + * + * This member is a function pointer that runs a synth for a + * block. This is identical in function to the LADSPA run() + * function, except that it also supplies events to the synth. + * + * A plugin may provide this function, run_multiple_synths() (see + * below), both, or neither (if it is not in fact a synth). A + * plugin that does not provide this function must set this member + * to NULL. Authors of synth plugins are encouraged to provide + * this function if at all possible. + * + * The Events pointer points to a block of EventCount ALSA + * sequencer events, which is used to communicate MIDI and related + * events to the synth. Each event is timestamped relative to the + * start of the block, (mis)using the ALSA "tick time" field as a + * frame count. The host is responsible for ensuring that events + * with differing timestamps are already ordered by time. + * + * See also the notes on activation, port connection etc in + * ladpsa.h, in the context of the LADSPA run() function. + * + * Note Events + * ~~~~~~~~~~~ + * There are two minor requirements aimed at making the plugin + * writer's life as simple as possible: + * + * 1. A host must never send events of type SND_SEQ_EVENT_NOTE. + * Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON + * and NOTE_OFF events. A plugin should discard any one-point + * NOTE events it sees. + * + * 2. A host must not attempt to switch notes off by sending + * zero-velocity NOTE_ON events. It should always send true + * NOTE_OFFs. It is the host's responsibility to remap events in + * cases where an external MIDI source has sent it zero-velocity + * NOTE_ONs. + * + * Bank and Program Events + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Hosts must map MIDI Bank Select MSB and LSB (0 and 32) + * controllers and MIDI Program Change events onto the banks and + * programs specified by the plugin, using the DSSI select_program + * call. No host should ever deliver a program change or bank + * select controller to a plugin via run_synth. + */ + void (*run_synth)(LADSPA_Handle Instance, + unsigned long SampleCount, + snd_seq_event_t *Events, + unsigned long EventCount); + + /** + * run_synth_adding() + * + * This member is a function pointer that runs an instance of a + * synth for a block, adding its outputs to the values already + * present at the output ports. This is provided for symmetry + * with LADSPA run_adding(), and is equally optional. A plugin + * that does not provide it must set this member to NULL. + */ + void (*run_synth_adding)(LADSPA_Handle Instance, + unsigned long SampleCount, + snd_seq_event_t *Events, + unsigned long EventCount); + + /** + * run_multiple_synths() + * + * This member is a function pointer that runs multiple synth + * instances for a block. This is very similar to run_synth(), + * except that Instances, Events, and EventCounts each point to + * arrays that hold the LADSPA handles, event buffers, and + * event counts for each of InstanceCount instances. That is, + * Instances points to an array of InstanceCount pointers to + * DSSI plugin instantiations, Events points to an array of + * pointers to each instantiation's respective event list, and + * EventCounts points to an array containing each instantiation's + * respective event count. + * + * A host using this function must guarantee that ALL active + * instances of the plugin are represented in each call to the + * function -- that is, a host may not call run_multiple_synths() + * for some instances of a given plugin and then call run_synth() + * as well for others. 'All .. instances of the plugin' means + * every instance sharing the same LADSPA label and shared object + * (*.so) file (rather than every instance sharing the same *.so). + * 'Active' means any instance for which activate() has been called + * but deactivate() has not. + * + * A plugin may provide this function, run_synths() (see above), + * both, or neither (if it not in fact a synth). A plugin that + * does not provide this function must set this member to NULL. + * Plugin authors implementing run_multiple_synths are strongly + * encouraged to implement run_synth as well if at all possible, + * to aid simplistic hosts, even where it would be less efficient + * to use it. + */ + void (*run_multiple_synths)(unsigned long InstanceCount, + LADSPA_Handle *Instances, + unsigned long SampleCount, + snd_seq_event_t **Events, + unsigned long *EventCounts); + + /** + * run_multiple_synths_adding() + * + * This member is a function pointer that runs multiple synth + * instances for a block, adding each synth's outputs to the + * values already present at the output ports. This is provided + * for symmetry with both the DSSI run_multiple_synths() and LADSPA + * run_adding() functions, and is equally optional. A plugin + * that does not provide it must set this member to NULL. + */ + void (*run_multiple_synths_adding)(unsigned long InstanceCount, + LADSPA_Handle *Instances, + unsigned long SampleCount, + snd_seq_event_t **Events, + unsigned long *EventCounts); + + /** + * set_custom_data() + */ + int (*set_custom_data)(LADSPA_Handle Instance, + void *Data, + unsigned long DataLength); + + /** + * get_custom_data() + */ + int (*get_custom_data)(LADSPA_Handle Instance, + void **Data, + unsigned long *DataLength); + +} DSSI_Descriptor; + +/** + * DSSI supports a plugin discovery method similar to that of LADSPA: + * + * - DSSI hosts may wish to locate DSSI plugin shared object files by + * searching the paths contained in the DSSI_PATH and LADSPA_PATH + * environment variables, if they are present. Both are expected + * to be colon-separated lists of directories to be searched (in + * order), and DSSI_PATH should be searched first if both variables + * are set. + * + * - Each shared object file containing DSSI plugins must include a + * function dssi_descriptor(), with the following function prototype + * and C-style linkage. Hosts may enumerate the plugin types + * available in the shared object file by repeatedly calling + * this function with successive Index values (beginning from 0), + * until a return value of NULL indicates no more plugin types are + * available. Each non-NULL return is the DSSI_Descriptor + * of a distinct plugin type. + */ + +DSSI_PLUGIN_EXPORT const DSSI_Descriptor *dssi_descriptor(unsigned long Index); + +typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); + +/* + * Macros to specify particular MIDI controllers in return values from + * get_midi_controller_for_port() + */ + +#define DSSI_CC_BITS 0x20000000 +#define DSSI_NRPN_BITS 0x40000000 + +#define DSSI_NONE -1 +#define DSSI_CONTROLLER_IS_SET(n) (DSSI_NONE != (n)) + +#define DSSI_CC(n) (DSSI_CC_BITS | (n)) +#define DSSI_IS_CC(n) (DSSI_CC_BITS & (n)) +#define DSSI_CC_NUMBER(n) ((n) & 0x7f) + +#define DSSI_NRPN(n) (DSSI_NRPN_BITS | ((n) << 7)) +#define DSSI_IS_NRPN(n) (DSSI_NRPN_BITS & (n)) +#define DSSI_NRPN_NUMBER(n) (((n) >> 7) & 0x3fff) + +#ifdef __cplusplus +} +#endif + +#endif /* DSSI_INCLUDED */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/dssi/seq_event-compat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/dssi/seq_event-compat.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,282 @@ +/** + * \file include/seq_event.h + * \brief Application interface library for the ALSA driver + * \author Jaroslav Kysela + * \author Abramo Bagnara + * \author Takashi Iwai + * \date 1998-2001 + * + * Application interface library for the ALSA driver + */ +/* + * 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.1 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 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 + * + */ + +#ifndef __ALSA_SEQ_EVENT_COMPAT_H +#define __ALSA_SEQ_EVENT_COMPAT_H + +/** + * Sequencer event data type + */ +typedef unsigned char snd_seq_event_type_t; + +/** Sequencer event type */ +enum snd_seq_event_type { + /** system status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_SYSTEM = 0, + /** returned result status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_RESULT, + + /** note on and off with duration; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTE = 5, + /** note on; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEON, + /** note off; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEOFF, + /** key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_KEYPRESS, + + /** controller; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROLLER = 10, + /** program change; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_PGMCHANGE, + /** channel pressure; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CHANPRESS, + /** pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */ + SND_SEQ_EVENT_PITCHBEND, + /** 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROL14, + /** 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_NONREGPARAM, + /** 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_REGPARAM, + + /** SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGPOS = 20, + /** Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGSEL, + /** midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_QFRAME, + /** SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_TIMESIGN, + /** SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_KEYSIGN, + + /** MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_START = 30, + /** MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CONTINUE, + /** MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_STOP, + /** Set tick queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TICK, + /** Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TIME, + /** (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TEMPO, + /** MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CLOCK, + /** MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TICK, + /** Queue timer skew; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_QUEUE_SKEW, + /** Sync position changed; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SYNC_POS, + + /** Tune request; event data type = none */ + SND_SEQ_EVENT_TUNE_REQUEST = 40, + /** Reset to power-on state; event data type = none */ + SND_SEQ_EVENT_RESET, + /** Active sensing event; event data type = none */ + SND_SEQ_EVENT_SENSING, + + /** Echo-back event; event data type = any type */ + SND_SEQ_EVENT_ECHO = 50, + /** OSS emulation raw event; event data type = any type */ + SND_SEQ_EVENT_OSS, + + /** New client has connected; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_START = 60, + /** Client has left the system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_EXIT, + /** Client status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_CHANGE, + /** New port was created; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_START, + /** Port was deleted from system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_EXIT, + /** Port status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_CHANGE, + + /** Ports connected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_SUBSCRIBED, + /** Ports disconnected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_UNSUBSCRIBED, + + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR0 = 90, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR1, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR2, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR3, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR4, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR5, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR6, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR7, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR8, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR9, + + /** system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_SYSEX = 130, + /** error event; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_BOUNCE, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR0 = 135, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR1, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR2, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR3, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR4, + + /** NOP; ignored in any case */ + SND_SEQ_EVENT_NONE = 255 +}; + +/** Sequencer event address */ +typedef struct snd_seq_addr { + unsigned char client; /**< Client id */ + unsigned char port; /**< Port id */ +} snd_seq_addr_t; + +/** Connection (subscription) between ports */ +typedef struct snd_seq_connect { + snd_seq_addr_t sender; /**< sender address */ + snd_seq_addr_t dest; /**< destination address */ +} snd_seq_connect_t; + +/** Real-time data record */ +typedef struct snd_seq_real_time { + unsigned int tv_sec; /**< seconds */ + unsigned int tv_nsec; /**< nanoseconds */ +} snd_seq_real_time_t; + +/** (MIDI) Tick-time data record */ +typedef unsigned int snd_seq_tick_time_t; + +/** unioned time stamp */ +typedef union snd_seq_timestamp { + snd_seq_tick_time_t tick; /**< tick-time */ + struct snd_seq_real_time time; /**< real-time */ +} snd_seq_timestamp_t; + +/** Note event */ +typedef struct snd_seq_ev_note { + unsigned char channel; /**< channel number */ + unsigned char note; /**< note */ + unsigned char velocity; /**< velocity */ + unsigned char off_velocity; /**< note-off velocity; only for #SND_SEQ_EVENT_NOTE */ + unsigned int duration; /**< duration until note-off; only for #SND_SEQ_EVENT_NOTE */ +} snd_seq_ev_note_t; + +/** Controller event */ +typedef struct snd_seq_ev_ctrl { + unsigned char channel; /**< channel number */ + unsigned char unused[3]; /**< reserved */ + unsigned int param; /**< control parameter */ + signed int value; /**< control value */ +} snd_seq_ev_ctrl_t; + +/** generic set of bytes (12x8 bit) */ +typedef struct snd_seq_ev_raw8 { + unsigned char d[12]; /**< 8 bit value */ +} snd_seq_ev_raw8_t; + +/** generic set of integers (3x32 bit) */ +typedef struct snd_seq_ev_raw32 { + unsigned int d[3]; /**< 32 bit value */ +} snd_seq_ev_raw32_t; + +/** external stored data */ +typedef struct snd_seq_ev_ext { + unsigned int len; /**< length of data */ + void *ptr; /**< pointer to data (note: can be 64-bit) */ +} __attribute__((packed)) snd_seq_ev_ext_t; + +/** Result events */ +typedef struct snd_seq_result { + int event; /**< processed event type */ + int result; /**< status */ +} snd_seq_result_t; + +/** Queue skew values */ +typedef struct snd_seq_queue_skew { + unsigned int value; /**< skew value */ + unsigned int base; /**< skew base */ +} snd_seq_queue_skew_t; + +/** queue timer control */ +typedef struct snd_seq_ev_queue_control { + unsigned char queue; /**< affected queue */ + unsigned char unused[3]; /**< reserved */ + union { + signed int value; /**< affected value (e.g. tempo) */ + snd_seq_timestamp_t time; /**< time */ + unsigned int position; /**< sync position */ + snd_seq_queue_skew_t skew; /**< queue skew */ + unsigned int d32[2]; /**< any data */ + unsigned char d8[8]; /**< any data */ + } param; /**< data value union */ +} snd_seq_ev_queue_control_t; + +/** Sequencer event */ +typedef struct snd_seq_event { + snd_seq_event_type_t type; /**< event type */ + unsigned char flags; /**< event flags */ + unsigned char tag; /**< tag */ + + unsigned char queue; /**< schedule queue */ + snd_seq_timestamp_t time; /**< schedule time */ + + snd_seq_addr_t source; /**< source address */ + snd_seq_addr_t dest; /**< destination address */ + + union { + snd_seq_ev_note_t note; /**< note information */ + snd_seq_ev_ctrl_t control; /**< MIDI control information */ + snd_seq_ev_raw8_t raw8; /**< raw8 data */ + snd_seq_ev_raw32_t raw32; /**< raw32 data */ + snd_seq_ev_ext_t ext; /**< external data */ + snd_seq_ev_queue_control_t queue; /**< queue control */ + snd_seq_timestamp_t time; /**< timestamp */ + snd_seq_addr_t addr; /**< address */ + snd_seq_connect_t connect; /**< connect information */ + snd_seq_result_t result; /**< operation result code */ + } data; /**< event data... */ +} snd_seq_event_t; + +#endif /* __ALSA_SEQ_EVENT_COMPAT_H */ + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/JackBridge.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/JackBridge.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2463 @@ +/* + * JackBridge for DPF + * Copyright (C) 2013-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "JackBridge.hpp" +#include "../../DistrhoStandaloneUtils.hpp" + +#if ! (defined(JACKBRIDGE_DIRECT) || defined(JACKBRIDGE_DUMMY)) + +#ifdef __WINE__ +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include +#endif + +#if defined(DISTRHO_OS_WINDOWS) && ! defined(__WINE__) +# define JACKSYM_API __cdecl +#else +# define JACKSYM_API +#endif + +#include + +#ifdef HAVE_JACK +# include "../../extra/LibraryUtils.hpp" +#else +typedef void* lib_t; +#endif + +// in case JACK fails, we fallback to native bridges simulating JACK API +#include "NativeBridge.hpp" + +#if defined(DISTRHO_OS_WASM) +# include "WebBridge.hpp" +#endif + +#ifndef DISTRHO_PROPER_CPP11_SUPPORT +# undef HAVE_RTAUDIO +#endif + +#ifdef DPF_JACK_STANDALONE_SKIP_RTAUDIO_FALLBACK +# undef HAVE_RTAUDIO +#endif + +#ifdef DPF_JACK_STANDALONE_SKIP_SDL2_FALLBACK +# undef HAVE_SDL2 +#endif + +#if defined(HAVE_RTAUDIO) && DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 +// fix conflict between DGL and macOS names +# define Point CorePoint +# define Size CoreSize +# include "RtAudioBridge.hpp" +# ifdef RTAUDIO_API_TYPE +# include "rtaudio/RtAudio.cpp" +# endif +# ifdef RTMIDI_API_TYPE +# include "rtmidi/RtMidi.cpp" +# endif +# undef Point +# undef Size +#endif + +#if defined(HAVE_SDL2) && DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 +# include "SDL2Bridge.hpp" +#endif + +// ----------------------------------------------------------------------------- + +extern "C" { + +typedef void (JACKSYM_API *JackSymLatencyCallback)(jack_latency_callback_mode_t, void*); +typedef int (JACKSYM_API *JackSymProcessCallback)(jack_nframes_t, void*); +typedef void (JACKSYM_API *JackSymThreadInitCallback)(void*); +typedef int (JACKSYM_API *JackSymGraphOrderCallback)(void*); +typedef int (JACKSYM_API *JackSymXRunCallback)(void*); +typedef int (JACKSYM_API *JackSymBufferSizeCallback)(jack_nframes_t, void*); +typedef int (JACKSYM_API *JackSymSampleRateCallback)(jack_nframes_t, void*); +typedef void (JACKSYM_API *JackSymPortRegistrationCallback)(jack_port_id_t, int, void*); +typedef void (JACKSYM_API *JackSymClientRegistrationCallback)(const char*, int, void*); +typedef void (JACKSYM_API *JackSymPortConnectCallback)(jack_port_id_t, jack_port_id_t, int, void*); +typedef void (JACKSYM_API *JackSymPortRenameCallback)(jack_port_id_t, const char*, const char*, void*); +typedef void (JACKSYM_API *JackSymFreewheelCallback)(int, void*); +typedef void (JACKSYM_API *JackSymShutdownCallback)(void*); +typedef void (JACKSYM_API *JackSymInfoShutdownCallback)(jack_status_t, const char*, void*); +typedef int (JACKSYM_API *JackSymSyncCallback)(jack_transport_state_t, jack_position_t*, void*); +typedef void (JACKSYM_API *JackSymTimebaseCallback)(jack_transport_state_t, jack_nframes_t, jack_position_t*, int, void*); +typedef void (JACKSYM_API *JackSymSessionCallback)(jack_session_event_t*, void*); +typedef void (JACKSYM_API *JackSymPropertyChangeCallback)(jack_uuid_t, const char*, jack_property_change_t, void*); +typedef void* (JACKSYM_API *JackSymThreadCallback)(void*); + +typedef void (JACKSYM_API *jacksym_get_version)(int*, int*, int*, int*); +typedef const char* (JACKSYM_API *jacksym_get_version_string)(void); + +typedef jack_client_t* (JACKSYM_API *jacksym_client_open)(const char*, jack_options_t, jack_status_t*, ...); +typedef int (JACKSYM_API *jacksym_client_close)(jack_client_t*); + +typedef int (JACKSYM_API *jacksym_client_name_size)(void); +typedef char* (JACKSYM_API *jacksym_get_client_name)(jack_client_t*); + +typedef char* (JACKSYM_API *jacksym_client_get_uuid)(jack_client_t*); +typedef char* (JACKSYM_API *jacksym_get_uuid_for_client_name)(jack_client_t*, const char*); +typedef char* (JACKSYM_API *jacksym_get_client_name_by_uuid)(jack_client_t*, const char*); + +typedef int (JACKBRIDGE_API *jacksym_uuid_parse)(const char*, jack_uuid_t*); +typedef void (JACKBRIDGE_API *jacksym_uuid_unparse)(jack_uuid_t, char buf[JACK_UUID_STRING_SIZE]); + +typedef int (JACKSYM_API *jacksym_activate)(jack_client_t*); +typedef int (JACKSYM_API *jacksym_deactivate)(jack_client_t*); +typedef int (JACKSYM_API *jacksym_is_realtime)(jack_client_t*); + +typedef int (JACKSYM_API *jacksym_set_thread_init_callback)(jack_client_t*, JackSymThreadInitCallback, void*); +typedef void (JACKSYM_API *jacksym_on_shutdown)(jack_client_t*, JackSymShutdownCallback, void*); +typedef void (JACKSYM_API *jacksym_on_info_shutdown)(jack_client_t*, JackSymInfoShutdownCallback, void*); +typedef int (JACKSYM_API *jacksym_set_process_callback)(jack_client_t*, JackSymProcessCallback, void*); +typedef int (JACKSYM_API *jacksym_set_freewheel_callback)(jack_client_t*, JackSymFreewheelCallback, void*); +typedef int (JACKSYM_API *jacksym_set_buffer_size_callback)(jack_client_t*, JackSymBufferSizeCallback, void*); +typedef int (JACKSYM_API *jacksym_set_sample_rate_callback)(jack_client_t*, JackSymSampleRateCallback, void*); +typedef int (JACKSYM_API *jacksym_set_client_registration_callback)(jack_client_t*, JackSymClientRegistrationCallback, void*); +typedef int (JACKSYM_API *jacksym_set_port_registration_callback)(jack_client_t*, JackSymPortRegistrationCallback, void*); +typedef int (JACKSYM_API *jacksym_set_port_rename_callback)(jack_client_t*, JackSymPortRenameCallback, void*); +typedef int (JACKSYM_API *jacksym_set_port_connect_callback)(jack_client_t*, JackSymPortConnectCallback, void*); +typedef int (JACKSYM_API *jacksym_set_graph_order_callback)(jack_client_t*, JackSymGraphOrderCallback, void*); +typedef int (JACKSYM_API *jacksym_set_xrun_callback)(jack_client_t*, JackSymXRunCallback, void*); +typedef int (JACKSYM_API *jacksym_set_latency_callback)(jack_client_t*, JackSymLatencyCallback, void*); + +typedef int (JACKSYM_API *jacksym_set_freewheel)(jack_client_t*, int); +typedef int (JACKSYM_API *jacksym_set_buffer_size)(jack_client_t*, jack_nframes_t); + +typedef jack_nframes_t (JACKSYM_API *jacksym_get_sample_rate)(jack_client_t*); +typedef jack_nframes_t (JACKSYM_API *jacksym_get_buffer_size)(jack_client_t*); +typedef float (JACKSYM_API *jacksym_cpu_load)(jack_client_t*); + +typedef jack_port_t* (JACKSYM_API *jacksym_port_register)(jack_client_t*, const char*, const char*, ulong, ulong); +typedef int (JACKSYM_API *jacksym_port_unregister)(jack_client_t*, jack_port_t*); +typedef void* (JACKSYM_API *jacksym_port_get_buffer)(jack_port_t*, jack_nframes_t); + +typedef const char* (JACKSYM_API *jacksym_port_name)(const jack_port_t*); +typedef jack_uuid_t (JACKSYM_API *jacksym_port_uuid)(const jack_port_t*); +typedef const char* (JACKSYM_API *jacksym_port_short_name)(const jack_port_t*); +typedef int (JACKSYM_API *jacksym_port_flags)(const jack_port_t*); +typedef const char* (JACKSYM_API *jacksym_port_type)(const jack_port_t*); +typedef int (JACKSYM_API *jacksym_port_is_mine)(const jack_client_t*, const jack_port_t*); +typedef int (JACKSYM_API *jacksym_port_connected)(const jack_port_t*); +typedef int (JACKSYM_API *jacksym_port_connected_to)(const jack_port_t*, const char*); +typedef const char** (JACKSYM_API *jacksym_port_get_connections)(const jack_port_t*); +typedef const char** (JACKSYM_API *jacksym_port_get_all_connections)(const jack_client_t*, const jack_port_t*); + +typedef int (JACKSYM_API *jacksym_port_rename)(jack_client_t*, jack_port_t*, const char*); +typedef int (JACKSYM_API *jacksym_port_set_name)(jack_port_t*, const char*); +typedef int (JACKSYM_API *jacksym_port_set_alias)(jack_port_t*, const char*); +typedef int (JACKSYM_API *jacksym_port_unset_alias)(jack_port_t*, const char*); +typedef int (JACKSYM_API *jacksym_port_get_aliases)(const jack_port_t*, char* const aliases[2]); + +typedef int (JACKSYM_API *jacksym_port_request_monitor)(jack_port_t*, int); +typedef int (JACKSYM_API *jacksym_port_request_monitor_by_name)(jack_client_t*, const char*, int); +typedef int (JACKSYM_API *jacksym_port_ensure_monitor)(jack_port_t*, int); +typedef int (JACKSYM_API *jacksym_port_monitoring_input)(jack_port_t*); + +typedef int (JACKSYM_API *jacksym_connect)(jack_client_t*, const char*, const char*); +typedef int (JACKSYM_API *jacksym_disconnect)(jack_client_t*, const char*, const char*); +typedef int (JACKSYM_API *jacksym_port_disconnect)(jack_client_t*, jack_port_t*); + +typedef int (JACKSYM_API *jacksym_port_name_size)(void); +typedef int (JACKSYM_API *jacksym_port_type_size)(void); +typedef size_t (JACKSYM_API *jacksym_port_type_get_buffer_size)(jack_client_t*, const char*); + +typedef void (JACKSYM_API *jacksym_port_get_latency_range)(jack_port_t*, jack_latency_callback_mode_t, jack_latency_range_t*); +typedef void (JACKSYM_API *jacksym_port_set_latency_range)(jack_port_t*, jack_latency_callback_mode_t, jack_latency_range_t*); +typedef int (JACKSYM_API *jacksym_recompute_total_latencies)(jack_client_t*); + +typedef const char** (JACKSYM_API *jacksym_get_ports)(jack_client_t*, const char*, const char*, ulong); +typedef jack_port_t* (JACKSYM_API *jacksym_port_by_name)(jack_client_t*, const char*); +typedef jack_port_t* (JACKSYM_API *jacksym_port_by_id)(jack_client_t*, jack_port_id_t); + +typedef void (JACKSYM_API *jacksym_free)(void*); + +typedef uint32_t (JACKSYM_API *jacksym_midi_get_event_count)(void*); +typedef int (JACKSYM_API *jacksym_midi_event_get)(jack_midi_event_t*, void*, uint32_t); +typedef void (JACKSYM_API *jacksym_midi_clear_buffer)(void*); +typedef int (JACKSYM_API *jacksym_midi_event_write)(void*, jack_nframes_t, const jack_midi_data_t*, size_t); +typedef jack_midi_data_t* (JACKSYM_API *jacksym_midi_event_reserve)(void*, jack_nframes_t, size_t); + +typedef int (JACKSYM_API *jacksym_release_timebase)(jack_client_t*); +typedef int (JACKSYM_API *jacksym_set_sync_callback)(jack_client_t*, JackSymSyncCallback, void*); +typedef int (JACKSYM_API *jacksym_set_sync_timeout)(jack_client_t*, jack_time_t); +typedef int (JACKSYM_API *jacksym_set_timebase_callback)(jack_client_t*, int, JackSymTimebaseCallback, void*); +typedef int (JACKSYM_API *jacksym_transport_locate)(jack_client_t*, jack_nframes_t); + +typedef jack_transport_state_t (JACKSYM_API *jacksym_transport_query)(const jack_client_t*, jack_position_t*); +typedef jack_nframes_t (JACKSYM_API *jacksym_get_current_transport_frame)(const jack_client_t*); + +typedef int (JACKSYM_API *jacksym_transport_reposition)(jack_client_t*, const jack_position_t*); +typedef void (JACKSYM_API *jacksym_transport_start)(jack_client_t*); +typedef void (JACKSYM_API *jacksym_transport_stop)(jack_client_t*); + +typedef int (JACKSYM_API *jacksym_set_property)(jack_client_t*, jack_uuid_t, const char*, const char*, const char*); +typedef int (JACKSYM_API *jacksym_get_property)(jack_uuid_t, const char*, char**, char**); +typedef void (JACKSYM_API *jacksym_free_description)(jack_description_t*, int); +typedef int (JACKSYM_API *jacksym_get_properties)(jack_uuid_t, jack_description_t*); +typedef int (JACKSYM_API *jacksym_get_all_properties)(jack_description_t**); +typedef int (JACKSYM_API *jacksym_remove_property)(jack_client_t*, jack_uuid_t, const char*); +typedef int (JACKSYM_API *jacksym_remove_properties)(jack_client_t*, jack_uuid_t); +typedef int (JACKSYM_API *jacksym_remove_all_properties)(jack_client_t*); +typedef int (JACKSYM_API *jacksym_set_property_change_callback)(jack_client_t*, JackSymPropertyChangeCallback, void*); + +typedef bool (JACKSYM_API *jacksym_set_process_thread)(jack_client_t*, JackSymThreadCallback callback, void*); +typedef jack_nframes_t (JACKSYM_API *jacksym_cycle_wait)(jack_client_t*); +typedef void (JACKSYM_API *jacksym_cycle_signal)(jack_client_t*, int); + +#ifdef __WINE__ +typedef int (JACKSYM_API *jacksym_thread_creator_t)(pthread_t*, const pthread_attr_t*, void *(*)(void*), void*); +typedef void (JACKSYM_API *jacksym_set_thread_creator)(jacksym_thread_creator_t); +#endif + +} // extern "C" + +// ----------------------------------------------------------------------------- + +struct JackBridge { + lib_t lib; + + jacksym_get_version get_version_ptr; + jacksym_get_version_string get_version_string_ptr; + + jacksym_client_open client_open_ptr; + jacksym_client_close client_close_ptr; + + jacksym_client_name_size client_name_size_ptr; + jacksym_get_client_name get_client_name_ptr; + + jacksym_client_get_uuid client_get_uuid_ptr; + jacksym_get_uuid_for_client_name get_uuid_for_client_name_ptr; + jacksym_get_client_name_by_uuid get_client_name_by_uuid_ptr; + + jacksym_uuid_parse uuid_parse_ptr; + jacksym_uuid_unparse uuid_unparse_ptr; + + jacksym_activate activate_ptr; + jacksym_deactivate deactivate_ptr; + jacksym_is_realtime is_realtime_ptr; + + jacksym_set_thread_init_callback set_thread_init_callback_ptr; + jacksym_on_shutdown on_shutdown_ptr; + jacksym_on_info_shutdown on_info_shutdown_ptr; + jacksym_set_process_callback set_process_callback_ptr; + jacksym_set_freewheel_callback set_freewheel_callback_ptr; + jacksym_set_buffer_size_callback set_buffer_size_callback_ptr; + jacksym_set_sample_rate_callback set_sample_rate_callback_ptr; + jacksym_set_client_registration_callback set_client_registration_callback_ptr; + jacksym_set_port_registration_callback set_port_registration_callback_ptr; + jacksym_set_port_rename_callback set_port_rename_callback_ptr; + jacksym_set_port_connect_callback set_port_connect_callback_ptr; + jacksym_set_graph_order_callback set_graph_order_callback_ptr; + jacksym_set_xrun_callback set_xrun_callback_ptr; + jacksym_set_latency_callback set_latency_callback_ptr; + + jacksym_set_freewheel set_freewheel_ptr; + jacksym_set_buffer_size set_buffer_size_ptr; + + jacksym_get_sample_rate get_sample_rate_ptr; + jacksym_get_buffer_size get_buffer_size_ptr; + jacksym_cpu_load cpu_load_ptr; + + jacksym_port_register port_register_ptr; + jacksym_port_unregister port_unregister_ptr; + jacksym_port_get_buffer port_get_buffer_ptr; + + jacksym_port_name port_name_ptr; + jacksym_port_uuid port_uuid_ptr; + jacksym_port_short_name port_short_name_ptr; + jacksym_port_flags port_flags_ptr; + jacksym_port_type port_type_ptr; + jacksym_port_is_mine port_is_mine_ptr; + jacksym_port_connected port_connected_ptr; + jacksym_port_connected_to port_connected_to_ptr; + jacksym_port_get_connections port_get_connections_ptr; + jacksym_port_get_all_connections port_get_all_connections_ptr; + + jacksym_port_rename port_rename_ptr; + jacksym_port_set_name port_set_name_ptr; + jacksym_port_set_alias port_set_alias_ptr; + jacksym_port_unset_alias port_unset_alias_ptr; + jacksym_port_get_aliases port_get_aliases_ptr; + + jacksym_port_request_monitor port_request_monitor_ptr; + jacksym_port_request_monitor_by_name port_request_monitor_by_name_ptr; + jacksym_port_ensure_monitor port_ensure_monitor_ptr; + jacksym_port_monitoring_input port_monitoring_input_ptr; + + jacksym_connect connect_ptr; + jacksym_disconnect disconnect_ptr; + jacksym_port_disconnect port_disconnect_ptr; + + jacksym_port_name_size port_name_size_ptr; + jacksym_port_type_size port_type_size_ptr; + jacksym_port_type_get_buffer_size port_type_get_buffer_size_ptr; + + jacksym_port_get_latency_range port_get_latency_range_ptr; + jacksym_port_set_latency_range port_set_latency_range_ptr; + jacksym_recompute_total_latencies recompute_total_latencies_ptr; + + jacksym_get_ports get_ports_ptr; + jacksym_port_by_name port_by_name_ptr; + jacksym_port_by_id port_by_id_ptr; + + jacksym_free free_ptr; + + jacksym_midi_get_event_count midi_get_event_count_ptr; + jacksym_midi_event_get midi_event_get_ptr; + jacksym_midi_clear_buffer midi_clear_buffer_ptr; + jacksym_midi_event_write midi_event_write_ptr; + jacksym_midi_event_reserve midi_event_reserve_ptr; + + jacksym_release_timebase release_timebase_ptr; + jacksym_set_sync_callback set_sync_callback_ptr; + jacksym_set_sync_timeout set_sync_timeout_ptr; + jacksym_set_timebase_callback set_timebase_callback_ptr; + jacksym_transport_locate transport_locate_ptr; + + jacksym_transport_query transport_query_ptr; + jacksym_get_current_transport_frame get_current_transport_frame_ptr; + + jacksym_transport_reposition transport_reposition_ptr; + jacksym_transport_start transport_start_ptr; + jacksym_transport_stop transport_stop_ptr; + + jacksym_set_property set_property_ptr; + jacksym_get_property get_property_ptr; + jacksym_free_description free_description_ptr; + jacksym_get_properties get_properties_ptr; + jacksym_get_all_properties get_all_properties_ptr; + jacksym_remove_property remove_property_ptr; + jacksym_remove_properties remove_properties_ptr; + jacksym_remove_all_properties remove_all_properties_ptr; + jacksym_set_property_change_callback set_property_change_callback_ptr; + + jacksym_set_process_thread set_process_thread_ptr; + jacksym_cycle_wait cycle_wait_ptr; + jacksym_cycle_signal cycle_signal_ptr; + + #ifdef __WINE__ + jacksym_set_thread_creator set_thread_creator_ptr; + #endif + + JackBridge() + : lib(nullptr), + get_version_ptr(nullptr), + get_version_string_ptr(nullptr), + client_open_ptr(nullptr), + client_close_ptr(nullptr), + client_name_size_ptr(nullptr), + get_client_name_ptr(nullptr), + client_get_uuid_ptr(nullptr), + get_uuid_for_client_name_ptr(nullptr), + get_client_name_by_uuid_ptr(nullptr), + uuid_parse_ptr(nullptr), + uuid_unparse_ptr(nullptr), + activate_ptr(nullptr), + deactivate_ptr(nullptr), + is_realtime_ptr(nullptr), + set_thread_init_callback_ptr(nullptr), + on_shutdown_ptr(nullptr), + on_info_shutdown_ptr(nullptr), + set_process_callback_ptr(nullptr), + set_freewheel_callback_ptr(nullptr), + set_buffer_size_callback_ptr(nullptr), + set_sample_rate_callback_ptr(nullptr), + set_client_registration_callback_ptr(nullptr), + set_port_registration_callback_ptr(nullptr), + set_port_rename_callback_ptr(nullptr), + set_port_connect_callback_ptr(nullptr), + set_graph_order_callback_ptr(nullptr), + set_xrun_callback_ptr(nullptr), + set_latency_callback_ptr(nullptr), + set_freewheel_ptr(nullptr), + set_buffer_size_ptr(nullptr), + get_sample_rate_ptr(nullptr), + get_buffer_size_ptr(nullptr), + cpu_load_ptr(nullptr), + port_register_ptr(nullptr), + port_unregister_ptr(nullptr), + port_get_buffer_ptr(nullptr), + port_name_ptr(nullptr), + port_uuid_ptr(nullptr), + port_short_name_ptr(nullptr), + port_flags_ptr(nullptr), + port_type_ptr(nullptr), + port_is_mine_ptr(nullptr), + port_connected_ptr(nullptr), + port_connected_to_ptr(nullptr), + port_get_connections_ptr(nullptr), + port_get_all_connections_ptr(nullptr), + port_rename_ptr(nullptr), + port_set_name_ptr(nullptr), + port_set_alias_ptr(nullptr), + port_unset_alias_ptr(nullptr), + port_get_aliases_ptr(nullptr), + port_request_monitor_ptr(nullptr), + port_request_monitor_by_name_ptr(nullptr), + port_ensure_monitor_ptr(nullptr), + port_monitoring_input_ptr(nullptr), + connect_ptr(nullptr), + disconnect_ptr(nullptr), + port_disconnect_ptr(nullptr), + port_name_size_ptr(nullptr), + port_type_size_ptr(nullptr), + port_type_get_buffer_size_ptr(nullptr), + port_get_latency_range_ptr(nullptr), + port_set_latency_range_ptr(nullptr), + recompute_total_latencies_ptr(nullptr), + get_ports_ptr(nullptr), + port_by_name_ptr(nullptr), + port_by_id_ptr(nullptr), + free_ptr(nullptr), + midi_get_event_count_ptr(nullptr), + midi_event_get_ptr(nullptr), + midi_clear_buffer_ptr(nullptr), + midi_event_write_ptr(nullptr), + midi_event_reserve_ptr(nullptr), + release_timebase_ptr(nullptr), + set_sync_callback_ptr(nullptr), + set_sync_timeout_ptr(nullptr), + set_timebase_callback_ptr(nullptr), + transport_locate_ptr(nullptr), + transport_query_ptr(nullptr), + get_current_transport_frame_ptr(nullptr), + transport_reposition_ptr(nullptr), + transport_start_ptr(nullptr), + transport_stop_ptr(nullptr), + set_property_ptr(nullptr), + get_property_ptr(nullptr), + free_description_ptr(nullptr), + get_properties_ptr(nullptr), + get_all_properties_ptr(nullptr), + remove_property_ptr(nullptr), + remove_properties_ptr(nullptr), + remove_all_properties_ptr(nullptr), + set_property_change_callback_ptr(nullptr), + set_process_thread_ptr(nullptr), + cycle_wait_ptr(nullptr), + cycle_signal_ptr(nullptr) + #ifdef __WINE__ + , set_thread_creator_ptr(nullptr) + #endif + { + #ifdef HAVE_JACK + #if defined(DISTRHO_OS_MAC) + const char* const filename = "libjack.dylib"; + #elif defined(DISTRHO_OS_WINDOWS) && defined(_WIN64) + const char* const filename = "libjack64.dll"; + #elif defined(DISTRHO_OS_WINDOWS) + const char* const filename = "libjack.dll"; + #else + const char* const filename = "libjack.so.0"; + #endif + + USE_NAMESPACE_DISTRHO + + lib = lib_open(filename); + + if (lib == nullptr) + { + fprintf(stderr, "Failed to load JACK DLL, reason:\n%s\n", lib_error(filename)); + return; + } + else + { + fprintf(stdout, "%s loaded successfully!\n", filename); + } + + #define JOIN(a, b) a ## b + #define LIB_SYMBOL(NAME) JOIN(NAME, _ptr) = lib_symbol(lib, "jack_" #NAME); + + LIB_SYMBOL(get_version) + LIB_SYMBOL(get_version_string) + + LIB_SYMBOL(client_open) + LIB_SYMBOL(client_close) + + LIB_SYMBOL(client_name_size) + LIB_SYMBOL(get_client_name) + + LIB_SYMBOL(client_get_uuid) + LIB_SYMBOL(get_uuid_for_client_name) + LIB_SYMBOL(get_client_name_by_uuid) + + LIB_SYMBOL(uuid_parse) + LIB_SYMBOL(uuid_unparse) + + LIB_SYMBOL(activate) + LIB_SYMBOL(deactivate) + LIB_SYMBOL(is_realtime) + + LIB_SYMBOL(set_thread_init_callback) + LIB_SYMBOL(on_shutdown) + LIB_SYMBOL(on_info_shutdown) + LIB_SYMBOL(set_process_callback) + LIB_SYMBOL(set_freewheel_callback) + LIB_SYMBOL(set_buffer_size_callback) + LIB_SYMBOL(set_sample_rate_callback) + LIB_SYMBOL(set_client_registration_callback) + LIB_SYMBOL(set_port_registration_callback) + LIB_SYMBOL(set_port_rename_callback) + LIB_SYMBOL(set_port_connect_callback) + LIB_SYMBOL(set_graph_order_callback) + LIB_SYMBOL(set_xrun_callback) + LIB_SYMBOL(set_latency_callback) + + LIB_SYMBOL(set_freewheel) + LIB_SYMBOL(set_buffer_size) + + LIB_SYMBOL(get_sample_rate) + LIB_SYMBOL(get_buffer_size) + LIB_SYMBOL(cpu_load) + + LIB_SYMBOL(port_register) + LIB_SYMBOL(port_unregister) + LIB_SYMBOL(port_get_buffer) + + LIB_SYMBOL(port_name) + LIB_SYMBOL(port_uuid) + LIB_SYMBOL(port_short_name) + LIB_SYMBOL(port_flags) + LIB_SYMBOL(port_type) + LIB_SYMBOL(port_is_mine) + LIB_SYMBOL(port_connected) + LIB_SYMBOL(port_connected_to) + LIB_SYMBOL(port_get_connections) + LIB_SYMBOL(port_get_all_connections) + + LIB_SYMBOL(port_rename) + LIB_SYMBOL(port_set_name) + LIB_SYMBOL(port_set_alias) + LIB_SYMBOL(port_unset_alias) + LIB_SYMBOL(port_get_aliases) + + LIB_SYMBOL(port_request_monitor) + LIB_SYMBOL(port_request_monitor_by_name) + LIB_SYMBOL(port_ensure_monitor) + LIB_SYMBOL(port_monitoring_input) + + LIB_SYMBOL(connect) + LIB_SYMBOL(disconnect) + LIB_SYMBOL(port_disconnect) + + LIB_SYMBOL(port_name_size) + LIB_SYMBOL(port_type_size) + LIB_SYMBOL(port_type_get_buffer_size) + + LIB_SYMBOL(port_get_latency_range) + LIB_SYMBOL(port_set_latency_range) + LIB_SYMBOL(recompute_total_latencies) + + LIB_SYMBOL(get_ports) + LIB_SYMBOL(port_by_name) + LIB_SYMBOL(port_by_id) + + LIB_SYMBOL(free) + + LIB_SYMBOL(midi_get_event_count) + LIB_SYMBOL(midi_event_get) + LIB_SYMBOL(midi_clear_buffer) + LIB_SYMBOL(midi_event_write) + LIB_SYMBOL(midi_event_reserve) + + LIB_SYMBOL(release_timebase) + LIB_SYMBOL(set_sync_callback) + LIB_SYMBOL(set_sync_timeout) + LIB_SYMBOL(set_timebase_callback) + LIB_SYMBOL(transport_locate) + LIB_SYMBOL(transport_query) + LIB_SYMBOL(get_current_transport_frame) + LIB_SYMBOL(transport_reposition) + LIB_SYMBOL(transport_start) + LIB_SYMBOL(transport_stop) + + LIB_SYMBOL(set_property) + LIB_SYMBOL(get_property) + LIB_SYMBOL(free_description) + LIB_SYMBOL(get_properties) + LIB_SYMBOL(get_all_properties) + LIB_SYMBOL(remove_property) + LIB_SYMBOL(remove_properties) + LIB_SYMBOL(remove_all_properties) + LIB_SYMBOL(set_property_change_callback) + + LIB_SYMBOL(set_process_thread) + LIB_SYMBOL(cycle_wait) + LIB_SYMBOL(cycle_signal) + + #ifdef __WINE__ + LIB_SYMBOL(set_thread_creator) + #endif + #endif + + #undef JOIN + #undef LIB_SYMBOL + } + + #ifdef HAVE_JACK + ~JackBridge() noexcept + { + USE_NAMESPACE_DISTRHO + + if (lib != nullptr) + { + lib_close(lib); + lib = nullptr; + } + } + #endif + + DISTRHO_DECLARE_NON_COPYABLE(JackBridge); +}; + +static bool usingNativeBridge = false; +static bool usingRealJACK = true; +static NativeBridge* nativeBridge = nullptr; + +// ----------------------------------------------------------------------------- + +static JackBridge& getBridgeInstance() noexcept +{ + static JackBridge bridge; + return bridge; +} + +#endif // ! (defined(JACKBRIDGE_DIRECT) || defined(JACKBRIDGE_DUMMY)) + +// ----------------------------------------------------------------------------- + +#if defined(__WINE__) && ! defined(JACKBRIDGE_DIRECT) + +struct WineBridge { + void* ptr; + JackLatencyCallback latency_cb; + JackProcessCallback process_cb; + JackThreadInitCallback thread_init_cb; + JackGraphOrderCallback graph_order_cb; + JackXRunCallback xrun_cb; + JackBufferSizeCallback bufsize_cb; + JackSampleRateCallback srate_cb; + JackPortRegistrationCallback port_reg_cb; + JackClientRegistrationCallback client_reg_cb; + JackPortConnectCallback port_conn_cb; + JackPortRenameCallback port_rename_cb; + JackFreewheelCallback freewheel_cb; + JackShutdownCallback shutdown_cb; + JackInfoShutdownCallback info_shutdown_cb; + JackSyncCallback sync_cb; + JackTimebaseCallback timebase_cb; + JackSessionCallback session_cb; + JackPropertyChangeCallback prop_change_cb; + JackThreadCallback proc_thread_cb; + + void* (*creator_func)(void*); + void* creator_arg; + HANDLE creator_handle; + pthread_t creator_pthread; + + WineBridge() noexcept + : ptr(nullptr), + latency_cb(nullptr), + process_cb(nullptr), + thread_init_cb(nullptr), + graph_order_cb(nullptr), + xrun_cb(nullptr), + bufsize_cb(nullptr), + srate_cb(nullptr), + port_reg_cb(nullptr), + client_reg_cb(nullptr), + port_conn_cb(nullptr), + port_rename_cb(nullptr), + freewheel_cb(nullptr), + shutdown_cb(nullptr), + info_shutdown_cb(nullptr), + sync_cb(nullptr), + timebase_cb(nullptr), + session_cb(nullptr), + prop_change_cb(nullptr), + proc_thread_cb(nullptr), + creator_func(nullptr), + creator_arg(nullptr), + creator_handle(nullptr), + creator_pthread(0) {} + + static WineBridge& getInstance() noexcept + { + static WineBridge bridge; + return bridge; + } + + void set_latency (JackLatencyCallback cb) noexcept { latency_cb = cb; } + void set_process (JackProcessCallback cb) noexcept { process_cb = cb; } + void set_thread_init (JackThreadInitCallback cb) noexcept { thread_init_cb = cb; } + void set_graph_order (JackGraphOrderCallback cb) noexcept { graph_order_cb = cb; } + void set_xrun (JackXRunCallback cb) noexcept { xrun_cb = cb; } + void set_bufsize (JackBufferSizeCallback cb) noexcept { bufsize_cb = cb; } + void set_srate (JackSampleRateCallback cb) noexcept { srate_cb = cb; } + void set_port_reg (JackPortRegistrationCallback cb) noexcept { port_reg_cb = cb; } + void set_client_reg (JackClientRegistrationCallback cb) noexcept { client_reg_cb = cb; } + void set_port_conn (JackPortConnectCallback cb) noexcept { port_conn_cb = cb; } + void set_port_rename (JackPortRenameCallback cb) noexcept { port_rename_cb = cb; } + void set_freewheel (JackFreewheelCallback cb) noexcept { freewheel_cb = cb; } + void set_shutdown (JackShutdownCallback cb) noexcept { shutdown_cb = cb; } + void set_info_shutdown (JackInfoShutdownCallback cb) noexcept { info_shutdown_cb = cb; } + void set_sync (JackSyncCallback cb) noexcept { sync_cb = cb; } + void set_timebase (JackTimebaseCallback cb) noexcept { timebase_cb = cb; } + void set_session (JackSessionCallback cb) noexcept { session_cb = cb; } + void set_prop_change (JackPropertyChangeCallback cb) noexcept { prop_change_cb = cb; } + void set_process_thread(JackThreadCallback cb) noexcept { proc_thread_cb = cb; } + + static DWORD WINAPI thread_creator_helper(LPVOID) + { + WineBridge& inst(getInstance()); + + inst.creator_pthread = pthread_self(); + SetEvent(inst.creator_handle); + inst.creator_func(inst.creator_arg); + return 0; + } + + static int thread_creator(pthread_t* thread_id, const pthread_attr_t*, void *(*function)(void*), void* arg) + { + WineBridge& inst(getInstance()); + + inst.creator_func = function; + inst.creator_arg = arg; + inst.creator_handle = ::CreateEventW(nullptr, false, false, nullptr); + +#if 0 + ::CreateThread(nullptr, 0, thread_creator_helper, arg, 0, nullptr); +#else + HANDLE handle = ::CreateThread(nullptr, 0, thread_creator_helper, arg, CREATE_SUSPENDED, nullptr); + + if (handle == INVALID_HANDLE_VALUE) + return 1; + + // TODO read attrs and decide this + ::SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); + ::ResumeThread(handle); +#endif + + ::WaitForSingleObject(inst.creator_handle, INFINITE); + *thread_id = inst.creator_pthread; + return 0; + } + + static void latency(jack_latency_callback_mode_t mode, void* arg) + { + return getInstance().latency_cb(mode, arg); + } + + static int process(jack_nframes_t nframes, void* arg) + { + return getInstance().process_cb(nframes, arg); + } + + static void thread_init(void* arg) + { + return getInstance().thread_init_cb(arg); + } + + static int graph_order(void* arg) + { + return getInstance().graph_order_cb(arg); + } + + static int xrun(void* arg) + { + return getInstance().xrun_cb(arg); + } + + static int bufsize(jack_nframes_t nframes, void* arg) + { + return getInstance().bufsize_cb(nframes, arg); + } + + static int srate(jack_nframes_t nframes, void* arg) + { + return getInstance().srate_cb(nframes, arg); + } + + static void port_reg(jack_port_id_t port, int register_, void* arg) + { + return getInstance().port_reg_cb(port, register_, arg); + } + + static void client_reg(const char* name, int register_, void* arg) + { + return getInstance().client_reg_cb(name, register_, arg); + } + + static void port_conn(jack_port_id_t a, jack_port_id_t b, int connect, void* arg) + { + return getInstance().port_conn_cb(a, b, connect, arg); + } + + static void port_rename(jack_port_id_t port, const char* old_name, const char* new_name, void* arg) + { + getInstance().port_rename_cb(port, old_name, new_name, arg); + } + + static void freewheel(int starting, void* arg) + { + return getInstance().freewheel_cb(starting, arg); + } + + static void shutdown(void* arg) + { + return getInstance().shutdown_cb(arg); + } + + static void info_shutdown(jack_status_t code, const char* reason, void* arg) + { + return getInstance().info_shutdown_cb(code, reason, arg); + } + + static int sync(jack_transport_state_t state, jack_position_t* pos, void* arg) + { + return getInstance().sync_cb(state, pos, arg); + } + + static void timebase(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg) + { + return getInstance().timebase_cb(state, nframes, pos, new_pos, arg); + } + + static void session(jack_session_event_t* event, void* arg) + { + return getInstance().session_cb(event, arg); + } + + static void prop_change(jack_uuid_t subject, const char* key, jack_property_change_t change, void* arg) + { + return getInstance().prop_change_cb(subject, key, change, arg); + } + + static void* process_thread(void* arg) + { + return getInstance().proc_thread_cb(arg); + } + + DISTRHO_DECLARE_NON_COPYABLE(WineBridge); +}; + +#endif // __WINE__ && ! JACKBRIDGE_DIRECT + +// ----------------------------------------------------------------------------- + +bool jackbridge_is_ok() noexcept +{ +#if defined(JACKBRIDGE_DUMMY) + return false; +#elif defined(JACKBRIDGE_DIRECT) || defined(DISTRHO_OS_WASM) || defined(RTAUDIO_API_TYPE) + return true; +#else + return (getBridgeInstance().lib != nullptr); +#endif +} + +void jackbridge_init() +{ +#if defined(__WINE__) && !defined(JACKBRIDGE_DIRECT) + if (getBridgeInstance().set_thread_creator_ptr != nullptr) + getBridgeInstance().set_thread_creator_ptr(WineBridge::thread_creator); +#endif +} + +// ----------------------------------------------------------------------------- + +void jackbridge_get_version(int* major_ptr, int* minor_ptr, int* micro_ptr, int* proto_ptr) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_version(major_ptr, minor_ptr, micro_ptr, proto_ptr); +#else + if (usingRealJACK && getBridgeInstance().get_version_ptr != nullptr) + return getBridgeInstance().get_version_ptr(major_ptr, minor_ptr, micro_ptr, proto_ptr); +#endif + if (major_ptr != nullptr) + *major_ptr = 0; + if (minor_ptr != nullptr) + *minor_ptr = 0; + if (micro_ptr != nullptr) + *micro_ptr = 0; + if (proto_ptr != nullptr) + *proto_ptr = 0; +} + +const char* jackbridge_get_version_string() +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_version_string(); +#else + if (usingRealJACK && getBridgeInstance().get_version_string_ptr != nullptr) + return getBridgeInstance().get_version_string_ptr(); +#endif + return nullptr; +} + +// ----------------------------------------------------------------------------- + +jack_client_t* jackbridge_client_open(const char* client_name, uint32_t options, jack_status_t* status) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_client_open(client_name, static_cast(options), status); +#else + #ifndef DISTRHO_OS_WASM + if (getBridgeInstance().client_open_ptr != nullptr) + if (jack_client_t* const client = getBridgeInstance().client_open_ptr(client_name, static_cast(options), status)) + return client; + #endif + + static jack_client_t* const kValidClient = (jack_client_t*)0x1; + + // maybe unused + (void)kValidClient; + + usingNativeBridge = true; + usingRealJACK = false; + + #ifdef DISTRHO_OS_WASM + nativeBridge = new WebBridge; + if (nativeBridge->open(client_name)) + return kValidClient; + delete nativeBridge; + #endif + + #if defined(HAVE_RTAUDIO) && defined(RTAUDIO_API_TYPE) + nativeBridge = new RtAudioBridge; + if (nativeBridge->open(client_name)) + return kValidClient; + delete nativeBridge; + #endif + + #if defined(HAVE_SDL2) && DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + nativeBridge = new SDL2Bridge; + if (nativeBridge->open(client_name)) + return kValidClient; + delete nativeBridge; + #endif +#endif + + if (status != nullptr) + { + int err = JackServerError; + + #if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (nativeBridge != nullptr) + { + err + #ifdef HAVE_JACK + |= + #else + = + #endif + JackBridgeNativeFailed; + } + #endif + + *status = static_cast(err); + } + + return nullptr; +} + +bool jackbridge_client_close(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_client_close(client) == 0); +#else + if (usingNativeBridge) + { + if (nativeBridge != nullptr) + { + nativeBridge->close(); + delete nativeBridge; + nativeBridge = nullptr; + } + usingNativeBridge = false; + usingRealJACK = true; + return true; + } + if (getBridgeInstance().client_close_ptr != nullptr) + return (getBridgeInstance().client_close_ptr(client) == 0); +#endif + return false; +} + +// ----------------------------------------------------------------------------- + +int jackbridge_client_name_size() +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_client_name_size(); +#else + if (usingRealJACK && getBridgeInstance().client_name_size_ptr != nullptr) + return getBridgeInstance().client_name_size_ptr(); +#endif + return 33; +} + +const char* jackbridge_get_client_name(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_client_name(client); +#else + if (usingNativeBridge) + return DISTRHO_PLUGIN_NAME; + if (getBridgeInstance().get_client_name_ptr != nullptr) + return getBridgeInstance().get_client_name_ptr(client); +#endif + return nullptr; +} + +// ----------------------------------------------------------------------------- + +char* jackbridge_client_get_uuid(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_client_get_uuid(client); +#else + if (usingRealJACK) + if (const jacksym_client_get_uuid func = getBridgeInstance().client_get_uuid_ptr) + return func(client); +#endif + return nullptr; +} + +char* jackbridge_get_uuid_for_client_name(jack_client_t* client, const char* name) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_uuid_for_client_name(client, name); +#else + if (usingRealJACK) + if (getBridgeInstance().get_uuid_for_client_name_ptr != nullptr) + return getBridgeInstance().get_uuid_for_client_name_ptr(client, name); +#endif + return nullptr; +} + +char* jackbridge_get_client_name_by_uuid(jack_client_t* client, const char* uuid) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_client_name_by_uuid(client, uuid); +#else + if (usingRealJACK) + if (getBridgeInstance().get_client_name_by_uuid_ptr != nullptr) + return getBridgeInstance().get_client_name_by_uuid_ptr(client, uuid); +#endif + return nullptr; +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_uuid_parse(const char* buf, jack_uuid_t* uuid) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_uuid_parse(buf, uuid) == 0); +#else + if (usingRealJACK) + if (const jacksym_uuid_parse func = getBridgeInstance().uuid_parse_ptr) + return (func(buf, uuid) == 0); +#endif + return false; +} + +void jackbridge_uuid_unparse(jack_uuid_t uuid, char buf[JACK_UUID_STRING_SIZE]) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_uuid_unparse(uuid, buf); +#else + if (usingRealJACK) + if (const jacksym_uuid_unparse func = getBridgeInstance().uuid_unparse_ptr) + return func(uuid, buf); +#endif +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_activate(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_activate(client) == 0); +#else + if (usingNativeBridge) + return nativeBridge->activate(); + if (getBridgeInstance().activate_ptr != nullptr) + return (getBridgeInstance().activate_ptr(client) == 0); +#endif + return false; +} + +bool jackbridge_deactivate(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_deactivate(client) == 0); +#else + if (usingNativeBridge) + return nativeBridge->deactivate(); + if (getBridgeInstance().deactivate_ptr != nullptr) + return (getBridgeInstance().deactivate_ptr(client) == 0); +#endif + return false; +} + +bool jackbridge_is_realtime(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_is_realtime(client); +#else + if (usingRealJACK) + if (getBridgeInstance().is_realtime_ptr != nullptr) + return getBridgeInstance().is_realtime_ptr(client); +#endif + return false; +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_set_thread_init_callback(jack_client_t* client, JackThreadInitCallback thread_init_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_thread_init_callback(client, thread_init_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_thread_init_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_thread_init(thread_init_callback); + return (getBridgeInstance().set_thread_init_callback_ptr(client, WineBridge::thread_init, arg) == 0); +# else + return (getBridgeInstance().set_thread_init_callback_ptr(client, thread_init_callback, arg) == 0); +# endif + } +#endif + return false; +} + +void jackbridge_on_shutdown(jack_client_t* client, JackShutdownCallback shutdown_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_on_shutdown(client, shutdown_callback, arg); +#else + if (usingRealJACK && getBridgeInstance().on_shutdown_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_shutdown(shutdown_callback); + getBridgeInstance().on_shutdown_ptr(client, WineBridge::shutdown, arg); +# else + getBridgeInstance().on_shutdown_ptr(client, shutdown_callback, arg); +# endif + } +#endif +} + +void jackbridge_on_info_shutdown(jack_client_t* client, JackInfoShutdownCallback shutdown_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_on_info_shutdown(client, shutdown_callback, arg); +#else + if (usingRealJACK && getBridgeInstance().on_info_shutdown_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_info_shutdown(shutdown_callback); + getBridgeInstance().on_info_shutdown_ptr(client, WineBridge::info_shutdown, arg); +# else + getBridgeInstance().on_info_shutdown_ptr(client, shutdown_callback, arg); +# endif + } +#endif +} + +bool jackbridge_set_process_callback(jack_client_t* client, JackProcessCallback process_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_process_callback(client, process_callback, arg) == 0); +#else + if (usingNativeBridge) + { + nativeBridge->jackProcessCallback = process_callback; + nativeBridge->jackProcessArg = arg; + return true; + } + if (getBridgeInstance().set_process_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_process(process_callback); + return (getBridgeInstance().set_process_callback_ptr(client, WineBridge::process, arg) == 0); +# else + return (getBridgeInstance().set_process_callback_ptr(client, process_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_freewheel_callback(jack_client_t* client, JackFreewheelCallback freewheel_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_freewheel_callback(client, freewheel_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_freewheel_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_freewheel(freewheel_callback); + return (getBridgeInstance().set_freewheel_callback_ptr(client, WineBridge::freewheel, arg) == 0); +# else + return (getBridgeInstance().set_freewheel_callback_ptr(client, freewheel_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCallback bufsize_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_buffer_size_callback(client, bufsize_callback, arg) == 0); +#else + if (usingNativeBridge) + { + nativeBridge->bufferSizeCallback = bufsize_callback; + nativeBridge->jackBufferSizeArg = arg; + return true; + } + if (getBridgeInstance().set_buffer_size_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_bufsize(bufsize_callback); + return (getBridgeInstance().set_buffer_size_callback_ptr(client, WineBridge::bufsize, arg) == 0); +# else + return (getBridgeInstance().set_buffer_size_callback_ptr(client, bufsize_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_sample_rate_callback(jack_client_t* client, JackSampleRateCallback srate_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_sample_rate_callback(client, srate_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_sample_rate_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_srate(srate_callback); + return (getBridgeInstance().set_sample_rate_callback_ptr(client, WineBridge::srate, arg) == 0); +# else + return (getBridgeInstance().set_sample_rate_callback_ptr(client, srate_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_client_registration_callback(jack_client_t* client, JackClientRegistrationCallback registration_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_client_registration_callback(client, registration_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_client_registration_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_client_reg(registration_callback); + return (getBridgeInstance().set_client_registration_callback_ptr(client, WineBridge::client_reg, arg) == 0); +# else + return (getBridgeInstance().set_client_registration_callback_ptr(client, registration_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_port_registration_callback(jack_client_t* client, JackPortRegistrationCallback registration_callback, void *arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_port_registration_callback(client, registration_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_port_registration_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_port_reg(registration_callback); + return (getBridgeInstance().set_port_registration_callback_ptr(client, WineBridge::port_reg, arg) == 0); +# else + return (getBridgeInstance().set_port_registration_callback_ptr(client, registration_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_port_rename_callback(jack_client_t* client, JackPortRenameCallback rename_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_port_rename_callback(client, rename_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_port_rename_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_port_rename(rename_callback); + return (getBridgeInstance().set_port_rename_callback_ptr(client, WineBridge::port_rename, arg) == 0); +# else + return (getBridgeInstance().set_port_rename_callback_ptr(client, rename_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_port_connect_callback(jack_client_t* client, JackPortConnectCallback connect_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_port_connect_callback(client, connect_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_port_connect_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_port_conn(connect_callback); + return (getBridgeInstance().set_port_connect_callback_ptr(client, WineBridge::port_conn, arg) == 0); +# else + return (getBridgeInstance().set_port_connect_callback_ptr(client, connect_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_graph_order_callback(jack_client_t* client, JackGraphOrderCallback graph_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_graph_order_callback(client, graph_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_graph_order_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_graph_order(graph_callback); + return (getBridgeInstance().set_graph_order_callback_ptr(client, WineBridge::graph_order, arg) == 0); +# else + return (getBridgeInstance().set_graph_order_callback_ptr(client, graph_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_xrun_callback(jack_client_t* client, JackXRunCallback xrun_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_xrun_callback(client, xrun_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_xrun_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_xrun(xrun_callback); + return (getBridgeInstance().set_xrun_callback_ptr(client, WineBridge::xrun, arg) == 0); +# else + return (getBridgeInstance().set_xrun_callback_ptr(client, xrun_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_latency_callback(jack_client_t* client, JackLatencyCallback latency_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_latency_callback(client, latency_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_latency_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_latency(latency_callback); + return (getBridgeInstance().set_latency_callback_ptr(client, WineBridge::latency, arg) == 0); +# else + return (getBridgeInstance().set_latency_callback_ptr(client, latency_callback, arg) == 0); +# endif + } +#endif + return false; +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_set_freewheel(jack_client_t* client, bool onoff) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_set_freewheel(client, onoff); +#else + if (usingRealJACK) + if (getBridgeInstance().set_freewheel_ptr != nullptr) + return getBridgeInstance().set_freewheel_ptr(client, onoff); +#endif + return false; +} + +bool jackbridge_set_buffer_size(jack_client_t* client, jack_nframes_t nframes) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_set_buffer_size(client, nframes); +#else + if (usingNativeBridge) + return nativeBridge->requestBufferSizeChange(nframes); + if (getBridgeInstance().set_buffer_size_ptr != nullptr) + return getBridgeInstance().set_buffer_size_ptr(client, nframes); +#endif + return false; +} + +// ----------------------------------------------------------------------------- + +jack_nframes_t jackbridge_get_sample_rate(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_sample_rate(client); +#else + if (usingNativeBridge) + return nativeBridge->sampleRate; + if (getBridgeInstance().get_sample_rate_ptr != nullptr) + return getBridgeInstance().get_sample_rate_ptr(client); +#endif + return 0; +} + +jack_nframes_t jackbridge_get_buffer_size(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_buffer_size(client); +#else + if (usingNativeBridge) + return nativeBridge->bufferSize; + if (getBridgeInstance().get_buffer_size_ptr != nullptr) + return getBridgeInstance().get_buffer_size_ptr(client); +#endif + return 0; +} + +float jackbridge_cpu_load(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_cpu_load(client); +#else + if (usingRealJACK) + if (getBridgeInstance().cpu_load_ptr != nullptr) + return getBridgeInstance().cpu_load_ptr(client); +#endif + return 0.0f; +} + +// ----------------------------------------------------------------------------- + +jack_port_t* jackbridge_port_register(jack_client_t* client, const char* port_name, const char* type, uint64_t flags, uint64_t buffer_size) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_register(client, port_name, type, flags, buffer_size); +#else + if (usingNativeBridge) + return nativeBridge->registerPort(type, flags); + if (getBridgeInstance().port_register_ptr != nullptr) + return getBridgeInstance().port_register_ptr(client, port_name, type, + static_cast(flags), + static_cast(buffer_size)); +#endif + return nullptr; +} + +bool jackbridge_port_unregister(jack_client_t* client, jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_unregister(client, port) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_unregister_ptr != nullptr) + return (getBridgeInstance().port_unregister_ptr(client, port) == 0); +#endif + return false; +} + +void* jackbridge_port_get_buffer(jack_port_t* port, jack_nframes_t nframes) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_get_buffer(port, nframes); +#else + if (usingNativeBridge) + return nativeBridge->getPortBuffer(port); + if (getBridgeInstance().port_get_buffer_ptr != nullptr) + return getBridgeInstance().port_get_buffer_ptr(port, nframes); +#endif + return nullptr; +} + +// ----------------------------------------------------------------------------- + +const char* jackbridge_port_name(const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_name(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_name_ptr != nullptr) + return getBridgeInstance().port_name_ptr(port); +#endif + return nullptr; +} + +jack_uuid_t jackbridge_port_uuid(const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_uuid(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_uuid_ptr != nullptr) + return getBridgeInstance().port_uuid_ptr(port); +#endif + return 0; +} + +const char* jackbridge_port_short_name(const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_short_name(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_short_name_ptr != nullptr) + return getBridgeInstance().port_short_name_ptr(port); +#endif + return nullptr; +} + +int jackbridge_port_flags(const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_flags(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_flags_ptr != nullptr) + return getBridgeInstance().port_flags_ptr(port); +#endif + return 0x0; +} + +const char* jackbridge_port_type(const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_type(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_type_ptr != nullptr) + return getBridgeInstance().port_type_ptr(port); +#endif + return nullptr; +} + +bool jackbridge_port_is_mine(const jack_client_t* client, const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_is_mine(client, port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_is_mine_ptr != nullptr) + return getBridgeInstance().port_is_mine_ptr(client, port); +#endif + return false; +} + +int jackbridge_port_connected(const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_connected(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_connected_ptr != nullptr) + return getBridgeInstance().port_connected_ptr(port); +#endif + return 0; +} + +bool jackbridge_port_connected_to(const jack_port_t* port, const char* port_name) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_connected_to(port, port_name); +#else + if (usingRealJACK) + if (getBridgeInstance().port_connected_to_ptr != nullptr) + return getBridgeInstance().port_connected_to_ptr(port, port_name); +#endif + return false; +} + +const char** jackbridge_port_get_connections(const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_get_connections(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_get_connections_ptr != nullptr) + return getBridgeInstance().port_get_connections_ptr(port); +#endif + return nullptr; +} + +const char** jackbridge_port_get_all_connections(const jack_client_t* client, const jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_get_all_connections(client, port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_get_all_connections_ptr != nullptr) + return getBridgeInstance().port_get_all_connections_ptr(client, port); +#endif + return nullptr; +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_port_rename(jack_client_t* client, jack_port_t* port, const char* port_name) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_rename(client, port, port_name) == 0); +#else + if (usingNativeBridge) + return false; + // Try new API first + if (getBridgeInstance().port_rename_ptr != nullptr) + return (getBridgeInstance().port_rename_ptr(client, port, port_name) == 0); + // Try old API if using JACK2 + if (getBridgeInstance().get_version_string_ptr != nullptr && getBridgeInstance().port_set_name_ptr != nullptr) + return (getBridgeInstance().port_set_name_ptr(port, port_name) == 0); +#endif + return false; +} + +bool jackbridge_port_set_alias(jack_port_t* port, const char* alias) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_set_alias(port, alias) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_set_alias_ptr != nullptr) + return (getBridgeInstance().port_set_alias_ptr(port, alias) == 0); +#endif + return false; +} + +bool jackbridge_port_unset_alias(jack_port_t* port, const char* alias) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_unset_alias(port, alias) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_unset_alias_ptr != nullptr) + return (getBridgeInstance().port_unset_alias_ptr(port, alias) == 0); +#endif + return false; +} + +int jackbridge_port_get_aliases(const jack_port_t* port, char* const aliases[2]) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_get_aliases(port, aliases) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_get_aliases_ptr != nullptr) + return getBridgeInstance().port_get_aliases_ptr(port, aliases); +#endif + return 0; +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_port_request_monitor(jack_port_t* port, bool onoff) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_request_monitor(port, onoff) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_request_monitor_ptr != nullptr) + return (getBridgeInstance().port_request_monitor_ptr(port, onoff) == 0); +#endif + return false; +} + +bool jackbridge_port_request_monitor_by_name(jack_client_t* client, const char* port_name, bool onoff) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_request_monitor_by_name(client, port_name, onoff) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_request_monitor_by_name_ptr != nullptr) + return (getBridgeInstance().port_request_monitor_by_name_ptr(client, port_name, onoff) == 0); +#endif + return false; +} + +bool jackbridge_port_ensure_monitor(jack_port_t* port, bool onoff) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_ensure_monitor(port, onoff) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_ensure_monitor_ptr != nullptr) + return (getBridgeInstance().port_ensure_monitor_ptr(port, onoff) == 0); +#endif + return false; +} + +bool jackbridge_port_monitoring_input(jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_monitoring_input(port); +#else + if (usingRealJACK) + if (getBridgeInstance().port_monitoring_input_ptr != nullptr) + return getBridgeInstance().port_monitoring_input_ptr(port); +#endif + return false; +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_connect(jack_client_t* client, const char* source_port, const char* destination_port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_connect(client, source_port, destination_port) == 0); +#else + if (usingRealJACK && getBridgeInstance().connect_ptr != nullptr) + { + const int ret = getBridgeInstance().connect_ptr(client, source_port, destination_port); + return ret == 0 || ret == EEXIST; + } +#endif + return false; +} + +bool jackbridge_disconnect(jack_client_t* client, const char* source_port, const char* destination_port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_disconnect(client, source_port, destination_port) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().disconnect_ptr != nullptr) + return (getBridgeInstance().disconnect_ptr(client, source_port, destination_port) == 0); +#endif + return false; +} + +bool jackbridge_port_disconnect(jack_client_t* client, jack_port_t* port) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_port_disconnect(client, port) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().port_disconnect_ptr != nullptr) + return (getBridgeInstance().port_disconnect_ptr(client, port) == 0); +#endif + return false; +} + +// ----------------------------------------------------------------------------- + +int jackbridge_port_name_size() +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_name_size(); +#else + if (usingRealJACK) + if (getBridgeInstance().port_name_size_ptr != nullptr) + return getBridgeInstance().port_name_size_ptr(); +#endif + return 256; +} + +int jackbridge_port_type_size() +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_type_size(); +#else + if (usingRealJACK) + if (getBridgeInstance().port_type_size_ptr != nullptr) + return getBridgeInstance().port_type_size_ptr(); +#endif + return 32; +} + +uint32_t jackbridge_port_type_get_buffer_size(jack_client_t* client, const char* port_type) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return static_cast(jack_port_type_get_buffer_size(client, port_type)); +#else + if (usingRealJACK) + if (getBridgeInstance().port_type_get_buffer_size_ptr != nullptr) + return static_cast(getBridgeInstance().port_type_get_buffer_size_ptr(client, port_type)); +#endif + return 0; +} + +// ----------------------------------------------------------------------------- + +void jackbridge_port_get_latency_range(jack_port_t* port, uint32_t mode, jack_latency_range_t* range) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_get_latency_range(port, static_cast(mode), range); +#else + if (usingRealJACK) + if (getBridgeInstance().port_get_latency_range_ptr != nullptr) + return getBridgeInstance().port_get_latency_range_ptr(port, + static_cast(mode), + range); +#endif + range->min = 0; + range->max = 0; +} + +void jackbridge_port_set_latency_range(jack_port_t* port, uint32_t mode, jack_latency_range_t* range) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_port_set_latency_range(port, static_cast(mode), range); +#else + if (usingRealJACK) + if (getBridgeInstance().port_set_latency_range_ptr != nullptr) + getBridgeInstance().port_set_latency_range_ptr(port, + static_cast(mode), + range); +#endif +} + +bool jackbridge_recompute_total_latencies(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_recompute_total_latencies(client) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().recompute_total_latencies_ptr != nullptr) + return (getBridgeInstance().recompute_total_latencies_ptr(client) == 0); +#endif + return false; +} + +// ----------------------------------------------------------------------------- + +const char** jackbridge_get_ports(jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, uint64_t flags) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_ports(client, port_name_pattern, type_name_pattern, flags); +#else + if (usingRealJACK) + if (getBridgeInstance().get_ports_ptr != nullptr) + return getBridgeInstance().get_ports_ptr(client, port_name_pattern, type_name_pattern, + static_cast(flags)); +#endif + return nullptr; +} + +jack_port_t* jackbridge_port_by_name(jack_client_t* client, const char* port_name) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_by_name(client, port_name); +#else + if (usingRealJACK) + if (getBridgeInstance().port_by_name_ptr != nullptr) + return getBridgeInstance().port_by_name_ptr(client, port_name); +#endif + return nullptr; +} + +jack_port_t* jackbridge_port_by_id(jack_client_t* client, jack_port_id_t port_id) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_port_by_id(client, port_id); +#else + if (usingRealJACK) + if (getBridgeInstance().port_by_id_ptr != nullptr) + return getBridgeInstance().port_by_id_ptr(client, port_id); +#endif + return nullptr; +} + +// ----------------------------------------------------------------------------- + +void jackbridge_free(void* ptr) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_free(ptr); +#else + if (usingRealJACK) + if (getBridgeInstance().free_ptr != nullptr) + return getBridgeInstance().free_ptr(ptr); + + // just in case + std::free(ptr); +#endif +} + +// ----------------------------------------------------------------------------- + +uint32_t jackbridge_midi_get_event_count(void* port_buffer) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_midi_get_event_count(port_buffer); +#else + if (usingNativeBridge) + return nativeBridge->getEventCount(); + if (getBridgeInstance().midi_get_event_count_ptr != nullptr) + return getBridgeInstance().midi_get_event_count_ptr(port_buffer); +#endif + return 0; +} + +bool jackbridge_midi_event_get(jack_midi_event_t* event, void* port_buffer, uint32_t event_index) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_midi_event_get(event, port_buffer, event_index) == 0); +#else + if (usingNativeBridge) + return nativeBridge->getEvent(event); + if (getBridgeInstance().midi_event_get_ptr != nullptr) + return (getBridgeInstance().midi_event_get_ptr(event, port_buffer, event_index) == 0); +#endif + return false; +} + +void jackbridge_midi_clear_buffer(void* port_buffer) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_midi_clear_buffer(port_buffer); +#else + if (usingNativeBridge) + return nativeBridge->clearEventBuffer(); + if (getBridgeInstance().midi_clear_buffer_ptr != nullptr) + getBridgeInstance().midi_clear_buffer_ptr(port_buffer); +#endif +} + +bool jackbridge_midi_event_write(void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, uint32_t data_size) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_midi_event_write(port_buffer, time, data, data_size) == 0); +#else + if (usingNativeBridge) + return nativeBridge->writeEvent(time, data, data_size); + if (getBridgeInstance().midi_event_write_ptr != nullptr) + return (getBridgeInstance().midi_event_write_ptr(port_buffer, time, data, data_size) == 0); +#endif + return false; +} + +jack_midi_data_t* jackbridge_midi_event_reserve(void* port_buffer, jack_nframes_t time, uint32_t data_size) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_midi_event_reserve(port_buffer, time, data_size); +#else + if (usingRealJACK) + if (getBridgeInstance().midi_event_reserve_ptr != nullptr) + return getBridgeInstance().midi_event_reserve_ptr(port_buffer, time, data_size); +#endif + return nullptr; +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_release_timebase(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_release_timebase(client) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().release_timebase_ptr != nullptr) + return (getBridgeInstance().release_timebase_ptr(client) == 0); +#endif + return false; +} + +bool jackbridge_set_sync_callback(jack_client_t* client, JackSyncCallback sync_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_sync_callback(client, sync_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_sync_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_sync(sync_callback); + return (getBridgeInstance().set_sync_callback_ptr(client, WineBridge::sync, arg) == 0); +# else + return (getBridgeInstance().set_sync_callback_ptr(client, sync_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_sync_timeout(jack_client_t* client, jack_time_t timeout) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_sync_timeout(client, timeout) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().set_sync_timeout_ptr != nullptr) + return (getBridgeInstance().set_sync_timeout_ptr(client, timeout) == 0); +#endif + return false; +} + +bool jackbridge_set_timebase_callback(jack_client_t* client, bool conditional, JackTimebaseCallback timebase_callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_timebase_callback(client, conditional, timebase_callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_timebase_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_timebase(timebase_callback); + return (getBridgeInstance().set_timebase_callback_ptr(client, conditional, WineBridge::timebase, arg) == 0); +# else + return (getBridgeInstance().set_timebase_callback_ptr(client, conditional, timebase_callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_transport_locate(jack_client_t* client, jack_nframes_t frame) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_transport_locate(client, frame) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().transport_locate_ptr != nullptr) + return (getBridgeInstance().transport_locate_ptr(client, frame) == 0); +#endif + return false; +} + +uint32_t jackbridge_transport_query(const jack_client_t* client, jack_position_t* pos) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_transport_query(client, pos); +#else + if (usingRealJACK) + if (getBridgeInstance().transport_query_ptr != nullptr) + return getBridgeInstance().transport_query_ptr(client, pos); +#endif + if (pos != nullptr) + { + // invalidate + std::memset(pos, 0, sizeof(*pos)); + pos->unique_1 = 0; + pos->unique_2 = 1; + } + return JackTransportStopped; +} + +jack_nframes_t jackbridge_get_current_transport_frame(const jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_get_current_transport_frame(client); +#else + if (usingRealJACK) + if (getBridgeInstance().get_current_transport_frame_ptr != nullptr) + return getBridgeInstance().get_current_transport_frame_ptr(client); +#endif + return 0; +} + +bool jackbridge_transport_reposition(jack_client_t* client, const jack_position_t* pos) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_transport_reposition(client, pos) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().transport_reposition_ptr != nullptr) + return (getBridgeInstance().transport_reposition_ptr(client, pos) == 0); +#endif + return false; +} + +void jackbridge_transport_start(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_transport_start(client); +#else + if (usingRealJACK) + if (getBridgeInstance().transport_start_ptr != nullptr) + getBridgeInstance().transport_start_ptr(client); +#endif +} + +void jackbridge_transport_stop(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_transport_stop(client); +#else + if (usingRealJACK) + if (getBridgeInstance().transport_stop_ptr != nullptr) + getBridgeInstance().transport_stop_ptr(client); +#endif +} + +// ----------------------------------------------------------------------------- + +bool jackbridge_set_property(jack_client_t* client, jack_uuid_t subject, const char* key, const char* value, const char* type) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_property(client, subject, key, value, type) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().set_property_ptr != nullptr) + return (getBridgeInstance().set_property_ptr(client, subject, key, value, type) == 0); +#endif + return false; +} + +bool jackbridge_get_property(jack_uuid_t subject, const char* key, char** value, char** type) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_get_property(subject, key, value, type) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().get_property_ptr != nullptr) + return (getBridgeInstance().get_property_ptr(subject, key, value, type) == 0); +#endif + return false; +} + +void jackbridge_free_description(jack_description_t* desc, bool free_description_itself) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_free_description(desc, free_description_itself); +#else + if (usingRealJACK) + if (getBridgeInstance().free_description_ptr != nullptr) + getBridgeInstance().free_description_ptr(desc, free_description_itself); +#endif +} + +bool jackbridge_get_properties(jack_uuid_t subject, jack_description_t* desc) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_get_properties(subject, desc) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().get_properties_ptr != nullptr) + return (getBridgeInstance().get_properties_ptr(subject, desc) == 0); +#endif + return false; +} + +bool jackbridge_get_all_properties(jack_description_t** descs) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_get_all_properties(descs) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().get_all_properties_ptr != nullptr) + return (getBridgeInstance().get_all_properties_ptr(descs) == 0); +#endif + return false; +} + +bool jackbridge_remove_property(jack_client_t* client, jack_uuid_t subject, const char* key) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_remove_property(client, subject, key) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().remove_property_ptr != nullptr) + return (getBridgeInstance().remove_property_ptr(client, subject, key) == 0); +#endif + return false; +} + +int jackbridge_remove_properties(jack_client_t* client, jack_uuid_t subject) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_remove_properties(client, subject); +#else + if (usingRealJACK) + if (getBridgeInstance().remove_properties_ptr != nullptr) + return getBridgeInstance().remove_properties_ptr(client, subject); +#endif + return 0; +} + +bool jackbridge_remove_all_properties(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_remove_all_properties(client) == 0); +#else + if (usingRealJACK) + if (getBridgeInstance().remove_all_properties_ptr != nullptr) + return (getBridgeInstance().remove_all_properties_ptr(client) == 0); +#endif + return false; +} + +bool jackbridge_set_property_change_callback(jack_client_t* client, JackPropertyChangeCallback callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_property_change_callback(client, callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_property_change_callback_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_prop_change(callback); + return (getBridgeInstance().set_property_change_callback_ptr(client, WineBridge::prop_change, arg) == 0); +# else + return (getBridgeInstance().set_property_change_callback_ptr(client, callback, arg) == 0); +# endif + } +#endif + return false; +} + +bool jackbridge_set_process_thread(jack_client_t* client, JackThreadCallback callback, void* arg) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return (jack_set_process_thread(client, callback, arg) == 0); +#else + if (usingRealJACK && getBridgeInstance().set_process_thread_ptr != nullptr) + { +# ifdef __WINE__ + WineBridge::getInstance().set_process_thread(callback); + return (getBridgeInstance().set_process_thread_ptr(client, WineBridge::process_thread, arg) == 0); +# else + return (getBridgeInstance().set_process_thread_ptr(client, callback, arg) == 0); +# endif + } +#endif + return false; +} + +jack_nframes_t jackbridge_cycle_wait(jack_client_t* client) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + return jack_cycle_wait(client); +#else + if (usingRealJACK) + if (getBridgeInstance().cycle_wait_ptr != nullptr) + return getBridgeInstance().cycle_wait_ptr(client); +#endif + return 0; +} + +void jackbridge_cycle_signal(jack_client_t* client, int status) +{ +#if defined(JACKBRIDGE_DUMMY) +#elif defined(JACKBRIDGE_DIRECT) + jack_cycle_signal(client, status); +#else + if (usingRealJACK) + if (getBridgeInstance().cycle_signal_ptr != nullptr) + getBridgeInstance().cycle_signal_ptr(client, status); +#endif +} + +// ----------------------------------------------------------------------------- + +#ifndef JACKBRIDGE_SKIP_NATIVE_UTILS + +START_NAMESPACE_DISTRHO + +bool isUsingNativeAudio() noexcept +{ +#if defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT) + return false; +#else + return usingNativeBridge; +#endif +} + +bool supportsAudioInput() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->supportsAudioInput(); +#endif + return false; +} + +bool supportsBufferSizeChanges() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->supportsBufferSizeChanges(); +#endif + return false; +} + +bool supportsMIDI() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->supportsMIDI(); +#endif + return false; +} + +bool isAudioInputEnabled() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->isAudioInputEnabled(); +#endif + return false; +} + +bool isMIDIEnabled() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->isMIDIEnabled(); +#endif + return false; +} + +uint getBufferSize() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->getBufferSize(); +#endif + return 0; +} + +bool requestAudioInput() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->requestAudioInput(); +#endif + return false; +} + +bool requestBufferSizeChange(const uint newBufferSize) +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->requestBufferSizeChange(newBufferSize); +#endif + return false; +} + +bool requestMIDI() +{ +#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT)) + if (usingNativeBridge) + return nativeBridge->requestMIDI(); +#endif + return false; +} + +END_NAMESPACE_DISTRHO + +#endif // JACKBRIDGE_SKIP_NATIVE_UTILS + +// ----------------------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/JackBridge.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/JackBridge.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,417 @@ +/* + * JackBridge for DPF + * Copyright (C) 2013-2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef JACKBRIDGE_HPP_INCLUDED +#define JACKBRIDGE_HPP_INCLUDED + +#ifdef __WINE__ +# if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +# define __WINE64__ +# endif +# undef WIN32 +# undef WIN64 +# undef _WIN32 +# undef _WIN64 +# undef __WIN32__ +# undef __WIN64__ +#endif + +#include "../DistrhoDefines.h" + +#if (defined(__WINE__) || defined(DISTRHO_OS_WINDOWS)) && defined(__cdecl) +# define JACKBRIDGE_API __cdecl +#else +# define JACKBRIDGE_API +#endif + +#ifdef JACKBRIDGE_DIRECT +# include +# include +# include +# include +# include +# include +#else + +#include + +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +# include +#else +# include +#endif + +#ifndef POST_PACKED_STRUCTURE +# if defined(__GNUC__) + /* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. + */ + #define PRE_PACKED_STRUCTURE + #define POST_PACKED_STRUCTURE __attribute__((__packed__)) +# elif defined(_MSC_VER) + #define PRE_PACKED_STRUCTURE1 __pragma(pack(push,1)) + #define PRE_PACKED_STRUCTURE PRE_PACKED_STRUCTURE1 + /* PRE_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the following structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. + */ + #define POST_PACKED_STRUCTURE ;__pragma(pack(pop)) + /* and POST_PACKED_STRUCTURE needs to be a macro which + restores the packing to its previous setting */ +# else + #define PRE_PACKED_STRUCTURE + #define POST_PACKED_STRUCTURE +# endif +#endif + +#define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" +#define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi" + +#define JACK_MAX_FRAMES (4294967295U) + +#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) +#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) + +#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode|JackBBTFrameOffset|JackAudioVideoRatio|JackVideoFrameOffset) +#define EXTENDED_TIME_INFO + +#define JACK_UUID_SIZE 36 +#define JACK_UUID_STRING_SIZE (JACK_UUID_SIZE+1) /* includes trailing null */ +#define JACK_UUID_EMPTY_INITIALIZER 0 + +#define JACK_TICK_DOUBLE + +extern "C" { + +enum JackOptions { + JackNullOption = 0x00, + JackNoStartServer = 0x01, + JackUseExactName = 0x02, + JackServerName = 0x04, + JackLoadName = 0x08, + JackLoadInit = 0x10, + JackSessionID = 0x20 +}; + +enum JackStatus { + JackFailure = 0x0001, + JackInvalidOption = 0x0002, + JackNameNotUnique = 0x0004, + JackServerStarted = 0x0008, + JackServerFailed = 0x0010, + JackServerError = 0x0020, + JackNoSuchClient = 0x0040, + JackLoadFailure = 0x0080, + JackInitFailure = 0x0100, + JackShmFailure = 0x0200, + JackVersionError = 0x0400, + JackBackendError = 0x0800, + JackClientZombie = 0x1000, + JackBridgeNativeFailed = 0x10000 +}; + +enum JackLatencyCallbackMode { + JackCaptureLatency, + JackPlaybackLatency +}; + +enum JackPortFlags { + JackPortIsInput = 0x01, + JackPortIsOutput = 0x02, + JackPortIsPhysical = 0x04, + JackPortCanMonitor = 0x08, + JackPortIsTerminal = 0x10, + JackPortIsControlVoltage = 0x100 +}; + +enum JackTransportState { + JackTransportStopped = 0, + JackTransportRolling = 1, + JackTransportLooping = 2, + JackTransportStarting = 3 +}; + +enum JackPositionBits { + JackPositionBBT = 0x010, + JackPositionTimecode = 0x020, + JackBBTFrameOffset = 0x040, + JackAudioVideoRatio = 0x080, + JackVideoFrameOffset = 0x100, + JackTickDouble = 0x200 +}; + +enum JackSessionEventType { + JackSessionSave = 1, + JackSessionSaveAndQuit = 2, + JackSessionSaveTemplate = 3 +}; + +enum JackSessionFlags { + JackSessionSaveError = 0x1, + JackSessionNeedTerminal = 0x2 +}; + +enum JackPropertyChange { + PropertyCreated, + PropertyChanged, + PropertyDeleted +}; + +typedef uint32_t jack_nframes_t; +typedef uint32_t jack_port_id_t; +typedef uint64_t jack_time_t; +typedef uint64_t jack_uuid_t; +typedef uint64_t jack_unique_t; +typedef uchar jack_midi_data_t; +typedef float jack_default_audio_sample_t; + +typedef enum JackOptions jack_options_t; +typedef enum JackStatus jack_status_t; +typedef enum JackLatencyCallbackMode jack_latency_callback_mode_t; +typedef enum JackTransportState jack_transport_state_t; +typedef enum JackPositionBits jack_position_bits_t; +typedef enum JackSessionEventType jack_session_event_type_t; +typedef enum JackSessionFlags jack_session_flags_t; +typedef enum JackPropertyChange jack_property_change_t; + +struct _jack_midi_event { + jack_nframes_t time; + size_t size; + jack_midi_data_t* buffer; +}; + +// NOTE: packed in JACK2 but not in JACK1 +PRE_PACKED_STRUCTURE +struct _jack_latency_range { + jack_nframes_t min; + jack_nframes_t max; +} POST_PACKED_STRUCTURE; + +PRE_PACKED_STRUCTURE +struct _jack_position { + jack_unique_t unique_1; + jack_time_t usecs; + jack_nframes_t frame_rate; + jack_nframes_t frame; + jack_position_bits_t valid; + int32_t bar; + int32_t beat; + int32_t tick; + double bar_start_tick; + float beats_per_bar; + float beat_type; + double ticks_per_beat; + double beats_per_minute; + double frame_time; + double next_time; + jack_nframes_t bbt_offset; + float audio_frames_per_video_frame; + jack_nframes_t video_offset; + double tick_double; + int32_t padding[5]; + jack_unique_t unique_2; +} POST_PACKED_STRUCTURE; + +struct _jack_session_event { + jack_session_event_type_t type; + const char* session_dir; + const char* client_uuid; + char* command_line; + jack_session_flags_t flags; + uint32_t future; +}; + +struct _jack_session_command_t { + const char* uuid; + const char* client_name; + const char* command; + jack_session_flags_t flags; +}; + +typedef struct { + const char* key; + const char* data; + const char* type; +} jack_property_t; + +typedef struct { + jack_uuid_t subject; + uint32_t property_cnt; + jack_property_t* properties; + uint32_t property_size; +} jack_description_t; + +typedef struct _jack_port jack_port_t; +typedef struct _jack_client jack_client_t; +typedef struct _jack_midi_event jack_midi_event_t; +typedef struct _jack_latency_range jack_latency_range_t; +typedef struct _jack_position jack_position_t; +typedef struct _jack_session_event jack_session_event_t; +typedef struct _jack_session_command_t jack_session_command_t; + +typedef void (JACKBRIDGE_API *JackLatencyCallback)(jack_latency_callback_mode_t mode, void* arg); +typedef int (JACKBRIDGE_API *JackProcessCallback)(jack_nframes_t nframes, void* arg); +typedef void (JACKBRIDGE_API *JackThreadInitCallback)(void* arg); +typedef int (JACKBRIDGE_API *JackGraphOrderCallback)(void* arg); +typedef int (JACKBRIDGE_API *JackXRunCallback)(void* arg); +typedef int (JACKBRIDGE_API *JackBufferSizeCallback)(jack_nframes_t nframes, void* arg); +typedef int (JACKBRIDGE_API *JackSampleRateCallback)(jack_nframes_t nframes, void* arg); +typedef void (JACKBRIDGE_API *JackPortRegistrationCallback)(jack_port_id_t port, int register_, void* arg); +typedef void (JACKBRIDGE_API *JackClientRegistrationCallback)(const char* name, int register_, void* arg); +typedef void (JACKBRIDGE_API *JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); +typedef void (JACKBRIDGE_API *JackPortRenameCallback)(jack_port_id_t port, const char* old_name, const char* new_name, void* arg); +typedef void (JACKBRIDGE_API *JackFreewheelCallback)(int starting, void* arg); +typedef void (JACKBRIDGE_API *JackShutdownCallback)(void* arg); +typedef void (JACKBRIDGE_API *JackInfoShutdownCallback)(jack_status_t code, const char* reason, void* arg); +typedef int (JACKBRIDGE_API *JackSyncCallback)(jack_transport_state_t state, jack_position_t* pos, void* arg); +typedef void (JACKBRIDGE_API *JackTimebaseCallback)(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg); +typedef void (JACKBRIDGE_API *JackSessionCallback)(jack_session_event_t* event, void* arg); +typedef void (JACKBRIDGE_API *JackPropertyChangeCallback)(jack_uuid_t subject, const char* key, jack_property_change_t change, void* arg); +typedef void *(JACKBRIDGE_API *JackThreadCallback)(void* arg); + +} // extern "C" + +#endif // ! JACKBRIDGE_DIRECT + +JACKBRIDGE_API bool jackbridge_is_ok() noexcept; +JACKBRIDGE_API void jackbridge_init(); + +JACKBRIDGE_API void jackbridge_get_version(int* major_ptr, int* minor_ptr, int* micro_ptr, int* proto_ptr); +JACKBRIDGE_API const char* jackbridge_get_version_string(); + +JACKBRIDGE_API jack_client_t* jackbridge_client_open(const char* client_name, uint32_t options, jack_status_t* status); +JACKBRIDGE_API bool jackbridge_client_close(jack_client_t* client); + +JACKBRIDGE_API int jackbridge_client_name_size(); +JACKBRIDGE_API const char* jackbridge_get_client_name(jack_client_t* client); + +JACKBRIDGE_API char* jackbridge_client_get_uuid(jack_client_t* client); +JACKBRIDGE_API char* jackbridge_get_uuid_for_client_name(jack_client_t* client, const char* name); +JACKBRIDGE_API char* jackbridge_get_client_name_by_uuid(jack_client_t* client, const char* uuid); + +JACKBRIDGE_API bool jackbridge_uuid_parse(const char* buf, jack_uuid_t* uuid); +JACKBRIDGE_API void jackbridge_uuid_unparse(jack_uuid_t uuid, char buf[JACK_UUID_STRING_SIZE]); + +JACKBRIDGE_API bool jackbridge_activate(jack_client_t* client); +JACKBRIDGE_API bool jackbridge_deactivate(jack_client_t* client); +JACKBRIDGE_API bool jackbridge_is_realtime(jack_client_t* client); + +JACKBRIDGE_API bool jackbridge_set_thread_init_callback(jack_client_t* client, JackThreadInitCallback thread_init_callback, void* arg); +JACKBRIDGE_API void jackbridge_on_shutdown(jack_client_t* client, JackShutdownCallback shutdown_callback, void* arg); +JACKBRIDGE_API void jackbridge_on_info_shutdown(jack_client_t* client, JackInfoShutdownCallback shutdown_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_process_callback(jack_client_t* client, JackProcessCallback process_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_freewheel_callback(jack_client_t* client, JackFreewheelCallback freewheel_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCallback bufsize_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_sample_rate_callback(jack_client_t* client, JackSampleRateCallback srate_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_client_registration_callback(jack_client_t* client, JackClientRegistrationCallback registration_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_port_registration_callback(jack_client_t* client, JackPortRegistrationCallback registration_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_port_rename_callback(jack_client_t* client, JackPortRenameCallback rename_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_port_connect_callback(jack_client_t* client, JackPortConnectCallback connect_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_graph_order_callback(jack_client_t* client, JackGraphOrderCallback graph_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_xrun_callback(jack_client_t* client, JackXRunCallback xrun_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_latency_callback(jack_client_t* client, JackLatencyCallback latency_callback, void* arg); + +JACKBRIDGE_API bool jackbridge_set_freewheel(jack_client_t* client, bool onoff); +JACKBRIDGE_API bool jackbridge_set_buffer_size(jack_client_t* client, jack_nframes_t nframes); + +JACKBRIDGE_API jack_nframes_t jackbridge_get_sample_rate(jack_client_t* client); +JACKBRIDGE_API jack_nframes_t jackbridge_get_buffer_size(jack_client_t* client); +JACKBRIDGE_API float jackbridge_cpu_load(jack_client_t* client); + +JACKBRIDGE_API jack_port_t* jackbridge_port_register(jack_client_t* client, const char* port_name, const char* port_type, uint64_t flags, uint64_t buffer_size); +JACKBRIDGE_API bool jackbridge_port_unregister(jack_client_t* client, jack_port_t* port); +JACKBRIDGE_API void* jackbridge_port_get_buffer(jack_port_t* port, jack_nframes_t nframes); + +JACKBRIDGE_API const char* jackbridge_port_name(const jack_port_t* port); +JACKBRIDGE_API jack_uuid_t jackbridge_port_uuid(const jack_port_t* port); +JACKBRIDGE_API const char* jackbridge_port_short_name(const jack_port_t* port); +JACKBRIDGE_API int jackbridge_port_flags(const jack_port_t* port); +JACKBRIDGE_API const char* jackbridge_port_type(const jack_port_t* port); +JACKBRIDGE_API bool jackbridge_port_is_mine(const jack_client_t* client, const jack_port_t* port); +JACKBRIDGE_API int jackbridge_port_connected(const jack_port_t* port); +JACKBRIDGE_API bool jackbridge_port_connected_to(const jack_port_t* port, const char* port_name); +JACKBRIDGE_API const char** jackbridge_port_get_connections(const jack_port_t* port); +JACKBRIDGE_API const char** jackbridge_port_get_all_connections(const jack_client_t* client, const jack_port_t* port); + +JACKBRIDGE_API bool jackbridge_port_rename(jack_client_t* client, jack_port_t* port, const char* port_name); +JACKBRIDGE_API bool jackbridge_port_set_alias(jack_port_t* port, const char* alias); +JACKBRIDGE_API bool jackbridge_port_unset_alias(jack_port_t* port, const char* alias); +JACKBRIDGE_API int jackbridge_port_get_aliases(const jack_port_t* port, char* const al[2]); + +JACKBRIDGE_API bool jackbridge_port_request_monitor(jack_port_t* port, bool onoff); +JACKBRIDGE_API bool jackbridge_port_request_monitor_by_name(jack_client_t* client, const char* port_name, bool onoff); +JACKBRIDGE_API bool jackbridge_port_ensure_monitor(jack_port_t* port, bool onoff); +JACKBRIDGE_API bool jackbridge_port_monitoring_input(jack_port_t* port); + +JACKBRIDGE_API bool jackbridge_connect(jack_client_t* client, const char* source_port, const char* destination_port); +JACKBRIDGE_API bool jackbridge_disconnect(jack_client_t* client, const char* source_port, const char* destination_port); +JACKBRIDGE_API bool jackbridge_port_disconnect(jack_client_t* client, jack_port_t* port); + +JACKBRIDGE_API int jackbridge_port_name_size(); +JACKBRIDGE_API int jackbridge_port_type_size(); +JACKBRIDGE_API uint32_t jackbridge_port_type_get_buffer_size(jack_client_t* client, const char* port_type); + +JACKBRIDGE_API void jackbridge_port_get_latency_range(jack_port_t* port, uint32_t mode, jack_latency_range_t* range); +JACKBRIDGE_API void jackbridge_port_set_latency_range(jack_port_t* port, uint32_t mode, jack_latency_range_t* range); +JACKBRIDGE_API bool jackbridge_recompute_total_latencies(jack_client_t* client); + +JACKBRIDGE_API const char** jackbridge_get_ports(jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, uint64_t flags); +JACKBRIDGE_API jack_port_t* jackbridge_port_by_name(jack_client_t* client, const char* port_name); +JACKBRIDGE_API jack_port_t* jackbridge_port_by_id(jack_client_t* client, jack_port_id_t port_id); + +JACKBRIDGE_API void jackbridge_free(void* ptr); + +JACKBRIDGE_API uint32_t jackbridge_midi_get_event_count(void* port_buffer); +JACKBRIDGE_API bool jackbridge_midi_event_get(jack_midi_event_t* event, void* port_buffer, uint32_t event_index); +JACKBRIDGE_API void jackbridge_midi_clear_buffer(void* port_buffer); +JACKBRIDGE_API bool jackbridge_midi_event_write(void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, uint32_t data_size); +JACKBRIDGE_API jack_midi_data_t* jackbridge_midi_event_reserve(void* port_buffer, jack_nframes_t time, uint32_t data_size); + +JACKBRIDGE_API bool jackbridge_release_timebase(jack_client_t* client); +JACKBRIDGE_API bool jackbridge_set_sync_callback(jack_client_t* client, JackSyncCallback sync_callback, void* arg); +JACKBRIDGE_API bool jackbridge_set_sync_timeout(jack_client_t* client, jack_time_t timeout); +JACKBRIDGE_API bool jackbridge_set_timebase_callback(jack_client_t* client, bool conditional, JackTimebaseCallback timebase_callback, void* arg); +JACKBRIDGE_API bool jackbridge_transport_locate(jack_client_t* client, jack_nframes_t frame); + +JACKBRIDGE_API uint32_t jackbridge_transport_query(const jack_client_t* client, jack_position_t* pos); +JACKBRIDGE_API jack_nframes_t jackbridge_get_current_transport_frame(const jack_client_t* client); + +JACKBRIDGE_API bool jackbridge_transport_reposition(jack_client_t* client, const jack_position_t* pos); +JACKBRIDGE_API void jackbridge_transport_start(jack_client_t* client); +JACKBRIDGE_API void jackbridge_transport_stop(jack_client_t* client); + +JACKBRIDGE_API bool jackbridge_set_property(jack_client_t* client, jack_uuid_t subject, const char* key, const char* value, const char* type); +JACKBRIDGE_API bool jackbridge_get_property(jack_uuid_t subject, const char* key, char** value, char** type); +JACKBRIDGE_API void jackbridge_free_description(jack_description_t* desc, bool free_description_itself); +JACKBRIDGE_API bool jackbridge_get_properties(jack_uuid_t subject, jack_description_t* desc); +JACKBRIDGE_API bool jackbridge_get_all_properties(jack_description_t** descs); +JACKBRIDGE_API bool jackbridge_remove_property(jack_client_t* client, jack_uuid_t subject, const char* key); +JACKBRIDGE_API int jackbridge_remove_properties(jack_client_t* client, jack_uuid_t subject); +JACKBRIDGE_API bool jackbridge_remove_all_properties(jack_client_t* client); +JACKBRIDGE_API bool jackbridge_set_property_change_callback(jack_client_t* client, JackPropertyChangeCallback callback, void* arg); + +JACKBRIDGE_API bool jackbridge_set_process_thread(jack_client_t* client, JackThreadCallback callback, void* arg); +JACKBRIDGE_API jack_nframes_t jackbridge_cycle_wait(jack_client_t* client); +JACKBRIDGE_API void jackbridge_cycle_signal(jack_client_t* client, int status); + +#endif // JACKBRIDGE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/NativeBridge.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/NativeBridge.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,329 @@ +/* + * Native Bridge for DPF + * Copyright (C) 2021-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef NATIVE_BRIDGE_HPP_INCLUDED +#define NATIVE_BRIDGE_HPP_INCLUDED + +#include "JackBridge.hpp" + +#include "../../extra/RingBuffer.hpp" + +#if DISTRHO_PLUGIN_NUM_INPUTS > 2 +# define DISTRHO_PLUGIN_NUM_INPUTS_2 2 +#else +# define DISTRHO_PLUGIN_NUM_INPUTS_2 DISTRHO_PLUGIN_NUM_INPUTS +#endif + +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 2 +# define DISTRHO_PLUGIN_NUM_OUTPUTS_2 2 +#else +# define DISTRHO_PLUGIN_NUM_OUTPUTS_2 DISTRHO_PLUGIN_NUM_OUTPUTS +#endif + +using DISTRHO_NAMESPACE::HeapRingBuffer; + +struct NativeBridge { + // Current status information + uint bufferSize; + uint sampleRate; + + // Port caching information + uint numAudioIns; + uint numAudioOuts; + uint numCvIns; + uint numCvOuts; + uint numMidiIns; + uint numMidiOuts; + + // JACK callbacks + JackProcessCallback jackProcessCallback = nullptr; + JackBufferSizeCallback bufferSizeCallback = nullptr; + void* jackProcessArg = nullptr; + void* jackBufferSizeArg = nullptr; + + // Runtime buffers + enum PortMask { + kPortMaskAudio = 0x1000, + kPortMaskCV = 0x2000, + kPortMaskMIDI = 0x4000, + kPortMaskInput = 0x10000, + kPortMaskOutput = 0x20000, + kPortMaskInputMIDI = kPortMaskInput|kPortMaskMIDI, + kPortMaskOutputMIDI = kPortMaskOutput|kPortMaskMIDI, + }; +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + float* audioBuffers[DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS]; + float* audioBufferStorage; +#endif +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + bool midiAvailable; +#endif +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + static constexpr const uint32_t kMaxMIDIInputMessageSize = 3; + uint8_t midiDataStorage[kMaxMIDIInputMessageSize]; + HeapRingBuffer midiInBufferCurrent; + HeapRingBuffer midiInBufferPending; +#endif +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + HeapRingBuffer midiOutBuffer; +#endif + + NativeBridge() + : bufferSize(0), + sampleRate(0), + numAudioIns(0), + numAudioOuts(0), + numCvIns(0), + numCvOuts(0), + numMidiIns(0), + numMidiOuts(0), + jackProcessCallback(nullptr), + bufferSizeCallback(nullptr), + jackProcessArg(nullptr), + jackBufferSizeArg(nullptr) + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + , audioBuffers() + , audioBufferStorage(nullptr) + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + , midiAvailable(false) + #endif + { + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + std::memset(audioBuffers, 0, sizeof(audioBuffers)); + #endif + } + + virtual ~NativeBridge() {} + virtual bool open(const char* const clientName) = 0; + virtual bool close() = 0; + virtual bool activate() = 0; + virtual bool deactivate() = 0; + + virtual bool supportsAudioInput() const + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return true; + #else + return false; + #endif + } + + virtual bool isAudioInputEnabled() const + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return true; + #else + return false; + #endif + } + + virtual bool supportsBufferSizeChanges() const { return false; } + virtual bool isMIDIEnabled() const { return false; } + virtual bool requestAudioInput() { return false; } + virtual bool requestBufferSizeChange(uint32_t) { return false; } + virtual bool requestMIDI() { return false; } + + uint32_t getBufferSize() const noexcept + { + return bufferSize; + } + + bool supportsMIDI() const noexcept + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + return midiAvailable; + #else + return false; + #endif + } + + uint32_t getEventCount() + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (midiAvailable) + { + // NOTE: this function is only called once per run + midiInBufferCurrent.copyFromAndClearOther(midiInBufferPending); + return midiInBufferCurrent.getReadableDataSize() / (kMaxMIDIInputMessageSize + 1u); + } + #endif + + return 0; + } + + bool getEvent(jack_midi_event_t* const event) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + // NOTE: this function is called for all events in index succession + if (midiAvailable && midiInBufferCurrent.getReadableDataSize() >= (kMaxMIDIInputMessageSize + 1u)) + { + event->time = 0; // TODO + event->size = midiInBufferCurrent.readByte(); + event->buffer = midiDataStorage; + return midiInBufferCurrent.readCustomData(midiDataStorage, kMaxMIDIInputMessageSize); + } + #endif + return false; + // maybe unused + (void)event; + } + + void clearEventBuffer() + { + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if (midiAvailable) + midiOutBuffer.clearData(); + #endif + } + + bool writeEvent(const jack_nframes_t time, const jack_midi_data_t* const data, const uint32_t size) + { + if (size > 3) + return false; + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if (midiAvailable) + { + if (midiOutBuffer.writeByte(size) && midiOutBuffer.writeCustomData(data, size)) + { + bool fail = false; + // align + switch (size) + { + case 1: fail |= !midiOutBuffer.writeByte(0); + // fall-through + case 2: fail |= !midiOutBuffer.writeByte(0); + } + fail |= !midiOutBuffer.writeUInt(time); + midiOutBuffer.commitWrite(); + return !fail; + } + midiOutBuffer.commitWrite(); + } + #endif + + return false; + // maybe unused + (void)data; + (void)time; + } + + void allocBuffers(const bool audio, const bool midi) + { + DISTRHO_SAFE_ASSERT_RETURN(bufferSize != 0,); + + if (audio) + { + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + audioBufferStorage = new float[bufferSize*(DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS)]; + + for (uint i=0; i 0 + std::memset(audioBufferStorage, 0, sizeof(float)*bufferSize*DISTRHO_PLUGIN_NUM_INPUTS); + #endif + } + + if (midi) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + midiInBufferCurrent.createBuffer(kMaxMIDIInputMessageSize * 512); + midiInBufferPending.createBuffer(kMaxMIDIInputMessageSize * 512); + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + midiOutBuffer.createBuffer(2048); + #endif + } + } + + void freeBuffers() + { + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + delete[] audioBufferStorage; + audioBufferStorage = nullptr; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + midiInBufferCurrent.deleteBuffer(); + midiInBufferPending.deleteBuffer(); + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + midiOutBuffer.deleteBuffer(); + #endif + } + + jack_port_t* registerPort(const char* const type, const ulong flags) + { + uintptr_t ret = 0; + + /**/ if (flags & JackPortIsInput) + ret |= kPortMaskInput; + else if (flags & JackPortIsOutput) + ret |= kPortMaskOutput; + else + return nullptr; + + /**/ if (std::strcmp(type, JACK_DEFAULT_AUDIO_TYPE) == 0) + { + if (flags & JackPortIsControlVoltage) + { + ret |= kPortMaskAudio; + ret += flags & JackPortIsInput ? numAudioIns++ : numAudioOuts++; + } + else + { + ret |= kPortMaskCV; + ret += flags & JackPortIsInput ? numCvIns++ : numCvOuts++; + } + } + else if (std::strcmp(type, JACK_DEFAULT_MIDI_TYPE) == 0) + { + ret |= kPortMaskMIDI; + ret += flags & JackPortIsInput ? numMidiIns++ : numMidiOuts++; + } + else + { + return nullptr; + } + + return (jack_port_t*)ret; + } + + void* getPortBuffer(jack_port_t* const port) + { + const uintptr_t portMask = (uintptr_t)port; + DISTRHO_SAFE_ASSERT_RETURN(portMask != 0x0, nullptr); + + #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (portMask & (kPortMaskAudio|kPortMaskCV)) + return audioBuffers[(portMask & kPortMaskInput ? 0 : DISTRHO_PLUGIN_NUM_INPUTS) + (portMask & 0x0fff)]; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + if ((portMask & kPortMaskInputMIDI) == kPortMaskInputMIDI) + return (void*)0x1; + #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if ((portMask & kPortMaskOutputMIDI) == kPortMaskOutputMIDI) + return (void*)0x2; + #endif + + return nullptr; + } +}; + +#endif // NATIVE_BRIDGE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/RtAudioBridge.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/RtAudioBridge.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,417 @@ +/* + * RtAudio Bridge for DPF + * Copyright (C) 2021-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef RTAUDIO_BRIDGE_HPP_INCLUDED +#define RTAUDIO_BRIDGE_HPP_INCLUDED + +#include "NativeBridge.hpp" + +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS == 0 +# error RtAudio without audio does not make sense +#endif + +#if defined(DISTRHO_OS_MAC) +# define __MACOSX_CORE__ +# define RTAUDIO_API_TYPE MACOSX_CORE +# define RTMIDI_API_TYPE MACOSX_CORE +#elif defined(DISTRHO_OS_WINDOWS) && !defined(_MSC_VER) +# define __WINDOWS_WASAPI__ +# define __WINDOWS_MM__ +# define RTAUDIO_API_TYPE WINDOWS_WASAPI +# define RTMIDI_API_TYPE WINDOWS_MM +#else +# if defined(HAVE_PULSEAUDIO) +# define __LINUX_PULSE__ +# define RTAUDIO_API_TYPE LINUX_PULSE +# elif defined(HAVE_ALSA) +# define RTAUDIO_API_TYPE LINUX_ALSA +# endif +# ifdef HAVE_ALSA +# define __LINUX_ALSA__ +# define RTMIDI_API_TYPE LINUX_ALSA +# endif +#endif + +#ifdef RTAUDIO_API_TYPE +# include "rtaudio/RtAudio.h" +# include "rtmidi/RtMidi.h" +# include "../../extra/ScopedPointer.hpp" +# include "../../extra/String.hpp" +# include "../../extra/ScopedDenormalDisable.hpp" + +using DISTRHO_NAMESPACE::ScopedDenormalDisable; +using DISTRHO_NAMESPACE::ScopedPointer; +using DISTRHO_NAMESPACE::String; + +struct RtAudioBridge : NativeBridge { + // pointer to RtAudio instance + ScopedPointer handle; + bool captureEnabled = false; + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT + std::vector midiIns; + #endif + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + std::vector midiOuts; + #endif + + // caching + String name; + uint nextBufferSize = 512; + + RtAudioBridge() + { + #if defined(RTMIDI_API_TYPE) && (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT) + midiAvailable = true; + #endif + } + + const char* getVersion() const noexcept + { + return RTAUDIO_VERSION; + } + + bool open(const char* const clientName) override + { + name = clientName; + return _open(false); + } + + bool close() override + { + DISTRHO_SAFE_ASSERT_RETURN(handle != nullptr, false); + + if (handle->isStreamRunning()) + { + try { + handle->abortStream(); + } DISTRHO_SAFE_EXCEPTION("handle->abortStream()"); + } + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + freeBuffers(); + #endif + handle = nullptr; + return true; + } + + bool activate() override + { + DISTRHO_SAFE_ASSERT_RETURN(handle != nullptr, false); + + try { + handle->startStream(); + } DISTRHO_SAFE_EXCEPTION_RETURN("handle->startStream()", false); + + return true; + } + + bool deactivate() override + { + DISTRHO_SAFE_ASSERT_RETURN(handle != nullptr, false); + + try { + handle->stopStream(); + } DISTRHO_SAFE_EXCEPTION_RETURN("handle->stopStream()", false); + + return true; + } + + bool isAudioInputEnabled() const override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return captureEnabled; + #else + return false; + #endif + } + + bool requestAudioInput() override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + // stop audio first + deactivate(); + close(); + + // try to open with capture enabled + const bool ok = _open(true); + + if (ok) + captureEnabled = true; + else + _open(false); + + activate(); + return ok; + #else + return false; + #endif + } + + bool isMIDIEnabled() const override + { + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (!midiIns.empty()) + return true; + #endif + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if (!midiOuts.empty()) + return true; + #endif + return false; + } + + bool requestMIDI() override + { + d_stdout("%s %d", __PRETTY_FUNCTION__, __LINE__); + // clear ports in use first + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT + if (!midiIns.empty()) + { + try { + midiIns.clear(); + } catch (const RtMidiError& err) { + d_safe_exception(err.getMessage().c_str(), __FILE__, __LINE__); + return false; + } DISTRHO_SAFE_EXCEPTION_RETURN("midiIns.clear()", false); + } + #endif + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if (!midiOuts.size()) + { + try { + midiOuts.clear(); + } catch (const RtMidiError& err) { + d_safe_exception(err.getMessage().c_str(), __FILE__, __LINE__); + return false; + } DISTRHO_SAFE_EXCEPTION_RETURN("midiOuts.clear()", false); + } + #endif + + // query port count + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT + uint midiInCount; + try { + RtMidiIn midiIn(RtMidi::RTMIDI_API_TYPE, name.buffer()); + midiInCount = midiIn.getPortCount(); + } catch (const RtMidiError& err) { + d_safe_exception(err.getMessage().c_str(), __FILE__, __LINE__); + return false; + } DISTRHO_SAFE_EXCEPTION_RETURN("midiIn.getPortCount()", false); + #endif + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + uint midiOutCount; + try { + RtMidiOut midiOut(RtMidi::RTMIDI_API_TYPE, name.buffer()); + midiOutCount = midiOut.getPortCount(); + } catch (const RtMidiError& err) { + d_safe_exception(err.getMessage().c_str(), __FILE__, __LINE__); + return false; + } DISTRHO_SAFE_EXCEPTION_RETURN("midiOut.getPortCount()", false); + #endif + + // open all possible ports + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT + for (uint i=0; i rtAudio; + + if (tryingAgain == nullptr) + { + try { + rtAudio = new RtAudio(RtAudio::RTAUDIO_API_TYPE); + } DISTRHO_SAFE_EXCEPTION_RETURN("new RtAudio()", false); + } + else + { + rtAudio = tryingAgain; + } + + uint rtAudioBufferFrames = nextBufferSize; + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + RtAudio::StreamParameters inParams; + #endif + RtAudio::StreamParameters* inParamsPtr = nullptr; + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (withInput) + { + inParams.deviceId = rtAudio->getDefaultInputDevice(); + inParams.nChannels = DISTRHO_PLUGIN_NUM_INPUTS_2; + inParamsPtr = &inParams; + } + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + RtAudio::StreamParameters outParams; + outParams.deviceId = tryingAgain != nullptr ? 1 : rtAudio->getDefaultOutputDevice(); + outParams.nChannels = DISTRHO_PLUGIN_NUM_OUTPUTS_2; + RtAudio::StreamParameters* const outParamsPtr = &outParams; + #else + RtAudio::StreamParameters* const outParamsPtr = nullptr; + #endif + + RtAudio::StreamOptions opts; + opts.flags = RTAUDIO_NONINTERLEAVED | RTAUDIO_ALSA_USE_DEFAULT; + #ifndef DISTRHO_OS_MAC + /* RtAudio in macOS uses a different than usual way to handle audio block size, + * where RTAUDIO_MINIMIZE_LATENCY makes CoreAudio use very low latencies (around 15 samples). + * That has serious performance drawbacks, so we skip that here. + */ + opts.flags |= RTAUDIO_MINIMIZE_LATENCY; + #endif + opts.numberOfBuffers = 2; + opts.streamName = name.buffer(); + + try { + rtAudio->openStream(outParamsPtr, inParamsPtr, RTAUDIO_FLOAT32, 48000, &rtAudioBufferFrames, + RtAudioCallback, this, &opts, nullptr); + } catch (const RtAudioError& err) { + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (outParams.deviceId == 0 && rtAudio->getDeviceCount() > 1) + return _open(withInput, rtAudio.release()); + #endif + d_safe_exception(err.getMessage().c_str(), __FILE__, __LINE__); + return false; + } DISTRHO_SAFE_EXCEPTION_RETURN("rtAudio->openStream()", false); + + handle = rtAudio; + bufferSize = rtAudioBufferFrames; + sampleRate = handle->getStreamSampleRate(); + allocBuffers(!withInput, true); + return true; + } + + static int RtAudioCallback(void* const outputBuffer, + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + void* const inputBuffer, + #else + void*, + #endif + const uint numFrames, + const double /* streamTime */, + const RtAudioStreamStatus /* status */, + void* const userData) + { + RtAudioBridge* const self = static_cast(userData); + + if (self->jackProcessCallback == nullptr) + { + if (outputBuffer != nullptr) + std::memset((float*)outputBuffer, 0, sizeof(float)*numFrames*DISTRHO_PLUGIN_NUM_OUTPUTS_2); + return 0; + } + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (float* const insPtr = static_cast(inputBuffer)) + { + for (uint i=0; iaudioBuffers[i] = insPtr + (i * numFrames); + } + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (float* const outsPtr = static_cast(outputBuffer)) + { + for (uint i=0; iaudioBuffers[DISTRHO_PLUGIN_NUM_INPUTS + i] = outsPtr + (i * numFrames); + } + #endif + + const ScopedDenormalDisable sdd; + self->jackProcessCallback(numFrames, self->jackProcessArg); + + return 0; + } + + #if defined(RTMIDI_API_TYPE) && DISTRHO_PLUGIN_WANT_MIDI_INPUT + static void RtMidiCallback(double /*timeStamp*/, std::vector* message, void* userData) + { + const size_t len = message->size(); + DISTRHO_SAFE_ASSERT_RETURN(len > 0 && len <= kMaxMIDIInputMessageSize,); + + RtAudioBridge* const self = static_cast(userData); + + // TODO timestamp handling + self->midiInBufferPending.writeByte(static_cast(len)); + self->midiInBufferPending.writeCustomData(message->data(), len); + for (uint8_t i=0; imidiInBufferPending.writeByte(0); + self->midiInBufferPending.commitWrite(); + } + #endif +}; + +#endif // RTAUDIO_API_TYPE +#endif // RTAUDIO_BRIDGE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/SDL2Bridge.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/SDL2Bridge.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,265 @@ +/* + * SDL Bridge for DPF + * Copyright (C) 2021-2023 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef SDL_BRIDGE_HPP_INCLUDED +#define SDL_BRIDGE_HPP_INCLUDED + +#include "NativeBridge.hpp" +#include "../../extra/ScopedDenormalDisable.hpp" + +#include + +#ifndef SDL_HINT_AUDIO_DEVICE_APP_NAME +# define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME" +#endif + +#ifndef SDL_HINT_AUDIO_DEVICE_STREAM_NAME +# define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME" +#endif + +#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS == 0 +# error SDL without audio does not make sense +#endif + +struct SDL2Bridge : NativeBridge { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + SDL_AudioDeviceID captureDeviceId; + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + SDL_AudioDeviceID playbackDeviceId; + #endif + + SDL2Bridge() + : NativeBridge() + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + , captureDeviceId(0) + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + , playbackDeviceId(0) + #endif + {} + + bool open(const char* const clientName) override + { + SDL_InitSubSystem(SDL_INIT_AUDIO); + + SDL_AudioSpec requested; + std::memset(&requested, 0, sizeof(requested)); + requested.format = AUDIO_F32SYS; + requested.freq = 48000; + requested.samples = 512; + requested.userdata = this; + + SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, clientName); + // SDL_SetHint(SDL_HINT_AUDIO_RESAMPLING_MODE, "1"); + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + SDL_SetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME, "Capure"); + requested.channels = DISTRHO_PLUGIN_NUM_INPUTS_2; + requested.callback = AudioInputCallback; + + SDL_AudioSpec receivedCapture; + captureDeviceId = SDL_OpenAudioDevice(nullptr, 1, &requested, &receivedCapture, + SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE); + if (captureDeviceId == 0) + { + d_stderr2("Failed to open SDL capture device, error was: %s", SDL_GetError()); + #if DISTRHO_PLUGIN_NUM_OUTPUTS == 0 + return false; + #endif + } + else if (receivedCapture.channels != DISTRHO_PLUGIN_NUM_INPUTS_2) + { + SDL_CloseAudioDevice(captureDeviceId); + captureDeviceId = 0; + d_stderr2("Invalid or missing audio input channels"); + return false; + } + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + SDL_AudioSpec receivedPlayback; + SDL_SetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME, "Playback"); + requested.channels = DISTRHO_PLUGIN_NUM_OUTPUTS_2; + requested.callback = AudioOutputCallback; + + playbackDeviceId = SDL_OpenAudioDevice(nullptr, 0, &requested, &receivedPlayback, + SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE); + if (playbackDeviceId == 0) + { + d_stderr2("Failed to open SDL playback device, error was: %s", SDL_GetError()); + return false; + } + + if (receivedPlayback.channels != DISTRHO_PLUGIN_NUM_OUTPUTS_2) + { + SDL_CloseAudioDevice(playbackDeviceId); + playbackDeviceId = 0; + d_stderr2("Invalid or missing audio output channels"); + return false; + } + #endif + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 && DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + // if using both input and output, make sure they match + if (receivedCapture.samples != receivedPlayback.samples && captureDeviceId != 0) + { + SDL_CloseAudioDevice(captureDeviceId); + SDL_CloseAudioDevice(playbackDeviceId); + captureDeviceId = playbackDeviceId = 0; + d_stderr2("Mismatch buffer size %u vs %u", receivedCapture.samples, receivedPlayback.samples); + return false; + } + if (receivedCapture.freq != receivedPlayback.freq && captureDeviceId != 0) + { + SDL_CloseAudioDevice(captureDeviceId); + SDL_CloseAudioDevice(playbackDeviceId); + captureDeviceId = playbackDeviceId = 0; + d_stderr2("Mismatch sample rate %u vs %u", receivedCapture.freq, receivedPlayback.freq); + return false; + } + #endif + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (captureDeviceId != 0) + { + bufferSize = receivedCapture.samples; + sampleRate = receivedCapture.freq; + } + #endif + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 && DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + else + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + { + bufferSize = receivedPlayback.samples; + sampleRate = receivedPlayback.freq; + } + #endif + + allocBuffers(true, false); + return true; + } + + bool close() override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (captureDeviceId != 0) + { + SDL_CloseAudioDevice(captureDeviceId); + captureDeviceId = 0; + } + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + DISTRHO_SAFE_ASSERT_RETURN(playbackDeviceId != 0, false); + SDL_CloseAudioDevice(playbackDeviceId); + playbackDeviceId = 0; + #endif + + freeBuffers(); + return true; + } + + bool activate() override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (captureDeviceId != 0) + SDL_PauseAudioDevice(captureDeviceId, 0); + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + DISTRHO_SAFE_ASSERT_RETURN(playbackDeviceId != 0, false); + SDL_PauseAudioDevice(playbackDeviceId, 0); + #endif + return true; + } + + bool deactivate() override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (captureDeviceId != 0) + SDL_PauseAudioDevice(captureDeviceId, 1); + #endif + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + DISTRHO_SAFE_ASSERT_RETURN(playbackDeviceId != 0, false); + SDL_PauseAudioDevice(playbackDeviceId, 1); + #endif + return true; + } + + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + static void AudioInputCallback(void* const userData, uchar* const stream, const int len) + { + NativeBridge* const self = static_cast(userData); + + // safety checks + DISTRHO_SAFE_ASSERT_RETURN(stream != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(len > 0,); + + if (self->jackProcessCallback == nullptr) + return; + + const uint numFrames = static_cast(len / sizeof(float) / DISTRHO_PLUGIN_NUM_INPUTS_2); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(numFrames == self->bufferSize, numFrames, self->bufferSize,); + + const float* const fstream = (const float*)stream; + + for (uint i=0; iaudioBuffers[i][j] = fstream[j * DISTRHO_PLUGIN_NUM_INPUTS_2 + i]; + } + + #if DISTRHO_PLUGIN_NUM_OUTPUTS == 0 + // if there are no outputs, run process callback now + const ScopedDenormalDisable sdd; + self->jackProcessCallback(numFrames, self->jackProcessArg); + #endif + } + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + static void AudioOutputCallback(void* const userData, uchar* const stream, const int len) + { + NativeBridge* const self = static_cast(userData); + + // safety checks + DISTRHO_SAFE_ASSERT_RETURN(stream != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(len > 0,); + + if (self->jackProcessCallback == nullptr) + { + std::memset(stream, 0, len); + return; + } + + const uint numFrames = static_cast(len / sizeof(float) / DISTRHO_PLUGIN_NUM_OUTPUTS_2); + DISTRHO_SAFE_ASSERT_UINT2_RETURN(numFrames == self->bufferSize, numFrames, self->bufferSize,); + + const ScopedDenormalDisable sdd; + self->jackProcessCallback(numFrames, self->jackProcessArg); + + float* const fstream = (float*)stream; + + for (uint i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS_2; ++i) + { + for (uint j=0; j < numFrames; ++j) + fstream[j * DISTRHO_PLUGIN_NUM_OUTPUTS_2 + i] = self->audioBuffers[DISTRHO_PLUGIN_NUM_INPUTS + i][j]; + } + } + #endif +}; + +#endif // SDL_BRIDGE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/WebBridge.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/WebBridge.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,495 @@ +/* + * Web Audio + MIDI Bridge for DPF + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef WEB_BRIDGE_HPP_INCLUDED +#define WEB_BRIDGE_HPP_INCLUDED + +#include "NativeBridge.hpp" + +#include + +struct WebBridge : NativeBridge { +#if DISTRHO_PLUGIN_NUM_INPUTS > 0 + bool captureAvailable = false; +#endif +#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + bool playbackAvailable = false; +#endif + bool active = false; + double timestamp = 0; + + WebBridge() + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + captureAvailable = EM_ASM_INT({ + if (typeof(navigator.mediaDevices) !== 'undefined' && typeof(navigator.mediaDevices.getUserMedia) !== 'undefined') + return 1; + if (typeof(navigator.webkitGetUserMedia) !== 'undefined') + return 1; + return false; + }) != 0; + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + playbackAvailable = EM_ASM_INT({ + if (typeof(AudioContext) !== 'undefined') + return 1; + if (typeof(webkitAudioContext) !== 'undefined') + return 1; + return 0; + }) != 0; + #endif + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + midiAvailable = EM_ASM_INT({ + return typeof(navigator.requestMIDIAccess) === 'function' ? 1 : 0; + }) != 0; + #endif + } + + bool open(const char*) override + { + // early bail out if required features are not supported + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + if (!captureAvailable) + { + #if DISTRHO_PLUGIN_NUM_OUTPUTS == 0 + d_stderr2("Audio capture is not supported"); + return false; + #else + if (!playbackAvailable) + { + d_stderr2("Audio capture and playback are not supported"); + return false; + } + d_stderr2("Audio capture is not supported, but can still use playback"); + #endif + } + #endif + + #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 + if (!playbackAvailable) + { + d_stderr2("Audio playback is not supported"); + return false; + } + #endif + + const bool initialized = EM_ASM_INT({ + if (typeof(Module['WebAudioBridge']) === 'undefined') { + Module['WebAudioBridge'] = {}; + } + + var WAB = Module['WebAudioBridge']; + if (!WAB.audioContext) { + if (typeof(AudioContext) !== 'undefined') { + WAB.audioContext = new AudioContext(); + } else if (typeof(webkitAudioContext) !== 'undefined') { + WAB.audioContext = new webkitAudioContext(); + } + } + + return WAB.audioContext === undefined ? 0 : 1; + }) != 0; + + if (!initialized) + { + d_stderr2("Failed to initialize web audio"); + return false; + } + + bufferSize = EM_ASM_INT({ + var WAB = Module['WebAudioBridge']; + return WAB['minimizeBufferSize'] ? 256 : 2048; + }); + sampleRate = EM_ASM_INT_V({ + var WAB = Module['WebAudioBridge']; + return WAB.audioContext.sampleRate; + }); + + allocBuffers(true, true); + + EM_ASM({ + var numInputs = $0; + var numOutputs = $1; + var bufferSize = $2; + var WAB = Module['WebAudioBridge']; + + var realBufferSize = WAB['minimizeBufferSize'] ? 2048 : bufferSize; + var divider = realBufferSize / bufferSize; + + // main processor + WAB.processor = WAB.audioContext['createScriptProcessor'](realBufferSize, numInputs, numOutputs); + WAB.processor['onaudioprocess'] = function (e) { + // var timestamp = performance.now(); + for (var k = 0; k < divider; ++k) { + for (var i = 0; i < numInputs; ++i) { + var buffer = e['inputBuffer']['getChannelData'](i); + for (var j = 0; j < bufferSize; ++j) { + // setValue($3 + ((bufferSize * i) + j) * 4, buffer[j], 'float'); + HEAPF32[$3 + (((bufferSize * i) + j) << 2) >> 2] = buffer[bufferSize * k + j]; + } + } + dynCall('vi', $4, [$5]); + for (var i = 0; i < numOutputs; ++i) { + var buffer = e['outputBuffer']['getChannelData'](i); + var offset = bufferSize * (numInputs + i); + for (var j = 0; j < bufferSize; ++j) { + buffer[bufferSize * k + j] = HEAPF32[$3 + ((offset + j) << 2) >> 2]; + } + } + } + }; + + // connect to output + WAB.processor['connect'](WAB.audioContext['destination']); + + // resume/start playback on first click + document.addEventListener('click', function(e) { + var WAB = Module['WebAudioBridge']; + if (WAB.audioContext.state === 'suspended') + WAB.audioContext.resume(); + }); + }, DISTRHO_PLUGIN_NUM_INPUTS_2, DISTRHO_PLUGIN_NUM_OUTPUTS_2, bufferSize, audioBufferStorage, WebAudioCallback, this); + + return true; + } + + bool close() override + { + freeBuffers(); + return true; + } + + bool activate() override + { + active = true; + return true; + } + + bool deactivate() override + { + active = false; + return true; + } + + bool supportsAudioInput() const override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return captureAvailable; + #else + return false; + #endif + } + + bool isAudioInputEnabled() const override + { + #if DISTRHO_PLUGIN_NUM_INPUTS > 0 + return EM_ASM_INT({ return Module['WebAudioBridge'].captureStreamNode ? 1 : 0 }) != 0; + #else + return false; + #endif + } + + bool requestAudioInput() override + { + DISTRHO_SAFE_ASSERT_RETURN(DISTRHO_PLUGIN_NUM_INPUTS > 0, false); + + EM_ASM({ + var numInputs = $0; + var WAB = Module['WebAudioBridge']; + + var constraints = {}; + // we need to use this weird awkward way for objects, otherwise build fails + constraints['audio'] = true; + constraints['video'] = false; + constraints['autoGainControl'] = {}; + constraints['autoGainControl']['ideal'] = false; + constraints['echoCancellation'] = {}; + constraints['echoCancellation']['ideal'] = false; + constraints['noiseSuppression'] = {}; + constraints['noiseSuppression']['ideal'] = false; + constraints['channelCount'] = {}; + constraints['channelCount']['min'] = 0; + constraints['channelCount']['ideal'] = numInputs; + constraints['latency'] = {}; + constraints['latency']['min'] = 0; + constraints['latency']['ideal'] = 0; + constraints['sampleSize'] = {}; + constraints['sampleSize']['min'] = 8; + constraints['sampleSize']['max'] = 32; + constraints['sampleSize']['ideal'] = 16; + // old property for chrome + constraints['googAutoGainControl'] = false; + + var success = function(stream) { + var track = stream.getAudioTracks()[0]; + + // try to force as much as we can + track.applyConstraints({'autoGainControl': { 'exact': false } }) + .then(function(){console.log("Mic/Input auto-gain control has been disabled")}) + .catch(function(){console.log("Cannot disable Mic/Input auto-gain")}); + + track.applyConstraints({'echoCancellation': { 'exact': false } }) + .then(function(){console.log("Mic/Input echo-cancellation has been disabled")}) + .catch(function(){console.log("Cannot disable Mic/Input echo-cancellation")}); + + track.applyConstraints({'noiseSuppression': { 'exact': false } }) + .then(function(){console.log("Mic/Input noise-suppression has been disabled")}) + .catch(function(){console.log("Cannot disable Mic/Input noise-suppression")}); + + track.applyConstraints({'googAutoGainControl': { 'exact': false } }) + .then(function(){}) + .catch(function(){}); + + WAB.captureStreamNode = WAB.audioContext['createMediaStreamSource'](stream); + WAB.captureStreamNode.connect(WAB.processor); + }; + var fail = function() { + }; + + if (navigator.mediaDevices !== undefined && navigator.mediaDevices.getUserMedia !== undefined) { + navigator.mediaDevices.getUserMedia(constraints).then(success).catch(fail); + } else if (navigator.webkitGetUserMedia !== undefined) { + navigator.webkitGetUserMedia(constraints, success, fail); + } + }, DISTRHO_PLUGIN_NUM_INPUTS_2); + + return true; + } + + bool supportsBufferSizeChanges() const override + { + return true; + } + + bool requestBufferSizeChange(const uint32_t newBufferSize) override + { + // try to create new processor first + bool success = EM_ASM_INT({ + var numInputs = $0; + var numOutputs = $1; + var newBufferSize = $2; + var WAB = Module['WebAudioBridge']; + + try { + WAB.newProcessor = WAB.audioContext['createScriptProcessor'](newBufferSize, numInputs, numOutputs); + } catch (e) { + return 0; + } + + // got new processor, disconnect old one + WAB.processor['disconnect'](WAB.audioContext['destination']); + + if (WAB.captureStreamNode) + WAB.captureStreamNode.disconnect(WAB.processor); + + return 1; + }, DISTRHO_PLUGIN_NUM_INPUTS_2, DISTRHO_PLUGIN_NUM_OUTPUTS_2, newBufferSize) != 0; + + if (!success) + return false; + + bufferSize = newBufferSize; + freeBuffers(); + allocBuffers(true, true); + + if (bufferSizeCallback != nullptr) + bufferSizeCallback(newBufferSize, jackBufferSizeArg); + + EM_ASM({ + var numInputsR = $0; + var numInputs = $1; + var numOutputs = $2; + var bufferSize = $3; + var WAB = Module['WebAudioBridge']; + + // store the new processor + delete WAB.processor; + WAB.processor = WAB.newProcessor; + delete WAB.newProcessor; + + // setup new processor the same way as old one + WAB.processor['onaudioprocess'] = function (e) { + // var timestamp = performance.now(); + for (var i = 0; i < numInputs; ++i) { + var buffer = e['inputBuffer']['getChannelData'](i); + for (var j = 0; j < bufferSize; ++j) { + // setValue($3 + ((bufferSize * i) + j) * 4, buffer[j], 'float'); + HEAPF32[$4 + (((bufferSize * i) + j) << 2) >> 2] = buffer[j]; + } + } + dynCall('vi', $5, [$6]); + for (var i = 0; i < numOutputs; ++i) { + var buffer = e['outputBuffer']['getChannelData'](i); + var offset = bufferSize * (numInputsR + i); + for (var j = 0; j < bufferSize; ++j) { + buffer[j] = HEAPF32[$3 + ((offset + j) << 2) >> 2]; + } + } + }; + + // connect to output + WAB.processor['connect'](WAB.audioContext['destination']); + + // and input, if available + if (WAB.captureStreamNode) + WAB.captureStreamNode.connect(WAB.processor); + + }, DISTRHO_PLUGIN_NUM_INPUTS, DISTRHO_PLUGIN_NUM_INPUTS_2, DISTRHO_PLUGIN_NUM_OUTPUTS_2, bufferSize, audioBufferStorage, WebAudioCallback, this); + + return true; + } + + bool isMIDIEnabled() const override + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + return EM_ASM_INT({ return Module['WebAudioBridge'].midi ? 1 : 0 }) != 0; + #else + return false; + #endif + } + + bool requestMIDI() override + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if (midiAvailable) + { + EM_ASM({ + var useInput = !!$0; + var useOutput = !!$1; + var maxSize = $2; + var WAB = Module['WebAudioBridge']; + + var offset = Module._malloc(maxSize); + + var inputCallback = function(event) { + if (event.data.length > maxSize) + return; + var buffer = new Uint8Array(Module.HEAPU8.buffer, offset, maxSize); + buffer.set(event.data); + dynCall('viiif', $3, [$4, buffer.byteOffset, event.data.length, event.timeStamp]); + }; + var stateCallback = function(event) { + if (event.port.state === 'connected' && event.port.connection === 'open') { + if (useInput && event.port.type === 'input') { + if (event.port.name.indexOf('Midi Through') < 0) + event.port.onmidimessage = inputCallback; + } else if (useOutput && event.port.type === 'output') { + event.port.open(); + } + } + }; + + var success = function(midi) { + WAB.midi = midi; + midi.onstatechange = stateCallback; + if (useInput) { + midi.inputs.forEach(function(port) { + if (port.name.indexOf('Midi Through') < 0) + port.onmidimessage = inputCallback; + }); + } + if (useOutput) { + midi.outputs.forEach(function(port) { + port.open(); + }); + } + }; + var fail = function(why) { + console.log("midi access failed:", why); + }; + + navigator.requestMIDIAccess().then(success, fail); + }, DISTRHO_PLUGIN_WANT_MIDI_INPUT, DISTRHO_PLUGIN_WANT_MIDI_OUTPUT, kMaxMIDIInputMessageSize, WebMIDICallback, this); + + return true; + } + else + #endif + { + d_stderr2("MIDI is not supported"); + return false; + } + } + + static void WebAudioCallback(void* const userData /* , const double timestamp */) + { + WebBridge* const self = static_cast(userData); + // self->timestamp = timestamp; + + const uint numFrames = self->bufferSize; + + if (self->jackProcessCallback != nullptr && self->active) + { + self->jackProcessCallback(numFrames, self->jackProcessArg); + + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if (self->midiAvailable && self->midiOutBuffer.isDataAvailableForReading()) + { + static_assert(kMaxMIDIInputMessageSize + 1u == 4, "change code if bumping this value"); + uint32_t offset = 0; + uint8_t bytes[4] = {}; + double timestamp = EM_ASM_DOUBLE({ return performance.now(); }); + + while (self->midiOutBuffer.isDataAvailableForReading() && + self->midiOutBuffer.readCustomData(bytes, ARRAY_SIZE(bytes))) + { + offset = self->midiOutBuffer.readUInt(); + + EM_ASM({ + var WAB = Module['WebAudioBridge']; + if (WAB.midi) { + var timestamp = $5 + $0; + var size = $1; + WAB.midi.outputs.forEach(function(port) { + if (port.state !== 'disconnected') { + port.send(size == 3 ? [ $2, $3, $4 ] : + size == 2 ? [ $2, $3 ] : + [ $2 ], timestamp); + } + }); + } + }, offset, bytes[0], bytes[1], bytes[2], bytes[3], timestamp); + } + + self->midiOutBuffer.clearData(); + } + #endif + } + else + { + for (uint i=0; iaudioBuffers[DISTRHO_PLUGIN_NUM_INPUTS + i], 0, sizeof(float)*numFrames); + } + } + + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + static void WebMIDICallback(void* const userData, uint8_t* const data, const int len, const double timestamp) + { + DISTRHO_SAFE_ASSERT_RETURN(len > 0 && len <= (int)kMaxMIDIInputMessageSize,); + + WebBridge* const self = static_cast(userData); + + // TODO timestamp handling + self->midiInBufferPending.writeByte(static_cast(len)); + self->midiInBufferPending.writeCustomData(data, kMaxMIDIInputMessageSize); + self->midiInBufferPending.commitWrite(); + } + #endif +}; + +#endif // WEB_BRIDGE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtaudio/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtaudio/LICENSE Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,27 @@ + +RtAudio: a set of realtime audio i/o C++ classes +Copyright (c) 2001-2019 Gary P. Scavone + +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. + +Any person wishing to distribute modifications to the Software is +asked to send the modifications to the original developer so that +they can be incorporated into the canonical version. This is, +however, not a binding provision of this license. + +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 -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtaudio/RtAudio.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtaudio/RtAudio.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,10908 @@ +/************************************************************************/ +/*! \class RtAudio + \brief Realtime audio i/o C++ classes. + + RtAudio provides a common API (Application Programming Interface) + for realtime audio input/output across Linux (native ALSA, Jack, + and OSS), Macintosh OS X (CoreAudio and Jack), and Windows + (DirectSound, ASIO and WASAPI) operating systems. + + RtAudio GitHub site: https://github.com/thestk/rtaudio + RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/ + + RtAudio: realtime audio i/o C++ classes + Copyright (c) 2001-2019 Gary P. Scavone + + 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. + + Any person wishing to distribute modifications to the Software is + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + 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. +*/ +/************************************************************************/ + +// RtAudio: Version 5.1.0 + +#include "RtAudio.h" +#include +#include +#include +#include +#include +#include + +// Static variable definitions. +const unsigned int RtApi::MAX_SAMPLE_RATES = 14; +const unsigned int RtApi::SAMPLE_RATES[] = { + 4000, 5512, 8000, 9600, 11025, 16000, 22050, + 32000, 44100, 48000, 88200, 96000, 176400, 192000 +}; + +#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__) + #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A) + #define MUTEX_DESTROY(A) DeleteCriticalSection(A) + #define MUTEX_LOCK(A) EnterCriticalSection(A) + #define MUTEX_UNLOCK(A) LeaveCriticalSection(A) + + #include "tchar.h" + + template inline + std::string convertCharPointerToStdString(const T *text); + + template<> inline + std::string convertCharPointerToStdString(const char *text) + { + return std::string(text); + } + + template<> inline + std::string convertCharPointerToStdString(const wchar_t *text) + { + int length = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL); + std::string s( length-1, '\0' ); + WideCharToMultiByte(CP_UTF8, 0, text, -1, &s[0], length, NULL, NULL); + return s; + } + +#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) + // pthread API + #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL) + #define MUTEX_DESTROY(A) pthread_mutex_destroy(A) + #define MUTEX_LOCK(A) pthread_mutex_lock(A) + #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A) +#else + #define MUTEX_INITIALIZE(A) abs(*A) // dummy definitions + #define MUTEX_DESTROY(A) abs(*A) // dummy definitions +#endif + +// *************************************************** // +// +// RtAudio definitions. +// +// *************************************************** // + +std::string RtAudio :: getVersion( void ) +{ + return RTAUDIO_VERSION; +} + +// Define API names and display names. +// Must be in same order as API enum. +extern "C" { +const char* rtaudio_api_names[][2] = { + { "unspecified" , "Unknown" }, + { "alsa" , "ALSA" }, + { "pulse" , "Pulse" }, + { "oss" , "OpenSoundSystem" }, + { "jack" , "Jack" }, + { "core" , "CoreAudio" }, + { "wasapi" , "WASAPI" }, + { "asio" , "ASIO" }, + { "ds" , "DirectSound" }, + { "dummy" , "Dummy" }, +}; +const unsigned int rtaudio_num_api_names = + sizeof(rtaudio_api_names)/sizeof(rtaudio_api_names[0]); + +// The order here will control the order of RtAudio's API search in +// the constructor. +extern "C" const RtAudio::Api rtaudio_compiled_apis[] = { +#if defined(__UNIX_JACK__) + RtAudio::UNIX_JACK, +#endif +#if defined(__LINUX_PULSE__) + RtAudio::LINUX_PULSE, +#endif +#if defined(__LINUX_ALSA__) + RtAudio::LINUX_ALSA, +#endif +#if defined(__LINUX_OSS__) + RtAudio::LINUX_OSS, +#endif +#if defined(__WINDOWS_ASIO__) + RtAudio::WINDOWS_ASIO, +#endif +#if defined(__WINDOWS_WASAPI__) + RtAudio::WINDOWS_WASAPI, +#endif +#if defined(__WINDOWS_DS__) + RtAudio::WINDOWS_DS, +#endif +#if defined(__MACOSX_CORE__) + RtAudio::MACOSX_CORE, +#endif +#if defined(__RTAUDIO_DUMMY__) + RtAudio::RTAUDIO_DUMMY, +#endif + RtAudio::UNSPECIFIED, +}; +extern "C" const unsigned int rtaudio_num_compiled_apis = + sizeof(rtaudio_compiled_apis)/sizeof(rtaudio_compiled_apis[0])-1; +} + +// This is a compile-time check that rtaudio_num_api_names == RtAudio::NUM_APIS. +// If the build breaks here, check that they match. +template class StaticAssert { private: StaticAssert() {} }; +template<> class StaticAssert{ public: StaticAssert() {} }; +class StaticAssertions { StaticAssertions() { + StaticAssert(); +}}; + +void RtAudio :: getCompiledApi( std::vector &apis ) +{ + apis = std::vector(rtaudio_compiled_apis, + rtaudio_compiled_apis + rtaudio_num_compiled_apis); +} + +std::string RtAudio :: getApiName( RtAudio::Api api ) +{ + if (api < 0 || api >= RtAudio::NUM_APIS) + return ""; + return rtaudio_api_names[api][0]; +} + +std::string RtAudio :: getApiDisplayName( RtAudio::Api api ) +{ + if (api < 0 || api >= RtAudio::NUM_APIS) + return "Unknown"; + return rtaudio_api_names[api][1]; +} + +RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name ) +{ + unsigned int i=0; + for (i = 0; i < rtaudio_num_compiled_apis; ++i) + if (name == rtaudio_api_names[rtaudio_compiled_apis[i]][0]) + return rtaudio_compiled_apis[i]; + return RtAudio::UNSPECIFIED; +} + +void RtAudio :: openRtApi( RtAudio::Api api ) +{ + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; + +#if defined(__UNIX_JACK__) + if ( api == UNIX_JACK ) + rtapi_ = new RtApiJack(); +#endif +#if defined(__LINUX_ALSA__) + if ( api == LINUX_ALSA ) + rtapi_ = new RtApiAlsa(); +#endif +#if defined(__LINUX_PULSE__) + if ( api == LINUX_PULSE ) + rtapi_ = new RtApiPulse(); +#endif +#if defined(__LINUX_OSS__) + if ( api == LINUX_OSS ) + rtapi_ = new RtApiOss(); +#endif +#if defined(__WINDOWS_ASIO__) + if ( api == WINDOWS_ASIO ) + rtapi_ = new RtApiAsio(); +#endif +#if defined(__WINDOWS_WASAPI__) + if ( api == WINDOWS_WASAPI ) + rtapi_ = new RtApiWasapi(); +#endif +#if defined(__WINDOWS_DS__) + if ( api == WINDOWS_DS ) + rtapi_ = new RtApiDs(); +#endif +#if defined(__MACOSX_CORE__) + if ( api == MACOSX_CORE ) + rtapi_ = new RtApiCore(); +#endif +#if defined(__RTAUDIO_DUMMY__) + if ( api == RTAUDIO_DUMMY ) + rtapi_ = new RtApiDummy(); +#endif +} + +RtAudio :: RtAudio( RtAudio::Api api ) +{ + rtapi_ = 0; + + if ( api != UNSPECIFIED ) { + // Attempt to open the specified API. + openRtApi( api ); + if ( rtapi_ ) return; + + // No compiled support for specified API value. Issue a debug + // warning and continue as if no API was specified. + std::cerr << "\nRtAudio: no compiled support for specified API argument!\n" << std::endl; + } + + // Iterate through the compiled APIs and return as soon as we find + // one with at least one device or we reach the end of the list. + std::vector< RtAudio::Api > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; igetDeviceCount() ) break; + } + + if ( rtapi_ ) return; + + // It should not be possible to get here because the preprocessor + // definition __RTAUDIO_DUMMY__ is automatically defined if no + // API-specific definitions are passed to the compiler. But just in + // case something weird happens, we'll thow an error. + std::string errorText = "\nRtAudio: no compiled API support found ... critical error!!\n\n"; + throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) ); +} + +RtAudio :: ~RtAudio() +{ + if ( rtapi_ ) + delete rtapi_; +} + +void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters, + RtAudio::StreamParameters *inputParameters, + RtAudioFormat format, unsigned int sampleRate, + unsigned int *bufferFrames, + RtAudioCallback callback, void *userData, + RtAudio::StreamOptions *options, + RtAudioErrorCallback errorCallback ) +{ + return rtapi_->openStream( outputParameters, inputParameters, format, + sampleRate, bufferFrames, callback, + userData, options, errorCallback ); +} + +// *************************************************** // +// +// Public RtApi definitions (see end of file for +// private or protected utility functions). +// +// *************************************************** // + +RtApi :: RtApi() +{ + stream_.state = STREAM_CLOSED; + stream_.mode = UNINITIALIZED; + stream_.apiHandle = 0; + stream_.userBuffer[0] = 0; + stream_.userBuffer[1] = 0; + MUTEX_INITIALIZE( &stream_.mutex ); + showWarnings_ = true; + firstErrorOccurred_ = false; +} + +RtApi :: ~RtApi() +{ + MUTEX_DESTROY( &stream_.mutex ); +} + +void RtApi :: openStream( RtAudio::StreamParameters *oParams, + RtAudio::StreamParameters *iParams, + RtAudioFormat format, unsigned int sampleRate, + unsigned int *bufferFrames, + RtAudioCallback callback, void *userData, + RtAudio::StreamOptions *options, + RtAudioErrorCallback errorCallback ) +{ + if ( stream_.state != STREAM_CLOSED ) { + errorText_ = "RtApi::openStream: a stream is already open!"; + error( RtAudioError::INVALID_USE ); + return; + } + + // Clear stream information potentially left from a previously open stream. + clearStreamInfo(); + + if ( oParams && oParams->nChannels < 1 ) { + errorText_ = "RtApi::openStream: a non-NULL output StreamParameters structure cannot have an nChannels value less than one."; + error( RtAudioError::INVALID_USE ); + return; + } + + if ( iParams && iParams->nChannels < 1 ) { + errorText_ = "RtApi::openStream: a non-NULL input StreamParameters structure cannot have an nChannels value less than one."; + error( RtAudioError::INVALID_USE ); + return; + } + + if ( oParams == NULL && iParams == NULL ) { + errorText_ = "RtApi::openStream: input and output StreamParameters structures are both NULL!"; + error( RtAudioError::INVALID_USE ); + return; + } + + if ( formatBytes(format) == 0 ) { + errorText_ = "RtApi::openStream: 'format' parameter value is undefined."; + error( RtAudioError::INVALID_USE ); + return; + } + + unsigned int nDevices = getDeviceCount(); + unsigned int oChannels = 0; + if ( oParams ) { + oChannels = oParams->nChannels; + if ( oParams->deviceId >= nDevices ) { + errorText_ = "RtApi::openStream: output device parameter value is invalid."; + error( RtAudioError::INVALID_USE ); + return; + } + } + + unsigned int iChannels = 0; + if ( iParams ) { + iChannels = iParams->nChannels; + if ( iParams->deviceId >= nDevices ) { + errorText_ = "RtApi::openStream: input device parameter value is invalid."; + error( RtAudioError::INVALID_USE ); + return; + } + } + + bool result; + + if ( oChannels > 0 ) { + + result = probeDeviceOpen( oParams->deviceId, OUTPUT, oChannels, oParams->firstChannel, + sampleRate, format, bufferFrames, options ); + if ( result == false ) { + error( RtAudioError::SYSTEM_ERROR ); + return; + } + } + + if ( iChannels > 0 ) { + + result = probeDeviceOpen( iParams->deviceId, INPUT, iChannels, iParams->firstChannel, + sampleRate, format, bufferFrames, options ); + if ( result == false ) { + if ( oChannels > 0 ) closeStream(); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + } + + stream_.callbackInfo.callback = (void *) callback; + stream_.callbackInfo.userData = userData; + stream_.callbackInfo.errorCallback = (void *) errorCallback; + + if ( options ) options->numberOfBuffers = stream_.nBuffers; + stream_.state = STREAM_STOPPED; +} + +unsigned int RtApi :: getDefaultInputDevice( void ) +{ + // Should be implemented in subclasses if possible. + return 0; +} + +unsigned int RtApi :: getDefaultOutputDevice( void ) +{ + // Should be implemented in subclasses if possible. + return 0; +} + +void RtApi :: closeStream( void ) +{ + // MUST be implemented in subclasses! + return; +} + +bool RtApi :: probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, + unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, + RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, + RtAudio::StreamOptions * /*options*/ ) +{ + // MUST be implemented in subclasses! + return FAILURE; +} + +void RtApi :: tickStreamTime( void ) +{ + // Subclasses that do not provide their own implementation of + // getStreamTime should call this function once per buffer I/O to + // provide basic stream time support. + + stream_.streamTime += ( stream_.bufferSize * 1.0 / stream_.sampleRate ); + +#if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); +#endif +} + +long RtApi :: getStreamLatency( void ) +{ + verifyStream(); + + long totalLatency = 0; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) + totalLatency = stream_.latency[0]; + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) + totalLatency += stream_.latency[1]; + + return totalLatency; +} + +double RtApi :: getStreamTime( void ) +{ + verifyStream(); + +#if defined( HAVE_GETTIMEOFDAY ) + // Return a very accurate estimate of the stream time by + // adding in the elapsed time since the last tick. + struct timeval then; + struct timeval now; + + if ( stream_.state != STREAM_RUNNING || stream_.streamTime == 0.0 ) + return stream_.streamTime; + + gettimeofday( &now, NULL ); + then = stream_.lastTickTimestamp; + return stream_.streamTime + + ((now.tv_sec + 0.000001 * now.tv_usec) - + (then.tv_sec + 0.000001 * then.tv_usec)); +#else + return stream_.streamTime; +#endif +} + +void RtApi :: setStreamTime( double time ) +{ + verifyStream(); + + if ( time >= 0.0 ) + stream_.streamTime = time; +#if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); +#endif +} + +unsigned int RtApi :: getStreamSampleRate( void ) +{ + verifyStream(); + + return stream_.sampleRate; +} + + +// *************************************************** // +// +// OS/API-specific methods. +// +// *************************************************** // + +#if defined(__MACOSX_CORE__) + +#include + +// The OS X CoreAudio API is designed to use a separate callback +// procedure for each of its audio devices. A single RtAudio duplex +// stream using two different devices is supported here, though it +// cannot be guaranteed to always behave correctly because we cannot +// synchronize these two callbacks. +// +// A property listener is installed for over/underrun information. +// However, no functionality is currently provided to allow property +// listeners to trigger user handlers because it is unclear what could +// be done if a critical stream parameter (buffer size, sample rate, +// device disconnect) notification arrived. The listeners entail +// quite a bit of extra code and most likely, a user program wouldn't +// be prepared for the result anyway. However, we do provide a flag +// to the client callback function to inform of an over/underrun. + +// A structure to hold various information related to the CoreAudio API +// implementation. +struct CoreHandle { + AudioDeviceID id[2]; // device ids +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + AudioDeviceIOProcID procId[2]; +#endif + UInt32 iStream[2]; // device stream index (or first if using multiple) + UInt32 nStreams[2]; // number of streams to use + bool xrun[2]; + char *deviceBuffer; + pthread_cond_t condition; + int drainCounter; // Tracks callback counts when draining + bool internalDrain; // Indicates if stop is initiated from callback or not. + + CoreHandle() + :deviceBuffer(0), drainCounter(0), internalDrain(false) { nStreams[0] = 1; nStreams[1] = 1; id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; } +}; + +RtApiCore:: RtApiCore() +{ +#if defined( AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER ) + // This is a largely undocumented but absolutely necessary + // requirement starting with OS-X 10.6. If not called, queries and + // updates to various audio device properties are not handled + // correctly. + CFRunLoopRef theRunLoop = NULL; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + OSStatus result = AudioObjectSetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop); + if ( result != noErr ) { + errorText_ = "RtApiCore::RtApiCore: error setting run loop property!"; + error( RtAudioError::WARNING ); + } +#endif +} + +RtApiCore :: ~RtApiCore() +{ + // The subclass destructor gets called before the base class + // destructor, so close an existing stream before deallocating + // apiDeviceId memory. + if ( stream_.state != STREAM_CLOSED ) closeStream(); +} + +unsigned int RtApiCore :: getDeviceCount( void ) +{ + // Find out how many audio devices there are, if any. + UInt32 dataSize; + AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + OSStatus result = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize ); + if ( result != noErr ) { + errorText_ = "RtApiCore::getDeviceCount: OS-X error getting device info!"; + error( RtAudioError::WARNING ); + return 0; + } + + return dataSize / sizeof( AudioDeviceID ); +} + +unsigned int RtApiCore :: getDefaultInputDevice( void ) +{ + unsigned int nDevices = getDeviceCount(); + if ( nDevices <= 1 ) return 0; + + AudioDeviceID id; + UInt32 dataSize = sizeof( AudioDeviceID ); + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id ); + if ( result != noErr ) { + errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device."; + error( RtAudioError::WARNING ); + return 0; + } + + dataSize *= nDevices; + AudioDeviceID deviceList[ nDevices ]; + property.mSelector = kAudioHardwarePropertyDevices; + result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList ); + if ( result != noErr ) { + errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device IDs."; + error( RtAudioError::WARNING ); + return 0; + } + + for ( unsigned int i=0; i= nDevices ) { + errorText_ = "RtApiCore::getDeviceInfo: device ID is invalid!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + AudioDeviceID deviceList[ nDevices ]; + UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, + 0, NULL, &dataSize, (void *) &deviceList ); + if ( result != noErr ) { + errorText_ = "RtApiCore::getDeviceInfo: OS-X system error getting device IDs."; + error( RtAudioError::WARNING ); + return info; + } + + AudioDeviceID id = deviceList[ device ]; + + // Get the device name. + info.name.erase(); + CFStringRef cfname; + dataSize = sizeof( CFStringRef ); + property.mSelector = kAudioObjectPropertyManufacturer; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device manufacturer."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + //const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() ); + int length = CFStringGetLength(cfname); + char *mname = (char *)malloc(length * 3 + 1); +#if defined( UNICODE ) || defined( _UNICODE ) + CFStringGetCString(cfname, mname, length * 3 + 1, kCFStringEncodingUTF8); +#else + CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding()); +#endif + info.name.append( (const char *)mname, strlen(mname) ); + info.name.append( ": " ); + CFRelease( cfname ); + free(mname); + + property.mSelector = kAudioObjectPropertyName; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device name."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + //const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() ); + length = CFStringGetLength(cfname); + char *name = (char *)malloc(length * 3 + 1); +#if defined( UNICODE ) || defined( _UNICODE ) + CFStringGetCString(cfname, name, length * 3 + 1, kCFStringEncodingUTF8); +#else + CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding()); +#endif + info.name.append( (const char *)name, strlen(name) ); + CFRelease( cfname ); + free(name); + + // Get the output stream "configuration". + AudioBufferList *bufferList = nil; + property.mSelector = kAudioDevicePropertyStreamConfiguration; + property.mScope = kAudioDevicePropertyScopeOutput; + // property.mElement = kAudioObjectPropertyElementWildcard; + dataSize = 0; + result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); + if ( result != noErr || dataSize == 0 ) { + errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration info for device (" << device << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Allocate the AudioBufferList. + bufferList = (AudioBufferList *) malloc( dataSize ); + if ( bufferList == NULL ) { + errorText_ = "RtApiCore::getDeviceInfo: memory error allocating output AudioBufferList."; + error( RtAudioError::WARNING ); + return info; + } + + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); + if ( result != noErr || dataSize == 0 ) { + free( bufferList ); + errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration for device (" << device << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Get output channel information. + unsigned int i, nStreams = bufferList->mNumberBuffers; + for ( i=0; imBuffers[i].mNumberChannels; + free( bufferList ); + + // Get the input stream "configuration". + property.mScope = kAudioDevicePropertyScopeInput; + result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); + if ( result != noErr || dataSize == 0 ) { + errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration info for device (" << device << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Allocate the AudioBufferList. + bufferList = (AudioBufferList *) malloc( dataSize ); + if ( bufferList == NULL ) { + errorText_ = "RtApiCore::getDeviceInfo: memory error allocating input AudioBufferList."; + error( RtAudioError::WARNING ); + return info; + } + + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); + if (result != noErr || dataSize == 0) { + free( bufferList ); + errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration for device (" << device << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Get input channel information. + nStreams = bufferList->mNumberBuffers; + for ( i=0; imBuffers[i].mNumberChannels; + free( bufferList ); + + // If device opens for both playback and capture, we determine the channels. + if ( info.outputChannels > 0 && info.inputChannels > 0 ) + info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; + + // Probe the device sample rates. + bool isInput = false; + if ( info.outputChannels == 0 ) isInput = true; + + // Determine the supported sample rates. + property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; + if ( isInput == false ) property.mScope = kAudioDevicePropertyScopeOutput; + result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); + if ( result != kAudioHardwareNoError || dataSize == 0 ) { + errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rate info."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + UInt32 nRanges = dataSize / sizeof( AudioValueRange ); + AudioValueRange rangeList[ nRanges ]; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &rangeList ); + if ( result != kAudioHardwareNoError ) { + errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rates."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // The sample rate reporting mechanism is a bit of a mystery. It + // seems that it can either return individual rates or a range of + // rates. I assume that if the min / max range values are the same, + // then that represents a single supported rate and if the min / max + // range values are different, the device supports an arbitrary + // range of values (though there might be multiple ranges, so we'll + // use the most conservative range). + Float64 minimumRate = 1.0, maximumRate = 10000000000.0; + bool haveValueRange = false; + info.sampleRates.clear(); + for ( UInt32 i=0; i info.preferredSampleRate ) ) + info.preferredSampleRate = tmpSr; + + } else { + haveValueRange = true; + if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum; + if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum; + } + } + + if ( haveValueRange ) { + for ( unsigned int k=0; k= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) { + info.sampleRates.push_back( SAMPLE_RATES[k] ); + + if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) + info.preferredSampleRate = SAMPLE_RATES[k]; + } + } + } + + // Sort and remove any redundant values + std::sort( info.sampleRates.begin(), info.sampleRates.end() ); + info.sampleRates.erase( unique( info.sampleRates.begin(), info.sampleRates.end() ), info.sampleRates.end() ); + + if ( info.sampleRates.size() == 0 ) { + errorStream_ << "RtApiCore::probeDeviceInfo: No supported sample rates found for device (" << device << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // CoreAudio always uses 32-bit floating point data for PCM streams. + // Thus, any other "physical" formats supported by the device are of + // no interest to the client. + info.nativeFormats = RTAUDIO_FLOAT32; + + if ( info.outputChannels > 0 ) + if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true; + if ( info.inputChannels > 0 ) + if ( getDefaultInputDevice() == device ) info.isDefaultInput = true; + + info.probed = true; + return info; +} + +static OSStatus callbackHandler( AudioDeviceID inDevice, + const AudioTimeStamp* /*inNow*/, + const AudioBufferList* inInputData, + const AudioTimeStamp* /*inInputTime*/, + AudioBufferList* outOutputData, + const AudioTimeStamp* /*inOutputTime*/, + void* infoPointer ) +{ + CallbackInfo *info = (CallbackInfo *) infoPointer; + + RtApiCore *object = (RtApiCore *) info->object; + if ( object->callbackEvent( inDevice, inInputData, outOutputData ) == false ) + return kAudioHardwareUnspecifiedError; + else + return kAudioHardwareNoError; +} + +static OSStatus xrunListener( AudioObjectID /*inDevice*/, + UInt32 nAddresses, + const AudioObjectPropertyAddress properties[], + void* handlePointer ) +{ + CoreHandle *handle = (CoreHandle *) handlePointer; + for ( UInt32 i=0; ixrun[1] = true; + else + handle->xrun[0] = true; + } + } + + return kAudioHardwareNoError; +} + +static OSStatus rateListener( AudioObjectID inDevice, + UInt32 /*nAddresses*/, + const AudioObjectPropertyAddress /*properties*/[], + void* ratePointer ) +{ + Float64 *rate = (Float64 *) ratePointer; + UInt32 dataSize = sizeof( Float64 ); + AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + AudioObjectGetPropertyData( inDevice, &property, 0, NULL, &dataSize, rate ); + return kAudioHardwareNoError; +} + +bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) +{ + // Get device ID + unsigned int nDevices = getDeviceCount(); + if ( nDevices == 0 ) { + // This should not happen because a check is made before this function is called. + errorText_ = "RtApiCore::probeDeviceOpen: no devices found!"; + return FAILURE; + } + + if ( device >= nDevices ) { + // This should not happen because a check is made before this function is called. + errorText_ = "RtApiCore::probeDeviceOpen: device ID is invalid!"; + return FAILURE; + } + + AudioDeviceID deviceList[ nDevices ]; + UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, + 0, NULL, &dataSize, (void *) &deviceList ); + if ( result != noErr ) { + errorText_ = "RtApiCore::probeDeviceOpen: OS-X system error getting device IDs."; + return FAILURE; + } + + AudioDeviceID id = deviceList[ device ]; + + // Setup for stream mode. + bool isInput = false; + if ( mode == INPUT ) { + isInput = true; + property.mScope = kAudioDevicePropertyScopeInput; + } + else + property.mScope = kAudioDevicePropertyScopeOutput; + + // Get the stream "configuration". + AudioBufferList *bufferList = nil; + dataSize = 0; + property.mSelector = kAudioDevicePropertyStreamConfiguration; + result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize ); + if ( result != noErr || dataSize == 0 ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration info for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Allocate the AudioBufferList. + bufferList = (AudioBufferList *) malloc( dataSize ); + if ( bufferList == NULL ) { + errorText_ = "RtApiCore::probeDeviceOpen: memory error allocating AudioBufferList."; + return FAILURE; + } + + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); + if (result != noErr || dataSize == 0) { + free( bufferList ); + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Search for one or more streams that contain the desired number of + // channels. CoreAudio devices can have an arbitrary number of + // streams and each stream can have an arbitrary number of channels. + // For each stream, a single buffer of interleaved samples is + // provided. RtAudio prefers the use of one stream of interleaved + // data or multiple consecutive single-channel streams. However, we + // now support multiple consecutive multi-channel streams of + // interleaved data as well. + UInt32 iStream, offsetCounter = firstChannel; + UInt32 nStreams = bufferList->mNumberBuffers; + bool monoMode = false; + bool foundStream = false; + + // First check that the device supports the requested number of + // channels. + UInt32 deviceChannels = 0; + for ( iStream=0; iStreammBuffers[iStream].mNumberChannels; + + if ( deviceChannels < ( channels + firstChannel ) ) { + free( bufferList ); + errorStream_ << "RtApiCore::probeDeviceOpen: the device (" << device << ") does not support the requested channel count."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Look for a single stream meeting our needs. + UInt32 firstStream, streamCount = 1, streamChannels = 0, channelOffset = 0; + for ( iStream=0; iStreammBuffers[iStream].mNumberChannels; + if ( streamChannels >= channels + offsetCounter ) { + firstStream = iStream; + channelOffset = offsetCounter; + foundStream = true; + break; + } + if ( streamChannels > offsetCounter ) break; + offsetCounter -= streamChannels; + } + + // If we didn't find a single stream above, then we should be able + // to meet the channel specification with multiple streams. + if ( foundStream == false ) { + monoMode = true; + offsetCounter = firstChannel; + for ( iStream=0; iStreammBuffers[iStream].mNumberChannels; + if ( streamChannels > offsetCounter ) break; + offsetCounter -= streamChannels; + } + + firstStream = iStream; + channelOffset = offsetCounter; + Int32 channelCounter = channels + offsetCounter - streamChannels; + + if ( streamChannels > 1 ) monoMode = false; + while ( channelCounter > 0 ) { + streamChannels = bufferList->mBuffers[++iStream].mNumberChannels; + if ( streamChannels > 1 ) monoMode = false; + channelCounter -= streamChannels; + streamCount++; + } + } + + free( bufferList ); + + // Determine the buffer size. + AudioValueRange bufferRange; + dataSize = sizeof( AudioValueRange ); + property.mSelector = kAudioDevicePropertyBufferFrameSizeRange; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &bufferRange ); + + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting buffer size range for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + if ( bufferRange.mMinimum > *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMinimum; + else if ( bufferRange.mMaximum < *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMaximum; + if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) *bufferSize = (unsigned long) bufferRange.mMinimum; + + // Set the buffer size. For multiple streams, I'm assuming we only + // need to make this setting for the master channel. + UInt32 theSize = (UInt32) *bufferSize; + dataSize = sizeof( UInt32 ); + property.mSelector = kAudioDevicePropertyBufferFrameSize; + result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &theSize ); + + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting the buffer size for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // If attempting to setup a duplex stream, the bufferSize parameter + // MUST be the same in both directions! + *bufferSize = theSize; + if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + stream_.bufferSize = *bufferSize; + stream_.nBuffers = 1; + + // Try to set "hog" mode ... it's not clear to me this is working. + if ( options && options->flags & RTAUDIO_HOG_DEVICE ) { + pid_t hog_pid; + dataSize = sizeof( hog_pid ); + property.mSelector = kAudioDevicePropertyHogMode; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &hog_pid ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting 'hog' state!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + if ( hog_pid != getpid() ) { + hog_pid = getpid(); + result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &hog_pid ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting 'hog' state!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + } + + // Check and if necessary, change the sample rate for the device. + Float64 nominalRate; + dataSize = sizeof( Float64 ); + property.mSelector = kAudioDevicePropertyNominalSampleRate; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting current sample rate."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Only change the sample rate if off by more than 1 Hz. + if ( fabs( nominalRate - (double)sampleRate ) > 1.0 ) { + + // Set a property listener for the sample rate change + Float64 reportedRate = 0.0; + AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + result = AudioObjectAddPropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate property listener for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + nominalRate = (Float64) sampleRate; + result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate ); + if ( result != noErr ) { + AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Now wait until the reported nominal rate is what we just set. + UInt32 microCounter = 0; + while ( reportedRate != nominalRate ) { + microCounter += 5000; + if ( microCounter > 5000000 ) break; + usleep( 5000 ); + } + + // Remove the property listener. + AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); + + if ( microCounter > 5000000 ) { + errorStream_ << "RtApiCore::probeDeviceOpen: timeout waiting for sample rate update for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + + // Now set the stream format for all streams. Also, check the + // physical format of the device and change that if necessary. + AudioStreamBasicDescription description; + dataSize = sizeof( AudioStreamBasicDescription ); + property.mSelector = kAudioStreamPropertyVirtualFormat; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream format for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Set the sample rate and data format id. However, only make the + // change if the sample rate is not within 1.0 of the desired + // rate and the format is not linear pcm. + bool updateFormat = false; + if ( fabs( description.mSampleRate - (Float64)sampleRate ) > 1.0 ) { + description.mSampleRate = (Float64) sampleRate; + updateFormat = true; + } + + if ( description.mFormatID != kAudioFormatLinearPCM ) { + description.mFormatID = kAudioFormatLinearPCM; + updateFormat = true; + } + + if ( updateFormat ) { + result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &description ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate or data format for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + + // Now check the physical format. + property.mSelector = kAudioStreamPropertyPhysicalFormat; + result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description ); + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream physical format for device (" << device << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + //std::cout << "Current physical stream format:" << std::endl; + //std::cout << " mBitsPerChan = " << description.mBitsPerChannel << std::endl; + //std::cout << " aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl; + //std::cout << " bytesPerFrame = " << description.mBytesPerFrame << std::endl; + //std::cout << " sample rate = " << description.mSampleRate << std::endl; + + if ( description.mFormatID != kAudioFormatLinearPCM || description.mBitsPerChannel < 16 ) { + description.mFormatID = kAudioFormatLinearPCM; + //description.mSampleRate = (Float64) sampleRate; + AudioStreamBasicDescription testDescription = description; + UInt32 formatFlags; + + // We'll try higher bit rates first and then work our way down. + std::vector< std::pair > physicalFormats; + formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger; + physicalFormats.push_back( std::pair( 32, formatFlags ) ); + formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat; + physicalFormats.push_back( std::pair( 32, formatFlags ) ); + physicalFormats.push_back( std::pair( 24, formatFlags ) ); // 24-bit packed + formatFlags &= ~( kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh ); + physicalFormats.push_back( std::pair( 24.2, formatFlags ) ); // 24-bit in 4 bytes, aligned low + formatFlags |= kAudioFormatFlagIsAlignedHigh; + physicalFormats.push_back( std::pair( 24.4, formatFlags ) ); // 24-bit in 4 bytes, aligned high + formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat; + physicalFormats.push_back( std::pair( 16, formatFlags ) ); + physicalFormats.push_back( std::pair( 8, formatFlags ) ); + + bool setPhysicalFormat = false; + for( unsigned int i=0; iflags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; + else stream_.userInterleaved = true; + stream_.deviceInterleaved[mode] = true; + if ( monoMode == true ) stream_.deviceInterleaved[mode] = false; + + // Set flags for buffer conversion. + stream_.doConvertBuffer[mode] = false; + if ( stream_.userFormat != stream_.deviceFormat[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( streamCount == 1 ) { + if ( stream_.nUserChannels[mode] > 1 && + stream_.userInterleaved != stream_.deviceInterleaved[mode] ) + stream_.doConvertBuffer[mode] = true; + } + else if ( monoMode && stream_.userInterleaved ) + stream_.doConvertBuffer[mode] = true; + + // Allocate our CoreHandle structure for the stream. + CoreHandle *handle = 0; + if ( stream_.apiHandle == 0 ) { + try { + handle = new CoreHandle; + } + catch ( std::bad_alloc& ) { + errorText_ = "RtApiCore::probeDeviceOpen: error allocating CoreHandle memory."; + goto error; + } + + if ( pthread_cond_init( &handle->condition, NULL ) ) { + errorText_ = "RtApiCore::probeDeviceOpen: error initializing pthread condition variable."; + goto error; + } + stream_.apiHandle = (void *) handle; + } + else + handle = (CoreHandle *) stream_.apiHandle; + handle->iStream[mode] = firstStream; + handle->nStreams[mode] = streamCount; + handle->id[mode] = id; + + // Allocate necessary internal buffers. + unsigned long bufferBytes; + bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + // stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); + stream_.userBuffer[mode] = (char *) malloc( bufferBytes * sizeof(char) ); + memset( stream_.userBuffer[mode], 0, bufferBytes * sizeof(char) ); + if ( stream_.userBuffer[mode] == NULL ) { + errorText_ = "RtApiCore::probeDeviceOpen: error allocating user buffer memory."; + goto error; + } + + // If possible, we will make use of the CoreAudio stream buffers as + // "device buffers". However, we can't do this if using multiple + // streams. + if ( stream_.doConvertBuffer[mode] && handle->nStreams[mode] > 1 ) { + + bool makeBuffer = true; + bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); + if ( mode == INPUT ) { + if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { + unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); + if ( bufferBytes <= bytesOut ) makeBuffer = false; + } + } + + if ( makeBuffer ) { + bufferBytes *= *bufferSize; + if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); + stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); + if ( stream_.deviceBuffer == NULL ) { + errorText_ = "RtApiCore::probeDeviceOpen: error allocating device buffer memory."; + goto error; + } + } + } + + stream_.sampleRate = sampleRate; + stream_.device[mode] = device; + stream_.state = STREAM_STOPPED; + stream_.callbackInfo.object = (void *) this; + + // Setup the buffer conversion information structure. + if ( stream_.doConvertBuffer[mode] ) { + if ( streamCount > 1 ) setConvertInfo( mode, 0 ); + else setConvertInfo( mode, channelOffset ); + } + + if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device ) + // Only one callback procedure per device. + stream_.mode = DUPLEX; + else { +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + result = AudioDeviceCreateIOProcID( id, callbackHandler, (void *) &stream_.callbackInfo, &handle->procId[mode] ); +#else + // deprecated in favor of AudioDeviceCreateIOProcID() + result = AudioDeviceAddIOProc( id, callbackHandler, (void *) &stream_.callbackInfo ); +#endif + if ( result != noErr ) { + errorStream_ << "RtApiCore::probeDeviceOpen: system error setting callback for device (" << device << ")."; + errorText_ = errorStream_.str(); + goto error; + } + if ( stream_.mode == OUTPUT && mode == INPUT ) + stream_.mode = DUPLEX; + else + stream_.mode = mode; + } + + // Setup the device property listener for over/underload. + property.mSelector = kAudioDeviceProcessorOverload; + property.mScope = kAudioObjectPropertyScopeGlobal; + result = AudioObjectAddPropertyListener( id, &property, xrunListener, (void *) handle ); + + return SUCCESS; + + error: + if ( handle ) { + pthread_cond_destroy( &handle->condition ); + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.state = STREAM_CLOSED; + return FAILURE; +} + +void RtApiCore :: closeStream( void ) +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiCore::closeStream(): no open stream to close!"; + error( RtAudioError::WARNING ); + return; + } + + CoreHandle *handle = (CoreHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + if (handle) { + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + + property.mSelector = kAudioDeviceProcessorOverload; + property.mScope = kAudioObjectPropertyScopeGlobal; + if (AudioObjectRemovePropertyListener( handle->id[0], &property, xrunListener, (void *) handle ) != noErr) { + errorText_ = "RtApiCore::closeStream(): error removing property listener!"; + error( RtAudioError::WARNING ); + } + +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + if ( stream_.state == STREAM_RUNNING ) + AudioDeviceStop( handle->id[0], handle->procId[0] ); + AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] ); +#else // deprecated behaviour + if ( stream_.state == STREAM_RUNNING ) + AudioDeviceStop( handle->id[0], callbackHandler ); + AudioDeviceRemoveIOProc( handle->id[0], callbackHandler ); +#endif + } + } + + if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { + if (handle) { + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + + property.mSelector = kAudioDeviceProcessorOverload; + property.mScope = kAudioObjectPropertyScopeGlobal; + if (AudioObjectRemovePropertyListener( handle->id[1], &property, xrunListener, (void *) handle ) != noErr) { + errorText_ = "RtApiCore::closeStream(): error removing property listener!"; + error( RtAudioError::WARNING ); + } + +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + if ( stream_.state == STREAM_RUNNING ) + AudioDeviceStop( handle->id[1], handle->procId[1] ); + AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] ); +#else // deprecated behaviour + if ( stream_.state == STREAM_RUNNING ) + AudioDeviceStop( handle->id[1], callbackHandler ); + AudioDeviceRemoveIOProc( handle->id[1], callbackHandler ); +#endif + } + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + // Destroy pthread condition variable. + pthread_cond_destroy( &handle->condition ); + delete handle; + stream_.apiHandle = 0; + + stream_.mode = UNINITIALIZED; + stream_.state = STREAM_CLOSED; +} + +void RtApiCore :: startStream( void ) +{ + verifyStream(); + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiCore::startStream(): the stream is already running!"; + error( RtAudioError::WARNING ); + return; + } + +#if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); +#endif + + OSStatus result = noErr; + CoreHandle *handle = (CoreHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + result = AudioDeviceStart( handle->id[0], handle->procId[0] ); +#else // deprecated behaviour + result = AudioDeviceStart( handle->id[0], callbackHandler ); +#endif + if ( result != noErr ) { + errorStream_ << "RtApiCore::startStream: system error (" << getErrorCode( result ) << ") starting callback procedure on device (" << stream_.device[0] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + if ( stream_.mode == INPUT || + ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { + +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + result = AudioDeviceStart( handle->id[1], handle->procId[1] ); +#else // deprecated behaviour + result = AudioDeviceStart( handle->id[1], callbackHandler ); +#endif + if ( result != noErr ) { + errorStream_ << "RtApiCore::startStream: system error starting input callback procedure on device (" << stream_.device[1] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + handle->drainCounter = 0; + handle->internalDrain = false; + stream_.state = STREAM_RUNNING; + + unlock: + if ( result == noErr ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiCore :: stopStream( void ) +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiCore::stopStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + OSStatus result = noErr; + CoreHandle *handle = (CoreHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + if ( handle->drainCounter == 0 ) { + handle->drainCounter = 2; + pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled + } + +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + result = AudioDeviceStop( handle->id[0], handle->procId[0] ); +#else // deprecated behaviour + result = AudioDeviceStop( handle->id[0], callbackHandler ); +#endif + if ( result != noErr ) { + errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping callback procedure on device (" << stream_.device[0] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) { + +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) + result = AudioDeviceStop( handle->id[1], handle->procId[1] ); +#else // deprecated behaviour + result = AudioDeviceStop( handle->id[1], callbackHandler ); +#endif + if ( result != noErr ) { + errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + stream_.state = STREAM_STOPPED; + + unlock: + if ( result == noErr ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiCore :: abortStream( void ) +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiCore::abortStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + CoreHandle *handle = (CoreHandle *) stream_.apiHandle; + handle->drainCounter = 2; + + stopStream(); +} + +// This function will be called by a spawned thread when the user +// callback function signals that the stream should be stopped or +// aborted. It is better to handle it this way because the +// callbackEvent() function probably should return before the AudioDeviceStop() +// function is called. +static void *coreStopStream( void *ptr ) +{ + CallbackInfo *info = (CallbackInfo *) ptr; + RtApiCore *object = (RtApiCore *) info->object; + + object->stopStream(); + pthread_exit( NULL ); +} + +bool RtApiCore :: callbackEvent( AudioDeviceID deviceId, + const AudioBufferList *inBufferList, + const AudioBufferList *outBufferList ) +{ + if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!"; + error( RtAudioError::WARNING ); + return FAILURE; + } + + CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; + CoreHandle *handle = (CoreHandle *) stream_.apiHandle; + + // Check if we were draining the stream and signal is finished. + if ( handle->drainCounter > 3 ) { + ThreadHandle threadId; + + stream_.state = STREAM_STOPPING; + if ( handle->internalDrain == true ) + pthread_create( &threadId, NULL, coreStopStream, info ); + else // external call to stopStream() + pthread_cond_signal( &handle->condition ); + return SUCCESS; + } + + AudioDeviceID outputDevice = handle->id[0]; + + // Invoke user callback to get fresh output data UNLESS we are + // draining stream or duplex mode AND the input/output devices are + // different AND this function is called for the input device. + if ( handle->drainCounter == 0 && ( stream_.mode != DUPLEX || deviceId == outputDevice ) ) { + RtAudioCallback callback = (RtAudioCallback) info->callback; + double streamTime = getStreamTime(); + RtAudioStreamStatus status = 0; + if ( stream_.mode != INPUT && handle->xrun[0] == true ) { + status |= RTAUDIO_OUTPUT_UNDERFLOW; + handle->xrun[0] = false; + } + if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { + status |= RTAUDIO_INPUT_OVERFLOW; + handle->xrun[1] = false; + } + + int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], + stream_.bufferSize, streamTime, status, info->userData ); + if ( cbReturnValue == 2 ) { + stream_.state = STREAM_STOPPING; + handle->drainCounter = 2; + abortStream(); + return SUCCESS; + } + else if ( cbReturnValue == 1 ) { + handle->drainCounter = 1; + handle->internalDrain = true; + } + } + + if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == outputDevice ) ) { + + if ( handle->drainCounter > 1 ) { // write zeros to the output stream + + if ( handle->nStreams[0] == 1 ) { + memset( outBufferList->mBuffers[handle->iStream[0]].mData, + 0, + outBufferList->mBuffers[handle->iStream[0]].mDataByteSize ); + } + else { // fill multiple streams with zeros + for ( unsigned int i=0; inStreams[0]; i++ ) { + memset( outBufferList->mBuffers[handle->iStream[0]+i].mData, + 0, + outBufferList->mBuffers[handle->iStream[0]+i].mDataByteSize ); + } + } + } + else if ( handle->nStreams[0] == 1 ) { + if ( stream_.doConvertBuffer[0] ) { // convert directly to CoreAudio stream buffer + convertBuffer( (char *) outBufferList->mBuffers[handle->iStream[0]].mData, + stream_.userBuffer[0], stream_.convertInfo[0] ); + } + else { // copy from user buffer + memcpy( outBufferList->mBuffers[handle->iStream[0]].mData, + stream_.userBuffer[0], + outBufferList->mBuffers[handle->iStream[0]].mDataByteSize ); + } + } + else { // fill multiple streams + Float32 *inBuffer = (Float32 *) stream_.userBuffer[0]; + if ( stream_.doConvertBuffer[0] ) { + convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); + inBuffer = (Float32 *) stream_.deviceBuffer; + } + + if ( stream_.deviceInterleaved[0] == false ) { // mono mode + UInt32 bufferBytes = outBufferList->mBuffers[handle->iStream[0]].mDataByteSize; + for ( unsigned int i=0; imBuffers[handle->iStream[0]+i].mData, + (void *)&inBuffer[i*stream_.bufferSize], bufferBytes ); + } + } + else { // fill multiple multi-channel streams with interleaved data + UInt32 streamChannels, channelsLeft, inJump, outJump, inOffset; + Float32 *out, *in; + + bool inInterleaved = ( stream_.userInterleaved ) ? true : false; + UInt32 inChannels = stream_.nUserChannels[0]; + if ( stream_.doConvertBuffer[0] ) { + inInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode + inChannels = stream_.nDeviceChannels[0]; + } + + if ( inInterleaved ) inOffset = 1; + else inOffset = stream_.bufferSize; + + channelsLeft = inChannels; + for ( unsigned int i=0; inStreams[0]; i++ ) { + in = inBuffer; + out = (Float32 *) outBufferList->mBuffers[handle->iStream[0]+i].mData; + streamChannels = outBufferList->mBuffers[handle->iStream[0]+i].mNumberChannels; + + outJump = 0; + // Account for possible channel offset in first stream + if ( i == 0 && stream_.channelOffset[0] > 0 ) { + streamChannels -= stream_.channelOffset[0]; + outJump = stream_.channelOffset[0]; + out += outJump; + } + + // Account for possible unfilled channels at end of the last stream + if ( streamChannels > channelsLeft ) { + outJump = streamChannels - channelsLeft; + streamChannels = channelsLeft; + } + + // Determine input buffer offsets and skips + if ( inInterleaved ) { + inJump = inChannels; + in += inChannels - channelsLeft; + } + else { + inJump = 1; + in += (inChannels - channelsLeft) * inOffset; + } + + for ( unsigned int i=0; idrainCounter ) { + handle->drainCounter++; + goto unlock; + } + + AudioDeviceID inputDevice; + inputDevice = handle->id[1]; + if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == inputDevice ) ) { + + if ( handle->nStreams[1] == 1 ) { + if ( stream_.doConvertBuffer[1] ) { // convert directly from CoreAudio stream buffer + convertBuffer( stream_.userBuffer[1], + (char *) inBufferList->mBuffers[handle->iStream[1]].mData, + stream_.convertInfo[1] ); + } + else { // copy to user buffer + memcpy( stream_.userBuffer[1], + inBufferList->mBuffers[handle->iStream[1]].mData, + inBufferList->mBuffers[handle->iStream[1]].mDataByteSize ); + } + } + else { // read from multiple streams + Float32 *outBuffer = (Float32 *) stream_.userBuffer[1]; + if ( stream_.doConvertBuffer[1] ) outBuffer = (Float32 *) stream_.deviceBuffer; + + if ( stream_.deviceInterleaved[1] == false ) { // mono mode + UInt32 bufferBytes = inBufferList->mBuffers[handle->iStream[1]].mDataByteSize; + for ( unsigned int i=0; imBuffers[handle->iStream[1]+i].mData, bufferBytes ); + } + } + else { // read from multiple multi-channel streams + UInt32 streamChannels, channelsLeft, inJump, outJump, outOffset; + Float32 *out, *in; + + bool outInterleaved = ( stream_.userInterleaved ) ? true : false; + UInt32 outChannels = stream_.nUserChannels[1]; + if ( stream_.doConvertBuffer[1] ) { + outInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode + outChannels = stream_.nDeviceChannels[1]; + } + + if ( outInterleaved ) outOffset = 1; + else outOffset = stream_.bufferSize; + + channelsLeft = outChannels; + for ( unsigned int i=0; inStreams[1]; i++ ) { + out = outBuffer; + in = (Float32 *) inBufferList->mBuffers[handle->iStream[1]+i].mData; + streamChannels = inBufferList->mBuffers[handle->iStream[1]+i].mNumberChannels; + + inJump = 0; + // Account for possible channel offset in first stream + if ( i == 0 && stream_.channelOffset[1] > 0 ) { + streamChannels -= stream_.channelOffset[1]; + inJump = stream_.channelOffset[1]; + in += inJump; + } + + // Account for possible unread channels at end of the last stream + if ( streamChannels > channelsLeft ) { + inJump = streamChannels - channelsLeft; + streamChannels = channelsLeft; + } + + // Determine output buffer offsets and skips + if ( outInterleaved ) { + outJump = outChannels; + out += outChannels - channelsLeft; + } + else { + outJump = 1; + out += (outChannels - channelsLeft) * outOffset; + } + + for ( unsigned int i=0; iid[0] != handle->id[1] && deviceId == handle->id[0] ) ) + RtApi::tickStreamTime(); + + return SUCCESS; +} + +const char* RtApiCore :: getErrorCode( OSStatus code ) +{ + switch( code ) { + + case kAudioHardwareNotRunningError: + return "kAudioHardwareNotRunningError"; + + case kAudioHardwareUnspecifiedError: + return "kAudioHardwareUnspecifiedError"; + + case kAudioHardwareUnknownPropertyError: + return "kAudioHardwareUnknownPropertyError"; + + case kAudioHardwareBadPropertySizeError: + return "kAudioHardwareBadPropertySizeError"; + + case kAudioHardwareIllegalOperationError: + return "kAudioHardwareIllegalOperationError"; + + case kAudioHardwareBadObjectError: + return "kAudioHardwareBadObjectError"; + + case kAudioHardwareBadDeviceError: + return "kAudioHardwareBadDeviceError"; + + case kAudioHardwareBadStreamError: + return "kAudioHardwareBadStreamError"; + + case kAudioHardwareUnsupportedOperationError: + return "kAudioHardwareUnsupportedOperationError"; + + case kAudioDeviceUnsupportedFormatError: + return "kAudioDeviceUnsupportedFormatError"; + + case kAudioDevicePermissionsError: + return "kAudioDevicePermissionsError"; + + default: + return "CoreAudio unknown error"; + } +} + + //******************** End of __MACOSX_CORE__ *********************// +#endif + +#if defined(__UNIX_JACK__) + +// JACK is a low-latency audio server, originally written for the +// GNU/Linux operating system and now also ported to OS-X. It can +// connect a number of different applications to an audio device, as +// well as allowing them to share audio between themselves. +// +// When using JACK with RtAudio, "devices" refer to JACK clients that +// have ports connected to the server. The JACK server is typically +// started in a terminal as follows: +// +// .jackd -d alsa -d hw:0 +// +// or through an interface program such as qjackctl. Many of the +// parameters normally set for a stream are fixed by the JACK server +// and can be specified when the JACK server is started. In +// particular, +// +// .jackd -d alsa -d hw:0 -r 44100 -p 512 -n 4 +// +// specifies a sample rate of 44100 Hz, a buffer size of 512 sample +// frames, and number of buffers = 4. Once the server is running, it +// is not possible to override these values. If the values are not +// specified in the command-line, the JACK server uses default values. +// +// The JACK server does not have to be running when an instance of +// RtApiJack is created, though the function getDeviceCount() will +// report 0 devices found until JACK has been started. When no +// devices are available (i.e., the JACK server is not running), a +// stream cannot be opened. + +#include +#include +#include + +// A structure to hold various information related to the Jack API +// implementation. +struct JackHandle { + jack_client_t *client; + jack_port_t **ports[2]; + std::string deviceName[2]; + bool xrun[2]; + pthread_cond_t condition; + int drainCounter; // Tracks callback counts when draining + bool internalDrain; // Indicates if stop is initiated from callback or not. + + JackHandle() + :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; } +}; + +#if !defined(__RTAUDIO_DEBUG__) +static void jackSilentError( const char * ) {}; +#endif + +RtApiJack :: RtApiJack() + :shouldAutoconnect_(true) { + // Nothing to do here. +#if !defined(__RTAUDIO_DEBUG__) + // Turn off Jack's internal error reporting. + jack_set_error_function( &jackSilentError ); +#endif +} + +RtApiJack :: ~RtApiJack() +{ + if ( stream_.state != STREAM_CLOSED ) closeStream(); +} + +unsigned int RtApiJack :: getDeviceCount( void ) +{ + // See if we can become a jack client. + jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption; + jack_status_t *status = NULL; + jack_client_t *client = jack_client_open( "RtApiJackCount", options, status ); + if ( client == 0 ) return 0; + + const char **ports; + std::string port, previousPort; + unsigned int nChannels = 0, nDevices = 0; + ports = jack_get_ports( client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0 ); + if ( ports ) { + // Parse the port names up to the first colon (:). + size_t iColon = 0; + do { + port = (char *) ports[ nChannels ]; + iColon = port.find(":"); + if ( iColon != std::string::npos ) { + port = port.substr( 0, iColon + 1 ); + if ( port != previousPort ) { + nDevices++; + previousPort = port; + } + } + } while ( ports[++nChannels] ); + free( ports ); + } + + jack_client_close( client ); + return nDevices; +} + +RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device ) +{ + RtAudio::DeviceInfo info; + info.probed = false; + + jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption + jack_status_t *status = NULL; + jack_client_t *client = jack_client_open( "RtApiJackInfo", options, status ); + if ( client == 0 ) { + errorText_ = "RtApiJack::getDeviceInfo: Jack server not found or connection error!"; + error( RtAudioError::WARNING ); + return info; + } + + const char **ports; + std::string port, previousPort; + unsigned int nPorts = 0, nDevices = 0; + ports = jack_get_ports( client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0 ); + if ( ports ) { + // Parse the port names up to the first colon (:). + size_t iColon = 0; + do { + port = (char *) ports[ nPorts ]; + iColon = port.find(":"); + if ( iColon != std::string::npos ) { + port = port.substr( 0, iColon ); + if ( port != previousPort ) { + if ( nDevices == device ) info.name = port; + nDevices++; + previousPort = port; + } + } + } while ( ports[++nPorts] ); + free( ports ); + } + + if ( device >= nDevices ) { + jack_client_close( client ); + errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + // Get the current jack server sample rate. + info.sampleRates.clear(); + + info.preferredSampleRate = jack_get_sample_rate( client ); + info.sampleRates.push_back( info.preferredSampleRate ); + + // Count the available ports containing the client name as device + // channels. Jack "input ports" equal RtAudio output channels. + unsigned int nChannels = 0; + ports = jack_get_ports( client, info.name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput ); + if ( ports ) { + while ( ports[ nChannels ] ) nChannels++; + free( ports ); + info.outputChannels = nChannels; + } + + // Jack "output ports" equal RtAudio input channels. + nChannels = 0; + ports = jack_get_ports( client, info.name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput ); + if ( ports ) { + while ( ports[ nChannels ] ) nChannels++; + free( ports ); + info.inputChannels = nChannels; + } + + if ( info.outputChannels == 0 && info.inputChannels == 0 ) { + jack_client_close(client); + errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!"; + error( RtAudioError::WARNING ); + return info; + } + + // If device opens for both playback and capture, we determine the channels. + if ( info.outputChannels > 0 && info.inputChannels > 0 ) + info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; + + // Jack always uses 32-bit floats. + info.nativeFormats = RTAUDIO_FLOAT32; + + // Jack doesn't provide default devices so we'll use the first available one. + if ( device == 0 && info.outputChannels > 0 ) + info.isDefaultOutput = true; + if ( device == 0 && info.inputChannels > 0 ) + info.isDefaultInput = true; + + jack_client_close(client); + info.probed = true; + return info; +} + +static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer ) +{ + CallbackInfo *info = (CallbackInfo *) infoPointer; + + RtApiJack *object = (RtApiJack *) info->object; + if ( object->callbackEvent( (unsigned long) nframes ) == false ) return 1; + + return 0; +} + +// This function will be called by a spawned thread when the Jack +// server signals that it is shutting down. It is necessary to handle +// it this way because the jackShutdown() function must return before +// the jack_deactivate() function (in closeStream()) will return. +static void *jackCloseStream( void *ptr ) +{ + CallbackInfo *info = (CallbackInfo *) ptr; + RtApiJack *object = (RtApiJack *) info->object; + + object->closeStream(); + + pthread_exit( NULL ); +} +static void jackShutdown( void *infoPointer ) +{ + CallbackInfo *info = (CallbackInfo *) infoPointer; + RtApiJack *object = (RtApiJack *) info->object; + + // Check current stream state. If stopped, then we'll assume this + // was called as a result of a call to RtApiJack::stopStream (the + // deactivation of a client handle causes this function to be called). + // If not, we'll assume the Jack server is shutting down or some + // other problem occurred and we should close the stream. + if ( object->isStreamRunning() == false ) return; + + ThreadHandle threadId; + pthread_create( &threadId, NULL, jackCloseStream, info ); + std::cerr << "\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\n" << std::endl; +} + +static int jackXrun( void *infoPointer ) +{ + JackHandle *handle = *((JackHandle **) infoPointer); + + if ( handle->ports[0] ) handle->xrun[0] = true; + if ( handle->ports[1] ) handle->xrun[1] = true; + + return 0; +} + +bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) +{ + JackHandle *handle = (JackHandle *) stream_.apiHandle; + + // Look for jack server and try to become a client (only do once per stream). + jack_client_t *client = 0; + if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) { + jack_options_t jackoptions = (jack_options_t) ( JackNoStartServer ); //JackNullOption; + jack_status_t *status = NULL; + if ( options && !options->streamName.empty() ) + client = jack_client_open( options->streamName.c_str(), jackoptions, status ); + else + client = jack_client_open( "RtApiJack", jackoptions, status ); + if ( client == 0 ) { + errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!"; + error( RtAudioError::WARNING ); + return FAILURE; + } + } + else { + // The handle must have been created on an earlier pass. + client = handle->client; + } + + const char **ports; + std::string port, previousPort, deviceName; + unsigned int nPorts = 0, nDevices = 0; + ports = jack_get_ports( client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0 ); + if ( ports ) { + // Parse the port names up to the first colon (:). + size_t iColon = 0; + do { + port = (char *) ports[ nPorts ]; + iColon = port.find(":"); + if ( iColon != std::string::npos ) { + port = port.substr( 0, iColon ); + if ( port != previousPort ) { + if ( nDevices == device ) deviceName = port; + nDevices++; + previousPort = port; + } + } + } while ( ports[++nPorts] ); + free( ports ); + } + + if ( device >= nDevices ) { + errorText_ = "RtApiJack::probeDeviceOpen: device ID is invalid!"; + return FAILURE; + } + + unsigned long flag = JackPortIsInput; + if ( mode == INPUT ) flag = JackPortIsOutput; + + if ( ! (options && (options->flags & RTAUDIO_JACK_DONT_CONNECT)) ) { + // Count the available ports containing the client name as device + // channels. Jack "input ports" equal RtAudio output channels. + unsigned int nChannels = 0; + ports = jack_get_ports( client, deviceName.c_str(), JACK_DEFAULT_AUDIO_TYPE, flag ); + if ( ports ) { + while ( ports[ nChannels ] ) nChannels++; + free( ports ); + } + // Compare the jack ports for specified client to the requested number of channels. + if ( nChannels < (channels + firstChannel) ) { + errorStream_ << "RtApiJack::probeDeviceOpen: requested number of channels (" << channels << ") + offset (" << firstChannel << ") not found for specified device (" << device << ":" << deviceName << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + + // Check the jack server sample rate. + unsigned int jackRate = jack_get_sample_rate( client ); + if ( sampleRate != jackRate ) { + jack_client_close( client ); + errorStream_ << "RtApiJack::probeDeviceOpen: the requested sample rate (" << sampleRate << ") is different than the JACK server rate (" << jackRate << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + stream_.sampleRate = jackRate; + + // Get the latency of the JACK port. + ports = jack_get_ports( client, deviceName.c_str(), JACK_DEFAULT_AUDIO_TYPE, flag ); + if ( ports[ firstChannel ] ) { + // Added by Ge Wang + jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency); + // the range (usually the min and max are equal) + jack_latency_range_t latrange; latrange.min = latrange.max = 0; + // get the latency range + jack_port_get_latency_range( jack_port_by_name( client, ports[firstChannel] ), cbmode, &latrange ); + // be optimistic, use the min! + stream_.latency[mode] = latrange.min; + //stream_.latency[mode] = jack_port_get_latency( jack_port_by_name( client, ports[ firstChannel ] ) ); + } + free( ports ); + + // The jack server always uses 32-bit floating-point data. + stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; + stream_.userFormat = format; + + if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; + else stream_.userInterleaved = true; + + // Jack always uses non-interleaved buffers. + stream_.deviceInterleaved[mode] = false; + + // Jack always provides host byte-ordered data. + stream_.doByteSwap[mode] = false; + + // Get the buffer size. The buffer size and number of buffers + // (periods) is set when the jack server is started. + stream_.bufferSize = (int) jack_get_buffer_size( client ); + *bufferSize = stream_.bufferSize; + + stream_.nDeviceChannels[mode] = channels; + stream_.nUserChannels[mode] = channels; + + // Set flags for buffer conversion. + stream_.doConvertBuffer[mode] = false; + if ( stream_.userFormat != stream_.deviceFormat[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && + stream_.nUserChannels[mode] > 1 ) + stream_.doConvertBuffer[mode] = true; + + // Allocate our JackHandle structure for the stream. + if ( handle == 0 ) { + try { + handle = new JackHandle; + } + catch ( std::bad_alloc& ) { + errorText_ = "RtApiJack::probeDeviceOpen: error allocating JackHandle memory."; + goto error; + } + + if ( pthread_cond_init(&handle->condition, NULL) ) { + errorText_ = "RtApiJack::probeDeviceOpen: error initializing pthread condition variable."; + goto error; + } + stream_.apiHandle = (void *) handle; + handle->client = client; + } + handle->deviceName[mode] = deviceName; + + // Allocate necessary internal buffers. + unsigned long bufferBytes; + bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); + if ( stream_.userBuffer[mode] == NULL ) { + errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory."; + goto error; + } + + if ( stream_.doConvertBuffer[mode] ) { + + bool makeBuffer = true; + if ( mode == OUTPUT ) + bufferBytes = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); + else { // mode == INPUT + bufferBytes = stream_.nDeviceChannels[1] * formatBytes( stream_.deviceFormat[1] ); + if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { + unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); + if ( bufferBytes < bytesOut ) makeBuffer = false; + } + } + + if ( makeBuffer ) { + bufferBytes *= *bufferSize; + if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); + stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); + if ( stream_.deviceBuffer == NULL ) { + errorText_ = "RtApiJack::probeDeviceOpen: error allocating device buffer memory."; + goto error; + } + } + } + + // Allocate memory for the Jack ports (channels) identifiers. + handle->ports[mode] = (jack_port_t **) malloc ( sizeof (jack_port_t *) * channels ); + if ( handle->ports[mode] == NULL ) { + errorText_ = "RtApiJack::probeDeviceOpen: error allocating port memory."; + goto error; + } + + stream_.device[mode] = device; + stream_.channelOffset[mode] = firstChannel; + stream_.state = STREAM_STOPPED; + stream_.callbackInfo.object = (void *) this; + + if ( stream_.mode == OUTPUT && mode == INPUT ) + // We had already set up the stream for output. + stream_.mode = DUPLEX; + else { + stream_.mode = mode; + jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo ); + jack_set_xrun_callback( handle->client, jackXrun, (void *) &stream_.apiHandle ); + jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo ); + } + + // Register our ports. + char label[64]; + if ( mode == OUTPUT ) { + for ( unsigned int i=0; iports[0][i] = jack_port_register( handle->client, (const char *)label, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); + } + } + else { + for ( unsigned int i=0; iports[1][i] = jack_port_register( handle->client, (const char *)label, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ); + } + } + + // Setup the buffer conversion information structure. We don't use + // buffers to do channel offsets, so we override that parameter + // here. + if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 ); + + if ( options && options->flags & RTAUDIO_JACK_DONT_CONNECT ) shouldAutoconnect_ = false; + + return SUCCESS; + + error: + if ( handle ) { + pthread_cond_destroy( &handle->condition ); + jack_client_close( handle->client ); + + if ( handle->ports[0] ) free( handle->ports[0] ); + if ( handle->ports[1] ) free( handle->ports[1] ); + + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + return FAILURE; +} + +void RtApiJack :: closeStream( void ) +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiJack::closeStream(): no open stream to close!"; + error( RtAudioError::WARNING ); + return; + } + + JackHandle *handle = (JackHandle *) stream_.apiHandle; + if ( handle ) { + + if ( stream_.state == STREAM_RUNNING ) + jack_deactivate( handle->client ); + + jack_client_close( handle->client ); + } + + if ( handle ) { + if ( handle->ports[0] ) free( handle->ports[0] ); + if ( handle->ports[1] ) free( handle->ports[1] ); + pthread_cond_destroy( &handle->condition ); + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.mode = UNINITIALIZED; + stream_.state = STREAM_CLOSED; +} + +void RtApiJack :: startStream( void ) +{ + verifyStream(); + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiJack::startStream(): the stream is already running!"; + error( RtAudioError::WARNING ); + return; + } + + #if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); + #endif + + JackHandle *handle = (JackHandle *) stream_.apiHandle; + int result = jack_activate( handle->client ); + if ( result ) { + errorText_ = "RtApiJack::startStream(): unable to activate JACK client!"; + goto unlock; + } + + const char **ports; + + // Get the list of available ports. + if ( shouldAutoconnect_ && (stream_.mode == OUTPUT || stream_.mode == DUPLEX) ) { + result = 1; + ports = jack_get_ports( handle->client, handle->deviceName[0].c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput); + if ( ports == NULL) { + errorText_ = "RtApiJack::startStream(): error determining available JACK input ports!"; + goto unlock; + } + + // Now make the port connections. Since RtAudio wasn't designed to + // allow the user to select particular channels of a device, we'll + // just open the first "nChannels" ports with offset. + for ( unsigned int i=0; iclient, jack_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] ); + if ( result ) { + free( ports ); + errorText_ = "RtApiJack::startStream(): error connecting output ports!"; + goto unlock; + } + } + free(ports); + } + + if ( shouldAutoconnect_ && (stream_.mode == INPUT || stream_.mode == DUPLEX) ) { + result = 1; + ports = jack_get_ports( handle->client, handle->deviceName[1].c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput ); + if ( ports == NULL) { + errorText_ = "RtApiJack::startStream(): error determining available JACK output ports!"; + goto unlock; + } + + // Now make the port connections. See note above. + for ( unsigned int i=0; iclient, ports[ stream_.channelOffset[1] + i ], jack_port_name( handle->ports[1][i] ) ); + if ( result ) { + free( ports ); + errorText_ = "RtApiJack::startStream(): error connecting input ports!"; + goto unlock; + } + } + free(ports); + } + + handle->drainCounter = 0; + handle->internalDrain = false; + stream_.state = STREAM_RUNNING; + + unlock: + if ( result == 0 ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiJack :: stopStream( void ) +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiJack::stopStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + JackHandle *handle = (JackHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + if ( handle->drainCounter == 0 ) { + handle->drainCounter = 2; + pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled + } + } + + jack_deactivate( handle->client ); + stream_.state = STREAM_STOPPED; +} + +void RtApiJack :: abortStream( void ) +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiJack::abortStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + JackHandle *handle = (JackHandle *) stream_.apiHandle; + handle->drainCounter = 2; + + stopStream(); +} + +// This function will be called by a spawned thread when the user +// callback function signals that the stream should be stopped or +// aborted. It is necessary to handle it this way because the +// callbackEvent() function must return before the jack_deactivate() +// function will return. +static void *jackStopStream( void *ptr ) +{ + CallbackInfo *info = (CallbackInfo *) ptr; + RtApiJack *object = (RtApiJack *) info->object; + + object->stopStream(); + pthread_exit( NULL ); +} + +bool RtApiJack :: callbackEvent( unsigned long nframes ) +{ + if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!"; + error( RtAudioError::WARNING ); + return FAILURE; + } + if ( stream_.bufferSize != nframes ) { + errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!"; + error( RtAudioError::WARNING ); + return FAILURE; + } + + CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; + JackHandle *handle = (JackHandle *) stream_.apiHandle; + + // Check if we were draining the stream and signal is finished. + if ( handle->drainCounter > 3 ) { + ThreadHandle threadId; + + stream_.state = STREAM_STOPPING; + if ( handle->internalDrain == true ) + pthread_create( &threadId, NULL, jackStopStream, info ); + else + pthread_cond_signal( &handle->condition ); + return SUCCESS; + } + + // Invoke user callback first, to get fresh output data. + if ( handle->drainCounter == 0 ) { + RtAudioCallback callback = (RtAudioCallback) info->callback; + double streamTime = getStreamTime(); + RtAudioStreamStatus status = 0; + if ( stream_.mode != INPUT && handle->xrun[0] == true ) { + status |= RTAUDIO_OUTPUT_UNDERFLOW; + handle->xrun[0] = false; + } + if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { + status |= RTAUDIO_INPUT_OVERFLOW; + handle->xrun[1] = false; + } + int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], + stream_.bufferSize, streamTime, status, info->userData ); + if ( cbReturnValue == 2 ) { + stream_.state = STREAM_STOPPING; + handle->drainCounter = 2; + ThreadHandle id; + pthread_create( &id, NULL, jackStopStream, info ); + return SUCCESS; + } + else if ( cbReturnValue == 1 ) { + handle->drainCounter = 1; + handle->internalDrain = true; + } + } + + jack_default_audio_sample_t *jackbuffer; + unsigned long bufferBytes = nframes * sizeof( jack_default_audio_sample_t ); + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + if ( handle->drainCounter > 1 ) { // write zeros to the output stream + + for ( unsigned int i=0; iports[0][i], (jack_nframes_t) nframes ); + memset( jackbuffer, 0, bufferBytes ); + } + + } + else if ( stream_.doConvertBuffer[0] ) { + + convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); + + for ( unsigned int i=0; iports[0][i], (jack_nframes_t) nframes ); + memcpy( jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes ); + } + } + else { // no buffer conversion + for ( unsigned int i=0; iports[0][i], (jack_nframes_t) nframes ); + memcpy( jackbuffer, &stream_.userBuffer[0][i*bufferBytes], bufferBytes ); + } + } + } + + // Don't bother draining input + if ( handle->drainCounter ) { + handle->drainCounter++; + goto unlock; + } + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { + + if ( stream_.doConvertBuffer[1] ) { + for ( unsigned int i=0; iports[1][i], (jack_nframes_t) nframes ); + memcpy( &stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes ); + } + convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); + } + else { // no buffer conversion + for ( unsigned int i=0; iports[1][i], (jack_nframes_t) nframes ); + memcpy( &stream_.userBuffer[1][i*bufferBytes], jackbuffer, bufferBytes ); + } + } + } + + unlock: + RtApi::tickStreamTime(); + return SUCCESS; +} + //******************** End of __UNIX_JACK__ *********************// +#endif + +#if defined(__WINDOWS_ASIO__) // ASIO API on Windows + +// The ASIO API is designed around a callback scheme, so this +// implementation is similar to that used for OS-X CoreAudio and Linux +// Jack. The primary constraint with ASIO is that it only allows +// access to a single driver at a time. Thus, it is not possible to +// have more than one simultaneous RtAudio stream. +// +// This implementation also requires a number of external ASIO files +// and a few global variables. The ASIO callback scheme does not +// allow for the passing of user data, so we must create a global +// pointer to our callbackInfo structure. +// +// On unix systems, we make use of a pthread condition variable. +// Since there is no equivalent in Windows, I hacked something based +// on information found in +// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. + +#include "asiosys.h" +#include "asio.h" +#include "iasiothiscallresolver.h" +#include "asiodrivers.h" +#include + +static AsioDrivers drivers; +static ASIOCallbacks asioCallbacks; +static ASIODriverInfo driverInfo; +static CallbackInfo *asioCallbackInfo; +static bool asioXRun; + +struct AsioHandle { + int drainCounter; // Tracks callback counts when draining + bool internalDrain; // Indicates if stop is initiated from callback or not. + ASIOBufferInfo *bufferInfos; + HANDLE condition; + + AsioHandle() + :drainCounter(0), internalDrain(false), bufferInfos(0) {} +}; + +// Function declarations (definitions at end of section) +static const char* getAsioErrorString( ASIOError result ); +static void sampleRateChanged( ASIOSampleRate sRate ); +static long asioMessages( long selector, long value, void* message, double* opt ); + +RtApiAsio :: RtApiAsio() +{ + // ASIO cannot run on a multi-threaded appartment. You can call + // CoInitialize beforehand, but it must be for appartment threading + // (in which case, CoInitilialize will return S_FALSE here). + coInitialized_ = false; + HRESULT hr = CoInitialize( NULL ); + if ( FAILED(hr) ) { + errorText_ = "RtApiAsio::ASIO requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)"; + error( RtAudioError::WARNING ); + } + coInitialized_ = true; + + drivers.removeCurrentDriver(); + driverInfo.asioVersion = 2; + + // See note in DirectSound implementation about GetDesktopWindow(). + driverInfo.sysRef = GetForegroundWindow(); +} + +RtApiAsio :: ~RtApiAsio() +{ + if ( stream_.state != STREAM_CLOSED ) closeStream(); + if ( coInitialized_ ) CoUninitialize(); +} + +unsigned int RtApiAsio :: getDeviceCount( void ) +{ + return (unsigned int) drivers.asioGetNumDev(); +} + +RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device ) +{ + RtAudio::DeviceInfo info; + info.probed = false; + + // Get device ID + unsigned int nDevices = getDeviceCount(); + if ( nDevices == 0 ) { + errorText_ = "RtApiAsio::getDeviceInfo: no devices found!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + if ( device >= nDevices ) { + errorText_ = "RtApiAsio::getDeviceInfo: device ID is invalid!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + // If a stream is already open, we cannot probe other devices. Thus, use the saved results. + if ( stream_.state != STREAM_CLOSED ) { + if ( device >= devices_.size() ) { + errorText_ = "RtApiAsio::getDeviceInfo: device ID was not present before stream was opened."; + error( RtAudioError::WARNING ); + return info; + } + return devices_[ device ]; + } + + char driverName[32]; + ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::getDeviceInfo: unable to get driver name (" << getAsioErrorString( result ) << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + info.name = driverName; + + if ( !drivers.loadDriver( driverName ) ) { + errorStream_ << "RtApiAsio::getDeviceInfo: unable to load driver (" << driverName << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + result = ASIOInit( &driverInfo ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Determine the device channel information. + long inputChannels, outputChannels; + result = ASIOGetChannels( &inputChannels, &outputChannels ); + if ( result != ASE_OK ) { + drivers.removeCurrentDriver(); + errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + info.outputChannels = outputChannels; + info.inputChannels = inputChannels; + if ( info.outputChannels > 0 && info.inputChannels > 0 ) + info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; + + // Determine the supported sample rates. + info.sampleRates.clear(); + for ( unsigned int i=0; i info.preferredSampleRate ) ) + info.preferredSampleRate = SAMPLE_RATES[i]; + } + } + + // Determine supported data types ... just check first channel and assume rest are the same. + ASIOChannelInfo channelInfo; + channelInfo.channel = 0; + channelInfo.isInput = true; + if ( info.inputChannels <= 0 ) channelInfo.isInput = false; + result = ASIOGetChannelInfo( &channelInfo ); + if ( result != ASE_OK ) { + drivers.removeCurrentDriver(); + errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting driver channel info (" << driverName << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + info.nativeFormats = 0; + if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) + info.nativeFormats |= RTAUDIO_SINT16; + else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) + info.nativeFormats |= RTAUDIO_SINT32; + else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) + info.nativeFormats |= RTAUDIO_FLOAT32; + else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) + info.nativeFormats |= RTAUDIO_FLOAT64; + else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) + info.nativeFormats |= RTAUDIO_SINT24; + + if ( info.outputChannels > 0 ) + if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true; + if ( info.inputChannels > 0 ) + if ( getDefaultInputDevice() == device ) info.isDefaultInput = true; + + info.probed = true; + drivers.removeCurrentDriver(); + return info; +} + +static void bufferSwitch( long index, ASIOBool /*processNow*/ ) +{ + RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object; + object->callbackEvent( index ); +} + +void RtApiAsio :: saveDeviceInfo( void ) +{ + devices_.clear(); + + unsigned int nDevices = getDeviceCount(); + devices_.resize( nDevices ); + for ( unsigned int i=0; isaveDeviceInfo(); + + if ( !drivers.loadDriver( driverName ) ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: unable to load driver (" << driverName << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + result = ASIOInit( &driverInfo ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + + // keep them before any "goto error", they are used for error cleanup + goto device boundary checks + bool buffersAllocated = false; + AsioHandle *handle = (AsioHandle *) stream_.apiHandle; + unsigned int nChannels; + + + // Check the device channel count. + long inputChannels, outputChannels; + result = ASIOGetChannels( &inputChannels, &outputChannels ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ")."; + errorText_ = errorStream_.str(); + goto error; + } + + if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) || + ( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested channel count (" << channels << ") + offset (" << firstChannel << ")."; + errorText_ = errorStream_.str(); + goto error; + } + stream_.nDeviceChannels[mode] = channels; + stream_.nUserChannels[mode] = channels; + stream_.channelOffset[mode] = firstChannel; + + // Verify the sample rate is supported. + result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested sample rate (" << sampleRate << ")."; + errorText_ = errorStream_.str(); + goto error; + } + + // Get the current sample rate + ASIOSampleRate currentRate; + result = ASIOGetSampleRate( ¤tRate ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate."; + errorText_ = errorStream_.str(); + goto error; + } + + // Set the sample rate only if necessary + if ( currentRate != sampleRate ) { + result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ")."; + errorText_ = errorStream_.str(); + goto error; + } + } + + // Determine the driver data type. + ASIOChannelInfo channelInfo; + channelInfo.channel = 0; + if ( mode == OUTPUT ) channelInfo.isInput = false; + else channelInfo.isInput = true; + result = ASIOGetChannelInfo( &channelInfo ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting data format."; + errorText_ = errorStream_.str(); + goto error; + } + + // Assuming WINDOWS host is always little-endian. + stream_.doByteSwap[mode] = false; + stream_.userFormat = format; + stream_.deviceFormat[mode] = 0; + if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) { + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + if ( channelInfo.type == ASIOSTInt16MSB ) stream_.doByteSwap[mode] = true; + } + else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) { + stream_.deviceFormat[mode] = RTAUDIO_SINT32; + if ( channelInfo.type == ASIOSTInt32MSB ) stream_.doByteSwap[mode] = true; + } + else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) { + stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; + if ( channelInfo.type == ASIOSTFloat32MSB ) stream_.doByteSwap[mode] = true; + } + else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) { + stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; + if ( channelInfo.type == ASIOSTFloat64MSB ) stream_.doByteSwap[mode] = true; + } + else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) { + stream_.deviceFormat[mode] = RTAUDIO_SINT24; + if ( channelInfo.type == ASIOSTInt24MSB ) stream_.doByteSwap[mode] = true; + } + + if ( stream_.deviceFormat[mode] == 0 ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") data format not supported by RtAudio."; + errorText_ = errorStream_.str(); + goto error; + } + + // Set the buffer size. For a duplex stream, this will end up + // setting the buffer size based on the input constraints, which + // should be ok. + long minSize, maxSize, preferSize, granularity; + result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting buffer size."; + errorText_ = errorStream_.str(); + goto error; + } + + if ( isDuplexInput ) { + // When this is the duplex input (output was opened before), then we have to use the same + // buffersize as the output, because it might use the preferred buffer size, which most + // likely wasn't passed as input to this. The buffer sizes have to be identically anyway, + // So instead of throwing an error, make them equal. The caller uses the reference + // to the "bufferSize" param as usual to set up processing buffers. + + *bufferSize = stream_.bufferSize; + + } else { + if ( *bufferSize == 0 ) *bufferSize = preferSize; + else if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize; + else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize; + else if ( granularity == -1 ) { + // Make sure bufferSize is a power of two. + int log2_of_min_size = 0; + int log2_of_max_size = 0; + + for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) { + if ( minSize & ((long)1 << i) ) log2_of_min_size = i; + if ( maxSize & ((long)1 << i) ) log2_of_max_size = i; + } + + long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) ); + int min_delta_num = log2_of_min_size; + + for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) { + long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) ); + if (current_delta < min_delta) { + min_delta = current_delta; + min_delta_num = i; + } + } + + *bufferSize = ( (unsigned int)1 << min_delta_num ); + if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize; + else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize; + } + else if ( granularity != 0 ) { + // Set to an even multiple of granularity, rounding up. + *bufferSize = (*bufferSize + granularity-1) / granularity * granularity; + } + } + + /* + // we don't use it anymore, see above! + // Just left it here for the case... + if ( isDuplexInput && stream_.bufferSize != *bufferSize ) { + errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!"; + goto error; + } + */ + + stream_.bufferSize = *bufferSize; + stream_.nBuffers = 2; + + if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; + else stream_.userInterleaved = true; + + // ASIO always uses non-interleaved buffers. + stream_.deviceInterleaved[mode] = false; + + // Allocate, if necessary, our AsioHandle structure for the stream. + if ( handle == 0 ) { + try { + handle = new AsioHandle; + } + catch ( std::bad_alloc& ) { + errorText_ = "RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory."; + goto error; + } + handle->bufferInfos = 0; + + // Create a manual-reset event. + handle->condition = CreateEvent( NULL, // no security + TRUE, // manual-reset + FALSE, // non-signaled initially + NULL ); // unnamed + stream_.apiHandle = (void *) handle; + } + + // Create the ASIO internal buffers. Since RtAudio sets up input + // and output separately, we'll have to dispose of previously + // created output buffers for a duplex stream. + if ( mode == INPUT && stream_.mode == OUTPUT ) { + ASIODisposeBuffers(); + if ( handle->bufferInfos ) free( handle->bufferInfos ); + } + + // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure. + unsigned int i; + nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; + handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) ); + if ( handle->bufferInfos == NULL ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (" << driverName << ")."; + errorText_ = errorStream_.str(); + goto error; + } + + ASIOBufferInfo *infos; + infos = handle->bufferInfos; + for ( i=0; iisInput = ASIOFalse; + infos->channelNum = i + stream_.channelOffset[0]; + infos->buffers[0] = infos->buffers[1] = 0; + } + for ( i=0; iisInput = ASIOTrue; + infos->channelNum = i + stream_.channelOffset[1]; + infos->buffers[0] = infos->buffers[1] = 0; + } + + // prepare for callbacks + stream_.sampleRate = sampleRate; + stream_.device[mode] = device; + stream_.mode = isDuplexInput ? DUPLEX : mode; + + // store this class instance before registering callbacks, that are going to use it + asioCallbackInfo = &stream_.callbackInfo; + stream_.callbackInfo.object = (void *) this; + + // Set up the ASIO callback structure and create the ASIO data buffers. + asioCallbacks.bufferSwitch = &bufferSwitch; + asioCallbacks.sampleRateDidChange = &sampleRateChanged; + asioCallbacks.asioMessage = &asioMessages; + asioCallbacks.bufferSwitchTimeInfo = NULL; + result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks ); + if ( result != ASE_OK ) { + // Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges + // but only accept the preferred buffer size as parameter for ASIOCreateBuffers (e.g. Creative's ASIO driver). + // In that case, let's be naïve and try that instead. + *bufferSize = preferSize; + stream_.bufferSize = *bufferSize; + result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks ); + } + + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") creating buffers."; + errorText_ = errorStream_.str(); + goto error; + } + buffersAllocated = true; + stream_.state = STREAM_STOPPED; + + // Set flags for buffer conversion. + stream_.doConvertBuffer[mode] = false; + if ( stream_.userFormat != stream_.deviceFormat[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && + stream_.nUserChannels[mode] > 1 ) + stream_.doConvertBuffer[mode] = true; + + // Allocate necessary internal buffers + unsigned long bufferBytes; + bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); + if ( stream_.userBuffer[mode] == NULL ) { + errorText_ = "RtApiAsio::probeDeviceOpen: error allocating user buffer memory."; + goto error; + } + + if ( stream_.doConvertBuffer[mode] ) { + + bool makeBuffer = true; + bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); + if ( isDuplexInput && stream_.deviceBuffer ) { + unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); + if ( bufferBytes <= bytesOut ) makeBuffer = false; + } + + if ( makeBuffer ) { + bufferBytes *= *bufferSize; + if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); + stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); + if ( stream_.deviceBuffer == NULL ) { + errorText_ = "RtApiAsio::probeDeviceOpen: error allocating device buffer memory."; + goto error; + } + } + } + + // Determine device latencies + long inputLatency, outputLatency; + result = ASIOGetLatencies( &inputLatency, &outputLatency ); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting latency."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING); // warn but don't fail + } + else { + stream_.latency[0] = outputLatency; + stream_.latency[1] = inputLatency; + } + + // Setup the buffer conversion information structure. We don't use + // buffers to do channel offsets, so we override that parameter + // here. + if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 ); + + return SUCCESS; + + error: + if ( !isDuplexInput ) { + // the cleanup for error in the duplex input, is done by RtApi::openStream + // So we clean up for single channel only + + if ( buffersAllocated ) + ASIODisposeBuffers(); + + drivers.removeCurrentDriver(); + + if ( handle ) { + CloseHandle( handle->condition ); + if ( handle->bufferInfos ) + free( handle->bufferInfos ); + + delete handle; + stream_.apiHandle = 0; + } + + + if ( stream_.userBuffer[mode] ) { + free( stream_.userBuffer[mode] ); + stream_.userBuffer[mode] = 0; + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + } + + return FAILURE; +}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void RtApiAsio :: closeStream() +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiAsio::closeStream(): no open stream to close!"; + error( RtAudioError::WARNING ); + return; + } + + if ( stream_.state == STREAM_RUNNING ) { + stream_.state = STREAM_STOPPED; + ASIOStop(); + } + ASIODisposeBuffers(); + drivers.removeCurrentDriver(); + + AsioHandle *handle = (AsioHandle *) stream_.apiHandle; + if ( handle ) { + CloseHandle( handle->condition ); + if ( handle->bufferInfos ) + free( handle->bufferInfos ); + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.mode = UNINITIALIZED; + stream_.state = STREAM_CLOSED; +} + +bool stopThreadCalled = false; + +void RtApiAsio :: startStream() +{ + verifyStream(); + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiAsio::startStream(): the stream is already running!"; + error( RtAudioError::WARNING ); + return; + } + + #if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); + #endif + + AsioHandle *handle = (AsioHandle *) stream_.apiHandle; + ASIOError result = ASIOStart(); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::startStream: error (" << getAsioErrorString( result ) << ") starting device."; + errorText_ = errorStream_.str(); + goto unlock; + } + + handle->drainCounter = 0; + handle->internalDrain = false; + ResetEvent( handle->condition ); + stream_.state = STREAM_RUNNING; + asioXRun = false; + + unlock: + stopThreadCalled = false; + + if ( result == ASE_OK ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiAsio :: stopStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiAsio::stopStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + AsioHandle *handle = (AsioHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + if ( handle->drainCounter == 0 ) { + handle->drainCounter = 2; + WaitForSingleObject( handle->condition, INFINITE ); // block until signaled + } + } + + stream_.state = STREAM_STOPPED; + + ASIOError result = ASIOStop(); + if ( result != ASE_OK ) { + errorStream_ << "RtApiAsio::stopStream: error (" << getAsioErrorString( result ) << ") stopping device."; + errorText_ = errorStream_.str(); + } + + if ( result == ASE_OK ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiAsio :: abortStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiAsio::abortStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + // The following lines were commented-out because some behavior was + // noted where the device buffers need to be zeroed to avoid + // continuing sound, even when the device buffers are completely + // disposed. So now, calling abort is the same as calling stop. + // AsioHandle *handle = (AsioHandle *) stream_.apiHandle; + // handle->drainCounter = 2; + stopStream(); +} + +// This function will be called by a spawned thread when the user +// callback function signals that the stream should be stopped or +// aborted. It is necessary to handle it this way because the +// callbackEvent() function must return before the ASIOStop() +// function will return. +static unsigned __stdcall asioStopStream( void *ptr ) +{ + CallbackInfo *info = (CallbackInfo *) ptr; + RtApiAsio *object = (RtApiAsio *) info->object; + + object->stopStream(); + _endthreadex( 0 ); + return 0; +} + +bool RtApiAsio :: callbackEvent( long bufferIndex ) +{ + if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS; + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiAsio::callbackEvent(): the stream is closed ... this shouldn't happen!"; + error( RtAudioError::WARNING ); + return FAILURE; + } + + CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; + AsioHandle *handle = (AsioHandle *) stream_.apiHandle; + + // Check if we were draining the stream and signal if finished. + if ( handle->drainCounter > 3 ) { + + stream_.state = STREAM_STOPPING; + if ( handle->internalDrain == false ) + SetEvent( handle->condition ); + else { // spawn a thread to stop the stream + unsigned threadId; + stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream, + &stream_.callbackInfo, 0, &threadId ); + } + return SUCCESS; + } + + // Invoke user callback to get fresh output data UNLESS we are + // draining stream. + if ( handle->drainCounter == 0 ) { + RtAudioCallback callback = (RtAudioCallback) info->callback; + double streamTime = getStreamTime(); + RtAudioStreamStatus status = 0; + if ( stream_.mode != INPUT && asioXRun == true ) { + status |= RTAUDIO_OUTPUT_UNDERFLOW; + asioXRun = false; + } + if ( stream_.mode != OUTPUT && asioXRun == true ) { + status |= RTAUDIO_INPUT_OVERFLOW; + asioXRun = false; + } + int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], + stream_.bufferSize, streamTime, status, info->userData ); + if ( cbReturnValue == 2 ) { + stream_.state = STREAM_STOPPING; + handle->drainCounter = 2; + unsigned threadId; + stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream, + &stream_.callbackInfo, 0, &threadId ); + return SUCCESS; + } + else if ( cbReturnValue == 1 ) { + handle->drainCounter = 1; + handle->internalDrain = true; + } + } + + unsigned int nChannels, bufferBytes, i, j; + nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + bufferBytes = stream_.bufferSize * formatBytes( stream_.deviceFormat[0] ); + + if ( handle->drainCounter > 1 ) { // write zeros to the output stream + + for ( i=0, j=0; ibufferInfos[i].isInput != ASIOTrue ) + memset( handle->bufferInfos[i].buffers[bufferIndex], 0, bufferBytes ); + } + + } + else if ( stream_.doConvertBuffer[0] ) { + + convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] ); + if ( stream_.doByteSwap[0] ) + byteSwapBuffer( stream_.deviceBuffer, + stream_.bufferSize * stream_.nDeviceChannels[0], + stream_.deviceFormat[0] ); + + for ( i=0, j=0; ibufferInfos[i].isInput != ASIOTrue ) + memcpy( handle->bufferInfos[i].buffers[bufferIndex], + &stream_.deviceBuffer[j++*bufferBytes], bufferBytes ); + } + + } + else { + + if ( stream_.doByteSwap[0] ) + byteSwapBuffer( stream_.userBuffer[0], + stream_.bufferSize * stream_.nUserChannels[0], + stream_.userFormat ); + + for ( i=0, j=0; ibufferInfos[i].isInput != ASIOTrue ) + memcpy( handle->bufferInfos[i].buffers[bufferIndex], + &stream_.userBuffer[0][bufferBytes*j++], bufferBytes ); + } + + } + } + + // Don't bother draining input + if ( handle->drainCounter ) { + handle->drainCounter++; + goto unlock; + } + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { + + bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[1]); + + if (stream_.doConvertBuffer[1]) { + + // Always interleave ASIO input data. + for ( i=0, j=0; ibufferInfos[i].isInput == ASIOTrue ) + memcpy( &stream_.deviceBuffer[j++*bufferBytes], + handle->bufferInfos[i].buffers[bufferIndex], + bufferBytes ); + } + + if ( stream_.doByteSwap[1] ) + byteSwapBuffer( stream_.deviceBuffer, + stream_.bufferSize * stream_.nDeviceChannels[1], + stream_.deviceFormat[1] ); + convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); + + } + else { + for ( i=0, j=0; ibufferInfos[i].isInput == ASIOTrue ) { + memcpy( &stream_.userBuffer[1][bufferBytes*j++], + handle->bufferInfos[i].buffers[bufferIndex], + bufferBytes ); + } + } + + if ( stream_.doByteSwap[1] ) + byteSwapBuffer( stream_.userBuffer[1], + stream_.bufferSize * stream_.nUserChannels[1], + stream_.userFormat ); + } + } + + unlock: + // The following call was suggested by Malte Clasen. While the API + // documentation indicates it should not be required, some device + // drivers apparently do not function correctly without it. + ASIOOutputReady(); + + RtApi::tickStreamTime(); + return SUCCESS; +} + +static void sampleRateChanged( ASIOSampleRate sRate ) +{ + // The ASIO documentation says that this usually only happens during + // external sync. Audio processing is not stopped by the driver, + // actual sample rate might not have even changed, maybe only the + // sample rate status of an AES/EBU or S/PDIF digital input at the + // audio device. + + RtApi *object = (RtApi *) asioCallbackInfo->object; + try { + object->stopStream(); + } + catch ( RtAudioError &exception ) { + std::cerr << "\nRtApiAsio: sampleRateChanged() error (" << exception.getMessage() << ")!\n" << std::endl; + return; + } + + std::cerr << "\nRtApiAsio: driver reports sample rate changed to " << sRate << " ... stream stopped!!!\n" << std::endl; +} + +static long asioMessages( long selector, long value, void* /*message*/, double* /*opt*/ ) +{ + long ret = 0; + + switch( selector ) { + case kAsioSelectorSupported: + if ( value == kAsioResetRequest + || value == kAsioEngineVersion + || value == kAsioResyncRequest + || value == kAsioLatenciesChanged + // The following three were added for ASIO 2.0, you don't + // necessarily have to support them. + || value == kAsioSupportsTimeInfo + || value == kAsioSupportsTimeCode + || value == kAsioSupportsInputMonitor) + ret = 1L; + break; + case kAsioResetRequest: + // Defer the task and perform the reset of the driver during the + // next "safe" situation. You cannot reset the driver right now, + // as this code is called from the driver. Reset the driver is + // done by completely destruct is. I.e. ASIOStop(), + // ASIODisposeBuffers(), Destruction Afterwards you initialize the + // driver again. + std::cerr << "\nRtApiAsio: driver reset requested!!!" << std::endl; + ret = 1L; + break; + case kAsioResyncRequest: + // This informs the application that the driver encountered some + // non-fatal data loss. It is used for synchronization purposes + // of different media. Added mainly to work around the Win16Mutex + // problems in Windows 95/98 with the Windows Multimedia system, + // which could lose data because the Mutex was held too long by + // another thread. However a driver can issue it in other + // situations, too. + // std::cerr << "\nRtApiAsio: driver resync requested!!!" << std::endl; + asioXRun = true; + ret = 1L; + break; + case kAsioLatenciesChanged: + // This will inform the host application that the drivers were + // latencies changed. Beware, it this does not mean that the + // buffer sizes have changed! You might need to update internal + // delay data. + std::cerr << "\nRtApiAsio: driver latency may have changed!!!" << std::endl; + ret = 1L; + break; + case kAsioEngineVersion: + // Return the supported ASIO version of the host application. If + // a host application does not implement this selector, ASIO 1.0 + // is assumed by the driver. + ret = 2L; + break; + case kAsioSupportsTimeInfo: + // Informs the driver whether the + // asioCallbacks.bufferSwitchTimeInfo() callback is supported. + // For compatibility with ASIO 1.0 drivers the host application + // should always support the "old" bufferSwitch method, too. + ret = 0; + break; + case kAsioSupportsTimeCode: + // Informs the driver whether application is interested in time + // code info. If an application does not need to know about time + // code, the driver has less work to do. + ret = 0; + break; + } + return ret; +} + +static const char* getAsioErrorString( ASIOError result ) +{ + struct Messages + { + ASIOError value; + const char*message; + }; + + static const Messages m[] = + { + { ASE_NotPresent, "Hardware input or output is not present or available." }, + { ASE_HWMalfunction, "Hardware is malfunctioning." }, + { ASE_InvalidParameter, "Invalid input parameter." }, + { ASE_InvalidMode, "Invalid mode." }, + { ASE_SPNotAdvancing, "Sample position not advancing." }, + { ASE_NoClock, "Sample clock or rate cannot be determined or is not present." }, + { ASE_NoMemory, "Not enough memory to complete the request." } + }; + + for ( unsigned int i = 0; i < sizeof(m)/sizeof(m[0]); ++i ) + if ( m[i].value == result ) return m[i].message; + + return "Unknown error."; +} + +//******************** End of __WINDOWS_ASIO__ *********************// +#endif + + +#if defined(__WINDOWS_WASAPI__) // Windows WASAPI API + +// Authored by Marcus Tomlinson , April 2014 +// - Introduces support for the Windows WASAPI API +// - Aims to deliver bit streams to and from hardware at the lowest possible latency, via the absolute minimum buffer sizes required +// - Provides flexible stream configuration to an otherwise strict and inflexible WASAPI interface +// - Includes automatic internal conversion of sample rate and buffer size between hardware and the user + +#ifndef INITGUID + #define INITGUID +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef MF_E_TRANSFORM_NEED_MORE_INPUT + #define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xc00d6d72) +#endif + +#ifndef MFSTARTUP_NOSOCKET + #define MFSTARTUP_NOSOCKET 0x1 +#endif + +#ifdef _MSC_VER + #pragma comment( lib, "ksuser" ) + #pragma comment( lib, "mfplat.lib" ) + #pragma comment( lib, "mfuuid.lib" ) + #pragma comment( lib, "wmcodecdspuuid" ) +#endif + +//============================================================================= + +#define SAFE_RELEASE( objectPtr )\ +if ( objectPtr )\ +{\ + objectPtr->Release();\ + objectPtr = NULL;\ +} + +typedef HANDLE ( __stdcall *TAvSetMmThreadCharacteristicsPtr )( LPCWSTR TaskName, LPDWORD TaskIndex ); + +//----------------------------------------------------------------------------- + +// WASAPI dictates stream sample rate, format, channel count, and in some cases, buffer size. +// Therefore we must perform all necessary conversions to user buffers in order to satisfy these +// requirements. WasapiBuffer ring buffers are used between HwIn->UserIn and UserOut->HwOut to +// provide intermediate storage for read / write synchronization. +class WasapiBuffer +{ +public: + WasapiBuffer() + : buffer_( NULL ), + bufferSize_( 0 ), + inIndex_( 0 ), + outIndex_( 0 ) {} + + ~WasapiBuffer() { + free( buffer_ ); + } + + // sets the length of the internal ring buffer + void setBufferSize( unsigned int bufferSize, unsigned int formatBytes ) { + free( buffer_ ); + + buffer_ = ( char* ) calloc( bufferSize, formatBytes ); + + bufferSize_ = bufferSize; + inIndex_ = 0; + outIndex_ = 0; + } + + // attempt to push a buffer into the ring buffer at the current "in" index + bool pushBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format ) + { + if ( !buffer || // incoming buffer is NULL + bufferSize == 0 || // incoming buffer has no data + bufferSize > bufferSize_ ) // incoming buffer too large + { + return false; + } + + unsigned int relOutIndex = outIndex_; + unsigned int inIndexEnd = inIndex_ + bufferSize; + if ( relOutIndex < inIndex_ && inIndexEnd >= bufferSize_ ) { + relOutIndex += bufferSize_; + } + + // the "IN" index CAN BEGIN at the "OUT" index + // the "IN" index CANNOT END at the "OUT" index + if ( inIndex_ < relOutIndex && inIndexEnd >= relOutIndex ) { + return false; // not enough space between "in" index and "out" index + } + + // copy buffer from external to internal + int fromZeroSize = inIndex_ + bufferSize - bufferSize_; + fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize; + int fromInSize = bufferSize - fromZeroSize; + + switch( format ) + { + case RTAUDIO_SINT8: + memcpy( &( ( char* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( char ) ); + memcpy( buffer_, &( ( char* ) buffer )[fromInSize], fromZeroSize * sizeof( char ) ); + break; + case RTAUDIO_SINT16: + memcpy( &( ( short* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( short ) ); + memcpy( buffer_, &( ( short* ) buffer )[fromInSize], fromZeroSize * sizeof( short ) ); + break; + case RTAUDIO_SINT24: + memcpy( &( ( S24* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( S24 ) ); + memcpy( buffer_, &( ( S24* ) buffer )[fromInSize], fromZeroSize * sizeof( S24 ) ); + break; + case RTAUDIO_SINT32: + memcpy( &( ( int* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( int ) ); + memcpy( buffer_, &( ( int* ) buffer )[fromInSize], fromZeroSize * sizeof( int ) ); + break; + case RTAUDIO_FLOAT32: + memcpy( &( ( float* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( float ) ); + memcpy( buffer_, &( ( float* ) buffer )[fromInSize], fromZeroSize * sizeof( float ) ); + break; + case RTAUDIO_FLOAT64: + memcpy( &( ( double* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( double ) ); + memcpy( buffer_, &( ( double* ) buffer )[fromInSize], fromZeroSize * sizeof( double ) ); + break; + } + + // update "in" index + inIndex_ += bufferSize; + inIndex_ %= bufferSize_; + + return true; + } + + // attempt to pull a buffer from the ring buffer from the current "out" index + bool pullBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format ) + { + if ( !buffer || // incoming buffer is NULL + bufferSize == 0 || // incoming buffer has no data + bufferSize > bufferSize_ ) // incoming buffer too large + { + return false; + } + + unsigned int relInIndex = inIndex_; + unsigned int outIndexEnd = outIndex_ + bufferSize; + if ( relInIndex < outIndex_ && outIndexEnd >= bufferSize_ ) { + relInIndex += bufferSize_; + } + + // the "OUT" index CANNOT BEGIN at the "IN" index + // the "OUT" index CAN END at the "IN" index + if ( outIndex_ <= relInIndex && outIndexEnd > relInIndex ) { + return false; // not enough space between "out" index and "in" index + } + + // copy buffer from internal to external + int fromZeroSize = outIndex_ + bufferSize - bufferSize_; + fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize; + int fromOutSize = bufferSize - fromZeroSize; + + switch( format ) + { + case RTAUDIO_SINT8: + memcpy( buffer, &( ( char* ) buffer_ )[outIndex_], fromOutSize * sizeof( char ) ); + memcpy( &( ( char* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( char ) ); + break; + case RTAUDIO_SINT16: + memcpy( buffer, &( ( short* ) buffer_ )[outIndex_], fromOutSize * sizeof( short ) ); + memcpy( &( ( short* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( short ) ); + break; + case RTAUDIO_SINT24: + memcpy( buffer, &( ( S24* ) buffer_ )[outIndex_], fromOutSize * sizeof( S24 ) ); + memcpy( &( ( S24* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( S24 ) ); + break; + case RTAUDIO_SINT32: + memcpy( buffer, &( ( int* ) buffer_ )[outIndex_], fromOutSize * sizeof( int ) ); + memcpy( &( ( int* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( int ) ); + break; + case RTAUDIO_FLOAT32: + memcpy( buffer, &( ( float* ) buffer_ )[outIndex_], fromOutSize * sizeof( float ) ); + memcpy( &( ( float* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( float ) ); + break; + case RTAUDIO_FLOAT64: + memcpy( buffer, &( ( double* ) buffer_ )[outIndex_], fromOutSize * sizeof( double ) ); + memcpy( &( ( double* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( double ) ); + break; + } + + // update "out" index + outIndex_ += bufferSize; + outIndex_ %= bufferSize_; + + return true; + } + +private: + char* buffer_; + unsigned int bufferSize_; + unsigned int inIndex_; + unsigned int outIndex_; +}; + +//----------------------------------------------------------------------------- + +// In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate +// between HW and the user. The WasapiResampler class is used to perform this conversion between +// HwIn->UserIn and UserOut->HwOut during the stream callback loop. +class WasapiResampler +{ +public: + WasapiResampler( bool isFloat, unsigned int bitsPerSample, unsigned int channelCount, + unsigned int inSampleRate, unsigned int outSampleRate ) + : _bytesPerSample( bitsPerSample / 8 ) + , _channelCount( channelCount ) + , _sampleRatio( ( float ) outSampleRate / inSampleRate ) + , _transformUnk( NULL ) + , _transform( NULL ) + , _mediaType( NULL ) + , _inputMediaType( NULL ) + , _outputMediaType( NULL ) + + #ifdef __IWMResamplerProps_FWD_DEFINED__ + , _resamplerProps( NULL ) + #endif + { + // 1. Initialization + + MFStartup( MF_VERSION, MFSTARTUP_NOSOCKET ); + + // 2. Create Resampler Transform Object + + CoCreateInstance( CLSID_CResamplerMediaObject, NULL, CLSCTX_INPROC_SERVER, + IID_IUnknown, ( void** ) &_transformUnk ); + + _transformUnk->QueryInterface( IID_PPV_ARGS( &_transform ) ); + + #ifdef __IWMResamplerProps_FWD_DEFINED__ + _transformUnk->QueryInterface( IID_PPV_ARGS( &_resamplerProps ) ); + _resamplerProps->SetHalfFilterLength( 60 ); // best conversion quality + #endif + + // 3. Specify input / output format + + MFCreateMediaType( &_mediaType ); + _mediaType->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Audio ); + _mediaType->SetGUID( MF_MT_SUBTYPE, isFloat ? MFAudioFormat_Float : MFAudioFormat_PCM ); + _mediaType->SetUINT32( MF_MT_AUDIO_NUM_CHANNELS, channelCount ); + _mediaType->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, inSampleRate ); + _mediaType->SetUINT32( MF_MT_AUDIO_BLOCK_ALIGNMENT, _bytesPerSample * channelCount ); + _mediaType->SetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, _bytesPerSample * channelCount * inSampleRate ); + _mediaType->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample ); + _mediaType->SetUINT32( MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE ); + + MFCreateMediaType( &_inputMediaType ); + _mediaType->CopyAllItems( _inputMediaType ); + + _transform->SetInputType( 0, _inputMediaType, 0 ); + + MFCreateMediaType( &_outputMediaType ); + _mediaType->CopyAllItems( _outputMediaType ); + + _outputMediaType->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, outSampleRate ); + _outputMediaType->SetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, _bytesPerSample * channelCount * outSampleRate ); + + _transform->SetOutputType( 0, _outputMediaType, 0 ); + + // 4. Send stream start messages to Resampler + + _transform->ProcessMessage( MFT_MESSAGE_COMMAND_FLUSH, 0 ); + _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0 ); + _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0 ); + } + + ~WasapiResampler() + { + // 8. Send stream stop messages to Resampler + + _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0 ); + _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_STREAMING, 0 ); + + // 9. Cleanup + + MFShutdown(); + + SAFE_RELEASE( _transformUnk ); + SAFE_RELEASE( _transform ); + SAFE_RELEASE( _mediaType ); + SAFE_RELEASE( _inputMediaType ); + SAFE_RELEASE( _outputMediaType ); + + #ifdef __IWMResamplerProps_FWD_DEFINED__ + SAFE_RELEASE( _resamplerProps ); + #endif + } + + void Convert( char* outBuffer, const char* inBuffer, unsigned int inSampleCount, unsigned int& outSampleCount, int maxOutSampleCount = -1 ) + { + unsigned int inputBufferSize = _bytesPerSample * _channelCount * inSampleCount; + if ( _sampleRatio == 1 ) + { + // no sample rate conversion required + memcpy( outBuffer, inBuffer, inputBufferSize ); + outSampleCount = inSampleCount; + return; + } + + unsigned int outputBufferSize = 0; + if ( maxOutSampleCount != -1 ) + { + outputBufferSize = _bytesPerSample * _channelCount * maxOutSampleCount; + } + else + { + outputBufferSize = ( unsigned int ) ceilf( inputBufferSize * _sampleRatio ) + ( _bytesPerSample * _channelCount ); + } + + IMFMediaBuffer* rInBuffer; + IMFSample* rInSample; + BYTE* rInByteBuffer = NULL; + + // 5. Create Sample object from input data + + MFCreateMemoryBuffer( inputBufferSize, &rInBuffer ); + + rInBuffer->Lock( &rInByteBuffer, NULL, NULL ); + memcpy( rInByteBuffer, inBuffer, inputBufferSize ); + rInBuffer->Unlock(); + rInByteBuffer = NULL; + + rInBuffer->SetCurrentLength( inputBufferSize ); + + MFCreateSample( &rInSample ); + rInSample->AddBuffer( rInBuffer ); + + // 6. Pass input data to Resampler + + _transform->ProcessInput( 0, rInSample, 0 ); + + SAFE_RELEASE( rInBuffer ); + SAFE_RELEASE( rInSample ); + + // 7. Perform sample rate conversion + + IMFMediaBuffer* rOutBuffer = NULL; + BYTE* rOutByteBuffer = NULL; + + MFT_OUTPUT_DATA_BUFFER rOutDataBuffer; + DWORD rStatus; + DWORD rBytes = outputBufferSize; // maximum bytes accepted per ProcessOutput + + // 7.1 Create Sample object for output data + + memset( &rOutDataBuffer, 0, sizeof rOutDataBuffer ); + MFCreateSample( &( rOutDataBuffer.pSample ) ); + MFCreateMemoryBuffer( rBytes, &rOutBuffer ); + rOutDataBuffer.pSample->AddBuffer( rOutBuffer ); + rOutDataBuffer.dwStreamID = 0; + rOutDataBuffer.dwStatus = 0; + rOutDataBuffer.pEvents = NULL; + + // 7.2 Get output data from Resampler + + if ( _transform->ProcessOutput( 0, 1, &rOutDataBuffer, &rStatus ) == MF_E_TRANSFORM_NEED_MORE_INPUT ) + { + outSampleCount = 0; + SAFE_RELEASE( rOutBuffer ); + SAFE_RELEASE( rOutDataBuffer.pSample ); + return; + } + + // 7.3 Write output data to outBuffer + + SAFE_RELEASE( rOutBuffer ); + rOutDataBuffer.pSample->ConvertToContiguousBuffer( &rOutBuffer ); + rOutBuffer->GetCurrentLength( &rBytes ); + + rOutBuffer->Lock( &rOutByteBuffer, NULL, NULL ); + memcpy( outBuffer, rOutByteBuffer, rBytes ); + rOutBuffer->Unlock(); + rOutByteBuffer = NULL; + + outSampleCount = rBytes / _bytesPerSample / _channelCount; + SAFE_RELEASE( rOutBuffer ); + SAFE_RELEASE( rOutDataBuffer.pSample ); + } + +private: + unsigned int _bytesPerSample; + unsigned int _channelCount; + float _sampleRatio; + + IUnknown* _transformUnk; + IMFTransform* _transform; + IMFMediaType* _mediaType; + IMFMediaType* _inputMediaType; + IMFMediaType* _outputMediaType; + + #ifdef __IWMResamplerProps_FWD_DEFINED__ + IWMResamplerProps* _resamplerProps; + #endif +}; + +//----------------------------------------------------------------------------- + +// A structure to hold various information related to the WASAPI implementation. +struct WasapiHandle +{ + IAudioClient* captureAudioClient; + IAudioClient* renderAudioClient; + IAudioCaptureClient* captureClient; + IAudioRenderClient* renderClient; + HANDLE captureEvent; + HANDLE renderEvent; + + WasapiHandle() + : captureAudioClient( NULL ), + renderAudioClient( NULL ), + captureClient( NULL ), + renderClient( NULL ), + captureEvent( NULL ), + renderEvent( NULL ) {} +}; + +//============================================================================= + +RtApiWasapi::RtApiWasapi() + : coInitialized_( false ), deviceEnumerator_( NULL ) +{ + // WASAPI can run either apartment or multi-threaded + HRESULT hr = CoInitialize( NULL ); + if ( !FAILED( hr ) ) + coInitialized_ = true; + + // Instantiate device enumerator + hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL, + CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ), + ( void** ) &deviceEnumerator_ ); + + // If this runs on an old Windows, it will fail. Ignore and proceed. + if ( FAILED( hr ) ) + deviceEnumerator_ = NULL; +} + +//----------------------------------------------------------------------------- + +RtApiWasapi::~RtApiWasapi() +{ + if ( stream_.state != STREAM_CLOSED ) + closeStream(); + + SAFE_RELEASE( deviceEnumerator_ ); + + // If this object previously called CoInitialize() + if ( coInitialized_ ) + CoUninitialize(); +} + +//============================================================================= + +unsigned int RtApiWasapi::getDeviceCount( void ) +{ + unsigned int captureDeviceCount = 0; + unsigned int renderDeviceCount = 0; + + IMMDeviceCollection* captureDevices = NULL; + IMMDeviceCollection* renderDevices = NULL; + + if ( !deviceEnumerator_ ) + return 0; + + // Count capture devices + errorText_.clear(); + HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device collection."; + goto Exit; + } + + hr = captureDevices->GetCount( &captureDeviceCount ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device count."; + goto Exit; + } + + // Count render devices + hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device collection."; + goto Exit; + } + + hr = renderDevices->GetCount( &renderDeviceCount ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device count."; + goto Exit; + } + +Exit: + // release all references + SAFE_RELEASE( captureDevices ); + SAFE_RELEASE( renderDevices ); + + if ( errorText_.empty() ) + return captureDeviceCount + renderDeviceCount; + + error( RtAudioError::DRIVER_ERROR ); + return 0; +} + +//----------------------------------------------------------------------------- + +RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device ) +{ + RtAudio::DeviceInfo info; + unsigned int captureDeviceCount = 0; + unsigned int renderDeviceCount = 0; + std::string defaultDeviceName; + bool isCaptureDevice = false; + + PROPVARIANT deviceNameProp; + PROPVARIANT defaultDeviceNameProp; + + IMMDeviceCollection* captureDevices = NULL; + IMMDeviceCollection* renderDevices = NULL; + IMMDevice* devicePtr = NULL; + IMMDevice* defaultDevicePtr = NULL; + IAudioClient* audioClient = NULL; + IPropertyStore* devicePropStore = NULL; + IPropertyStore* defaultDevicePropStore = NULL; + + WAVEFORMATEX* deviceFormat = NULL; + WAVEFORMATEX* closestMatchFormat = NULL; + + // probed + info.probed = false; + + // Count capture devices + errorText_.clear(); + RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; + HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device collection."; + goto Exit; + } + + hr = captureDevices->GetCount( &captureDeviceCount ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device count."; + goto Exit; + } + + // Count render devices + hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device collection."; + goto Exit; + } + + hr = renderDevices->GetCount( &renderDeviceCount ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device count."; + goto Exit; + } + + // validate device index + if ( device >= captureDeviceCount + renderDeviceCount ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Invalid device index."; + errorType = RtAudioError::INVALID_USE; + goto Exit; + } + + // determine whether index falls within capture or render devices + if ( device >= renderDeviceCount ) { + hr = captureDevices->Item( device - renderDeviceCount, &devicePtr ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device handle."; + goto Exit; + } + isCaptureDevice = true; + } + else { + hr = renderDevices->Item( device, &devicePtr ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device handle."; + goto Exit; + } + isCaptureDevice = false; + } + + // get default device name + if ( isCaptureDevice ) { + hr = deviceEnumerator_->GetDefaultAudioEndpoint( eCapture, eConsole, &defaultDevicePtr ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default capture device handle."; + goto Exit; + } + } + else { + hr = deviceEnumerator_->GetDefaultAudioEndpoint( eRender, eConsole, &defaultDevicePtr ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default render device handle."; + goto Exit; + } + } + + hr = defaultDevicePtr->OpenPropertyStore( STGM_READ, &defaultDevicePropStore ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open default device property store."; + goto Exit; + } + PropVariantInit( &defaultDeviceNameProp ); + + hr = defaultDevicePropStore->GetValue( PKEY_Device_FriendlyName, &defaultDeviceNameProp ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default device property: PKEY_Device_FriendlyName."; + goto Exit; + } + + defaultDeviceName = convertCharPointerToStdString(defaultDeviceNameProp.pwszVal); + + // name + hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open device property store."; + goto Exit; + } + + PropVariantInit( &deviceNameProp ); + + hr = devicePropStore->GetValue( PKEY_Device_FriendlyName, &deviceNameProp ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device property: PKEY_Device_FriendlyName."; + goto Exit; + } + + info.name =convertCharPointerToStdString(deviceNameProp.pwszVal); + + // is default + if ( isCaptureDevice ) { + info.isDefaultInput = info.name == defaultDeviceName; + info.isDefaultOutput = false; + } + else { + info.isDefaultInput = false; + info.isDefaultOutput = info.name == defaultDeviceName; + } + + // channel count + hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, NULL, ( void** ) &audioClient ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device audio client."; + goto Exit; + } + + hr = audioClient->GetMixFormat( &deviceFormat ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device mix format."; + goto Exit; + } + + if ( isCaptureDevice ) { + info.inputChannels = deviceFormat->nChannels; + info.outputChannels = 0; + info.duplexChannels = 0; + } + else { + info.inputChannels = 0; + info.outputChannels = deviceFormat->nChannels; + info.duplexChannels = 0; + } + + // sample rates + info.sampleRates.clear(); + + // allow support for all sample rates as we have a built-in sample rate converter + for ( unsigned int i = 0; i < MAX_SAMPLE_RATES; i++ ) { + info.sampleRates.push_back( SAMPLE_RATES[i] ); + } + info.preferredSampleRate = deviceFormat->nSamplesPerSec; + + // native format + info.nativeFormats = 0; + + if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT || + ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && + ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) ) + { + if ( deviceFormat->wBitsPerSample == 32 ) { + info.nativeFormats |= RTAUDIO_FLOAT32; + } + else if ( deviceFormat->wBitsPerSample == 64 ) { + info.nativeFormats |= RTAUDIO_FLOAT64; + } + } + else if ( deviceFormat->wFormatTag == WAVE_FORMAT_PCM || + ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && + ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_PCM ) ) + { + if ( deviceFormat->wBitsPerSample == 8 ) { + info.nativeFormats |= RTAUDIO_SINT8; + } + else if ( deviceFormat->wBitsPerSample == 16 ) { + info.nativeFormats |= RTAUDIO_SINT16; + } + else if ( deviceFormat->wBitsPerSample == 24 ) { + info.nativeFormats |= RTAUDIO_SINT24; + } + else if ( deviceFormat->wBitsPerSample == 32 ) { + info.nativeFormats |= RTAUDIO_SINT32; + } + } + + // probed + info.probed = true; + +Exit: + // release all references + PropVariantClear( &deviceNameProp ); + PropVariantClear( &defaultDeviceNameProp ); + + SAFE_RELEASE( captureDevices ); + SAFE_RELEASE( renderDevices ); + SAFE_RELEASE( devicePtr ); + SAFE_RELEASE( defaultDevicePtr ); + SAFE_RELEASE( audioClient ); + SAFE_RELEASE( devicePropStore ); + SAFE_RELEASE( defaultDevicePropStore ); + + CoTaskMemFree( deviceFormat ); + CoTaskMemFree( closestMatchFormat ); + + if ( !errorText_.empty() ) + error( errorType ); + return info; +} + +//----------------------------------------------------------------------------- + +unsigned int RtApiWasapi::getDefaultOutputDevice( void ) +{ + for ( unsigned int i = 0; i < getDeviceCount(); i++ ) { + if ( getDeviceInfo( i ).isDefaultOutput ) { + return i; + } + } + + return 0; +} + +//----------------------------------------------------------------------------- + +unsigned int RtApiWasapi::getDefaultInputDevice( void ) +{ + for ( unsigned int i = 0; i < getDeviceCount(); i++ ) { + if ( getDeviceInfo( i ).isDefaultInput ) { + return i; + } + } + + return 0; +} + +//----------------------------------------------------------------------------- + +void RtApiWasapi::closeStream( void ) +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiWasapi::closeStream: No open stream to close."; + error( RtAudioError::WARNING ); + return; + } + + if ( stream_.state != STREAM_STOPPED ) + stopStream(); + + // clean up stream memory + SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) + SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) + + SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureClient ) + SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderClient ) + + if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent ) + CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent ); + + if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent ) + CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent ); + + delete ( WasapiHandle* ) stream_.apiHandle; + stream_.apiHandle = NULL; + + for ( int i = 0; i < 2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + // update stream state + stream_.state = STREAM_CLOSED; +} + +//----------------------------------------------------------------------------- + +void RtApiWasapi::startStream( void ) +{ + verifyStream(); + + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiWasapi::startStream: The stream is already running."; + error( RtAudioError::WARNING ); + return; + } + + #if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); + #endif + + // update stream state + stream_.state = STREAM_RUNNING; + + // create WASAPI stream thread + stream_.callbackInfo.thread = ( ThreadHandle ) CreateThread( NULL, 0, runWasapiThread, this, CREATE_SUSPENDED, NULL ); + + if ( !stream_.callbackInfo.thread ) { + errorText_ = "RtApiWasapi::startStream: Unable to instantiate callback thread."; + error( RtAudioError::THREAD_ERROR ); + } + else { + SetThreadPriority( ( void* ) stream_.callbackInfo.thread, stream_.callbackInfo.priority ); + ResumeThread( ( void* ) stream_.callbackInfo.thread ); + } +} + +//----------------------------------------------------------------------------- + +void RtApiWasapi::stopStream( void ) +{ + verifyStream(); + + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiWasapi::stopStream: The stream is already stopped."; + error( RtAudioError::WARNING ); + return; + } + + // inform stream thread by setting stream state to STREAM_STOPPING + stream_.state = STREAM_STOPPING; + + // wait until stream thread is stopped + for (int i=0; i < 2 && stream_.state != STREAM_STOPPED; ++i ) { + Sleep( 1000 * stream_.bufferSize / stream_.sampleRate ); + } + + // close thread handle + if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) { + errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread."; + error( RtAudioError::THREAD_ERROR ); + return; + } + + stream_.callbackInfo.thread = (ThreadHandle) NULL; +} + +//----------------------------------------------------------------------------- + +void RtApiWasapi::abortStream( void ) +{ + verifyStream(); + + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiWasapi::abortStream: The stream is already stopped."; + error( RtAudioError::WARNING ); + return; + } + + // inform stream thread by setting stream state to STREAM_STOPPING + stream_.state = STREAM_STOPPING; + + // wait until stream thread is stopped + while ( stream_.state != STREAM_STOPPED ) { + Sleep( 1 ); + } + + // close thread handle + if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) { + errorText_ = "RtApiWasapi::abortStream: Unable to close callback thread."; + error( RtAudioError::THREAD_ERROR ); + return; + } + + stream_.callbackInfo.thread = (ThreadHandle) NULL; +} + +//----------------------------------------------------------------------------- + +bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int* bufferSize, + RtAudio::StreamOptions* options ) +{ + bool methodResult = FAILURE; + unsigned int captureDeviceCount = 0; + unsigned int renderDeviceCount = 0; + + IMMDeviceCollection* captureDevices = NULL; + IMMDeviceCollection* renderDevices = NULL; + IMMDevice* devicePtr = NULL; + WAVEFORMATEX* deviceFormat = NULL; + unsigned int bufferBytes; + stream_.state = STREAM_STOPPED; + + // create API Handle if not already created + if ( !stream_.apiHandle ) + stream_.apiHandle = ( void* ) new WasapiHandle(); + + // Count capture devices + errorText_.clear(); + RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; + HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device collection."; + goto Exit; + } + + hr = captureDevices->GetCount( &captureDeviceCount ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device count."; + goto Exit; + } + + // Count render devices + hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device collection."; + goto Exit; + } + + hr = renderDevices->GetCount( &renderDeviceCount ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device count."; + goto Exit; + } + + // validate device index + if ( device >= captureDeviceCount + renderDeviceCount ) { + errorType = RtAudioError::INVALID_USE; + errorText_ = "RtApiWasapi::probeDeviceOpen: Invalid device index."; + goto Exit; + } + + // if device index falls within capture devices + if ( device >= renderDeviceCount ) { + if ( mode != INPUT ) { + errorType = RtAudioError::INVALID_USE; + errorText_ = "RtApiWasapi::probeDeviceOpen: Capture device selected as output device."; + goto Exit; + } + + // retrieve captureAudioClient from devicePtr + IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient; + + hr = captureDevices->Item( device - renderDeviceCount, &devicePtr ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device handle."; + goto Exit; + } + + hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, + NULL, ( void** ) &captureAudioClient ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device audio client."; + goto Exit; + } + + hr = captureAudioClient->GetMixFormat( &deviceFormat ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device mix format."; + goto Exit; + } + + stream_.nDeviceChannels[mode] = deviceFormat->nChannels; + captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] ); + } + + // if device index falls within render devices and is configured for loopback + if ( device < renderDeviceCount && mode == INPUT ) + { + // if renderAudioClient is not initialised, initialise it now + IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient; + if ( !renderAudioClient ) + { + probeDeviceOpen( device, OUTPUT, channels, firstChannel, sampleRate, format, bufferSize, options ); + } + + // retrieve captureAudioClient from devicePtr + IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient; + + hr = renderDevices->Item( device, &devicePtr ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle."; + goto Exit; + } + + hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, + NULL, ( void** ) &captureAudioClient ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device audio client."; + goto Exit; + } + + hr = captureAudioClient->GetMixFormat( &deviceFormat ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device mix format."; + goto Exit; + } + + stream_.nDeviceChannels[mode] = deviceFormat->nChannels; + captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] ); + } + + // if device index falls within render devices and is configured for output + if ( device < renderDeviceCount && mode == OUTPUT ) + { + // if renderAudioClient is already initialised, don't initialise it again + IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient; + if ( renderAudioClient ) + { + methodResult = SUCCESS; + goto Exit; + } + + hr = renderDevices->Item( device, &devicePtr ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle."; + goto Exit; + } + + hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, + NULL, ( void** ) &renderAudioClient ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device audio client."; + goto Exit; + } + + hr = renderAudioClient->GetMixFormat( &deviceFormat ); + if ( FAILED( hr ) ) { + errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device mix format."; + goto Exit; + } + + stream_.nDeviceChannels[mode] = deviceFormat->nChannels; + renderAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] ); + } + + // fill stream data + if ( ( stream_.mode == OUTPUT && mode == INPUT ) || + ( stream_.mode == INPUT && mode == OUTPUT ) ) { + stream_.mode = DUPLEX; + } + else { + stream_.mode = mode; + } + + stream_.device[mode] = device; + stream_.doByteSwap[mode] = false; + stream_.sampleRate = sampleRate; + stream_.bufferSize = *bufferSize; + stream_.nBuffers = 1; + stream_.nUserChannels[mode] = channels; + stream_.channelOffset[mode] = firstChannel; + stream_.userFormat = format; + stream_.deviceFormat[mode] = getDeviceInfo( device ).nativeFormats; + + if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) + stream_.userInterleaved = false; + else + stream_.userInterleaved = true; + stream_.deviceInterleaved[mode] = true; + + // Set flags for buffer conversion. + stream_.doConvertBuffer[mode] = false; + if ( stream_.userFormat != stream_.deviceFormat[mode] || + stream_.nUserChannels[0] != stream_.nDeviceChannels[0] || + stream_.nUserChannels[1] != stream_.nDeviceChannels[1] ) + stream_.doConvertBuffer[mode] = true; + else if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && + stream_.nUserChannels[mode] > 1 ) + stream_.doConvertBuffer[mode] = true; + + if ( stream_.doConvertBuffer[mode] ) + setConvertInfo( mode, firstChannel ); + + // Allocate necessary internal buffers + bufferBytes = stream_.nUserChannels[mode] * stream_.bufferSize * formatBytes( stream_.userFormat ); + + stream_.userBuffer[mode] = ( char* ) calloc( bufferBytes, 1 ); + if ( !stream_.userBuffer[mode] ) { + errorType = RtAudioError::MEMORY_ERROR; + errorText_ = "RtApiWasapi::probeDeviceOpen: Error allocating user buffer memory."; + goto Exit; + } + + if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) + stream_.callbackInfo.priority = 15; + else + stream_.callbackInfo.priority = 0; + + ///! TODO: RTAUDIO_MINIMIZE_LATENCY // Provide stream buffers directly to callback + ///! TODO: RTAUDIO_HOG_DEVICE // Exclusive mode + + methodResult = SUCCESS; + +Exit: + //clean up + SAFE_RELEASE( captureDevices ); + SAFE_RELEASE( renderDevices ); + SAFE_RELEASE( devicePtr ); + CoTaskMemFree( deviceFormat ); + + // if method failed, close the stream + if ( methodResult == FAILURE ) + closeStream(); + + if ( !errorText_.empty() ) + error( errorType ); + return methodResult; +} + +//============================================================================= + +DWORD WINAPI RtApiWasapi::runWasapiThread( void* wasapiPtr ) +{ + if ( wasapiPtr ) + ( ( RtApiWasapi* ) wasapiPtr )->wasapiThread(); + + return 0; +} + +DWORD WINAPI RtApiWasapi::stopWasapiThread( void* wasapiPtr ) +{ + if ( wasapiPtr ) + ( ( RtApiWasapi* ) wasapiPtr )->stopStream(); + + return 0; +} + +DWORD WINAPI RtApiWasapi::abortWasapiThread( void* wasapiPtr ) +{ + if ( wasapiPtr ) + ( ( RtApiWasapi* ) wasapiPtr )->abortStream(); + + return 0; +} + +//----------------------------------------------------------------------------- + +void RtApiWasapi::wasapiThread() +{ + // as this is a new thread, we must CoInitialize it + CoInitialize( NULL ); + + HRESULT hr; + + IAudioClient* captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient; + IAudioClient* renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient; + IAudioCaptureClient* captureClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureClient; + IAudioRenderClient* renderClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderClient; + HANDLE captureEvent = ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent; + HANDLE renderEvent = ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent; + + WAVEFORMATEX* captureFormat = NULL; + WAVEFORMATEX* renderFormat = NULL; + float captureSrRatio = 0.0f; + float renderSrRatio = 0.0f; + WasapiBuffer captureBuffer; + WasapiBuffer renderBuffer; + WasapiResampler* captureResampler = NULL; + WasapiResampler* renderResampler = NULL; + + // declare local stream variables + RtAudioCallback callback = ( RtAudioCallback ) stream_.callbackInfo.callback; + BYTE* streamBuffer = NULL; + DWORD captureFlags = 0; + unsigned int bufferFrameCount = 0; + unsigned int numFramesPadding = 0; + unsigned int convBufferSize = 0; + bool loopbackEnabled = stream_.device[INPUT] == stream_.device[OUTPUT]; + bool callbackPushed = true; + bool callbackPulled = false; + bool callbackStopped = false; + int callbackResult = 0; + + // convBuffer is used to store converted buffers between WASAPI and the user + char* convBuffer = NULL; + unsigned int convBuffSize = 0; + unsigned int deviceBuffSize = 0; + + std::string errorText; + RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR; + + // Attempt to assign "Pro Audio" characteristic to thread + HMODULE AvrtDll = LoadLibraryW( L"AVRT.dll" ); + if ( AvrtDll ) { + DWORD taskIndex = 0; + TAvSetMmThreadCharacteristicsPtr AvSetMmThreadCharacteristicsPtr = + ( TAvSetMmThreadCharacteristicsPtr ) (void(*)()) GetProcAddress( AvrtDll, "AvSetMmThreadCharacteristicsW" ); + AvSetMmThreadCharacteristicsPtr( L"Pro Audio", &taskIndex ); + FreeLibrary( AvrtDll ); + } + + // start capture stream if applicable + if ( captureAudioClient ) { + hr = captureAudioClient->GetMixFormat( &captureFormat ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format."; + goto Exit; + } + + // init captureResampler + captureResampler = new WasapiResampler( stream_.deviceFormat[INPUT] == RTAUDIO_FLOAT32 || stream_.deviceFormat[INPUT] == RTAUDIO_FLOAT64, + formatBytes( stream_.deviceFormat[INPUT] ) * 8, stream_.nDeviceChannels[INPUT], + captureFormat->nSamplesPerSec, stream_.sampleRate ); + + captureSrRatio = ( ( float ) captureFormat->nSamplesPerSec / stream_.sampleRate ); + + if ( !captureClient ) { + hr = captureAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED, + loopbackEnabled ? AUDCLNT_STREAMFLAGS_LOOPBACK : AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + 0, + 0, + captureFormat, + NULL ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to initialize capture audio client."; + goto Exit; + } + + hr = captureAudioClient->GetService( __uuidof( IAudioCaptureClient ), + ( void** ) &captureClient ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve capture client handle."; + goto Exit; + } + + // don't configure captureEvent if in loopback mode + if ( !loopbackEnabled ) + { + // configure captureEvent to trigger on every available capture buffer + captureEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + if ( !captureEvent ) { + errorType = RtAudioError::SYSTEM_ERROR; + errorText = "RtApiWasapi::wasapiThread: Unable to create capture event."; + goto Exit; + } + + hr = captureAudioClient->SetEventHandle( captureEvent ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to set capture event handle."; + goto Exit; + } + + ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent = captureEvent; + } + + ( ( WasapiHandle* ) stream_.apiHandle )->captureClient = captureClient; + + // reset the capture stream + hr = captureAudioClient->Reset(); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to reset capture stream."; + goto Exit; + } + + // start the capture stream + hr = captureAudioClient->Start(); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to start capture stream."; + goto Exit; + } + } + + unsigned int inBufferSize = 0; + hr = captureAudioClient->GetBufferSize( &inBufferSize ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to get capture buffer size."; + goto Exit; + } + + // scale outBufferSize according to stream->user sample rate ratio + unsigned int outBufferSize = ( unsigned int ) ceilf( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT]; + inBufferSize *= stream_.nDeviceChannels[INPUT]; + + // set captureBuffer size + captureBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[INPUT] ) ); + } + + // start render stream if applicable + if ( renderAudioClient ) { + hr = renderAudioClient->GetMixFormat( &renderFormat ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format."; + goto Exit; + } + + // init renderResampler + renderResampler = new WasapiResampler( stream_.deviceFormat[OUTPUT] == RTAUDIO_FLOAT32 || stream_.deviceFormat[OUTPUT] == RTAUDIO_FLOAT64, + formatBytes( stream_.deviceFormat[OUTPUT] ) * 8, stream_.nDeviceChannels[OUTPUT], + stream_.sampleRate, renderFormat->nSamplesPerSec ); + + renderSrRatio = ( ( float ) renderFormat->nSamplesPerSec / stream_.sampleRate ); + + if ( !renderClient ) { + hr = renderAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED, + AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + 0, + 0, + renderFormat, + NULL ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to initialize render audio client."; + goto Exit; + } + + hr = renderAudioClient->GetService( __uuidof( IAudioRenderClient ), + ( void** ) &renderClient ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render client handle."; + goto Exit; + } + + // configure renderEvent to trigger on every available render buffer + renderEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + if ( !renderEvent ) { + errorType = RtAudioError::SYSTEM_ERROR; + errorText = "RtApiWasapi::wasapiThread: Unable to create render event."; + goto Exit; + } + + hr = renderAudioClient->SetEventHandle( renderEvent ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to set render event handle."; + goto Exit; + } + + ( ( WasapiHandle* ) stream_.apiHandle )->renderClient = renderClient; + ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent = renderEvent; + + // reset the render stream + hr = renderAudioClient->Reset(); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to reset render stream."; + goto Exit; + } + + // start the render stream + hr = renderAudioClient->Start(); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to start render stream."; + goto Exit; + } + } + + unsigned int outBufferSize = 0; + hr = renderAudioClient->GetBufferSize( &outBufferSize ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to get render buffer size."; + goto Exit; + } + + // scale inBufferSize according to user->stream sample rate ratio + unsigned int inBufferSize = ( unsigned int ) ceilf( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT]; + outBufferSize *= stream_.nDeviceChannels[OUTPUT]; + + // set renderBuffer size + renderBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[OUTPUT] ) ); + } + + // malloc buffer memory + if ( stream_.mode == INPUT ) + { + using namespace std; // for ceilf + convBuffSize = ( size_t ) ( ceilf( stream_.bufferSize * captureSrRatio ) ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ); + deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ); + } + else if ( stream_.mode == OUTPUT ) + { + convBuffSize = ( size_t ) ( ceilf( stream_.bufferSize * renderSrRatio ) ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ); + deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ); + } + else if ( stream_.mode == DUPLEX ) + { + convBuffSize = std::max( ( size_t ) ( ceilf( stream_.bufferSize * captureSrRatio ) ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ), + ( size_t ) ( ceilf( stream_.bufferSize * renderSrRatio ) ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) ); + deviceBuffSize = std::max( stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ), + stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) ); + } + + convBuffSize *= 2; // allow overflow for *SrRatio remainders + convBuffer = ( char* ) calloc( convBuffSize, 1 ); + stream_.deviceBuffer = ( char* ) calloc( deviceBuffSize, 1 ); + if ( !convBuffer || !stream_.deviceBuffer ) { + errorType = RtAudioError::MEMORY_ERROR; + errorText = "RtApiWasapi::wasapiThread: Error allocating device buffer memory."; + goto Exit; + } + + // stream process loop + while ( stream_.state != STREAM_STOPPING ) { + if ( !callbackPulled ) { + // Callback Input + // ============== + // 1. Pull callback buffer from inputBuffer + // 2. If 1. was successful: Convert callback buffer to user sample rate and channel count + // Convert callback buffer to user format + + if ( captureAudioClient ) + { + int samplesToPull = ( unsigned int ) floorf( stream_.bufferSize * captureSrRatio ); + + convBufferSize = 0; + while ( convBufferSize < stream_.bufferSize ) + { + // Pull callback buffer from inputBuffer + callbackPulled = captureBuffer.pullBuffer( convBuffer, + samplesToPull * stream_.nDeviceChannels[INPUT], + stream_.deviceFormat[INPUT] ); + + if ( !callbackPulled ) + { + break; + } + + // Convert callback buffer to user sample rate + unsigned int deviceBufferOffset = convBufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ); + unsigned int convSamples = 0; + + captureResampler->Convert( stream_.deviceBuffer + deviceBufferOffset, + convBuffer, + samplesToPull, + convSamples, + convBufferSize == 0 ? -1 : stream_.bufferSize - convBufferSize ); + + convBufferSize += convSamples; + samplesToPull = 1; // now pull one sample at a time until we have stream_.bufferSize samples + } + + if ( callbackPulled ) + { + if ( stream_.doConvertBuffer[INPUT] ) { + // Convert callback buffer to user format + convertBuffer( stream_.userBuffer[INPUT], + stream_.deviceBuffer, + stream_.convertInfo[INPUT] ); + } + else { + // no further conversion, simple copy deviceBuffer to userBuffer + memcpy( stream_.userBuffer[INPUT], + stream_.deviceBuffer, + stream_.bufferSize * stream_.nUserChannels[INPUT] * formatBytes( stream_.userFormat ) ); + } + } + } + else { + // if there is no capture stream, set callbackPulled flag + callbackPulled = true; + } + + // Execute Callback + // ================ + // 1. Execute user callback method + // 2. Handle return value from callback + + // if callback has not requested the stream to stop + if ( callbackPulled && !callbackStopped ) { + // Execute user callback method + callbackResult = callback( stream_.userBuffer[OUTPUT], + stream_.userBuffer[INPUT], + stream_.bufferSize, + getStreamTime(), + captureFlags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY ? RTAUDIO_INPUT_OVERFLOW : 0, + stream_.callbackInfo.userData ); + + // tick stream time + RtApi::tickStreamTime(); + + // Handle return value from callback + if ( callbackResult == 1 ) { + // instantiate a thread to stop this thread + HANDLE threadHandle = CreateThread( NULL, 0, stopWasapiThread, this, 0, NULL ); + if ( !threadHandle ) { + errorType = RtAudioError::THREAD_ERROR; + errorText = "RtApiWasapi::wasapiThread: Unable to instantiate stream stop thread."; + goto Exit; + } + else if ( !CloseHandle( threadHandle ) ) { + errorType = RtAudioError::THREAD_ERROR; + errorText = "RtApiWasapi::wasapiThread: Unable to close stream stop thread handle."; + goto Exit; + } + + callbackStopped = true; + } + else if ( callbackResult == 2 ) { + // instantiate a thread to stop this thread + HANDLE threadHandle = CreateThread( NULL, 0, abortWasapiThread, this, 0, NULL ); + if ( !threadHandle ) { + errorType = RtAudioError::THREAD_ERROR; + errorText = "RtApiWasapi::wasapiThread: Unable to instantiate stream abort thread."; + goto Exit; + } + else if ( !CloseHandle( threadHandle ) ) { + errorType = RtAudioError::THREAD_ERROR; + errorText = "RtApiWasapi::wasapiThread: Unable to close stream abort thread handle."; + goto Exit; + } + + callbackStopped = true; + } + } + } + + // Callback Output + // =============== + // 1. Convert callback buffer to stream format + // 2. Convert callback buffer to stream sample rate and channel count + // 3. Push callback buffer into outputBuffer + + if ( renderAudioClient && callbackPulled ) + { + // if the last call to renderBuffer.PushBuffer() was successful + if ( callbackPushed || convBufferSize == 0 ) + { + if ( stream_.doConvertBuffer[OUTPUT] ) + { + // Convert callback buffer to stream format + convertBuffer( stream_.deviceBuffer, + stream_.userBuffer[OUTPUT], + stream_.convertInfo[OUTPUT] ); + + } + else { + // no further conversion, simple copy userBuffer to deviceBuffer + memcpy( stream_.deviceBuffer, + stream_.userBuffer[OUTPUT], + stream_.bufferSize * stream_.nUserChannels[OUTPUT] * formatBytes( stream_.userFormat ) ); + } + + // Convert callback buffer to stream sample rate + renderResampler->Convert( convBuffer, + stream_.deviceBuffer, + stream_.bufferSize, + convBufferSize ); + } + + // Push callback buffer into outputBuffer + callbackPushed = renderBuffer.pushBuffer( convBuffer, + convBufferSize * stream_.nDeviceChannels[OUTPUT], + stream_.deviceFormat[OUTPUT] ); + } + else { + // if there is no render stream, set callbackPushed flag + callbackPushed = true; + } + + // Stream Capture + // ============== + // 1. Get capture buffer from stream + // 2. Push capture buffer into inputBuffer + // 3. If 2. was successful: Release capture buffer + + if ( captureAudioClient ) { + // if the callback input buffer was not pulled from captureBuffer, wait for next capture event + if ( !callbackPulled ) { + WaitForSingleObject( loopbackEnabled ? renderEvent : captureEvent, INFINITE ); + } + + // Get capture buffer from stream + hr = captureClient->GetBuffer( &streamBuffer, + &bufferFrameCount, + &captureFlags, NULL, NULL ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve capture buffer."; + goto Exit; + } + + if ( bufferFrameCount != 0 ) { + // Push capture buffer into inputBuffer + if ( captureBuffer.pushBuffer( ( char* ) streamBuffer, + bufferFrameCount * stream_.nDeviceChannels[INPUT], + stream_.deviceFormat[INPUT] ) ) + { + // Release capture buffer + hr = captureClient->ReleaseBuffer( bufferFrameCount ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; + goto Exit; + } + } + else + { + // Inform WASAPI that capture was unsuccessful + hr = captureClient->ReleaseBuffer( 0 ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; + goto Exit; + } + } + } + else + { + // Inform WASAPI that capture was unsuccessful + hr = captureClient->ReleaseBuffer( 0 ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to release capture buffer."; + goto Exit; + } + } + } + + // Stream Render + // ============= + // 1. Get render buffer from stream + // 2. Pull next buffer from outputBuffer + // 3. If 2. was successful: Fill render buffer with next buffer + // Release render buffer + + if ( renderAudioClient ) { + // if the callback output buffer was not pushed to renderBuffer, wait for next render event + if ( callbackPulled && !callbackPushed ) { + WaitForSingleObject( renderEvent, INFINITE ); + } + + // Get render buffer from stream + hr = renderAudioClient->GetBufferSize( &bufferFrameCount ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer size."; + goto Exit; + } + + hr = renderAudioClient->GetCurrentPadding( &numFramesPadding ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer padding."; + goto Exit; + } + + bufferFrameCount -= numFramesPadding; + + if ( bufferFrameCount != 0 ) { + hr = renderClient->GetBuffer( bufferFrameCount, &streamBuffer ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer."; + goto Exit; + } + + // Pull next buffer from outputBuffer + // Fill render buffer with next buffer + if ( renderBuffer.pullBuffer( ( char* ) streamBuffer, + bufferFrameCount * stream_.nDeviceChannels[OUTPUT], + stream_.deviceFormat[OUTPUT] ) ) + { + // Release render buffer + hr = renderClient->ReleaseBuffer( bufferFrameCount, 0 ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to release render buffer."; + goto Exit; + } + } + else + { + // Inform WASAPI that render was unsuccessful + hr = renderClient->ReleaseBuffer( 0, 0 ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to release render buffer."; + goto Exit; + } + } + } + else + { + // Inform WASAPI that render was unsuccessful + hr = renderClient->ReleaseBuffer( 0, 0 ); + if ( FAILED( hr ) ) { + errorText = "RtApiWasapi::wasapiThread: Unable to release render buffer."; + goto Exit; + } + } + } + + // if the callback buffer was pushed renderBuffer reset callbackPulled flag + if ( callbackPushed ) { + // unsetting the callbackPulled flag lets the stream know that + // the audio device is ready for another callback output buffer. + callbackPulled = false; + } + + } + +Exit: + // clean up + CoTaskMemFree( captureFormat ); + CoTaskMemFree( renderFormat ); + + free ( convBuffer ); + delete renderResampler; + delete captureResampler; + + CoUninitialize(); + + // update stream state + stream_.state = STREAM_STOPPED; + + if ( !errorText.empty() ) + { + errorText_ = errorText; + error( errorType ); + } +} + +//******************** End of __WINDOWS_WASAPI__ *********************// +#endif + + +#if defined(__WINDOWS_DS__) // Windows DirectSound API + +// Modified by Robin Davies, October 2005 +// - Improvements to DirectX pointer chasing. +// - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30. +// - Auto-call CoInitialize for DSOUND and ASIO platforms. +// Various revisions for RtAudio 4.0 by Gary Scavone, April 2007 +// Changed device query structure for RtAudio 4.0.7, January 2010 + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__MINGW32__) + // missing from latest mingw winapi +#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */ +#endif + +#define MINIMUM_DEVICE_BUFFER_SIZE 32768 + +#ifdef _MSC_VER // if Microsoft Visual C++ +#pragma comment( lib, "winmm.lib" ) // then, auto-link winmm.lib. Otherwise, it has to be added manually. +#endif + +static inline DWORD dsPointerBetween( DWORD pointer, DWORD laterPointer, DWORD earlierPointer, DWORD bufferSize ) +{ + if ( pointer > bufferSize ) pointer -= bufferSize; + if ( laterPointer < earlierPointer ) laterPointer += bufferSize; + if ( pointer < earlierPointer ) pointer += bufferSize; + return pointer >= earlierPointer && pointer < laterPointer; +} + +// A structure to hold various information related to the DirectSound +// API implementation. +struct DsHandle { + unsigned int drainCounter; // Tracks callback counts when draining + bool internalDrain; // Indicates if stop is initiated from callback or not. + void *id[2]; + void *buffer[2]; + bool xrun[2]; + UINT bufferPointer[2]; + DWORD dsBufferSize[2]; + DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by. + HANDLE condition; + + DsHandle() + :drainCounter(0), internalDrain(false) { id[0] = 0; id[1] = 0; buffer[0] = 0; buffer[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; } +}; + +// Declarations for utility functions, callbacks, and structures +// specific to the DirectSound implementation. +static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, + LPCTSTR description, + LPCTSTR module, + LPVOID lpContext ); + +static const char* getErrorString( int code ); + +static unsigned __stdcall callbackHandler( void *ptr ); + +struct DsDevice { + LPGUID id[2]; + bool validId[2]; + bool found; + std::string name; + + DsDevice() + : found(false) { validId[0] = false; validId[1] = false; } +}; + +struct DsProbeData { + bool isInput; + std::vector* dsDevices; +}; + +RtApiDs :: RtApiDs() +{ + // Dsound will run both-threaded. If CoInitialize fails, then just + // accept whatever the mainline chose for a threading model. + coInitialized_ = false; + HRESULT hr = CoInitialize( NULL ); + if ( !FAILED( hr ) ) coInitialized_ = true; +} + +RtApiDs :: ~RtApiDs() +{ + if ( stream_.state != STREAM_CLOSED ) closeStream(); + if ( coInitialized_ ) CoUninitialize(); // balanced call. +} + +// The DirectSound default output is always the first device. +unsigned int RtApiDs :: getDefaultOutputDevice( void ) +{ + return 0; +} + +// The DirectSound default input is always the first input device, +// which is the first capture device enumerated. +unsigned int RtApiDs :: getDefaultInputDevice( void ) +{ + return 0; +} + +unsigned int RtApiDs :: getDeviceCount( void ) +{ + // Set query flag for previously found devices to false, so that we + // can check for any devices that have disappeared. + for ( unsigned int i=0; i(dsDevices.size()); +} + +RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device ) +{ + RtAudio::DeviceInfo info; + info.probed = false; + + if ( dsDevices.size() == 0 ) { + // Force a query of all devices + getDeviceCount(); + if ( dsDevices.size() == 0 ) { + errorText_ = "RtApiDs::getDeviceInfo: no devices found!"; + error( RtAudioError::INVALID_USE ); + return info; + } + } + + if ( device >= dsDevices.size() ) { + errorText_ = "RtApiDs::getDeviceInfo: device ID is invalid!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + HRESULT result; + if ( dsDevices[ device ].validId[0] == false ) goto probeInput; + + LPDIRECTSOUND output; + DSCAPS outCaps; + result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto probeInput; + } + + outCaps.dwSize = sizeof( outCaps ); + result = output->GetCaps( &outCaps ); + if ( FAILED( result ) ) { + output->Release(); + errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting capabilities!"; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto probeInput; + } + + // Get output channel information. + info.outputChannels = ( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1; + + // Get sample rate information. + info.sampleRates.clear(); + for ( unsigned int k=0; k= (unsigned int) outCaps.dwMinSecondarySampleRate && + SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate ) { + info.sampleRates.push_back( SAMPLE_RATES[k] ); + + if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) + info.preferredSampleRate = SAMPLE_RATES[k]; + } + } + + // Get format information. + if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT ) info.nativeFormats |= RTAUDIO_SINT16; + if ( outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) info.nativeFormats |= RTAUDIO_SINT8; + + output->Release(); + + if ( getDefaultOutputDevice() == device ) + info.isDefaultOutput = true; + + if ( dsDevices[ device ].validId[1] == false ) { + info.name = dsDevices[ device ].name; + info.probed = true; + return info; + } + + probeInput: + + LPDIRECTSOUNDCAPTURE input; + result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + DSCCAPS inCaps; + inCaps.dwSize = sizeof( inCaps ); + result = input->GetCaps( &inCaps ); + if ( FAILED( result ) ) { + input->Release(); + errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting object capabilities (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Get input channel information. + info.inputChannels = inCaps.dwChannels; + + // Get sample rate and format information. + std::vector rates; + if ( inCaps.dwChannels >= 2 ) { + if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) info.nativeFormats |= RTAUDIO_SINT8; + if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) info.nativeFormats |= RTAUDIO_SINT8; + if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) info.nativeFormats |= RTAUDIO_SINT8; + if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) info.nativeFormats |= RTAUDIO_SINT8; + + if ( info.nativeFormats & RTAUDIO_SINT16 ) { + if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) rates.push_back( 11025 ); + if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) rates.push_back( 22050 ); + if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) rates.push_back( 44100 ); + if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) rates.push_back( 96000 ); + } + else if ( info.nativeFormats & RTAUDIO_SINT8 ) { + if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) rates.push_back( 11025 ); + if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) rates.push_back( 22050 ); + if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) rates.push_back( 44100 ); + if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) rates.push_back( 96000 ); + } + } + else if ( inCaps.dwChannels == 1 ) { + if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) info.nativeFormats |= RTAUDIO_SINT16; + if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) info.nativeFormats |= RTAUDIO_SINT8; + if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) info.nativeFormats |= RTAUDIO_SINT8; + if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) info.nativeFormats |= RTAUDIO_SINT8; + if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) info.nativeFormats |= RTAUDIO_SINT8; + + if ( info.nativeFormats & RTAUDIO_SINT16 ) { + if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) rates.push_back( 11025 ); + if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) rates.push_back( 22050 ); + if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) rates.push_back( 44100 ); + if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) rates.push_back( 96000 ); + } + else if ( info.nativeFormats & RTAUDIO_SINT8 ) { + if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) rates.push_back( 11025 ); + if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) rates.push_back( 22050 ); + if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) rates.push_back( 44100 ); + if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) rates.push_back( 96000 ); + } + } + else info.inputChannels = 0; // technically, this would be an error + + input->Release(); + + if ( info.inputChannels == 0 ) return info; + + // Copy the supported rates to the info structure but avoid duplication. + bool found; + for ( unsigned int i=0; i 0 && info.inputChannels > 0 ) + info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; + + if ( device == 0 ) info.isDefaultInput = true; + + // Copy name and return. + info.name = dsDevices[ device ].name; + info.probed = true; + return info; +} + +bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) +{ + if ( channels + firstChannel > 2 ) { + errorText_ = "RtApiDs::probeDeviceOpen: DirectSound does not support more than 2 channels per device."; + return FAILURE; + } + + size_t nDevices = dsDevices.size(); + if ( nDevices == 0 ) { + // This should not happen because a check is made before this function is called. + errorText_ = "RtApiDs::probeDeviceOpen: no devices found!"; + return FAILURE; + } + + if ( device >= nDevices ) { + // This should not happen because a check is made before this function is called. + errorText_ = "RtApiDs::probeDeviceOpen: device ID is invalid!"; + return FAILURE; + } + + if ( mode == OUTPUT ) { + if ( dsDevices[ device ].validId[0] == false ) { + errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support output!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + else { // mode == INPUT + if ( dsDevices[ device ].validId[1] == false ) { + errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support input!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + + // According to a note in PortAudio, using GetDesktopWindow() + // instead of GetForegroundWindow() is supposed to avoid problems + // that occur when the application's window is not the foreground + // window. Also, if the application window closes before the + // DirectSound buffer, DirectSound can crash. In the past, I had + // problems when using GetDesktopWindow() but it seems fine now + // (January 2010). I'll leave it commented here. + // HWND hWnd = GetForegroundWindow(); + HWND hWnd = GetDesktopWindow(); + + // Check the numberOfBuffers parameter and limit the lowest value to + // two. This is a judgement call and a value of two is probably too + // low for capture, but it should work for playback. + int nBuffers = 0; + if ( options ) nBuffers = options->numberOfBuffers; + if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) nBuffers = 2; + if ( nBuffers < 2 ) nBuffers = 3; + + // Check the lower range of the user-specified buffer size and set + // (arbitrarily) to a lower bound of 32. + if ( *bufferSize < 32 ) *bufferSize = 32; + + // Create the wave format structure. The data format setting will + // be determined later. + WAVEFORMATEX waveFormat; + ZeroMemory( &waveFormat, sizeof(WAVEFORMATEX) ); + waveFormat.wFormatTag = WAVE_FORMAT_PCM; + waveFormat.nChannels = channels + firstChannel; + waveFormat.nSamplesPerSec = (unsigned long) sampleRate; + + // Determine the device buffer size. By default, we'll use the value + // defined above (32K), but we will grow it to make allowances for + // very large software buffer sizes. + DWORD dsBufferSize = MINIMUM_DEVICE_BUFFER_SIZE; + DWORD dsPointerLeadTime = 0; + + void *ohandle = 0, *bhandle = 0; + HRESULT result; + if ( mode == OUTPUT ) { + + LPDIRECTSOUND output; + result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + DSCAPS outCaps; + outCaps.dwSize = sizeof( outCaps ); + result = output->GetCaps( &outCaps ); + if ( FAILED( result ) ) { + output->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting capabilities (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Check channel information. + if ( channels + firstChannel == 2 && !( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ) { + errorStream_ << "RtApiDs::getDeviceInfo: the output device (" << dsDevices[ device ].name << ") does not support stereo playback."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Check format information. Use 16-bit format unless not + // supported or user requests 8-bit. + if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT && + !( format == RTAUDIO_SINT8 && outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) ) { + waveFormat.wBitsPerSample = 16; + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + } + else { + waveFormat.wBitsPerSample = 8; + stream_.deviceFormat[mode] = RTAUDIO_SINT8; + } + stream_.userFormat = format; + + // Update wave format structure and buffer information. + waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels; + + // If the user wants an even bigger buffer, increase the device buffer size accordingly. + while ( dsPointerLeadTime * 2U > dsBufferSize ) + dsBufferSize *= 2; + + // Set cooperative level to DSSCL_EXCLUSIVE ... sound stops when window focus changes. + // result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE ); + // Set cooperative level to DSSCL_PRIORITY ... sound remains when window focus changes. + result = output->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); + if ( FAILED( result ) ) { + output->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting cooperative level (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Even though we will write to the secondary buffer, we need to + // access the primary buffer to set the correct output format + // (since the default is 8-bit, 22 kHz!). Setup the DS primary + // buffer description. + DSBUFFERDESC bufferDescription; + ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) ); + bufferDescription.dwSize = sizeof( DSBUFFERDESC ); + bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; + + // Obtain the primary buffer + LPDIRECTSOUNDBUFFER buffer; + result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); + if ( FAILED( result ) ) { + output->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") accessing primary buffer (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Set the primary DS buffer sound format. + result = buffer->SetFormat( &waveFormat ); + if ( FAILED( result ) ) { + output->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting primary buffer format (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Setup the secondary DS buffer description. + ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) ); + bufferDescription.dwSize = sizeof( DSBUFFERDESC ); + bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | + DSBCAPS_GLOBALFOCUS | + DSBCAPS_GETCURRENTPOSITION2 | + DSBCAPS_LOCHARDWARE ); // Force hardware mixing + bufferDescription.dwBufferBytes = dsBufferSize; + bufferDescription.lpwfxFormat = &waveFormat; + + // Try to create the secondary DS buffer. If that doesn't work, + // try to use software mixing. Otherwise, there's a problem. + result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); + if ( FAILED( result ) ) { + bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | + DSBCAPS_GLOBALFOCUS | + DSBCAPS_GETCURRENTPOSITION2 | + DSBCAPS_LOCSOFTWARE ); // Force software mixing + result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL ); + if ( FAILED( result ) ) { + output->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating secondary buffer (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + + // Get the buffer size ... might be different from what we specified. + DSBCAPS dsbcaps; + dsbcaps.dwSize = sizeof( DSBCAPS ); + result = buffer->GetCaps( &dsbcaps ); + if ( FAILED( result ) ) { + output->Release(); + buffer->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + dsBufferSize = dsbcaps.dwBufferBytes; + + // Lock the DS buffer + LPVOID audioPtr; + DWORD dataLen; + result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 ); + if ( FAILED( result ) ) { + output->Release(); + buffer->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking buffer (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Zero the DS buffer + ZeroMemory( audioPtr, dataLen ); + + // Unlock the DS buffer + result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); + if ( FAILED( result ) ) { + output->Release(); + buffer->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking buffer (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + ohandle = (void *) output; + bhandle = (void *) buffer; + } + + if ( mode == INPUT ) { + + LPDIRECTSOUNDCAPTURE input; + result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + DSCCAPS inCaps; + inCaps.dwSize = sizeof( inCaps ); + result = input->GetCaps( &inCaps ); + if ( FAILED( result ) ) { + input->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting input capabilities (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Check channel information. + if ( inCaps.dwChannels < channels + firstChannel ) { + errorText_ = "RtApiDs::getDeviceInfo: the input device does not support requested input channels."; + return FAILURE; + } + + // Check format information. Use 16-bit format unless user + // requests 8-bit. + DWORD deviceFormats; + if ( channels + firstChannel == 2 ) { + deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08; + if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) { + waveFormat.wBitsPerSample = 8; + stream_.deviceFormat[mode] = RTAUDIO_SINT8; + } + else { // assume 16-bit is supported + waveFormat.wBitsPerSample = 16; + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + } + } + else { // channel == 1 + deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08; + if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) { + waveFormat.wBitsPerSample = 8; + stream_.deviceFormat[mode] = RTAUDIO_SINT8; + } + else { // assume 16-bit is supported + waveFormat.wBitsPerSample = 16; + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + } + } + stream_.userFormat = format; + + // Update wave format structure and buffer information. + waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels; + + // If the user wants an even bigger buffer, increase the device buffer size accordingly. + while ( dsPointerLeadTime * 2U > dsBufferSize ) + dsBufferSize *= 2; + + // Setup the secondary DS buffer description. + DSCBUFFERDESC bufferDescription; + ZeroMemory( &bufferDescription, sizeof( DSCBUFFERDESC ) ); + bufferDescription.dwSize = sizeof( DSCBUFFERDESC ); + bufferDescription.dwFlags = 0; + bufferDescription.dwReserved = 0; + bufferDescription.dwBufferBytes = dsBufferSize; + bufferDescription.lpwfxFormat = &waveFormat; + + // Create the capture buffer. + LPDIRECTSOUNDCAPTUREBUFFER buffer; + result = input->CreateCaptureBuffer( &bufferDescription, &buffer, NULL ); + if ( FAILED( result ) ) { + input->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating input buffer (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Get the buffer size ... might be different from what we specified. + DSCBCAPS dscbcaps; + dscbcaps.dwSize = sizeof( DSCBCAPS ); + result = buffer->GetCaps( &dscbcaps ); + if ( FAILED( result ) ) { + input->Release(); + buffer->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + dsBufferSize = dscbcaps.dwBufferBytes; + + // NOTE: We could have a problem here if this is a duplex stream + // and the play and capture hardware buffer sizes are different + // (I'm actually not sure if that is a problem or not). + // Currently, we are not verifying that. + + // Lock the capture buffer + LPVOID audioPtr; + DWORD dataLen; + result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 ); + if ( FAILED( result ) ) { + input->Release(); + buffer->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking input buffer (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Zero the buffer + ZeroMemory( audioPtr, dataLen ); + + // Unlock the buffer + result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); + if ( FAILED( result ) ) { + input->Release(); + buffer->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking input buffer (" << dsDevices[ device ].name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + ohandle = (void *) input; + bhandle = (void *) buffer; + } + + // Set various stream parameters + DsHandle *handle = 0; + stream_.nDeviceChannels[mode] = channels + firstChannel; + stream_.nUserChannels[mode] = channels; + stream_.bufferSize = *bufferSize; + stream_.channelOffset[mode] = firstChannel; + stream_.deviceInterleaved[mode] = true; + if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; + else stream_.userInterleaved = true; + + // Set flag for buffer conversion + stream_.doConvertBuffer[mode] = false; + if (stream_.nUserChannels[mode] != stream_.nDeviceChannels[mode]) + stream_.doConvertBuffer[mode] = true; + if (stream_.userFormat != stream_.deviceFormat[mode]) + stream_.doConvertBuffer[mode] = true; + if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && + stream_.nUserChannels[mode] > 1 ) + stream_.doConvertBuffer[mode] = true; + + // Allocate necessary internal buffers + long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); + if ( stream_.userBuffer[mode] == NULL ) { + errorText_ = "RtApiDs::probeDeviceOpen: error allocating user buffer memory."; + goto error; + } + + if ( stream_.doConvertBuffer[mode] ) { + + bool makeBuffer = true; + bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); + if ( mode == INPUT ) { + if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { + unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); + if ( bufferBytes <= (long) bytesOut ) makeBuffer = false; + } + } + + if ( makeBuffer ) { + bufferBytes *= *bufferSize; + if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); + stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); + if ( stream_.deviceBuffer == NULL ) { + errorText_ = "RtApiDs::probeDeviceOpen: error allocating device buffer memory."; + goto error; + } + } + } + + // Allocate our DsHandle structures for the stream. + if ( stream_.apiHandle == 0 ) { + try { + handle = new DsHandle; + } + catch ( std::bad_alloc& ) { + errorText_ = "RtApiDs::probeDeviceOpen: error allocating AsioHandle memory."; + goto error; + } + + // Create a manual-reset event. + handle->condition = CreateEvent( NULL, // no security + TRUE, // manual-reset + FALSE, // non-signaled initially + NULL ); // unnamed + stream_.apiHandle = (void *) handle; + } + else + handle = (DsHandle *) stream_.apiHandle; + handle->id[mode] = ohandle; + handle->buffer[mode] = bhandle; + handle->dsBufferSize[mode] = dsBufferSize; + handle->dsPointerLeadTime[mode] = dsPointerLeadTime; + + stream_.device[mode] = device; + stream_.state = STREAM_STOPPED; + if ( stream_.mode == OUTPUT && mode == INPUT ) + // We had already set up an output stream. + stream_.mode = DUPLEX; + else + stream_.mode = mode; + stream_.nBuffers = nBuffers; + stream_.sampleRate = sampleRate; + + // Setup the buffer conversion information structure. + if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); + + // Setup the callback thread. + if ( stream_.callbackInfo.isRunning == false ) { + unsigned threadId; + stream_.callbackInfo.isRunning = true; + stream_.callbackInfo.object = (void *) this; + stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &callbackHandler, + &stream_.callbackInfo, 0, &threadId ); + if ( stream_.callbackInfo.thread == 0 ) { + errorText_ = "RtApiDs::probeDeviceOpen: error creating callback thread!"; + goto error; + } + + // Boost DS thread priority + SetThreadPriority( (HANDLE) stream_.callbackInfo.thread, THREAD_PRIORITY_HIGHEST ); + } + return SUCCESS; + + error: + if ( handle ) { + if ( handle->buffer[0] ) { // the object pointer can be NULL and valid + LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0]; + LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; + if ( buffer ) buffer->Release(); + object->Release(); + } + if ( handle->buffer[1] ) { + LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1]; + LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; + if ( buffer ) buffer->Release(); + object->Release(); + } + CloseHandle( handle->condition ); + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.state = STREAM_CLOSED; + return FAILURE; +} + +void RtApiDs :: closeStream() +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiDs::closeStream(): no open stream to close!"; + error( RtAudioError::WARNING ); + return; + } + + // Stop the callback thread. + stream_.callbackInfo.isRunning = false; + WaitForSingleObject( (HANDLE) stream_.callbackInfo.thread, INFINITE ); + CloseHandle( (HANDLE) stream_.callbackInfo.thread ); + + DsHandle *handle = (DsHandle *) stream_.apiHandle; + if ( handle ) { + if ( handle->buffer[0] ) { // the object pointer can be NULL and valid + LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0]; + LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; + if ( buffer ) { + buffer->Stop(); + buffer->Release(); + } + object->Release(); + } + if ( handle->buffer[1] ) { + LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1]; + LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; + if ( buffer ) { + buffer->Stop(); + buffer->Release(); + } + object->Release(); + } + CloseHandle( handle->condition ); + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.mode = UNINITIALIZED; + stream_.state = STREAM_CLOSED; +} + +void RtApiDs :: startStream() +{ + verifyStream(); + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiDs::startStream(): the stream is already running!"; + error( RtAudioError::WARNING ); + return; + } + + #if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); + #endif + + DsHandle *handle = (DsHandle *) stream_.apiHandle; + + // Increase scheduler frequency on lesser windows (a side-effect of + // increasing timer accuracy). On greater windows (Win2K or later), + // this is already in effect. + timeBeginPeriod( 1 ); + + buffersRolling = false; + duplexPrerollBytes = 0; + + if ( stream_.mode == DUPLEX ) { + // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize. + duplexPrerollBytes = (int) ( 0.5 * stream_.sampleRate * formatBytes( stream_.deviceFormat[1] ) * stream_.nDeviceChannels[1] ); + } + + HRESULT result = 0; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; + result = buffer->Play( 0, 0, DSBPLAY_LOOPING ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting output buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { + + LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; + result = buffer->Start( DSCBSTART_LOOPING ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting input buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + handle->drainCounter = 0; + handle->internalDrain = false; + ResetEvent( handle->condition ); + stream_.state = STREAM_RUNNING; + + unlock: + if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiDs :: stopStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiDs::stopStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + HRESULT result = 0; + LPVOID audioPtr; + DWORD dataLen; + DsHandle *handle = (DsHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + if ( handle->drainCounter == 0 ) { + handle->drainCounter = 2; + WaitForSingleObject( handle->condition, INFINITE ); // block until signaled + } + + stream_.state = STREAM_STOPPED; + + MUTEX_LOCK( &stream_.mutex ); + + // Stop the buffer and clear memory + LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; + result = buffer->Stop(); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping output buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + + // Lock the buffer and clear it so that if we start to play again, + // we won't have old data playing. + result = buffer->Lock( 0, handle->dsBufferSize[0], &audioPtr, &dataLen, NULL, NULL, 0 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking output buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + + // Zero the DS buffer + ZeroMemory( audioPtr, dataLen ); + + // Unlock the DS buffer + result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking output buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + + // If we start playing again, we must begin at beginning of buffer. + handle->bufferPointer[0] = 0; + } + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { + LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; + audioPtr = NULL; + dataLen = 0; + + stream_.state = STREAM_STOPPED; + + if ( stream_.mode != DUPLEX ) + MUTEX_LOCK( &stream_.mutex ); + + result = buffer->Stop(); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping input buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + + // Lock the buffer and clear it so that if we start to play again, + // we won't have old data playing. + result = buffer->Lock( 0, handle->dsBufferSize[1], &audioPtr, &dataLen, NULL, NULL, 0 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking input buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + + // Zero the DS buffer + ZeroMemory( audioPtr, dataLen ); + + // Unlock the DS buffer + result = buffer->Unlock( audioPtr, dataLen, NULL, 0 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking input buffer!"; + errorText_ = errorStream_.str(); + goto unlock; + } + + // If we start recording again, we must begin at beginning of buffer. + handle->bufferPointer[1] = 0; + } + + unlock: + timeEndPeriod( 1 ); // revert to normal scheduler frequency on lesser windows. + MUTEX_UNLOCK( &stream_.mutex ); + + if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiDs :: abortStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiDs::abortStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + DsHandle *handle = (DsHandle *) stream_.apiHandle; + handle->drainCounter = 2; + + stopStream(); +} + +void RtApiDs :: callbackEvent() +{ + if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) { + Sleep( 50 ); // sleep 50 milliseconds + return; + } + + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiDs::callbackEvent(): the stream is closed ... this shouldn't happen!"; + error( RtAudioError::WARNING ); + return; + } + + CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; + DsHandle *handle = (DsHandle *) stream_.apiHandle; + + // Check if we were draining the stream and signal is finished. + if ( handle->drainCounter > stream_.nBuffers + 2 ) { + + stream_.state = STREAM_STOPPING; + if ( handle->internalDrain == false ) + SetEvent( handle->condition ); + else + stopStream(); + return; + } + + // Invoke user callback to get fresh output data UNLESS we are + // draining stream. + if ( handle->drainCounter == 0 ) { + RtAudioCallback callback = (RtAudioCallback) info->callback; + double streamTime = getStreamTime(); + RtAudioStreamStatus status = 0; + if ( stream_.mode != INPUT && handle->xrun[0] == true ) { + status |= RTAUDIO_OUTPUT_UNDERFLOW; + handle->xrun[0] = false; + } + if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { + status |= RTAUDIO_INPUT_OVERFLOW; + handle->xrun[1] = false; + } + int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], + stream_.bufferSize, streamTime, status, info->userData ); + if ( cbReturnValue == 2 ) { + stream_.state = STREAM_STOPPING; + handle->drainCounter = 2; + abortStream(); + return; + } + else if ( cbReturnValue == 1 ) { + handle->drainCounter = 1; + handle->internalDrain = true; + } + } + + HRESULT result; + DWORD currentWritePointer, safeWritePointer; + DWORD currentReadPointer, safeReadPointer; + UINT nextWritePointer; + + LPVOID buffer1 = NULL; + LPVOID buffer2 = NULL; + DWORD bufferSize1 = 0; + DWORD bufferSize2 = 0; + + char *buffer; + long bufferBytes; + + MUTEX_LOCK( &stream_.mutex ); + if ( stream_.state == STREAM_STOPPED ) { + MUTEX_UNLOCK( &stream_.mutex ); + return; + } + + if ( buffersRolling == false ) { + if ( stream_.mode == DUPLEX ) { + //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); + + // It takes a while for the devices to get rolling. As a result, + // there's no guarantee that the capture and write device pointers + // will move in lockstep. Wait here for both devices to start + // rolling, and then set our buffer pointers accordingly. + // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600 + // bytes later than the write buffer. + + // Stub: a serious risk of having a pre-emptive scheduling round + // take place between the two GetCurrentPosition calls... but I'm + // really not sure how to solve the problem. Temporarily boost to + // Realtime priority, maybe; but I'm not sure what priority the + // DirectSound service threads run at. We *should* be roughly + // within a ms or so of correct. + + LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; + LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; + + DWORD startSafeWritePointer, startSafeReadPointer; + + result = dsWriteBuffer->GetCurrentPosition( NULL, &startSafeWritePointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + result = dsCaptureBuffer->GetCurrentPosition( NULL, &startSafeReadPointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + while ( true ) { + result = dsWriteBuffer->GetCurrentPosition( NULL, &safeWritePointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + result = dsCaptureBuffer->GetCurrentPosition( NULL, &safeReadPointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + if ( safeWritePointer != startSafeWritePointer && safeReadPointer != startSafeReadPointer ) break; + Sleep( 1 ); + } + + //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); + + handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0]; + if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0]; + handle->bufferPointer[1] = safeReadPointer; + } + else if ( stream_.mode == OUTPUT ) { + + // Set the proper nextWritePosition after initial startup. + LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; + result = dsWriteBuffer->GetCurrentPosition( ¤tWritePointer, &safeWritePointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0]; + if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0]; + } + + buffersRolling = true; + } + + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0]; + + if ( handle->drainCounter > 1 ) { // write zeros to the output stream + bufferBytes = stream_.bufferSize * stream_.nUserChannels[0]; + bufferBytes *= formatBytes( stream_.userFormat ); + memset( stream_.userBuffer[0], 0, bufferBytes ); + } + + // Setup parameters and do buffer conversion if necessary. + if ( stream_.doConvertBuffer[0] ) { + buffer = stream_.deviceBuffer; + convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); + bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[0]; + bufferBytes *= formatBytes( stream_.deviceFormat[0] ); + } + else { + buffer = stream_.userBuffer[0]; + bufferBytes = stream_.bufferSize * stream_.nUserChannels[0]; + bufferBytes *= formatBytes( stream_.userFormat ); + } + + // No byte swapping necessary in DirectSound implementation. + + // Ahhh ... windoze. 16-bit data is signed but 8-bit data is + // unsigned. So, we need to convert our signed 8-bit data here to + // unsigned. + if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 ) + for ( int i=0; idsBufferSize[0]; + nextWritePointer = handle->bufferPointer[0]; + + DWORD endWrite, leadPointer; + while ( true ) { + // Find out where the read and "safe write" pointers are. + result = dsBuffer->GetCurrentPosition( ¤tWritePointer, &safeWritePointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + + // We will copy our output buffer into the region between + // safeWritePointer and leadPointer. If leadPointer is not + // beyond the next endWrite position, wait until it is. + leadPointer = safeWritePointer + handle->dsPointerLeadTime[0]; + //std::cout << "safeWritePointer = " << safeWritePointer << ", leadPointer = " << leadPointer << ", nextWritePointer = " << nextWritePointer << std::endl; + if ( leadPointer > dsBufferSize ) leadPointer -= dsBufferSize; + if ( leadPointer < nextWritePointer ) leadPointer += dsBufferSize; // unwrap offset + endWrite = nextWritePointer + bufferBytes; + + // Check whether the entire write region is behind the play pointer. + if ( leadPointer >= endWrite ) break; + + // If we are here, then we must wait until the leadPointer advances + // beyond the end of our next write region. We use the + // Sleep() function to suspend operation until that happens. + double millis = ( endWrite - leadPointer ) * 1000.0; + millis /= ( formatBytes( stream_.deviceFormat[0]) * stream_.nDeviceChannels[0] * stream_.sampleRate); + if ( millis < 1.0 ) millis = 1.0; + Sleep( (DWORD) millis ); + } + + if ( dsPointerBetween( nextWritePointer, safeWritePointer, currentWritePointer, dsBufferSize ) + || dsPointerBetween( endWrite, safeWritePointer, currentWritePointer, dsBufferSize ) ) { + // We've strayed into the forbidden zone ... resync the read pointer. + handle->xrun[0] = true; + nextWritePointer = safeWritePointer + handle->dsPointerLeadTime[0] - bufferBytes; + if ( nextWritePointer >= dsBufferSize ) nextWritePointer -= dsBufferSize; + handle->bufferPointer[0] = nextWritePointer; + endWrite = nextWritePointer + bufferBytes; + } + + // Lock free space in the buffer + result = dsBuffer->Lock( nextWritePointer, bufferBytes, &buffer1, + &bufferSize1, &buffer2, &bufferSize2, 0 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + + // Copy our buffer into the DS buffer + CopyMemory( buffer1, buffer, bufferSize1 ); + if ( buffer2 != NULL ) CopyMemory( buffer2, buffer+bufferSize1, bufferSize2 ); + + // Update our buffer offset and unlock sound buffer + dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + nextWritePointer = ( nextWritePointer + bufferSize1 + bufferSize2 ) % dsBufferSize; + handle->bufferPointer[0] = nextWritePointer; + } + + // Don't bother draining input + if ( handle->drainCounter ) { + handle->drainCounter++; + goto unlock; + } + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { + + // Setup parameters. + if ( stream_.doConvertBuffer[1] ) { + buffer = stream_.deviceBuffer; + bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[1]; + bufferBytes *= formatBytes( stream_.deviceFormat[1] ); + } + else { + buffer = stream_.userBuffer[1]; + bufferBytes = stream_.bufferSize * stream_.nUserChannels[1]; + bufferBytes *= formatBytes( stream_.userFormat ); + } + + LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1]; + long nextReadPointer = handle->bufferPointer[1]; + DWORD dsBufferSize = handle->dsBufferSize[1]; + + // Find out where the write and "safe read" pointers are. + result = dsBuffer->GetCurrentPosition( ¤tReadPointer, &safeReadPointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + + if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset + DWORD endRead = nextReadPointer + bufferBytes; + + // Handling depends on whether we are INPUT or DUPLEX. + // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode, + // then a wait here will drag the write pointers into the forbidden zone. + // + // In DUPLEX mode, rather than wait, we will back off the read pointer until + // it's in a safe position. This causes dropouts, but it seems to be the only + // practical way to sync up the read and write pointers reliably, given the + // the very complex relationship between phase and increment of the read and write + // pointers. + // + // In order to minimize audible dropouts in DUPLEX mode, we will + // provide a pre-roll period of 0.5 seconds in which we return + // zeros from the read buffer while the pointers sync up. + + if ( stream_.mode == DUPLEX ) { + if ( safeReadPointer < endRead ) { + if ( duplexPrerollBytes <= 0 ) { + // Pre-roll time over. Be more agressive. + int adjustment = endRead-safeReadPointer; + + handle->xrun[1] = true; + // Two cases: + // - large adjustments: we've probably run out of CPU cycles, so just resync exactly, + // and perform fine adjustments later. + // - small adjustments: back off by twice as much. + if ( adjustment >= 2*bufferBytes ) + nextReadPointer = safeReadPointer-2*bufferBytes; + else + nextReadPointer = safeReadPointer-bufferBytes-adjustment; + + if ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize; + + } + else { + // In pre=roll time. Just do it. + nextReadPointer = safeReadPointer - bufferBytes; + while ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize; + } + endRead = nextReadPointer + bufferBytes; + } + } + else { // mode == INPUT + while ( safeReadPointer < endRead && stream_.callbackInfo.isRunning ) { + // See comments for playback. + double millis = (endRead - safeReadPointer) * 1000.0; + millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate); + if ( millis < 1.0 ) millis = 1.0; + Sleep( (DWORD) millis ); + + // Wake up and find out where we are now. + result = dsBuffer->GetCurrentPosition( ¤tReadPointer, &safeReadPointer ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + + if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset + } + } + + // Lock free space in the buffer + result = dsBuffer->Lock( nextReadPointer, bufferBytes, &buffer1, + &bufferSize1, &buffer2, &bufferSize2, 0 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + + if ( duplexPrerollBytes <= 0 ) { + // Copy our buffer into the DS buffer + CopyMemory( buffer, buffer1, bufferSize1 ); + if ( buffer2 != NULL ) CopyMemory( buffer+bufferSize1, buffer2, bufferSize2 ); + } + else { + memset( buffer, 0, bufferSize1 ); + if ( buffer2 != NULL ) memset( buffer + bufferSize1, 0, bufferSize2 ); + duplexPrerollBytes -= bufferSize1 + bufferSize2; + } + + // Update our buffer offset and unlock sound buffer + nextReadPointer = ( nextReadPointer + bufferSize1 + bufferSize2 ) % dsBufferSize; + dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 ); + if ( FAILED( result ) ) { + errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!"; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + handle->bufferPointer[1] = nextReadPointer; + + // No byte swapping necessary in DirectSound implementation. + + // If necessary, convert 8-bit data from unsigned to signed. + if ( stream_.deviceFormat[1] == RTAUDIO_SINT8 ) + for ( int j=0; jobject; + bool* isRunning = &info->isRunning; + + while ( *isRunning == true ) { + object->callbackEvent(); + } + + _endthreadex( 0 ); + return 0; +} + +static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, + LPCTSTR description, + LPCTSTR /*module*/, + LPVOID lpContext ) +{ + struct DsProbeData& probeInfo = *(struct DsProbeData*) lpContext; + std::vector& dsDevices = *probeInfo.dsDevices; + + HRESULT hr; + bool validDevice = false; + if ( probeInfo.isInput == true ) { + DSCCAPS caps; + LPDIRECTSOUNDCAPTURE object; + + hr = DirectSoundCaptureCreate( lpguid, &object, NULL ); + if ( hr != DS_OK ) return TRUE; + + caps.dwSize = sizeof(caps); + hr = object->GetCaps( &caps ); + if ( hr == DS_OK ) { + if ( caps.dwChannels > 0 && caps.dwFormats > 0 ) + validDevice = true; + } + object->Release(); + } + else { + DSCAPS caps; + LPDIRECTSOUND object; + hr = DirectSoundCreate( lpguid, &object, NULL ); + if ( hr != DS_OK ) return TRUE; + + caps.dwSize = sizeof(caps); + hr = object->GetCaps( &caps ); + if ( hr == DS_OK ) { + if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO ) + validDevice = true; + } + object->Release(); + } + + // If good device, then save its name and guid. + std::string name = convertCharPointerToStdString( description ); + //if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" ) + if ( lpguid == NULL ) + name = "Default Device"; + if ( validDevice ) { + for ( unsigned int i=0; i +#include + + // A structure to hold various information related to the ALSA API + // implementation. +struct AlsaHandle { + snd_pcm_t *handles[2]; + bool synchronized; + bool xrun[2]; + pthread_cond_t runnable_cv; + bool runnable; + + AlsaHandle() +#if _cplusplus >= 201103L + :handles{nullptr, nullptr}, synchronized(false), runnable(false) { xrun[0] = false; xrun[1] = false; } +#else + : synchronized(false), runnable(false) { handles[0] = NULL; handles[1] = NULL; xrun[0] = false; xrun[1] = false; } +#endif +}; + +static void *alsaCallbackHandler( void * ptr ); + +RtApiAlsa :: RtApiAlsa() +{ + // Nothing to do here. +} + +RtApiAlsa :: ~RtApiAlsa() +{ + if ( stream_.state != STREAM_CLOSED ) closeStream(); +} + +unsigned int RtApiAlsa :: getDeviceCount( void ) +{ + unsigned nDevices = 0; + int result, subdevice, card; + char name[64]; + snd_ctl_t *handle = 0; + + strcpy(name, "default"); + result = snd_ctl_open( &handle, "default", 0 ); + if (result == 0) { + nDevices++; + snd_ctl_close( handle ); + } + + // Count cards and devices + card = -1; + snd_card_next( &card ); + while ( card >= 0 ) { + sprintf( name, "hw:%d", card ); + result = snd_ctl_open( &handle, name, 0 ); + if ( result < 0 ) { + handle = 0; + errorStream_ << "RtApiAlsa::getDeviceCount: control open, card = " << card << ", " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto nextcard; + } + subdevice = -1; + while( 1 ) { + result = snd_ctl_pcm_next_device( handle, &subdevice ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::getDeviceCount: control next device, card = " << card << ", " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + break; + } + if ( subdevice < 0 ) + break; + nDevices++; + } + nextcard: + if ( handle ) + snd_ctl_close( handle ); + snd_card_next( &card ); + } + + return nDevices; +} + +RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) +{ + RtAudio::DeviceInfo info; + info.probed = false; + + unsigned nDevices = 0; + int result=-1, subdevice=-1, card=-1; + char name[64]; + snd_ctl_t *chandle = 0; + + result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK ); + if ( result == 0 ) { + if ( nDevices++ == device ) { + strcpy( name, "default" ); + goto foundDevice; + } + } + if ( chandle ) + snd_ctl_close( chandle ); + + // Count cards and devices + snd_card_next( &card ); + while ( card >= 0 ) { + sprintf( name, "hw:%d", card ); + result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK ); + if ( result < 0 ) { + chandle = 0; + errorStream_ << "RtApiAlsa::getDeviceInfo: control open, card = " << card << ", " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto nextcard; + } + subdevice = -1; + while( 1 ) { + result = snd_ctl_pcm_next_device( chandle, &subdevice ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::getDeviceInfo: control next device, card = " << card << ", " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + break; + } + if ( subdevice < 0 ) break; + if ( nDevices == device ) { + sprintf( name, "hw:%d,%d", card, subdevice ); + goto foundDevice; + } + nDevices++; + } + nextcard: + if ( chandle ) + snd_ctl_close( chandle ); + snd_card_next( &card ); + } + + if ( nDevices == 0 ) { + errorText_ = "RtApiAlsa::getDeviceInfo: no devices found!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + if ( device >= nDevices ) { + errorText_ = "RtApiAlsa::getDeviceInfo: device ID is invalid!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + foundDevice: + + // If a stream is already open, we cannot probe the stream devices. + // Thus, use the saved results. + if ( stream_.state != STREAM_CLOSED && + ( stream_.device[0] == device || stream_.device[1] == device ) ) { + snd_ctl_close( chandle ); + if ( device >= devices_.size() ) { + errorText_ = "RtApiAlsa::getDeviceInfo: device ID was not present before stream was opened."; + error( RtAudioError::WARNING ); + return info; + } + return devices_[ device ]; + } + + int openMode = SND_PCM_ASYNC; + snd_pcm_stream_t stream; + snd_pcm_info_t *pcminfo; + snd_pcm_info_alloca( &pcminfo ); + snd_pcm_t *phandle; + snd_pcm_hw_params_t *params; + snd_pcm_hw_params_alloca( ¶ms ); + + // First try for playback unless default device (which has subdev -1) + stream = SND_PCM_STREAM_PLAYBACK; + snd_pcm_info_set_stream( pcminfo, stream ); + if ( subdevice != -1 ) { + snd_pcm_info_set_device( pcminfo, subdevice ); + snd_pcm_info_set_subdevice( pcminfo, 0 ); + + result = snd_ctl_pcm_info( chandle, pcminfo ); + if ( result < 0 ) { + // Device probably doesn't support playback. + goto captureProbe; + } + } + + result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto captureProbe; + } + + // The device is open ... fill the parameter structure. + result = snd_pcm_hw_params_any( phandle, params ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto captureProbe; + } + + // Get output channel information. + unsigned int value; + result = snd_pcm_hw_params_get_channels_max( params, &value ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") output channels, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto captureProbe; + } + info.outputChannels = value; + snd_pcm_close( phandle ); + + captureProbe: + stream = SND_PCM_STREAM_CAPTURE; + snd_pcm_info_set_stream( pcminfo, stream ); + + // Now try for capture unless default device (with subdev = -1) + if ( subdevice != -1 ) { + result = snd_ctl_pcm_info( chandle, pcminfo ); + snd_ctl_close( chandle ); + if ( result < 0 ) { + // Device probably doesn't support capture. + if ( info.outputChannels == 0 ) return info; + goto probeParameters; + } + } + else + snd_ctl_close( chandle ); + + result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + if ( info.outputChannels == 0 ) return info; + goto probeParameters; + } + + // The device is open ... fill the parameter structure. + result = snd_pcm_hw_params_any( phandle, params ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + if ( info.outputChannels == 0 ) return info; + goto probeParameters; + } + + result = snd_pcm_hw_params_get_channels_max( params, &value ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") input channels, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + if ( info.outputChannels == 0 ) return info; + goto probeParameters; + } + info.inputChannels = value; + snd_pcm_close( phandle ); + + // If device opens for both playback and capture, we determine the channels. + if ( info.outputChannels > 0 && info.inputChannels > 0 ) + info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; + + // ALSA doesn't provide default devices so we'll use the first available one. + if ( device == 0 && info.outputChannels > 0 ) + info.isDefaultOutput = true; + if ( device == 0 && info.inputChannels > 0 ) + info.isDefaultInput = true; + + probeParameters: + // At this point, we just need to figure out the supported data + // formats and sample rates. We'll proceed by opening the device in + // the direction with the maximum number of channels, or playback if + // they are equal. This might limit our sample rate options, but so + // be it. + + if ( info.outputChannels >= info.inputChannels ) + stream = SND_PCM_STREAM_PLAYBACK; + else + stream = SND_PCM_STREAM_CAPTURE; + snd_pcm_info_set_stream( pcminfo, stream ); + + result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // The device is open ... fill the parameter structure. + result = snd_pcm_hw_params_any( phandle, params ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Test our discrete set of sample rate values. + info.sampleRates.clear(); + for ( unsigned int i=0; i info.preferredSampleRate ) ) + info.preferredSampleRate = SAMPLE_RATES[i]; + } + } + if ( info.sampleRates.size() == 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::getDeviceInfo: no supported sample rates found for device (" << name << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Probe the supported data formats ... we don't care about endian-ness just yet + snd_pcm_format_t format; + info.nativeFormats = 0; + format = SND_PCM_FORMAT_S8; + if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) + info.nativeFormats |= RTAUDIO_SINT8; + format = SND_PCM_FORMAT_S16; + if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) + info.nativeFormats |= RTAUDIO_SINT16; + format = SND_PCM_FORMAT_S24; + if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) + info.nativeFormats |= RTAUDIO_SINT24; + format = SND_PCM_FORMAT_S32; + if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) + info.nativeFormats |= RTAUDIO_SINT32; + format = SND_PCM_FORMAT_FLOAT; + if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) + info.nativeFormats |= RTAUDIO_FLOAT32; + format = SND_PCM_FORMAT_FLOAT64; + if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 ) + info.nativeFormats |= RTAUDIO_FLOAT64; + + // Check that we have at least one supported format + if ( info.nativeFormats == 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::getDeviceInfo: pcm device (" << name << ") data format not supported by RtAudio."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Get the device name + if (strncmp(name, "default", 7)!=0) { + char *cardname; + result = snd_card_get_name( card, &cardname ); + if ( result >= 0 ) { + sprintf( name, "hw:%s,%d", cardname, subdevice ); + free( cardname ); + } + } + info.name = name; + + // That's all ... close the device and return + snd_pcm_close( phandle ); + info.probed = true; + return info; +} + +void RtApiAlsa :: saveDeviceInfo( void ) +{ + devices_.clear(); + + unsigned int nDevices = getDeviceCount(); + devices_.resize( nDevices ); + for ( unsigned int i=0; iflags & RTAUDIO_ALSA_USE_DEFAULT) ) + { + strcpy(name, "default"); + result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK ); + if ( result == 0 ) { + if ( nDevices == device ) { + strcpy( name, "default" ); + snd_ctl_close( chandle ); + goto foundDevice; + } + nDevices++; + } + } + + else { + nDevices++; + // Count cards and devices + card = -1; + snd_card_next( &card ); + while ( card >= 0 ) { + sprintf( name, "hw:%d", card ); + result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::probeDeviceOpen: control open, card = " << card << ", " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + subdevice = -1; + while( 1 ) { + result = snd_ctl_pcm_next_device( chandle, &subdevice ); + if ( result < 0 ) break; + if ( subdevice < 0 ) break; + if ( nDevices == device ) { + sprintf( name, "hw:%d,%d", card, subdevice ); + snd_ctl_close( chandle ); + goto foundDevice; + } + nDevices++; + } + snd_ctl_close( chandle ); + snd_card_next( &card ); + } + + if ( nDevices == 0 ) { + // This should not happen because a check is made before this function is called. + errorText_ = "RtApiAlsa::probeDeviceOpen: no devices found!"; + return FAILURE; + } + + if ( device >= nDevices ) { + // This should not happen because a check is made before this function is called. + errorText_ = "RtApiAlsa::probeDeviceOpen: device ID is invalid!"; + return FAILURE; + } + } + + foundDevice: + + // The getDeviceInfo() function will not work for a device that is + // already open. Thus, we'll probe the system before opening a + // stream and save the results for use by getDeviceInfo(). + if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) // only do once + this->saveDeviceInfo(); + + snd_pcm_stream_t stream; + if ( mode == OUTPUT ) + stream = SND_PCM_STREAM_PLAYBACK; + else + stream = SND_PCM_STREAM_CAPTURE; + + snd_pcm_t *phandle; + int openMode = SND_PCM_ASYNC; + result = snd_pcm_open( &phandle, name, stream, openMode ); + if ( result < 0 ) { + if ( mode == OUTPUT ) + errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for output."; + else + errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for input."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Fill the parameter structure. + snd_pcm_hw_params_t *hw_params; + snd_pcm_hw_params_alloca( &hw_params ); + result = snd_pcm_hw_params_any( phandle, hw_params ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") parameters, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + +#if defined(__RTAUDIO_DEBUG__) + fprintf( stderr, "\nRtApiAlsa: dump hardware params just after device open:\n\n" ); + snd_pcm_hw_params_dump( hw_params, out ); +#endif + + // Set access ... check user preference. + if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) { + stream_.userInterleaved = false; + result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED ); + if ( result < 0 ) { + result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); + stream_.deviceInterleaved[mode] = true; + } + else + stream_.deviceInterleaved[mode] = false; + } + else { + stream_.userInterleaved = true; + result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED ); + if ( result < 0 ) { + result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED ); + stream_.deviceInterleaved[mode] = false; + } + else + stream_.deviceInterleaved[mode] = true; + } + + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") access, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Determine how to set the device format. + stream_.userFormat = format; + snd_pcm_format_t deviceFormat = SND_PCM_FORMAT_UNKNOWN; + + if ( format == RTAUDIO_SINT8 ) + deviceFormat = SND_PCM_FORMAT_S8; + else if ( format == RTAUDIO_SINT16 ) + deviceFormat = SND_PCM_FORMAT_S16; + else if ( format == RTAUDIO_SINT24 ) + deviceFormat = SND_PCM_FORMAT_S24; + else if ( format == RTAUDIO_SINT32 ) + deviceFormat = SND_PCM_FORMAT_S32; + else if ( format == RTAUDIO_FLOAT32 ) + deviceFormat = SND_PCM_FORMAT_FLOAT; + else if ( format == RTAUDIO_FLOAT64 ) + deviceFormat = SND_PCM_FORMAT_FLOAT64; + + if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat) == 0) { + stream_.deviceFormat[mode] = format; + goto setFormat; + } + + // The user requested format is not natively supported by the device. + deviceFormat = SND_PCM_FORMAT_FLOAT64; + if ( snd_pcm_hw_params_test_format( phandle, hw_params, deviceFormat ) == 0 ) { + stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; + goto setFormat; + } + + deviceFormat = SND_PCM_FORMAT_FLOAT; + if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { + stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; + goto setFormat; + } + + deviceFormat = SND_PCM_FORMAT_S32; + if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { + stream_.deviceFormat[mode] = RTAUDIO_SINT32; + goto setFormat; + } + + deviceFormat = SND_PCM_FORMAT_S24; + if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { + stream_.deviceFormat[mode] = RTAUDIO_SINT24; + goto setFormat; + } + + deviceFormat = SND_PCM_FORMAT_S16; + if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + goto setFormat; + } + + deviceFormat = SND_PCM_FORMAT_S8; + if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) { + stream_.deviceFormat[mode] = RTAUDIO_SINT8; + goto setFormat; + } + + // If we get here, no supported format was found. + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device " << device << " data format not supported by RtAudio."; + errorText_ = errorStream_.str(); + return FAILURE; + + setFormat: + result = snd_pcm_hw_params_set_format( phandle, hw_params, deviceFormat ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") data format, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Determine whether byte-swaping is necessary. + stream_.doByteSwap[mode] = false; + if ( deviceFormat != SND_PCM_FORMAT_S8 ) { + result = snd_pcm_format_cpu_endian( deviceFormat ); + if ( result == 0 ) + stream_.doByteSwap[mode] = true; + else if (result < 0) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") endian-ness, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + + // Set the sample rate. + result = snd_pcm_hw_params_set_rate_near( phandle, hw_params, (unsigned int*) &sampleRate, 0 ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting sample rate on device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Determine the number of channels for this device. We support a possible + // minimum device channel number > than the value requested by the user. + stream_.nUserChannels[mode] = channels; + unsigned int value; + result = snd_pcm_hw_params_get_channels_max( hw_params, &value ); + unsigned int deviceChannels = value; + if ( result < 0 || deviceChannels < channels + firstChannel ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: requested channel parameters not supported by device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + result = snd_pcm_hw_params_get_channels_min( hw_params, &value ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting minimum channels for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + deviceChannels = value; + if ( deviceChannels < channels + firstChannel ) deviceChannels = channels + firstChannel; + stream_.nDeviceChannels[mode] = deviceChannels; + + // Set the device channels. + result = snd_pcm_hw_params_set_channels( phandle, hw_params, deviceChannels ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting channels for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Set the buffer (or period) size. + int dir = 0; + snd_pcm_uframes_t periodSize = *bufferSize; + result = snd_pcm_hw_params_set_period_size_near( phandle, hw_params, &periodSize, &dir ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting period size for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + *bufferSize = periodSize; + + // Set the buffer number, which in ALSA is referred to as the "period". + unsigned int periods = 0; + if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) periods = 2; + if ( options && options->numberOfBuffers > 0 ) periods = options->numberOfBuffers; + if ( periods < 2 ) periods = 4; // a fairly safe default value + result = snd_pcm_hw_params_set_periods_near( phandle, hw_params, &periods, &dir ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting periods for device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // If attempting to setup a duplex stream, the bufferSize parameter + // MUST be the same in both directions! + if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + stream_.bufferSize = *bufferSize; + + // Install the hardware configuration + result = snd_pcm_hw_params( phandle, hw_params ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing hardware configuration on device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + +#if defined(__RTAUDIO_DEBUG__) + fprintf(stderr, "\nRtApiAlsa: dump hardware params after installation:\n\n"); + snd_pcm_hw_params_dump( hw_params, out ); +#endif + + // Set the software configuration to fill buffers with zeros and prevent device stopping on xruns. + snd_pcm_sw_params_t *sw_params = NULL; + snd_pcm_sw_params_alloca( &sw_params ); + snd_pcm_sw_params_current( phandle, sw_params ); + snd_pcm_sw_params_set_start_threshold( phandle, sw_params, *bufferSize ); + snd_pcm_sw_params_set_stop_threshold( phandle, sw_params, ULONG_MAX ); + snd_pcm_sw_params_set_silence_threshold( phandle, sw_params, 0 ); + + // The following two settings were suggested by Theo Veenker + //snd_pcm_sw_params_set_avail_min( phandle, sw_params, *bufferSize ); + //snd_pcm_sw_params_set_xfer_align( phandle, sw_params, 1 ); + + // here are two options for a fix + //snd_pcm_sw_params_set_silence_size( phandle, sw_params, ULONG_MAX ); + snd_pcm_uframes_t val; + snd_pcm_sw_params_get_boundary( sw_params, &val ); + snd_pcm_sw_params_set_silence_size( phandle, sw_params, val ); + + result = snd_pcm_sw_params( phandle, sw_params ); + if ( result < 0 ) { + snd_pcm_close( phandle ); + errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing software configuration on device (" << name << "), " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + return FAILURE; + } + +#if defined(__RTAUDIO_DEBUG__) + fprintf(stderr, "\nRtApiAlsa: dump software params after installation:\n\n"); + snd_pcm_sw_params_dump( sw_params, out ); +#endif + + // Set flags for buffer conversion + stream_.doConvertBuffer[mode] = false; + if ( stream_.userFormat != stream_.deviceFormat[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && + stream_.nUserChannels[mode] > 1 ) + stream_.doConvertBuffer[mode] = true; + + // Allocate the ApiHandle if necessary and then save. + AlsaHandle *apiInfo = 0; + if ( stream_.apiHandle == 0 ) { + try { + apiInfo = (AlsaHandle *) new AlsaHandle; + } + catch ( std::bad_alloc& ) { + errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating AlsaHandle memory."; + goto error; + } + + if ( pthread_cond_init( &apiInfo->runnable_cv, NULL ) ) { + errorText_ = "RtApiAlsa::probeDeviceOpen: error initializing pthread condition variable."; + goto error; + } + + stream_.apiHandle = (void *) apiInfo; + apiInfo->handles[0] = 0; + apiInfo->handles[1] = 0; + } + else { + apiInfo = (AlsaHandle *) stream_.apiHandle; + } + apiInfo->handles[mode] = phandle; + phandle = 0; + + // Allocate necessary internal buffers. + unsigned long bufferBytes; + bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); + if ( stream_.userBuffer[mode] == NULL ) { + errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating user buffer memory."; + goto error; + } + + if ( stream_.doConvertBuffer[mode] ) { + + bool makeBuffer = true; + bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); + if ( mode == INPUT ) { + if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { + unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); + if ( bufferBytes <= bytesOut ) makeBuffer = false; + } + } + + if ( makeBuffer ) { + bufferBytes *= *bufferSize; + if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); + stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); + if ( stream_.deviceBuffer == NULL ) { + errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating device buffer memory."; + goto error; + } + } + } + + stream_.sampleRate = sampleRate; + stream_.nBuffers = periods; + stream_.device[mode] = device; + stream_.state = STREAM_STOPPED; + + // Setup the buffer conversion information structure. + if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); + + // Setup thread if necessary. + if ( stream_.mode == OUTPUT && mode == INPUT ) { + // We had already set up an output stream. + stream_.mode = DUPLEX; + // Link the streams if possible. + apiInfo->synchronized = false; + if ( snd_pcm_link( apiInfo->handles[0], apiInfo->handles[1] ) == 0 ) + apiInfo->synchronized = true; + else { + errorText_ = "RtApiAlsa::probeDeviceOpen: unable to synchronize input and output devices."; + error( RtAudioError::WARNING ); + } + } + else { + stream_.mode = mode; + + // Setup callback thread. + stream_.callbackInfo.object = (void *) this; + + // Set the thread attributes for joinable and realtime scheduling + // priority (optional). The higher priority will only take affect + // if the program is run as root or suid. Note, under Linux + // processes with CAP_SYS_NICE privilege, a user can change + // scheduling policy and priority (thus need not be root). See + // POSIX "capabilities". + pthread_attr_t attr; + pthread_attr_init( &attr ); + pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); +#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread) + if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) { + stream_.callbackInfo.doRealtime = true; + struct sched_param param; + int priority = options->priority; + int min = sched_get_priority_min( SCHED_RR ); + int max = sched_get_priority_max( SCHED_RR ); + if ( priority < min ) priority = min; + else if ( priority > max ) priority = max; + param.sched_priority = priority; + + // Set the policy BEFORE the priority. Otherwise it fails. + pthread_attr_setschedpolicy(&attr, SCHED_RR); + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); + // This is definitely required. Otherwise it fails. + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedparam(&attr, ¶m); + } + else + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); +#else + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); +#endif + + stream_.callbackInfo.isRunning = true; + result = pthread_create( &stream_.callbackInfo.thread, &attr, alsaCallbackHandler, &stream_.callbackInfo ); + pthread_attr_destroy( &attr ); + if ( result ) { + // Failed. Try instead with default attributes. + result = pthread_create( &stream_.callbackInfo.thread, NULL, alsaCallbackHandler, &stream_.callbackInfo ); + if ( result ) { + stream_.callbackInfo.isRunning = false; + errorText_ = "RtApiAlsa::error creating callback thread!"; + goto error; + } + } + } + + return SUCCESS; + + error: + if ( apiInfo ) { + pthread_cond_destroy( &apiInfo->runnable_cv ); + if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] ); + if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] ); + delete apiInfo; + stream_.apiHandle = 0; + } + + if ( phandle) snd_pcm_close( phandle ); + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.state = STREAM_CLOSED; + return FAILURE; +} + +void RtApiAlsa :: closeStream() +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiAlsa::closeStream(): no open stream to close!"; + error( RtAudioError::WARNING ); + return; + } + + AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; + stream_.callbackInfo.isRunning = false; + MUTEX_LOCK( &stream_.mutex ); + if ( stream_.state == STREAM_STOPPED ) { + apiInfo->runnable = true; + pthread_cond_signal( &apiInfo->runnable_cv ); + } + MUTEX_UNLOCK( &stream_.mutex ); + pthread_join( stream_.callbackInfo.thread, NULL ); + + if ( stream_.state == STREAM_RUNNING ) { + stream_.state = STREAM_STOPPED; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) + snd_pcm_drop( apiInfo->handles[0] ); + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) + snd_pcm_drop( apiInfo->handles[1] ); + } + + if ( apiInfo ) { + pthread_cond_destroy( &apiInfo->runnable_cv ); + if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] ); + if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] ); + delete apiInfo; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.mode = UNINITIALIZED; + stream_.state = STREAM_CLOSED; +} + +void RtApiAlsa :: startStream() +{ + // This method calls snd_pcm_prepare if the device isn't already in that state. + + verifyStream(); + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiAlsa::startStream(): the stream is already running!"; + error( RtAudioError::WARNING ); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + + #if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); + #endif + + int result = 0; + snd_pcm_state_t state; + AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; + snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + state = snd_pcm_state( handle[0] ); + if ( state != SND_PCM_STATE_PREPARED ) { + result = snd_pcm_prepare( handle[0] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::startStream: error preparing output pcm device, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + } + + if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { + result = snd_pcm_drop(handle[1]); // fix to remove stale data received since device has been open + state = snd_pcm_state( handle[1] ); + if ( state != SND_PCM_STATE_PREPARED ) { + result = snd_pcm_prepare( handle[1] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::startStream: error preparing input pcm device, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + } + + stream_.state = STREAM_RUNNING; + + unlock: + apiInfo->runnable = true; + pthread_cond_signal( &apiInfo->runnable_cv ); + MUTEX_UNLOCK( &stream_.mutex ); + + if ( result >= 0 ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiAlsa :: stopStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiAlsa::stopStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + stream_.state = STREAM_STOPPED; + MUTEX_LOCK( &stream_.mutex ); + + int result = 0; + AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; + snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + if ( apiInfo->synchronized ) + result = snd_pcm_drop( handle[0] ); + else + result = snd_pcm_drain( handle[0] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::stopStream: error draining output pcm device, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { + result = snd_pcm_drop( handle[1] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::stopStream: error stopping input pcm device, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + unlock: + apiInfo->runnable = false; // fixes high CPU usage when stopped + MUTEX_UNLOCK( &stream_.mutex ); + + if ( result >= 0 ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiAlsa :: abortStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiAlsa::abortStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + stream_.state = STREAM_STOPPED; + MUTEX_LOCK( &stream_.mutex ); + + int result = 0; + AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; + snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + result = snd_pcm_drop( handle[0] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::abortStream: error aborting output pcm device, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) { + result = snd_pcm_drop( handle[1] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::abortStream: error aborting input pcm device, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + unlock: + apiInfo->runnable = false; // fixes high CPU usage when stopped + MUTEX_UNLOCK( &stream_.mutex ); + + if ( result >= 0 ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiAlsa :: callbackEvent() +{ + AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; + if ( stream_.state == STREAM_STOPPED ) { + MUTEX_LOCK( &stream_.mutex ); + while ( !apiInfo->runnable ) + pthread_cond_wait( &apiInfo->runnable_cv, &stream_.mutex ); + + if ( stream_.state != STREAM_RUNNING ) { + MUTEX_UNLOCK( &stream_.mutex ); + return; + } + MUTEX_UNLOCK( &stream_.mutex ); + } + + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiAlsa::callbackEvent(): the stream is closed ... this shouldn't happen!"; + error( RtAudioError::WARNING ); + return; + } + + int doStopStream = 0; + RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; + double streamTime = getStreamTime(); + RtAudioStreamStatus status = 0; + if ( stream_.mode != INPUT && apiInfo->xrun[0] == true ) { + status |= RTAUDIO_OUTPUT_UNDERFLOW; + apiInfo->xrun[0] = false; + } + if ( stream_.mode != OUTPUT && apiInfo->xrun[1] == true ) { + status |= RTAUDIO_INPUT_OVERFLOW; + apiInfo->xrun[1] = false; + } + doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1], + stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData ); + + if ( doStopStream == 2 ) { + abortStream(); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + + // The state might change while waiting on a mutex. + if ( stream_.state == STREAM_STOPPED ) goto unlock; + + int result; + char *buffer; + int channels; + snd_pcm_t **handle; + snd_pcm_sframes_t frames; + RtAudioFormat format; + handle = (snd_pcm_t **) apiInfo->handles; + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { + + // Setup parameters. + if ( stream_.doConvertBuffer[1] ) { + buffer = stream_.deviceBuffer; + channels = stream_.nDeviceChannels[1]; + format = stream_.deviceFormat[1]; + } + else { + buffer = stream_.userBuffer[1]; + channels = stream_.nUserChannels[1]; + format = stream_.userFormat; + } + + // Read samples from device in interleaved/non-interleaved format. + if ( stream_.deviceInterleaved[1] ) + result = snd_pcm_readi( handle[1], buffer, stream_.bufferSize ); + else { + void *bufs[channels]; + size_t offset = stream_.bufferSize * formatBytes( format ); + for ( int i=0; ixrun[1] = true; + result = snd_pcm_prepare( handle[1] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after overrun, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + } + } + else { + errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + } + } + else { + errorStream_ << "RtApiAlsa::callbackEvent: audio read error, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + } + error( RtAudioError::WARNING ); + goto tryOutput; + } + + // Do byte swapping if necessary. + if ( stream_.doByteSwap[1] ) + byteSwapBuffer( buffer, stream_.bufferSize * channels, format ); + + // Do buffer conversion if necessary. + if ( stream_.doConvertBuffer[1] ) + convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); + + // Check stream latency + result = snd_pcm_delay( handle[1], &frames ); + if ( result == 0 && frames > 0 ) stream_.latency[1] = frames; + } + + tryOutput: + + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + // Setup parameters and do buffer conversion if necessary. + if ( stream_.doConvertBuffer[0] ) { + buffer = stream_.deviceBuffer; + convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); + channels = stream_.nDeviceChannels[0]; + format = stream_.deviceFormat[0]; + } + else { + buffer = stream_.userBuffer[0]; + channels = stream_.nUserChannels[0]; + format = stream_.userFormat; + } + + // Do byte swapping if necessary. + if ( stream_.doByteSwap[0] ) + byteSwapBuffer(buffer, stream_.bufferSize * channels, format); + + // Write samples to device in interleaved/non-interleaved format. + if ( stream_.deviceInterleaved[0] ) + result = snd_pcm_writei( handle[0], buffer, stream_.bufferSize ); + else { + void *bufs[channels]; + size_t offset = stream_.bufferSize * formatBytes( format ); + for ( int i=0; ixrun[0] = true; + result = snd_pcm_prepare( handle[0] ); + if ( result < 0 ) { + errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after underrun, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + } + else + errorText_ = "RtApiAlsa::callbackEvent: audio write error, underrun."; + } + else { + errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + } + } + else { + errorStream_ << "RtApiAlsa::callbackEvent: audio write error, " << snd_strerror( result ) << "."; + errorText_ = errorStream_.str(); + } + error( RtAudioError::WARNING ); + goto unlock; + } + + // Check stream latency + result = snd_pcm_delay( handle[0], &frames ); + if ( result == 0 && frames > 0 ) stream_.latency[0] = frames; + } + + unlock: + MUTEX_UNLOCK( &stream_.mutex ); + + RtApi::tickStreamTime(); + if ( doStopStream == 1 ) this->stopStream(); +} + +static void *alsaCallbackHandler( void *ptr ) +{ + CallbackInfo *info = (CallbackInfo *) ptr; + RtApiAlsa *object = (RtApiAlsa *) info->object; + bool *isRunning = &info->isRunning; + +#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread) + if ( info->doRealtime ) { + std::cerr << "RtAudio alsa: " << + (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") << + "running realtime scheduling" << std::endl; + } +#endif + + while ( *isRunning == true ) { + pthread_testcancel(); + object->callbackEvent(); + } + + pthread_exit( NULL ); +} + +//******************** End of __LINUX_ALSA__ *********************// +#endif + +#if defined(__LINUX_PULSE__) + +// Code written by Peter Meerwald, pmeerw@pmeerw.net +// and Tristan Matthews. + +#include +#include +#include +#include + +static pa_mainloop_api *rt_pa_mainloop_api = NULL; +struct PaDeviceInfo { + PaDeviceInfo() : sink_index(-1), source_index(-1) {} + int sink_index; + int source_index; + std::string sink_name; + std::string source_name; + RtAudio::DeviceInfo info; +}; +static struct { + std::vector dev; + std::string default_sink_name; + std::string default_source_name; + int default_rate; +} rt_pa_info; + +static const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000, + 44100, 48000, 96000, 0}; + +struct rtaudio_pa_format_mapping_t { + RtAudioFormat rtaudio_format; + pa_sample_format_t pa_format; +}; + +static const rtaudio_pa_format_mapping_t supported_sampleformats[] = { + {RTAUDIO_SINT16, PA_SAMPLE_S16LE}, + {RTAUDIO_SINT24, PA_SAMPLE_S24LE}, + {RTAUDIO_SINT32, PA_SAMPLE_S32LE}, + {RTAUDIO_FLOAT32, PA_SAMPLE_FLOAT32LE}, + {0, PA_SAMPLE_INVALID}}; + +struct PulseAudioHandle { + pa_simple *s_play; + pa_simple *s_rec; + pthread_t thread; + pthread_cond_t runnable_cv; + bool runnable; + PulseAudioHandle() : s_play(0), s_rec(0), runnable(false) { } +}; + +static void rt_pa_mainloop_api_quit(int ret) { + rt_pa_mainloop_api->quit(rt_pa_mainloop_api, ret); +} + +static void rt_pa_server_callback(pa_context *context, const pa_server_info *info, void *data){ + (void)context; + (void)data; + pa_sample_spec ss; + + if (!info) + rt_pa_mainloop_api_quit(1); + + ss = info->sample_spec; + + rt_pa_info.default_rate = ss.rate; + rt_pa_info.default_sink_name = info->default_sink_name; + rt_pa_info.default_source_name = info->default_source_name; + rt_pa_mainloop_api_quit(0); +} + +static void rt_pa_sink_info_cb(pa_context * /*c*/, const pa_sink_info *i, + int eol, void * /*userdata*/) +{ + if (eol) return; + PaDeviceInfo inf; + inf.info.name = pa_proplist_gets(i->proplist, "device.description"); + inf.info.probed = true; + inf.info.outputChannels = i->sample_spec.channels; + inf.info.preferredSampleRate = i->sample_spec.rate; + inf.info.isDefaultOutput = (rt_pa_info.default_sink_name == i->name); + inf.sink_index = i->index; + inf.sink_name = i->name; + for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) + inf.info.sampleRates.push_back( *sr ); + for ( const rtaudio_pa_format_mapping_t *fm = supported_sampleformats; + fm->rtaudio_format; ++fm ) + inf.info.nativeFormats |= fm->rtaudio_format; + for (size_t i=0; i < rt_pa_info.dev.size(); i++) + { + /* Attempt to match up sink and source records by device description. */ + if (rt_pa_info.dev[i].info.name == inf.info.name) { + rt_pa_info.dev[i].sink_index = inf.sink_index; + rt_pa_info.dev[i].sink_name = inf.sink_name; + rt_pa_info.dev[i].info.outputChannels = inf.info.outputChannels; + rt_pa_info.dev[i].info.isDefaultOutput = inf.info.isDefaultOutput; + /* Assume duplex channels are minimum of input and output channels. */ + /* Uncomment if we add support for DUPLEX + if (rt_pa_info.dev[i].source_index > -1) + (inf.info.outputChannels < rt_pa_info.dev[i].info.inputChannels) + ? inf.info.outputChannels : rt_pa_info.dev[i].info.inputChannels; + */ + return; + } + } + /* try to ensure device #0 is the default */ + if (inf.info.isDefaultOutput) + rt_pa_info.dev.insert(rt_pa_info.dev.begin(), inf); + else + rt_pa_info.dev.push_back(inf); +} + +static void rt_pa_source_info_cb(pa_context * /*c*/, const pa_source_info *i, + int eol, void * /*userdata*/) +{ + if (eol) return; + PaDeviceInfo inf; + inf.info.name = pa_proplist_gets(i->proplist, "device.description"); + inf.info.probed = true; + inf.info.inputChannels = i->sample_spec.channels; + inf.info.preferredSampleRate = i->sample_spec.rate; + inf.info.isDefaultInput = (rt_pa_info.default_source_name == i->name); + inf.source_index = i->index; + inf.source_name = i->name; + for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) + inf.info.sampleRates.push_back( *sr ); + for ( const rtaudio_pa_format_mapping_t *fm = supported_sampleformats; + fm->rtaudio_format; ++fm ) + inf.info.nativeFormats |= fm->rtaudio_format; + + for (size_t i=0; i < rt_pa_info.dev.size(); i++) + { + /* Attempt to match up sink and source records by device description. */ + if (rt_pa_info.dev[i].info.name == inf.info.name) { + rt_pa_info.dev[i].source_index = inf.source_index; + rt_pa_info.dev[i].source_name = inf.source_name; + rt_pa_info.dev[i].info.inputChannels = inf.info.inputChannels; + rt_pa_info.dev[i].info.isDefaultInput = inf.info.isDefaultInput; + /* Assume duplex channels are minimum of input and output channels. */ + /* Uncomment if we add support for DUPLEX + if (rt_pa_info.dev[i].sink_index > -1) { + rt_pa_info.dev[i].info.duplexChannels = + (inf.info.inputChannels < rt_pa_info.dev[i].info.outputChannels) + ? inf.info.inputChannels : rt_pa_info.dev[i].info.outputChannels; + } + */ + return; + } + } + /* try to ensure device #0 is the default */ + if (inf.info.isDefaultInput) + rt_pa_info.dev.insert(rt_pa_info.dev.begin(), inf); + else + rt_pa_info.dev.push_back(inf); +} + +static void rt_pa_context_state_callback(pa_context *context, void *userdata) { + (void)userdata; + + switch (pa_context_get_state(context)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: + rt_pa_info.dev.clear(); + pa_context_get_server_info(context, rt_pa_server_callback, NULL); + pa_context_get_sink_info_list(context, rt_pa_sink_info_cb, NULL); + pa_context_get_source_info_list(context, rt_pa_source_info_cb, NULL); + break; + + case PA_CONTEXT_TERMINATED: + rt_pa_mainloop_api_quit(0); + break; + + case PA_CONTEXT_FAILED: + default: + rt_pa_mainloop_api_quit(1); + } +} + +RtApiPulse::~RtApiPulse() +{ + if ( stream_.state != STREAM_CLOSED ) + closeStream(); +} + +void RtApiPulse::collectDeviceInfo( void ) +{ + pa_context *context = NULL; + pa_mainloop *m = NULL; + char *server = NULL; + int ret = 1; + + if (!(m = pa_mainloop_new())) { + errorStream_ << "RtApiPulse::DeviceInfo pa_mainloop_new() failed."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto quit; + } + + rt_pa_mainloop_api = pa_mainloop_get_api(m); + + if (!(context = pa_context_new_with_proplist(rt_pa_mainloop_api, NULL, NULL))) { + errorStream_ << "pa_context_new() failed."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto quit; + } + + pa_context_set_state_callback(context, rt_pa_context_state_callback, NULL); + + if (pa_context_connect(context, server, PA_CONTEXT_NOFLAGS, NULL) < 0) { + errorStream_ << "RtApiPulse::DeviceInfo pa_context_connect() failed: " + << pa_strerror(pa_context_errno(context)); + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto quit; + } + + if (pa_mainloop_run(m, &ret) < 0) { + errorStream_ << "pa_mainloop_run() failed."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + goto quit; + } + +quit: + if (context) + pa_context_unref(context); + + if (m) { + pa_mainloop_free(m); + } + + pa_xfree(server); +} + +unsigned int RtApiPulse::getDeviceCount( void ) +{ + collectDeviceInfo(); + return rt_pa_info.dev.size(); +} + +RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int device ) +{ + if (rt_pa_info.dev.size()==0) + collectDeviceInfo(); + if (device < rt_pa_info.dev.size()) + return rt_pa_info.dev[device].info; + return RtAudio::DeviceInfo(); +} + +static void *pulseaudio_callback( void * user ) +{ + CallbackInfo *cbi = static_cast( user ); + RtApiPulse *context = static_cast( cbi->object ); + volatile bool *isRunning = &cbi->isRunning; + +#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread) + if (cbi->doRealtime) { + std::cerr << "RtAudio pulse: " << + (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") << + "running realtime scheduling" << std::endl; + } +#endif + + while ( *isRunning ) { + pthread_testcancel(); + context->callbackEvent(); + } + + pthread_exit( NULL ); +} + +void RtApiPulse::closeStream( void ) +{ + PulseAudioHandle *pah = static_cast( stream_.apiHandle ); + + stream_.callbackInfo.isRunning = false; + if ( pah ) { + MUTEX_LOCK( &stream_.mutex ); + if ( stream_.state == STREAM_STOPPED ) { + pah->runnable = true; + pthread_cond_signal( &pah->runnable_cv ); + } + MUTEX_UNLOCK( &stream_.mutex ); + + pthread_join( pah->thread, 0 ); + if ( pah->s_play ) { + pa_simple_flush( pah->s_play, NULL ); + pa_simple_free( pah->s_play ); + } + if ( pah->s_rec ) + pa_simple_free( pah->s_rec ); + + pthread_cond_destroy( &pah->runnable_cv ); + delete pah; + stream_.apiHandle = 0; + } + + if ( stream_.userBuffer[0] ) { + free( stream_.userBuffer[0] ); + stream_.userBuffer[0] = 0; + } + if ( stream_.userBuffer[1] ) { + free( stream_.userBuffer[1] ); + stream_.userBuffer[1] = 0; + } + + stream_.state = STREAM_CLOSED; + stream_.mode = UNINITIALIZED; +} + +void RtApiPulse::callbackEvent( void ) +{ + PulseAudioHandle *pah = static_cast( stream_.apiHandle ); + + if ( stream_.state == STREAM_STOPPED ) { + MUTEX_LOCK( &stream_.mutex ); + while ( !pah->runnable ) + pthread_cond_wait( &pah->runnable_cv, &stream_.mutex ); + + if ( stream_.state != STREAM_RUNNING ) { + MUTEX_UNLOCK( &stream_.mutex ); + return; + } + MUTEX_UNLOCK( &stream_.mutex ); + } + + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiPulse::callbackEvent(): the stream is closed ... " + "this shouldn't happen!"; + error( RtAudioError::WARNING ); + return; + } + + RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; + double streamTime = getStreamTime(); + RtAudioStreamStatus status = 0; + int doStopStream = callback( stream_.userBuffer[OUTPUT], stream_.userBuffer[INPUT], + stream_.bufferSize, streamTime, status, + stream_.callbackInfo.userData ); + + if ( doStopStream == 2 ) { + abortStream(); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + void *pulse_in = stream_.doConvertBuffer[INPUT] ? stream_.deviceBuffer : stream_.userBuffer[INPUT]; + void *pulse_out = stream_.doConvertBuffer[OUTPUT] ? stream_.deviceBuffer : stream_.userBuffer[OUTPUT]; + + if ( stream_.state != STREAM_RUNNING ) + goto unlock; + + int pa_error; + size_t bytes; + if (stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + if ( stream_.doConvertBuffer[OUTPUT] ) { + convertBuffer( stream_.deviceBuffer, + stream_.userBuffer[OUTPUT], + stream_.convertInfo[OUTPUT] ); + bytes = stream_.nDeviceChannels[OUTPUT] * stream_.bufferSize * + formatBytes( stream_.deviceFormat[OUTPUT] ); + } else + bytes = stream_.nUserChannels[OUTPUT] * stream_.bufferSize * + formatBytes( stream_.userFormat ); + + if ( pa_simple_write( pah->s_play, pulse_out, bytes, &pa_error ) < 0 ) { + errorStream_ << "RtApiPulse::callbackEvent: audio write error, " << + pa_strerror( pa_error ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + } + } + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX) { + if ( stream_.doConvertBuffer[INPUT] ) + bytes = stream_.nDeviceChannels[INPUT] * stream_.bufferSize * + formatBytes( stream_.deviceFormat[INPUT] ); + else + bytes = stream_.nUserChannels[INPUT] * stream_.bufferSize * + formatBytes( stream_.userFormat ); + + if ( pa_simple_read( pah->s_rec, pulse_in, bytes, &pa_error ) < 0 ) { + errorStream_ << "RtApiPulse::callbackEvent: audio read error, " << + pa_strerror( pa_error ) << "."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + } + if ( stream_.doConvertBuffer[INPUT] ) { + convertBuffer( stream_.userBuffer[INPUT], + stream_.deviceBuffer, + stream_.convertInfo[INPUT] ); + } + } + + unlock: + MUTEX_UNLOCK( &stream_.mutex ); + RtApi::tickStreamTime(); + + if ( doStopStream == 1 ) + stopStream(); +} + +void RtApiPulse::startStream( void ) +{ + PulseAudioHandle *pah = static_cast( stream_.apiHandle ); + + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiPulse::startStream(): the stream is not open!"; + error( RtAudioError::INVALID_USE ); + return; + } + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiPulse::startStream(): the stream is already running!"; + error( RtAudioError::WARNING ); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + + #if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); + #endif + + stream_.state = STREAM_RUNNING; + + pah->runnable = true; + pthread_cond_signal( &pah->runnable_cv ); + MUTEX_UNLOCK( &stream_.mutex ); +} + +void RtApiPulse::stopStream( void ) +{ + PulseAudioHandle *pah = static_cast( stream_.apiHandle ); + + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiPulse::stopStream(): the stream is not open!"; + error( RtAudioError::INVALID_USE ); + return; + } + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiPulse::stopStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + stream_.state = STREAM_STOPPED; + MUTEX_LOCK( &stream_.mutex ); + + if ( pah ) { + pah->runnable = false; + if ( pah->s_play ) { + int pa_error; + if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) { + errorStream_ << "RtApiPulse::stopStream: error draining output device, " << + pa_strerror( pa_error ) << "."; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + } + } + + stream_.state = STREAM_STOPPED; + MUTEX_UNLOCK( &stream_.mutex ); +} + +void RtApiPulse::abortStream( void ) +{ + PulseAudioHandle *pah = static_cast( stream_.apiHandle ); + + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiPulse::abortStream(): the stream is not open!"; + error( RtAudioError::INVALID_USE ); + return; + } + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiPulse::abortStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + stream_.state = STREAM_STOPPED; + MUTEX_LOCK( &stream_.mutex ); + + if ( pah ) { + pah->runnable = false; + if ( pah->s_play ) { + int pa_error; + if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) { + errorStream_ << "RtApiPulse::abortStream: error flushing output device, " << + pa_strerror( pa_error ) << "."; + errorText_ = errorStream_.str(); + MUTEX_UNLOCK( &stream_.mutex ); + error( RtAudioError::SYSTEM_ERROR ); + return; + } + } + } + + stream_.state = STREAM_STOPPED; + MUTEX_UNLOCK( &stream_.mutex ); +} + +bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode, + unsigned int channels, unsigned int firstChannel, + unsigned int sampleRate, RtAudioFormat format, + unsigned int *bufferSize, RtAudio::StreamOptions *options ) +{ + PulseAudioHandle *pah = 0; + unsigned long bufferBytes = 0; + pa_sample_spec ss; + + if ( device >= rt_pa_info.dev.size() ) return false; + if ( firstChannel != 0 ) { + errorText_ = "PulseAudio does not support channel offset mapping."; + return false; + } + + /* these may be NULL for default, but we've already got the names */ + const char *dev_input = NULL; + const char *dev_output = NULL; + if (!rt_pa_info.dev[device].source_name.empty()) + dev_input = rt_pa_info.dev[device].source_name.c_str(); + if (!rt_pa_info.dev[device].sink_name.empty()) + dev_output = rt_pa_info.dev[device].sink_name.c_str(); + + if (mode==INPUT && rt_pa_info.dev[device].info.inputChannels == 0) { + errorText_ = "PulseAudio device does not support input."; + return false; + } + if (mode==OUTPUT && rt_pa_info.dev[device].info.outputChannels == 0) { + errorText_ = "PulseAudio device does not support output."; + return false; + } + if (mode==DUPLEX && rt_pa_info.dev[device].info.duplexChannels == 0) { + /* Note: will always error, DUPLEX not yet supported */ + errorText_ = "PulseAudio device does not support duplex."; + return false; + } + + if (mode==INPUT && rt_pa_info.dev[device].info.inputChannels < channels) { + errorText_ = "PulseAudio: unsupported number of input channels."; + return false; + } + + if (mode==OUTPUT && rt_pa_info.dev[device].info.outputChannels < channels) { + errorText_ = "PulseAudio: unsupported number of output channels."; + return false; + } + + if (mode==DUPLEX && rt_pa_info.dev[device].info.duplexChannels < channels) { + /* Note: will always error, DUPLEX not yet supported */ + errorText_ = "PulseAudio: unsupported number of duplex channels."; + return false; + } + + ss.channels = channels; + + bool sr_found = false; + for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) { + if ( sampleRate == *sr ) { + sr_found = true; + stream_.sampleRate = sampleRate; + ss.rate = sampleRate; + break; + } + } + if ( !sr_found ) { + errorText_ = "RtApiPulse::probeDeviceOpen: unsupported sample rate."; + return false; + } + + bool sf_found = 0; + for ( const rtaudio_pa_format_mapping_t *sf = supported_sampleformats; + sf->rtaudio_format && sf->pa_format != PA_SAMPLE_INVALID; ++sf ) { + if ( format == sf->rtaudio_format ) { + sf_found = true; + stream_.userFormat = sf->rtaudio_format; + stream_.deviceFormat[mode] = stream_.userFormat; + ss.format = sf->pa_format; + break; + } + } + if ( !sf_found ) { // Use internal data format conversion. + stream_.userFormat = format; + stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; + ss.format = PA_SAMPLE_FLOAT32LE; + } + + // Set other stream parameters. + if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false; + else stream_.userInterleaved = true; + stream_.deviceInterleaved[mode] = true; + stream_.nBuffers = options ? options->numberOfBuffers : 1; + stream_.doByteSwap[mode] = false; + stream_.nUserChannels[mode] = channels; + stream_.nDeviceChannels[mode] = channels + firstChannel; + stream_.channelOffset[mode] = 0; + std::string streamName = "RtAudio"; + + // Set flags for buffer conversion. + stream_.doConvertBuffer[mode] = false; + if ( stream_.userFormat != stream_.deviceFormat[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] ) + stream_.doConvertBuffer[mode] = true; + + // Allocate necessary internal buffers. + bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); + if ( stream_.userBuffer[mode] == NULL ) { + errorText_ = "RtApiPulse::probeDeviceOpen: error allocating user buffer memory."; + goto error; + } + stream_.bufferSize = *bufferSize; + + if ( stream_.doConvertBuffer[mode] ) { + + bool makeBuffer = true; + bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); + if ( mode == INPUT ) { + if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { + unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); + if ( bufferBytes <= bytesOut ) makeBuffer = false; + } + } + + if ( makeBuffer ) { + bufferBytes *= *bufferSize; + if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); + stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); + if ( stream_.deviceBuffer == NULL ) { + errorText_ = "RtApiPulse::probeDeviceOpen: error allocating device buffer memory."; + goto error; + } + } + } + + stream_.device[mode] = device; + + // Setup the buffer conversion information structure. + if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); + + if ( !stream_.apiHandle ) { + PulseAudioHandle *pah = new PulseAudioHandle; + if ( !pah ) { + errorText_ = "RtApiPulse::probeDeviceOpen: error allocating memory for handle."; + goto error; + } + + stream_.apiHandle = pah; + if ( pthread_cond_init( &pah->runnable_cv, NULL ) != 0 ) { + errorText_ = "RtApiPulse::probeDeviceOpen: error creating condition variable."; + goto error; + } + } + pah = static_cast( stream_.apiHandle ); + + int error; + if ( options && !options->streamName.empty() ) streamName = options->streamName; + switch ( mode ) { + pa_buffer_attr buffer_attr; + case INPUT: + buffer_attr.fragsize = bufferBytes; + buffer_attr.maxlength = -1; + + pah->s_rec = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_RECORD, + dev_input, "Record", &ss, NULL, &buffer_attr, &error ); + if ( !pah->s_rec ) { + errorText_ = "RtApiPulse::probeDeviceOpen: error connecting input to PulseAudio server."; + goto error; + } + break; + case OUTPUT: { + pa_buffer_attr * attr_ptr; + + if ( options && options->numberOfBuffers > 0 ) { + // pa_buffer_attr::fragsize is recording-only. + // Hopefully PortAudio won't access uninitialized fields. + buffer_attr.maxlength = bufferBytes * options->numberOfBuffers; + buffer_attr.minreq = -1; + buffer_attr.prebuf = -1; + buffer_attr.tlength = -1; + attr_ptr = &buffer_attr; + } else { + attr_ptr = nullptr; + } + + pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK, + dev_output, "Playback", &ss, NULL, attr_ptr, &error ); + if ( !pah->s_play ) { + errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server."; + goto error; + } + break; + } + case DUPLEX: + /* Note: We could add DUPLEX by synchronizing multiple streams, + but it would mean moving from Simple API to Asynchronous API: + https://freedesktop.org/software/pulseaudio/doxygen/streams.html#sync_streams */ + errorText_ = "RtApiPulse::probeDeviceOpen: duplex not supported for PulseAudio."; + goto error; + default: + goto error; + } + + if ( stream_.mode == UNINITIALIZED ) + stream_.mode = mode; + else if ( stream_.mode == mode ) + goto error; + else + stream_.mode = DUPLEX; + + if ( !stream_.callbackInfo.isRunning ) { + stream_.callbackInfo.object = this; + + stream_.state = STREAM_STOPPED; + // Set the thread attributes for joinable and realtime scheduling + // priority (optional). The higher priority will only take affect + // if the program is run as root or suid. Note, under Linux + // processes with CAP_SYS_NICE privilege, a user can change + // scheduling policy and priority (thus need not be root). See + // POSIX "capabilities". + pthread_attr_t attr; + pthread_attr_init( &attr ); + pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); +#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread) + if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) { + stream_.callbackInfo.doRealtime = true; + struct sched_param param; + int priority = options->priority; + int min = sched_get_priority_min( SCHED_RR ); + int max = sched_get_priority_max( SCHED_RR ); + if ( priority < min ) priority = min; + else if ( priority > max ) priority = max; + param.sched_priority = priority; + + // Set the policy BEFORE the priority. Otherwise it fails. + pthread_attr_setschedpolicy(&attr, SCHED_RR); + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); + // This is definitely required. Otherwise it fails. + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedparam(&attr, ¶m); + } + else + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); +#else + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); +#endif + + stream_.callbackInfo.isRunning = true; + int result = pthread_create( &pah->thread, &attr, pulseaudio_callback, (void *)&stream_.callbackInfo); + pthread_attr_destroy(&attr); + if(result != 0) { + // Failed. Try instead with default attributes. + result = pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo); + if(result != 0) { + stream_.callbackInfo.isRunning = false; + errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread."; + goto error; + } + } + } + + return SUCCESS; + + error: + if ( pah && stream_.callbackInfo.isRunning ) { + pthread_cond_destroy( &pah->runnable_cv ); + delete pah; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.state = STREAM_CLOSED; + return FAILURE; +} + +//******************** End of __LINUX_PULSE__ *********************// +#endif + +#if defined(__LINUX_OSS__) + +#include +#include +#include +#include +#include +#include +#include + +static void *ossCallbackHandler(void * ptr); + +// A structure to hold various information related to the OSS API +// implementation. +struct OssHandle { + int id[2]; // device ids + bool xrun[2]; + bool triggered; + pthread_cond_t runnable; + + OssHandle() + :triggered(false) { id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; } +}; + +RtApiOss :: RtApiOss() +{ + // Nothing to do here. +} + +RtApiOss :: ~RtApiOss() +{ + if ( stream_.state != STREAM_CLOSED ) closeStream(); +} + +unsigned int RtApiOss :: getDeviceCount( void ) +{ + int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); + if ( mixerfd == -1 ) { + errorText_ = "RtApiOss::getDeviceCount: error opening '/dev/mixer'."; + error( RtAudioError::WARNING ); + return 0; + } + + oss_sysinfo sysinfo; + if ( ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ) == -1 ) { + close( mixerfd ); + errorText_ = "RtApiOss::getDeviceCount: error getting sysinfo, OSS version >= 4.0 is required."; + error( RtAudioError::WARNING ); + return 0; + } + + close( mixerfd ); + return sysinfo.numaudios; +} + +RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device ) +{ + RtAudio::DeviceInfo info; + info.probed = false; + + int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); + if ( mixerfd == -1 ) { + errorText_ = "RtApiOss::getDeviceInfo: error opening '/dev/mixer'."; + error( RtAudioError::WARNING ); + return info; + } + + oss_sysinfo sysinfo; + int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ); + if ( result == -1 ) { + close( mixerfd ); + errorText_ = "RtApiOss::getDeviceInfo: error getting sysinfo, OSS version >= 4.0 is required."; + error( RtAudioError::WARNING ); + return info; + } + + unsigned nDevices = sysinfo.numaudios; + if ( nDevices == 0 ) { + close( mixerfd ); + errorText_ = "RtApiOss::getDeviceInfo: no devices found!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + if ( device >= nDevices ) { + close( mixerfd ); + errorText_ = "RtApiOss::getDeviceInfo: device ID is invalid!"; + error( RtAudioError::INVALID_USE ); + return info; + } + + oss_audioinfo ainfo; + ainfo.dev = device; + result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo ); + close( mixerfd ); + if ( result == -1 ) { + errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Probe channels + if ( ainfo.caps & PCM_CAP_OUTPUT ) info.outputChannels = ainfo.max_channels; + if ( ainfo.caps & PCM_CAP_INPUT ) info.inputChannels = ainfo.max_channels; + if ( ainfo.caps & PCM_CAP_DUPLEX ) { + if ( info.outputChannels > 0 && info.inputChannels > 0 && ainfo.caps & PCM_CAP_DUPLEX ) + info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels; + } + + // Probe data formats ... do for input + unsigned long mask = ainfo.iformats; + if ( mask & AFMT_S16_LE || mask & AFMT_S16_BE ) + info.nativeFormats |= RTAUDIO_SINT16; + if ( mask & AFMT_S8 ) + info.nativeFormats |= RTAUDIO_SINT8; + if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE ) + info.nativeFormats |= RTAUDIO_SINT32; +#ifdef AFMT_FLOAT + if ( mask & AFMT_FLOAT ) + info.nativeFormats |= RTAUDIO_FLOAT32; +#endif + if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE ) + info.nativeFormats |= RTAUDIO_SINT24; + + // Check that we have at least one supported format + if ( info.nativeFormats == 0 ) { + errorStream_ << "RtApiOss::getDeviceInfo: device (" << ainfo.name << ") data format not supported by RtAudio."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + return info; + } + + // Probe the supported sample rates. + info.sampleRates.clear(); + if ( ainfo.nrates ) { + for ( unsigned int i=0; i info.preferredSampleRate ) ) + info.preferredSampleRate = SAMPLE_RATES[k]; + + break; + } + } + } + } + else { + // Check min and max rate values; + for ( unsigned int k=0; k= (int) SAMPLE_RATES[k] ) { + info.sampleRates.push_back( SAMPLE_RATES[k] ); + + if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) ) + info.preferredSampleRate = SAMPLE_RATES[k]; + } + } + } + + if ( info.sampleRates.size() == 0 ) { + errorStream_ << "RtApiOss::getDeviceInfo: no supported sample rates found for device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + error( RtAudioError::WARNING ); + } + else { + info.probed = true; + info.name = ainfo.name; + } + + return info; +} + + +bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) +{ + int mixerfd = open( "/dev/mixer", O_RDWR, 0 ); + if ( mixerfd == -1 ) { + errorText_ = "RtApiOss::probeDeviceOpen: error opening '/dev/mixer'."; + return FAILURE; + } + + oss_sysinfo sysinfo; + int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ); + if ( result == -1 ) { + close( mixerfd ); + errorText_ = "RtApiOss::probeDeviceOpen: error getting sysinfo, OSS version >= 4.0 is required."; + return FAILURE; + } + + unsigned nDevices = sysinfo.numaudios; + if ( nDevices == 0 ) { + // This should not happen because a check is made before this function is called. + close( mixerfd ); + errorText_ = "RtApiOss::probeDeviceOpen: no devices found!"; + return FAILURE; + } + + if ( device >= nDevices ) { + // This should not happen because a check is made before this function is called. + close( mixerfd ); + errorText_ = "RtApiOss::probeDeviceOpen: device ID is invalid!"; + return FAILURE; + } + + oss_audioinfo ainfo; + ainfo.dev = device; + result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo ); + close( mixerfd ); + if ( result == -1 ) { + errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Check if device supports input or output + if ( ( mode == OUTPUT && !( ainfo.caps & PCM_CAP_OUTPUT ) ) || + ( mode == INPUT && !( ainfo.caps & PCM_CAP_INPUT ) ) ) { + if ( mode == OUTPUT ) + errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support output."; + else + errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support input."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + int flags = 0; + OssHandle *handle = (OssHandle *) stream_.apiHandle; + if ( mode == OUTPUT ) + flags |= O_WRONLY; + else { // mode == INPUT + if (stream_.mode == OUTPUT && stream_.device[0] == device) { + // We just set the same device for playback ... close and reopen for duplex (OSS only). + close( handle->id[0] ); + handle->id[0] = 0; + if ( !( ainfo.caps & PCM_CAP_DUPLEX ) ) { + errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support duplex mode."; + errorText_ = errorStream_.str(); + return FAILURE; + } + // Check that the number previously set channels is the same. + if ( stream_.nUserChannels[0] != channels ) { + errorStream_ << "RtApiOss::probeDeviceOpen: input/output channels must be equal for OSS duplex device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + flags |= O_RDWR; + } + else + flags |= O_RDONLY; + } + + // Set exclusive access if specified. + if ( options && options->flags & RTAUDIO_HOG_DEVICE ) flags |= O_EXCL; + + // Try to open the device. + int fd; + fd = open( ainfo.devnode, flags, 0 ); + if ( fd == -1 ) { + if ( errno == EBUSY ) + errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") is busy."; + else + errorStream_ << "RtApiOss::probeDeviceOpen: error opening device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // For duplex operation, specifically set this mode (this doesn't seem to work). + /* + if ( flags | O_RDWR ) { + result = ioctl( fd, SNDCTL_DSP_SETDUPLEX, NULL ); + if ( result == -1) { + errorStream_ << "RtApiOss::probeDeviceOpen: error setting duplex mode for device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + */ + + // Check the device channel support. + stream_.nUserChannels[mode] = channels; + if ( ainfo.max_channels < (int)(channels + firstChannel) ) { + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: the device (" << ainfo.name << ") does not support requested channel parameters."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Set the number of channels. + int deviceChannels = channels + firstChannel; + result = ioctl( fd, SNDCTL_DSP_CHANNELS, &deviceChannels ); + if ( result == -1 || deviceChannels < (int)(channels + firstChannel) ) { + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: error setting channel parameters on device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + stream_.nDeviceChannels[mode] = deviceChannels; + + // Get the data format mask + int mask; + result = ioctl( fd, SNDCTL_DSP_GETFMTS, &mask ); + if ( result == -1 ) { + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: error getting device (" << ainfo.name << ") data formats."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Determine how to set the device format. + stream_.userFormat = format; + int deviceFormat = -1; + stream_.doByteSwap[mode] = false; + if ( format == RTAUDIO_SINT8 ) { + if ( mask & AFMT_S8 ) { + deviceFormat = AFMT_S8; + stream_.deviceFormat[mode] = RTAUDIO_SINT8; + } + } + else if ( format == RTAUDIO_SINT16 ) { + if ( mask & AFMT_S16_NE ) { + deviceFormat = AFMT_S16_NE; + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + } + else if ( mask & AFMT_S16_OE ) { + deviceFormat = AFMT_S16_OE; + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + stream_.doByteSwap[mode] = true; + } + } + else if ( format == RTAUDIO_SINT24 ) { + if ( mask & AFMT_S24_NE ) { + deviceFormat = AFMT_S24_NE; + stream_.deviceFormat[mode] = RTAUDIO_SINT24; + } + else if ( mask & AFMT_S24_OE ) { + deviceFormat = AFMT_S24_OE; + stream_.deviceFormat[mode] = RTAUDIO_SINT24; + stream_.doByteSwap[mode] = true; + } + } + else if ( format == RTAUDIO_SINT32 ) { + if ( mask & AFMT_S32_NE ) { + deviceFormat = AFMT_S32_NE; + stream_.deviceFormat[mode] = RTAUDIO_SINT32; + } + else if ( mask & AFMT_S32_OE ) { + deviceFormat = AFMT_S32_OE; + stream_.deviceFormat[mode] = RTAUDIO_SINT32; + stream_.doByteSwap[mode] = true; + } + } + + if ( deviceFormat == -1 ) { + // The user requested format is not natively supported by the device. + if ( mask & AFMT_S16_NE ) { + deviceFormat = AFMT_S16_NE; + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + } + else if ( mask & AFMT_S32_NE ) { + deviceFormat = AFMT_S32_NE; + stream_.deviceFormat[mode] = RTAUDIO_SINT32; + } + else if ( mask & AFMT_S24_NE ) { + deviceFormat = AFMT_S24_NE; + stream_.deviceFormat[mode] = RTAUDIO_SINT24; + } + else if ( mask & AFMT_S16_OE ) { + deviceFormat = AFMT_S16_OE; + stream_.deviceFormat[mode] = RTAUDIO_SINT16; + stream_.doByteSwap[mode] = true; + } + else if ( mask & AFMT_S32_OE ) { + deviceFormat = AFMT_S32_OE; + stream_.deviceFormat[mode] = RTAUDIO_SINT32; + stream_.doByteSwap[mode] = true; + } + else if ( mask & AFMT_S24_OE ) { + deviceFormat = AFMT_S24_OE; + stream_.deviceFormat[mode] = RTAUDIO_SINT24; + stream_.doByteSwap[mode] = true; + } + else if ( mask & AFMT_S8) { + deviceFormat = AFMT_S8; + stream_.deviceFormat[mode] = RTAUDIO_SINT8; + } + } + + if ( stream_.deviceFormat[mode] == 0 ) { + // This really shouldn't happen ... + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") data format not supported by RtAudio."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Set the data format. + int temp = deviceFormat; + result = ioctl( fd, SNDCTL_DSP_SETFMT, &deviceFormat ); + if ( result == -1 || deviceFormat != temp ) { + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: error setting data format on device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Attempt to set the buffer size. According to OSS, the minimum + // number of buffers is two. The supposed minimum buffer size is 16 + // bytes, so that will be our lower bound. The argument to this + // call is in the form 0xMMMMSSSS (hex), where the buffer size (in + // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM. + // We'll check the actual value used near the end of the setup + // procedure. + int ossBufferBytes = *bufferSize * formatBytes( stream_.deviceFormat[mode] ) * deviceChannels; + if ( ossBufferBytes < 16 ) ossBufferBytes = 16; + int buffers = 0; + if ( options ) buffers = options->numberOfBuffers; + if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) buffers = 2; + if ( buffers < 2 ) buffers = 3; + temp = ((int) buffers << 16) + (int)( log10( (double)ossBufferBytes ) / log10( 2.0 ) ); + result = ioctl( fd, SNDCTL_DSP_SETFRAGMENT, &temp ); + if ( result == -1 ) { + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: error setting buffer size on device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + stream_.nBuffers = buffers; + + // Save buffer size (in sample frames). + *bufferSize = ossBufferBytes / ( formatBytes(stream_.deviceFormat[mode]) * deviceChannels ); + stream_.bufferSize = *bufferSize; + + // Set the sample rate. + int srate = sampleRate; + result = ioctl( fd, SNDCTL_DSP_SPEED, &srate ); + if ( result == -1 ) { + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: error setting sample rate (" << sampleRate << ") on device (" << ainfo.name << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + + // Verify the sample rate setup worked. + if ( abs( srate - (int)sampleRate ) > 100 ) { + close( fd ); + errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support sample rate (" << sampleRate << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + stream_.sampleRate = sampleRate; + + if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device) { + // We're doing duplex setup here. + stream_.deviceFormat[0] = stream_.deviceFormat[1]; + stream_.nDeviceChannels[0] = deviceChannels; + } + + // Set interleaving parameters. + stream_.userInterleaved = true; + stream_.deviceInterleaved[mode] = true; + if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) + stream_.userInterleaved = false; + + // Set flags for buffer conversion + stream_.doConvertBuffer[mode] = false; + if ( stream_.userFormat != stream_.deviceFormat[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] ) + stream_.doConvertBuffer[mode] = true; + if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] && + stream_.nUserChannels[mode] > 1 ) + stream_.doConvertBuffer[mode] = true; + + // Allocate the stream handles if necessary and then save. + if ( stream_.apiHandle == 0 ) { + try { + handle = new OssHandle; + } + catch ( std::bad_alloc& ) { + errorText_ = "RtApiOss::probeDeviceOpen: error allocating OssHandle memory."; + goto error; + } + + if ( pthread_cond_init( &handle->runnable, NULL ) ) { + errorText_ = "RtApiOss::probeDeviceOpen: error initializing pthread condition variable."; + goto error; + } + + stream_.apiHandle = (void *) handle; + } + else { + handle = (OssHandle *) stream_.apiHandle; + } + handle->id[mode] = fd; + + // Allocate necessary internal buffers. + unsigned long bufferBytes; + bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); + if ( stream_.userBuffer[mode] == NULL ) { + errorText_ = "RtApiOss::probeDeviceOpen: error allocating user buffer memory."; + goto error; + } + + if ( stream_.doConvertBuffer[mode] ) { + + bool makeBuffer = true; + bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] ); + if ( mode == INPUT ) { + if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { + unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] ); + if ( bufferBytes <= bytesOut ) makeBuffer = false; + } + } + + if ( makeBuffer ) { + bufferBytes *= *bufferSize; + if ( stream_.deviceBuffer ) free( stream_.deviceBuffer ); + stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 ); + if ( stream_.deviceBuffer == NULL ) { + errorText_ = "RtApiOss::probeDeviceOpen: error allocating device buffer memory."; + goto error; + } + } + } + + stream_.device[mode] = device; + stream_.state = STREAM_STOPPED; + + // Setup the buffer conversion information structure. + if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel ); + + // Setup thread if necessary. + if ( stream_.mode == OUTPUT && mode == INPUT ) { + // We had already set up an output stream. + stream_.mode = DUPLEX; + if ( stream_.device[0] == device ) handle->id[0] = fd; + } + else { + stream_.mode = mode; + + // Setup callback thread. + stream_.callbackInfo.object = (void *) this; + + // Set the thread attributes for joinable and realtime scheduling + // priority. The higher priority will only take affect if the + // program is run as root or suid. + pthread_attr_t attr; + pthread_attr_init( &attr ); + pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); +#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread) + if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) { + stream_.callbackInfo.doRealtime = true; + struct sched_param param; + int priority = options->priority; + int min = sched_get_priority_min( SCHED_RR ); + int max = sched_get_priority_max( SCHED_RR ); + if ( priority < min ) priority = min; + else if ( priority > max ) priority = max; + param.sched_priority = priority; + + // Set the policy BEFORE the priority. Otherwise it fails. + pthread_attr_setschedpolicy(&attr, SCHED_RR); + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); + // This is definitely required. Otherwise it fails. + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedparam(&attr, ¶m); + } + else + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); +#else + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); +#endif + + stream_.callbackInfo.isRunning = true; + result = pthread_create( &stream_.callbackInfo.thread, &attr, ossCallbackHandler, &stream_.callbackInfo ); + pthread_attr_destroy( &attr ); + if ( result ) { + // Failed. Try instead with default attributes. + result = pthread_create( &stream_.callbackInfo.thread, NULL, ossCallbackHandler, &stream_.callbackInfo ); + if ( result ) { + stream_.callbackInfo.isRunning = false; + errorText_ = "RtApiOss::error creating callback thread!"; + goto error; + } + } + } + + return SUCCESS; + + error: + if ( handle ) { + pthread_cond_destroy( &handle->runnable ); + if ( handle->id[0] ) close( handle->id[0] ); + if ( handle->id[1] ) close( handle->id[1] ); + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.state = STREAM_CLOSED; + return FAILURE; +} + +void RtApiOss :: closeStream() +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiOss::closeStream(): no open stream to close!"; + error( RtAudioError::WARNING ); + return; + } + + OssHandle *handle = (OssHandle *) stream_.apiHandle; + stream_.callbackInfo.isRunning = false; + MUTEX_LOCK( &stream_.mutex ); + if ( stream_.state == STREAM_STOPPED ) + pthread_cond_signal( &handle->runnable ); + MUTEX_UNLOCK( &stream_.mutex ); + pthread_join( stream_.callbackInfo.thread, NULL ); + + if ( stream_.state == STREAM_RUNNING ) { + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) + ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); + else + ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); + stream_.state = STREAM_STOPPED; + } + + if ( handle ) { + pthread_cond_destroy( &handle->runnable ); + if ( handle->id[0] ) close( handle->id[0] ); + if ( handle->id[1] ) close( handle->id[1] ); + delete handle; + stream_.apiHandle = 0; + } + + for ( int i=0; i<2; i++ ) { + if ( stream_.userBuffer[i] ) { + free( stream_.userBuffer[i] ); + stream_.userBuffer[i] = 0; + } + } + + if ( stream_.deviceBuffer ) { + free( stream_.deviceBuffer ); + stream_.deviceBuffer = 0; + } + + stream_.mode = UNINITIALIZED; + stream_.state = STREAM_CLOSED; +} + +void RtApiOss :: startStream() +{ + verifyStream(); + if ( stream_.state == STREAM_RUNNING ) { + errorText_ = "RtApiOss::startStream(): the stream is already running!"; + error( RtAudioError::WARNING ); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + + #if defined( HAVE_GETTIMEOFDAY ) + gettimeofday( &stream_.lastTickTimestamp, NULL ); + #endif + + stream_.state = STREAM_RUNNING; + + // No need to do anything else here ... OSS automatically starts + // when fed samples. + + MUTEX_UNLOCK( &stream_.mutex ); + + OssHandle *handle = (OssHandle *) stream_.apiHandle; + pthread_cond_signal( &handle->runnable ); +} + +void RtApiOss :: stopStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiOss::stopStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + + // The state might change while waiting on a mutex. + if ( stream_.state == STREAM_STOPPED ) { + MUTEX_UNLOCK( &stream_.mutex ); + return; + } + + int result = 0; + OssHandle *handle = (OssHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + // Flush the output with zeros a few times. + char *buffer; + int samples; + RtAudioFormat format; + + if ( stream_.doConvertBuffer[0] ) { + buffer = stream_.deviceBuffer; + samples = stream_.bufferSize * stream_.nDeviceChannels[0]; + format = stream_.deviceFormat[0]; + } + else { + buffer = stream_.userBuffer[0]; + samples = stream_.bufferSize * stream_.nUserChannels[0]; + format = stream_.userFormat; + } + + memset( buffer, 0, samples * formatBytes(format) ); + for ( unsigned int i=0; iid[0], buffer, samples * formatBytes(format) ); + if ( result == -1 ) { + errorText_ = "RtApiOss::stopStream: audio write error."; + error( RtAudioError::WARNING ); + } + } + + result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); + if ( result == -1 ) { + errorStream_ << "RtApiOss::stopStream: system error stopping callback procedure on device (" << stream_.device[0] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + handle->triggered = false; + } + + if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) { + result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); + if ( result == -1 ) { + errorStream_ << "RtApiOss::stopStream: system error stopping input callback procedure on device (" << stream_.device[0] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + unlock: + stream_.state = STREAM_STOPPED; + MUTEX_UNLOCK( &stream_.mutex ); + + if ( result != -1 ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiOss :: abortStream() +{ + verifyStream(); + if ( stream_.state == STREAM_STOPPED ) { + errorText_ = "RtApiOss::abortStream(): the stream is already stopped!"; + error( RtAudioError::WARNING ); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + + // The state might change while waiting on a mutex. + if ( stream_.state == STREAM_STOPPED ) { + MUTEX_UNLOCK( &stream_.mutex ); + return; + } + + int result = 0; + OssHandle *handle = (OssHandle *) stream_.apiHandle; + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 ); + if ( result == -1 ) { + errorStream_ << "RtApiOss::abortStream: system error stopping callback procedure on device (" << stream_.device[0] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + handle->triggered = false; + } + + if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) { + result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 ); + if ( result == -1 ) { + errorStream_ << "RtApiOss::abortStream: system error stopping input callback procedure on device (" << stream_.device[0] << ")."; + errorText_ = errorStream_.str(); + goto unlock; + } + } + + unlock: + stream_.state = STREAM_STOPPED; + MUTEX_UNLOCK( &stream_.mutex ); + + if ( result != -1 ) return; + error( RtAudioError::SYSTEM_ERROR ); +} + +void RtApiOss :: callbackEvent() +{ + OssHandle *handle = (OssHandle *) stream_.apiHandle; + if ( stream_.state == STREAM_STOPPED ) { + MUTEX_LOCK( &stream_.mutex ); + pthread_cond_wait( &handle->runnable, &stream_.mutex ); + if ( stream_.state != STREAM_RUNNING ) { + MUTEX_UNLOCK( &stream_.mutex ); + return; + } + MUTEX_UNLOCK( &stream_.mutex ); + } + + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApiOss::callbackEvent(): the stream is closed ... this shouldn't happen!"; + error( RtAudioError::WARNING ); + return; + } + + // Invoke user callback to get fresh output data. + int doStopStream = 0; + RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; + double streamTime = getStreamTime(); + RtAudioStreamStatus status = 0; + if ( stream_.mode != INPUT && handle->xrun[0] == true ) { + status |= RTAUDIO_OUTPUT_UNDERFLOW; + handle->xrun[0] = false; + } + if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) { + status |= RTAUDIO_INPUT_OVERFLOW; + handle->xrun[1] = false; + } + doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1], + stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData ); + if ( doStopStream == 2 ) { + this->abortStream(); + return; + } + + MUTEX_LOCK( &stream_.mutex ); + + // The state might change while waiting on a mutex. + if ( stream_.state == STREAM_STOPPED ) goto unlock; + + int result; + char *buffer; + int samples; + RtAudioFormat format; + + if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { + + // Setup parameters and do buffer conversion if necessary. + if ( stream_.doConvertBuffer[0] ) { + buffer = stream_.deviceBuffer; + convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] ); + samples = stream_.bufferSize * stream_.nDeviceChannels[0]; + format = stream_.deviceFormat[0]; + } + else { + buffer = stream_.userBuffer[0]; + samples = stream_.bufferSize * stream_.nUserChannels[0]; + format = stream_.userFormat; + } + + // Do byte swapping if necessary. + if ( stream_.doByteSwap[0] ) + byteSwapBuffer( buffer, samples, format ); + + if ( stream_.mode == DUPLEX && handle->triggered == false ) { + int trig = 0; + ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig ); + result = write( handle->id[0], buffer, samples * formatBytes(format) ); + trig = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT; + ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig ); + handle->triggered = true; + } + else + // Write samples to device. + result = write( handle->id[0], buffer, samples * formatBytes(format) ); + + if ( result == -1 ) { + // We'll assume this is an underrun, though there isn't a + // specific means for determining that. + handle->xrun[0] = true; + errorText_ = "RtApiOss::callbackEvent: audio write error."; + error( RtAudioError::WARNING ); + // Continue on to input section. + } + } + + if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { + + // Setup parameters. + if ( stream_.doConvertBuffer[1] ) { + buffer = stream_.deviceBuffer; + samples = stream_.bufferSize * stream_.nDeviceChannels[1]; + format = stream_.deviceFormat[1]; + } + else { + buffer = stream_.userBuffer[1]; + samples = stream_.bufferSize * stream_.nUserChannels[1]; + format = stream_.userFormat; + } + + // Read samples from device. + result = read( handle->id[1], buffer, samples * formatBytes(format) ); + + if ( result == -1 ) { + // We'll assume this is an overrun, though there isn't a + // specific means for determining that. + handle->xrun[1] = true; + errorText_ = "RtApiOss::callbackEvent: audio read error."; + error( RtAudioError::WARNING ); + goto unlock; + } + + // Do byte swapping if necessary. + if ( stream_.doByteSwap[1] ) + byteSwapBuffer( buffer, samples, format ); + + // Do buffer conversion if necessary. + if ( stream_.doConvertBuffer[1] ) + convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] ); + } + + unlock: + MUTEX_UNLOCK( &stream_.mutex ); + + RtApi::tickStreamTime(); + if ( doStopStream == 1 ) this->stopStream(); +} + +static void *ossCallbackHandler( void *ptr ) +{ + CallbackInfo *info = (CallbackInfo *) ptr; + RtApiOss *object = (RtApiOss *) info->object; + bool *isRunning = &info->isRunning; + +#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread) + if (info->doRealtime) { + std::cerr << "RtAudio oss: " << + (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") << + "running realtime scheduling" << std::endl; + } +#endif + + while ( *isRunning == true ) { + pthread_testcancel(); + object->callbackEvent(); + } + + pthread_exit( NULL ); +} + +//******************** End of __LINUX_OSS__ *********************// +#endif + + +// *************************************************** // +// +// Protected common (OS-independent) RtAudio methods. +// +// *************************************************** // + +// This method can be modified to control the behavior of error +// message printing. +void RtApi :: error( RtAudioError::Type type ) +{ + errorStream_.str(""); // clear the ostringstream + + RtAudioErrorCallback errorCallback = (RtAudioErrorCallback) stream_.callbackInfo.errorCallback; + if ( errorCallback ) { + // abortStream() can generate new error messages. Ignore them. Just keep original one. + + if ( firstErrorOccurred_ ) + return; + + firstErrorOccurred_ = true; + const std::string errorMessage = errorText_; + + if ( type != RtAudioError::WARNING && stream_.state != STREAM_STOPPED) { + stream_.callbackInfo.isRunning = false; // exit from the thread + abortStream(); + } + + errorCallback( type, errorMessage ); + firstErrorOccurred_ = false; + return; + } + + if ( type == RtAudioError::WARNING && showWarnings_ == true ) + std::cerr << '\n' << errorText_ << "\n\n"; + else if ( type != RtAudioError::WARNING ) + throw( RtAudioError( errorText_, type ) ); +} + +void RtApi :: verifyStream() +{ + if ( stream_.state == STREAM_CLOSED ) { + errorText_ = "RtApi:: a stream is not open!"; + error( RtAudioError::INVALID_USE ); + } +} + +void RtApi :: clearStreamInfo() +{ + stream_.mode = UNINITIALIZED; + stream_.state = STREAM_CLOSED; + stream_.sampleRate = 0; + stream_.bufferSize = 0; + stream_.nBuffers = 0; + stream_.userFormat = 0; + stream_.userInterleaved = true; + stream_.streamTime = 0.0; + stream_.apiHandle = 0; + stream_.deviceBuffer = 0; + stream_.callbackInfo.callback = 0; + stream_.callbackInfo.userData = 0; + stream_.callbackInfo.isRunning = false; + stream_.callbackInfo.errorCallback = 0; + for ( int i=0; i<2; i++ ) { + stream_.device[i] = 11111; + stream_.doConvertBuffer[i] = false; + stream_.deviceInterleaved[i] = true; + stream_.doByteSwap[i] = false; + stream_.nUserChannels[i] = 0; + stream_.nDeviceChannels[i] = 0; + stream_.channelOffset[i] = 0; + stream_.deviceFormat[i] = 0; + stream_.latency[i] = 0; + stream_.userBuffer[i] = 0; + stream_.convertInfo[i].channels = 0; + stream_.convertInfo[i].inJump = 0; + stream_.convertInfo[i].outJump = 0; + stream_.convertInfo[i].inFormat = 0; + stream_.convertInfo[i].outFormat = 0; + stream_.convertInfo[i].inOffset.clear(); + stream_.convertInfo[i].outOffset.clear(); + } +} + +unsigned int RtApi :: formatBytes( RtAudioFormat format ) +{ + if ( format == RTAUDIO_SINT16 ) + return 2; + else if ( format == RTAUDIO_SINT32 || format == RTAUDIO_FLOAT32 ) + return 4; + else if ( format == RTAUDIO_FLOAT64 ) + return 8; + else if ( format == RTAUDIO_SINT24 ) + return 3; + else if ( format == RTAUDIO_SINT8 ) + return 1; + + errorText_ = "RtApi::formatBytes: undefined format."; + error( RtAudioError::WARNING ); + + return 0; +} + +void RtApi :: setConvertInfo( StreamMode mode, unsigned int firstChannel ) +{ + if ( mode == INPUT ) { // convert device to user buffer + stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; + stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; + stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; + stream_.convertInfo[mode].outFormat = stream_.userFormat; + } + else { // convert user to device buffer + stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; + stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; + stream_.convertInfo[mode].inFormat = stream_.userFormat; + stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; + } + + if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) + stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; + else + stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; + + // Set up the interleave/deinterleave offsets. + if ( stream_.deviceInterleaved[mode] != stream_.userInterleaved ) { + if ( ( mode == OUTPUT && stream_.deviceInterleaved[mode] ) || + ( mode == INPUT && stream_.userInterleaved ) ) { + for ( int k=0; k 0 ) { + if ( stream_.deviceInterleaved[mode] ) { + if ( mode == OUTPUT ) { + for ( int k=0; k info.inJump ) + memset( outBuffer, 0, stream_.bufferSize * info.outJump * formatBytes( info.outFormat ) ); + + int j; + if (info.outFormat == RTAUDIO_FLOAT64) { + Float64 *out = (Float64 *)outBuffer; + + if (info.inFormat == RTAUDIO_SINT8) { + signed char *in = (signed char *)inBuffer; + for (unsigned int i=0; i> 8); + //out[info.outOffset[j]] >>= 8; + } + in += info.inJump; + out += info.outJump; + } + } + else if (info.inFormat == RTAUDIO_FLOAT32) { + Float32 *in = (Float32 *)inBuffer; + for (unsigned int i=0; i> 8); + } + in += info.inJump; + out += info.outJump; + } + } + else if (info.inFormat == RTAUDIO_SINT32) { + Int32 *in = (Int32 *)inBuffer; + for (unsigned int i=0; i> 16) & 0x0000ffff); + } + in += info.inJump; + out += info.outJump; + } + } + else if (info.inFormat == RTAUDIO_FLOAT32) { + Float32 *in = (Float32 *)inBuffer; + for (unsigned int i=0; i> 8) & 0x00ff); + } + in += info.inJump; + out += info.outJump; + } + } + else if (info.inFormat == RTAUDIO_SINT24) { + Int24 *in = (Int24 *)inBuffer; + for (unsigned int i=0; i> 16); + } + in += info.inJump; + out += info.outJump; + } + } + else if (info.inFormat == RTAUDIO_SINT32) { + Int32 *in = (Int32 *)inBuffer; + for (unsigned int i=0; i> 24) & 0x000000ff); + } + in += info.inJump; + out += info.outJump; + } + } + else if (info.inFormat == RTAUDIO_FLOAT32) { + Float32 *in = (Float32 *)inBuffer; + for (unsigned int i=0; i>8) | (x<<8); } +//static inline uint32_t bswap_32(uint32_t x) { return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); } +//static inline uint64_t bswap_64(uint64_t x) { return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); } + +void RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ) +{ + char val; + char *ptr; + + ptr = buffer; + if ( format == RTAUDIO_SINT16 ) { + for ( unsigned int i=0; i= 4 + #define RTAUDIO_DLL_PUBLIC __attribute__( (visibility( "default" )) ) + #else + #define RTAUDIO_DLL_PUBLIC + #endif +#endif + +#include +#include +#include +#include + +/*! \typedef typedef unsigned long RtAudioFormat; + \brief RtAudio data format type. + + Support for signed integers and floats. Audio data fed to/from an + RtAudio stream is assumed to ALWAYS be in host byte order. The + internal routines will automatically take care of any necessary + byte-swapping between the host format and the soundcard. Thus, + endian-ness is not a concern in the following format definitions. + + - \e RTAUDIO_SINT8: 8-bit signed integer. + - \e RTAUDIO_SINT16: 16-bit signed integer. + - \e RTAUDIO_SINT24: 24-bit signed integer. + - \e RTAUDIO_SINT32: 32-bit signed integer. + - \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0. + - \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0. +*/ +typedef unsigned long RtAudioFormat; +static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer. +static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer. +static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // 24-bit signed integer. +static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer. +static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0. +static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0. + +/*! \typedef typedef unsigned long RtAudioStreamFlags; + \brief RtAudio stream option flags. + + The following flags can be OR'ed together to allow a client to + make changes to the default stream behavior: + + - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). + - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. + - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. + - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). + - \e RTAUDIO_JACK_DONT_CONNECT: Do not automatically connect ports (JACK only). + + By default, RtAudio streams pass and receive audio data from the + client in an interleaved format. By passing the + RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio + data will instead be presented in non-interleaved buffers. In + this case, each buffer argument in the RtAudioCallback function + will point to a single array of data, with \c nFrames samples for + each channel concatenated back-to-back. For example, the first + sample of data for the second channel would be located at index \c + nFrames (assuming the \c buffer pointer was recast to the correct + data type for the stream). + + Certain audio APIs offer a number of parameters that influence the + I/O latency of a stream. By default, RtAudio will attempt to set + these parameters internally for robust (glitch-free) performance + (though some APIs, like Windows DirectSound, make this difficult). + By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() + function, internal stream settings will be influenced in an attempt + to minimize stream latency, though possibly at the expense of stream + performance. + + If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to + open the input and/or output stream device(s) for exclusive use. + Note that this is not possible with all supported audio APIs. + + If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt + to select realtime scheduling (round-robin) for the callback thread. + + If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to + open the "default" PCM device when using the ALSA API. Note that this + will override any specified input or output device id. + + If the RTAUDIO_JACK_DONT_CONNECT flag is set, RtAudio will not attempt + to automatically connect the ports of the client to the audio device. +*/ +typedef unsigned int RtAudioStreamFlags; +static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved). +static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency. +static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others. +static const RtAudioStreamFlags RTAUDIO_SCHEDULE_REALTIME = 0x8; // Try to select realtime scheduling for callback thread. +static const RtAudioStreamFlags RTAUDIO_ALSA_USE_DEFAULT = 0x10; // Use the "default" PCM device (ALSA only). +static const RtAudioStreamFlags RTAUDIO_JACK_DONT_CONNECT = 0x20; // Do not automatically connect ports (JACK only). + +/*! \typedef typedef unsigned long RtAudioStreamStatus; + \brief RtAudio stream status (over- or underflow) flags. + + Notification of a stream over- or underflow is indicated by a + non-zero stream \c status argument in the RtAudioCallback function. + The stream status can be one of the following two options, + depending on whether the stream is open for output and/or input: + + - \e RTAUDIO_INPUT_OVERFLOW: Input data was discarded because of an overflow condition at the driver. + - \e RTAUDIO_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound. +*/ +typedef unsigned int RtAudioStreamStatus; +static const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1; // Input data was discarded because of an overflow condition at the driver. +static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output buffer ran low, likely causing a gap in the output sound. + +//! RtAudio callback function prototype. +/*! + All RtAudio clients must create a function of type RtAudioCallback + to read and/or write data from/to the audio stream. When the + underlying audio system is ready for new input or output data, this + function will be invoked. + + \param outputBuffer For output (or duplex) streams, the client + should write \c nFrames of audio sample frames into this + buffer. This argument should be recast to the datatype + specified when the stream was opened. For input-only + streams, this argument will be NULL. + + \param inputBuffer For input (or duplex) streams, this buffer will + hold \c nFrames of input audio sample frames. This + argument should be recast to the datatype specified when the + stream was opened. For output-only streams, this argument + will be NULL. + + \param nFrames The number of sample frames of input or output + data in the buffers. The actual buffer size in bytes is + dependent on the data type and number of channels in use. + + \param streamTime The number of seconds that have elapsed since the + stream was started. + + \param status If non-zero, this argument indicates a data overflow + or underflow condition for the stream. The particular + condition can be determined by comparison with the + RtAudioStreamStatus flags. + + \param userData A pointer to optional data provided by the client + when opening the stream (default = NULL). + + \return + To continue normal stream operation, the RtAudioCallback function + should return a value of zero. To stop the stream and drain the + output buffer, the function should return a value of one. To abort + the stream immediately, the client should return a value of two. + */ +typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer, + unsigned int nFrames, + double streamTime, + RtAudioStreamStatus status, + void *userData ); + +/************************************************************************/ +/*! \class RtAudioError + \brief Exception handling class for RtAudio. + + The RtAudioError class is quite simple but it does allow errors to be + "caught" by RtAudioError::Type. See the RtAudio documentation to know + which methods can throw an RtAudioError. +*/ +/************************************************************************/ + +class RTAUDIO_DLL_PUBLIC RtAudioError : public std::runtime_error +{ + public: + //! Defined RtAudioError types. + enum Type { + WARNING, /*!< A non-critical error. */ + DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ + UNSPECIFIED, /*!< The default, unspecified error type. */ + NO_DEVICES_FOUND, /*!< No devices found on system. */ + INVALID_DEVICE, /*!< An invalid device ID was specified. */ + MEMORY_ERROR, /*!< An error occured during memory allocation. */ + INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ + INVALID_USE, /*!< The function was called incorrectly. */ + DRIVER_ERROR, /*!< A system driver error occured. */ + SYSTEM_ERROR, /*!< A system error occured. */ + THREAD_ERROR /*!< A thread error occured. */ + }; + + //! The constructor. + RtAudioError( const std::string& message, + Type type = RtAudioError::UNSPECIFIED ) + : std::runtime_error(message), type_(type) {} + + //! Prints thrown error message to stderr. + virtual void printMessage( void ) const + { std::cerr << '\n' << what() << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType(void) const { return type_; } + + //! Returns the thrown error message string. + virtual const std::string getMessage(void) const + { return std::string(what()); } + + protected: + Type type_; +}; + +//! RtAudio error callback function prototype. +/*! + \param type Type of error. + \param errorText Error description. + */ +typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText ); + +// **************************************************************** // +// +// RtAudio class declaration. +// +// RtAudio is a "controller" used to select an available audio i/o +// interface. It presents a common API for the user to call but all +// functionality is implemented by the class RtApi and its +// subclasses. RtAudio creates an instance of an RtApi subclass +// based on the user's API choice. If no choice is made, RtAudio +// attempts to make a "logical" API selection. +// +// **************************************************************** // + +class RtApi; + +class RTAUDIO_DLL_PUBLIC RtAudio +{ + public: + + //! Audio API specifier arguments. + enum Api { + UNSPECIFIED, /*!< Search for a working compiled API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + LINUX_PULSE, /*!< The Linux PulseAudio API. */ + LINUX_OSS, /*!< The Linux Open Sound System API. */ + UNIX_JACK, /*!< The Jack Low-Latency Audio Server API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */ + WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ + WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ + WINDOWS_DS, /*!< The Microsoft DirectSound API. */ + RTAUDIO_DUMMY, /*!< A compilable but non-functional API. */ + NUM_APIS /*!< Number of values in this enum. */ + }; + + //! The public device information structure for returning queried values. + struct DeviceInfo { + bool probed; /*!< true if the device capabilities were successfully probed. */ + std::string name; /*!< Character string device identifier. */ + unsigned int outputChannels{}; /*!< Maximum output channels supported by device. */ + unsigned int inputChannels{}; /*!< Maximum input channels supported by device. */ + unsigned int duplexChannels{}; /*!< Maximum simultaneous input/output channels supported by device. */ + bool isDefaultOutput{false}; /*!< true if this is the default output device. */ + bool isDefaultInput{false}; /*!< true if this is the default input device. */ + std::vector sampleRates; /*!< Supported sample rates (queried from list of standard rates). */ + unsigned int preferredSampleRate{}; /*!< Preferred sample rate, e.g. for WASAPI the system sample rate. */ + RtAudioFormat nativeFormats{}; /*!< Bit mask of supported data formats. */ + }; + + //! The structure for specifying input or ouput stream parameters. + struct StreamParameters { + unsigned int deviceId{}; /*!< Device index (0 to getDeviceCount() - 1). */ + unsigned int nChannels{}; /*!< Number of channels. */ + unsigned int firstChannel{}; /*!< First channel index on device (default = 0). */ + }; + + //! The structure for specifying stream options. + /*! + The following flags can be OR'ed together to allow a client to + make changes to the default stream behavior: + + - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). + - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. + - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. + - \e RTAUDIO_SCHEDULE_REALTIME: Attempt to select realtime scheduling for callback thread. + - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). + + By default, RtAudio streams pass and receive audio data from the + client in an interleaved format. By passing the + RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio + data will instead be presented in non-interleaved buffers. In + this case, each buffer argument in the RtAudioCallback function + will point to a single array of data, with \c nFrames samples for + each channel concatenated back-to-back. For example, the first + sample of data for the second channel would be located at index \c + nFrames (assuming the \c buffer pointer was recast to the correct + data type for the stream). + + Certain audio APIs offer a number of parameters that influence the + I/O latency of a stream. By default, RtAudio will attempt to set + these parameters internally for robust (glitch-free) performance + (though some APIs, like Windows DirectSound, make this difficult). + By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() + function, internal stream settings will be influenced in an attempt + to minimize stream latency, though possibly at the expense of stream + performance. + + If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to + open the input and/or output stream device(s) for exclusive use. + Note that this is not possible with all supported audio APIs. + + If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt + to select realtime scheduling (round-robin) for the callback thread. + The \c priority parameter will only be used if the RTAUDIO_SCHEDULE_REALTIME + flag is set. It defines the thread's realtime priority. + + If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to + open the "default" PCM device when using the ALSA API. Note that this + will override any specified input or output device id. + + The \c numberOfBuffers parameter can be used to control stream + latency in the Windows DirectSound, Linux OSS, and Linux Alsa APIs + only. A value of two is usually the smallest allowed. Larger + numbers can potentially result in more robust stream performance, + though likely at the cost of stream latency. The value set by the + user is replaced during execution of the RtAudio::openStream() + function by the value actually used by the system. + + The \c streamName parameter can be used to set the client name + when using the Jack API. By default, the client name is set to + RtApiJack. However, if you wish to create multiple instances of + RtAudio with Jack, each instance must have a unique client name. + */ + struct StreamOptions { + RtAudioStreamFlags flags{}; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_ALSA_USE_DEFAULT). */ + unsigned int numberOfBuffers{}; /*!< Number of stream buffers. */ + std::string streamName; /*!< A stream name (currently used only in Jack). */ + int priority{}; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */ + }; + + //! A static function to determine the current RtAudio version. + static std::string getVersion( void ); + + //! A static function to determine the available compiled audio APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ); + + //! Return the name of a specified compiled audio API. + /*! + This obtains a short lower-case name used for identification purposes. + This value is guaranteed to remain identical across library versions. + If the API is unknown, this function will return the empty string. + */ + static std::string getApiName( RtAudio::Api api ); + + //! Return the display name of a specified compiled audio API. + /*! + This obtains a long name used for display purposes. + If the API is unknown, this function will return the empty string. + */ + static std::string getApiDisplayName( RtAudio::Api api ); + + //! Return the compiled audio API having the given name. + /*! + A case insensitive comparison will check the specified name + against the list of compiled APIs, and return the one which + matches. On failure, the function returns UNSPECIFIED. + */ + static RtAudio::Api getCompiledApiByName( const std::string &name ); + + //! The class constructor. + /*! + The constructor performs minor initialization tasks. An exception + can be thrown if no API support is compiled. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA, OSS (Linux + systems) and ASIO, DS (Windows systems). + */ + RtAudio( RtAudio::Api api=UNSPECIFIED ); + + //! The destructor. + /*! + If a stream is running or open, it will be stopped and closed + automatically. + */ + ~RtAudio(); + + //! Returns the audio API specifier for the current instance of RtAudio. + RtAudio::Api getCurrentApi( void ); + + //! A public function that queries for the number of audio devices available. + /*! + This function performs a system query of available devices each time it + is called, thus supporting devices connected \e after instantiation. If + a system error occurs during processing, a warning will be issued. + */ + unsigned int getDeviceCount( void ); + + //! Return an RtAudio::DeviceInfo structure for a specified device number. + /*! + + Any device integer between 0 and getDeviceCount() - 1 is valid. + If an invalid argument is provided, an RtAudioError (type = INVALID_USE) + will be thrown. If a device is busy or otherwise unavailable, the + structure member "probed" will have a value of "false" and all + other members are undefined. If the specified device is the + current default input or output device, the corresponding + "isDefault" member will have a value of "true". + */ + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + + //! A function that returns the index of the default output device. + /*! + If the underlying audio API does not provide a "default + device", or if no devices are available, the return value will be + 0. Note that this is a valid device identifier and it is the + client's responsibility to verify that a device is available + before attempting to open a stream. + */ + unsigned int getDefaultOutputDevice( void ); + + //! A function that returns the index of the default input device. + /*! + If the underlying audio API does not provide a "default + device", or if no devices are available, the return value will be + 0. Note that this is a valid device identifier and it is the + client's responsibility to verify that a device is available + before attempting to open a stream. + */ + unsigned int getDefaultInputDevice( void ); + + //! A public function for opening a stream with the specified parameters. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if a stream cannot be + opened with the specified parameters or an error occurs during + processing. An RtAudioError (type = INVALID_USE) is thrown if any + invalid device ID or channel number parameters are specified. + + \param outputParameters Specifies output stream parameters to use + when opening a stream, including a device ID, number of channels, + and starting channel number. For input-only streams, this + argument should be NULL. The device ID is an index value between + 0 and getDeviceCount() - 1. + \param inputParameters Specifies input stream parameters to use + when opening a stream, including a device ID, number of channels, + and starting channel number. For output-only streams, this + argument should be NULL. The device ID is an index value between + 0 and getDeviceCount() - 1. + \param format An RtAudioFormat specifying the desired sample data format. + \param sampleRate The desired sample rate (sample frames per second). + \param *bufferFrames A pointer to a value indicating the desired + internal buffer size in sample frames. The actual value + used by the device is returned via the same pointer. A + value of zero can be specified, in which case the lowest + allowable value is determined. + \param callback A client-defined function that will be invoked + when input data is available and/or output data is needed. + \param userData An optional pointer to data that can be accessed + from within the callback function. + \param options An optional pointer to a structure containing various + global stream options, including a list of OR'ed RtAudioStreamFlags + and a suggested number of stream buffers that can be used to + control stream latency. More buffers typically result in more + robust performance, though at a cost of greater latency. If a + value of zero is specified, a system-specific median value is + chosen. If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the + lowest allowable value is used. The actual value used is + returned via the structure argument. The parameter is API dependent. + \param errorCallback A client-defined function that will be invoked + when an error has occured. + */ + void openStream( RtAudio::StreamParameters *outputParameters, + RtAudio::StreamParameters *inputParameters, + RtAudioFormat format, unsigned int sampleRate, + unsigned int *bufferFrames, RtAudioCallback callback, + void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL ); + + //! A function that closes a stream and frees any associated stream memory. + /*! + If a stream is not open, this function issues a warning and + returns (no exception is thrown). + */ + void closeStream( void ); + + //! A function that starts a stream. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs + during processing. An RtAudioError (type = INVALID_USE) is thrown if a + stream is not open. A warning is issued if the stream is already + running. + */ + void startStream( void ); + + //! Stop a stream, allowing any samples remaining in the output queue to be played. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs + during processing. An RtAudioError (type = INVALID_USE) is thrown if a + stream is not open. A warning is issued if the stream is already + stopped. + */ + void stopStream( void ); + + //! Stop a stream, discarding any samples remaining in the input/output queue. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs + during processing. An RtAudioError (type = INVALID_USE) is thrown if a + stream is not open. A warning is issued if the stream is already + stopped. + */ + void abortStream( void ); + + //! Returns true if a stream is open and false if not. + bool isStreamOpen( void ) const; + + //! Returns true if the stream is running and false if it is stopped or not open. + bool isStreamRunning( void ) const; + + //! Returns the number of elapsed seconds since the stream was started. + /*! + If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. + */ + double getStreamTime( void ); + + //! Set the stream time to a time in seconds greater than or equal to 0.0. + /*! + If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. + */ + void setStreamTime( double time ); + + //! Returns the internal stream latency in sample frames. + /*! + The stream latency refers to delay in audio input and/or output + caused by internal buffering by the audio system and/or hardware. + For duplex streams, the returned value will represent the sum of + the input and output latencies. If a stream is not open, an + RtAudioError (type = INVALID_USE) will be thrown. If the API does not + report latency, the return value will be zero. + */ + long getStreamLatency( void ); + + //! Returns actual sample rate in use by the stream. + /*! + On some systems, the sample rate used may be slightly different + than that specified in the stream parameters. If a stream is not + open, an RtAudioError (type = INVALID_USE) will be thrown. + */ + unsigned int getStreamSampleRate( void ); + + //! Specify whether warning messages should be printed to stderr. + void showWarnings( bool value = true ); + + protected: + + void openRtApi( RtAudio::Api api ); + RtApi *rtapi_; +}; + +// Operating system dependent thread functionality. +#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__) + + #ifndef NOMINMAX + #define NOMINMAX + #endif + #include + #include + #include + + typedef uintptr_t ThreadHandle; + typedef CRITICAL_SECTION StreamMutex; + +#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) + // Using pthread library for various flavors of unix. + #include + + typedef pthread_t ThreadHandle; + typedef pthread_mutex_t StreamMutex; + +#else // Setup for "dummy" behavior + + #define __RTAUDIO_DUMMY__ + typedef int ThreadHandle; + typedef int StreamMutex; + +#endif + +// This global structure type is used to pass callback information +// between the private RtAudio stream structure and global callback +// handling functions. +struct CallbackInfo { + void *object{}; // Used as a "this" pointer. + ThreadHandle thread{}; + void *callback{}; + void *userData{}; + void *errorCallback{}; + void *apiInfo{}; // void pointer for API specific callback information + bool isRunning{false}; + bool doRealtime{false}; + int priority{}; +}; + +// **************************************************************** // +// +// RtApi class declaration. +// +// Subclasses of RtApi contain all API- and OS-specific code necessary +// to fully implement the RtAudio API. +// +// Note that RtApi is an abstract base class and cannot be +// explicitly instantiated. The class RtAudio will create an +// instance of an RtApi subclass (RtApiOss, RtApiAlsa, +// RtApiJack, RtApiCore, RtApiDs, or RtApiAsio). +// +// **************************************************************** // + +#pragma pack(push, 1) +class S24 { + + protected: + unsigned char c3[3]; + + public: + S24() {} + + S24& operator = ( const int& i ) { + c3[0] = (i & 0x000000ff); + c3[1] = (i & 0x0000ff00) >> 8; + c3[2] = (i & 0x00ff0000) >> 16; + return *this; + } + + S24( const double& d ) { *this = (int) d; } + S24( const float& f ) { *this = (int) f; } + S24( const signed short& s ) { *this = (int) s; } + S24( const char& c ) { *this = (int) c; } + + int asInt() { + int i = c3[0] | (c3[1] << 8) | (c3[2] << 16); + if (i & 0x800000) i |= ~0xffffff; + return i; + } +}; +#pragma pack(pop) + +#if defined( HAVE_GETTIMEOFDAY ) + #include +#endif + +#include + +class RTAUDIO_DLL_PUBLIC RtApi +{ +public: + + RtApi(); + virtual ~RtApi(); + virtual RtAudio::Api getCurrentApi( void ) = 0; + virtual unsigned int getDeviceCount( void ) = 0; + virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0; + virtual unsigned int getDefaultInputDevice( void ); + virtual unsigned int getDefaultOutputDevice( void ); + void openStream( RtAudio::StreamParameters *outputParameters, + RtAudio::StreamParameters *inputParameters, + RtAudioFormat format, unsigned int sampleRate, + unsigned int *bufferFrames, RtAudioCallback callback, + void *userData, RtAudio::StreamOptions *options, + RtAudioErrorCallback errorCallback ); + virtual void closeStream( void ); + virtual void startStream( void ) = 0; + virtual void stopStream( void ) = 0; + virtual void abortStream( void ) = 0; + long getStreamLatency( void ); + unsigned int getStreamSampleRate( void ); + virtual double getStreamTime( void ); + virtual void setStreamTime( double time ); + bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; } + bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; } + void showWarnings( bool value ) { showWarnings_ = value; } + + +protected: + + static const unsigned int MAX_SAMPLE_RATES; + static const unsigned int SAMPLE_RATES[]; + + enum { FAILURE, SUCCESS }; + + enum StreamState { + STREAM_STOPPED, + STREAM_STOPPING, + STREAM_RUNNING, + STREAM_CLOSED = -50 + }; + + enum StreamMode { + OUTPUT, + INPUT, + DUPLEX, + UNINITIALIZED = -75 + }; + + // A protected structure used for buffer conversion. + struct ConvertInfo { + int channels; + int inJump, outJump; + RtAudioFormat inFormat, outFormat; + std::vector inOffset; + std::vector outOffset; + }; + + // A protected structure for audio streams. + struct RtApiStream { + unsigned int device[2]; // Playback and record, respectively. + void *apiHandle; // void pointer for API specific stream handle information + StreamMode mode; // OUTPUT, INPUT, or DUPLEX. + StreamState state; // STOPPED, RUNNING, or CLOSED + char *userBuffer[2]; // Playback and record, respectively. + char *deviceBuffer; + bool doConvertBuffer[2]; // Playback and record, respectively. + bool userInterleaved; + bool deviceInterleaved[2]; // Playback and record, respectively. + bool doByteSwap[2]; // Playback and record, respectively. + unsigned int sampleRate; + unsigned int bufferSize; + unsigned int nBuffers; + unsigned int nUserChannels[2]; // Playback and record, respectively. + unsigned int nDeviceChannels[2]; // Playback and record channels, respectively. + unsigned int channelOffset[2]; // Playback and record, respectively. + unsigned long latency[2]; // Playback and record, respectively. + RtAudioFormat userFormat; + RtAudioFormat deviceFormat[2]; // Playback and record, respectively. + StreamMutex mutex; + CallbackInfo callbackInfo; + ConvertInfo convertInfo[2]; + double streamTime; // Number of elapsed seconds since the stream started. + +#if defined(HAVE_GETTIMEOFDAY) + struct timeval lastTickTimestamp; +#endif + + RtApiStream() + :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; } + }; + + typedef S24 Int24; + typedef signed short Int16; + typedef signed int Int32; + typedef float Float32; + typedef double Float64; + + std::ostringstream errorStream_; + std::string errorText_; + bool showWarnings_; + RtApiStream stream_; + bool firstErrorOccurred_; + + /*! + Protected, api-specific method that attempts to open a device + with the given parameters. This function MUST be implemented by + all subclasses. If an error is encountered during the probe, a + "warning" message is reported and FAILURE is returned. A + successful probe is indicated by a return value of SUCCESS. + */ + virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); + + //! A protected function used to increment the stream time. + void tickStreamTime( void ); + + //! Protected common method to clear an RtApiStream structure. + void clearStreamInfo(); + + /*! + Protected common method that throws an RtAudioError (type = + INVALID_USE) if a stream is not open. + */ + void verifyStream( void ); + + //! Protected common error method to allow global control over error handling. + void error( RtAudioError::Type type ); + + /*! + Protected method used to perform format, channel number, and/or interleaving + conversions between the user and device buffers. + */ + void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); + + //! Protected common method used to perform byte-swapping on buffers. + void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ); + + //! Protected common method that returns the number of bytes for a given format. + unsigned int formatBytes( RtAudioFormat format ); + + //! Protected common method that sets up the parameters for buffer conversion. + void setConvertInfo( StreamMode mode, unsigned int firstChannel ); +}; + +// **************************************************************** // +// +// Inline RtAudio definitions. +// +// **************************************************************** // + +inline RtAudio::Api RtAudio :: getCurrentApi( void ) { return rtapi_->getCurrentApi(); } +inline unsigned int RtAudio :: getDeviceCount( void ) { return rtapi_->getDeviceCount(); } +inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); } +inline unsigned int RtAudio :: getDefaultInputDevice( void ) { return rtapi_->getDefaultInputDevice(); } +inline unsigned int RtAudio :: getDefaultOutputDevice( void ) { return rtapi_->getDefaultOutputDevice(); } +inline void RtAudio :: closeStream( void ) { return rtapi_->closeStream(); } +inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); } +inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); } +inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); } +inline bool RtAudio :: isStreamOpen( void ) const { return rtapi_->isStreamOpen(); } +inline bool RtAudio :: isStreamRunning( void ) const { return rtapi_->isStreamRunning(); } +inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); } +inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); } +inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); } +inline void RtAudio :: setStreamTime( double time ) { return rtapi_->setStreamTime( time ); } +inline void RtAudio :: showWarnings( bool value ) { rtapi_->showWarnings( value ); } + +// RtApi Subclass prototypes. + +#if defined(__MACOSX_CORE__) + +#include + +class RtApiCore: public RtApi +{ +public: + + RtApiCore(); + ~RtApiCore(); + RtAudio::Api getCurrentApi( void ) override { return RtAudio::MACOSX_CORE; } + unsigned int getDeviceCount( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + unsigned int getDefaultOutputDevice( void ) override; + unsigned int getDefaultInputDevice( void ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + bool callbackEvent( AudioDeviceID deviceId, + const AudioBufferList *inBufferList, + const AudioBufferList *outBufferList ); + + private: + + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) override; + static const char* getErrorCode( OSStatus code ); +}; + +#endif + +#if defined(__UNIX_JACK__) + +class RtApiJack: public RtApi +{ +public: + + RtApiJack(); + ~RtApiJack(); + RtAudio::Api getCurrentApi( void ) override { return RtAudio::UNIX_JACK; } + unsigned int getDeviceCount( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + bool callbackEvent( unsigned long nframes ); + + private: + + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) override; + + bool shouldAutoconnect_; +}; + +#endif + +#if defined(__WINDOWS_ASIO__) + +class RtApiAsio: public RtApi +{ +public: + + RtApiAsio(); + ~RtApiAsio(); + RtAudio::Api getCurrentApi( void ) override { return RtAudio::WINDOWS_ASIO; } + unsigned int getDeviceCount( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + bool callbackEvent( long bufferIndex ); + + private: + + std::vector devices_; + void saveDeviceInfo( void ); + bool coInitialized_; + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) override; +}; + +#endif + +#if defined(__WINDOWS_DS__) + +class RtApiDs: public RtApi +{ +public: + + RtApiDs(); + ~RtApiDs(); + RtAudio::Api getCurrentApi( void ) override { return RtAudio::WINDOWS_DS; } + unsigned int getDeviceCount( void ) override; + unsigned int getDefaultOutputDevice( void ) override; + unsigned int getDefaultInputDevice( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + void callbackEvent( void ); + + private: + + bool coInitialized_; + bool buffersRolling; + long duplexPrerollBytes; + std::vector dsDevices; + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) override; +}; + +#endif + +#if defined(__WINDOWS_WASAPI__) + +struct IMMDeviceEnumerator; + +class RtApiWasapi : public RtApi +{ +public: + RtApiWasapi(); + virtual ~RtApiWasapi(); + + RtAudio::Api getCurrentApi( void ) override { return RtAudio::WINDOWS_WASAPI; } + unsigned int getDeviceCount( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + unsigned int getDefaultOutputDevice( void ) override; + unsigned int getDefaultInputDevice( void ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + +private: + bool coInitialized_; + IMMDeviceEnumerator* deviceEnumerator_; + + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int* bufferSize, + RtAudio::StreamOptions* options ) override; + + static DWORD WINAPI runWasapiThread( void* wasapiPtr ); + static DWORD WINAPI stopWasapiThread( void* wasapiPtr ); + static DWORD WINAPI abortWasapiThread( void* wasapiPtr ); + void wasapiThread(); +}; + +#endif + +#if defined(__LINUX_ALSA__) + +class RtApiAlsa: public RtApi +{ +public: + + RtApiAlsa(); + ~RtApiAlsa(); + RtAudio::Api getCurrentApi() override { return RtAudio::LINUX_ALSA; } + unsigned int getDeviceCount( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + void callbackEvent( void ); + + private: + + std::vector devices_; + void saveDeviceInfo( void ); + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) override; +}; + +#endif + +#if defined(__LINUX_PULSE__) + +class RtApiPulse: public RtApi +{ +public: + ~RtApiPulse(); + RtAudio::Api getCurrentApi() override { return RtAudio::LINUX_PULSE; } + unsigned int getDeviceCount( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + void callbackEvent( void ); + + private: + + void collectDeviceInfo( void ); + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) override; +}; + +#endif + +#if defined(__LINUX_OSS__) + +class RtApiOss: public RtApi +{ +public: + + RtApiOss(); + ~RtApiOss(); + RtAudio::Api getCurrentApi() override { return RtAudio::LINUX_OSS; } + unsigned int getDeviceCount( void ) override; + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) override; + void closeStream( void ) override; + void startStream( void ) override; + void stopStream( void ) override; + void abortStream( void ) override; + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + void callbackEvent( void ); + + private: + + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ) override; +}; + +#endif + +#if defined(__RTAUDIO_DUMMY__) + +class RtApiDummy: public RtApi +{ +public: + + RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtAudioError::WARNING ); } + RtAudio::Api getCurrentApi( void ) override { return RtAudio::RTAUDIO_DUMMY; } + unsigned int getDeviceCount( void ) override { return 0; } + RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) override { RtAudio::DeviceInfo info; return info; } + void closeStream( void ) override {} + void startStream( void ) override {} + void stopStream( void ) override {} + void abortStream( void ) override {} + + private: + + bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, + unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, + RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, + RtAudio::StreamOptions * /*options*/ ) override { return false; } +}; + +#endif + +#endif + +// Indentation settings for Vim and Emacs +// +// Local Variables: +// c-basic-offset: 2 +// indent-tabs-mode: nil +// End: +// +// vim: et sts=2 sw=2 diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtmidi/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtmidi/LICENSE Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,27 @@ + +RtMidi: realtime MIDI i/o C++ classes +Copyright (c) 2003-2021 Gary P. Scavone + +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. + +Any person wishing to distribute modifications to the Software is +asked to send the modifications to the original developer so that +they can be incorporated into the canonical version. This is, +however, not a binding provision of this license. + +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 -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtmidi/RtMidi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtmidi/RtMidi.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3930 @@ +/**********************************************************************/ +/*! \class RtMidi + \brief An abstract base class for realtime MIDI input/output. + + This class implements some common functionality for the realtime + MIDI input/output subclasses RtMidiIn and RtMidiOut. + + RtMidi GitHub site: https://github.com/thestk/rtmidi + RtMidi WWW site: http://www.music.mcgill.ca/~gary/rtmidi/ + + RtMidi: realtime MIDI i/o C++ classes + Copyright (c) 2003-2021 Gary P. Scavone + + 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. + + Any person wishing to distribute modifications to the Software is + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + 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. +*/ +/**********************************************************************/ + +#include "RtMidi.h" +#include +#if defined(__APPLE__) +#include +#endif + +#if (TARGET_OS_IPHONE == 1) + + #define AudioGetCurrentHostTime CAHostTimeBase::GetCurrentTime + #define AudioConvertHostTimeToNanos CAHostTimeBase::ConvertToNanos + + #include + class CTime2nsFactor + { + public: + CTime2nsFactor() + { + mach_timebase_info_data_t tinfo; + mach_timebase_info(&tinfo); + Factor = (double)tinfo.numer / tinfo.denom; + } + static double Factor; + }; + double CTime2nsFactor::Factor; + static CTime2nsFactor InitTime2nsFactor; + #undef AudioGetCurrentHostTime + #undef AudioConvertHostTimeToNanos + #define AudioGetCurrentHostTime (uint64_t) mach_absolute_time + #define AudioConvertHostTimeToNanos(t) t *CTime2nsFactor::Factor + #define EndianS32_BtoN(n) n + +#endif + +// Default for Windows is to add an identifier to the port names; this +// flag can be defined (e.g. in your project file) to disable this behaviour. +//#define RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES + +// **************************************************************** // +// +// MidiInApi and MidiOutApi subclass prototypes. +// +// **************************************************************** // + +#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) && !defined(TARGET_IPHONE_OS) && !defined(__WEB_MIDI_API__) + #define __RTMIDI_DUMMY__ +#endif + +#if defined(__MACOSX_CORE__) +#include + +class MidiInCore: public MidiInApi +{ + public: + MidiInCore( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInCore( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + MIDIClientRef getCoreMidiClientSingleton(const std::string& clientName) throw(); + void initialize( const std::string& clientName ); +}; + +class MidiOutCore: public MidiOutApi +{ + public: + MidiOutCore( const std::string &clientName ); + ~MidiOutCore( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + MIDIClientRef getCoreMidiClientSingleton(const std::string& clientName) throw(); + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__UNIX_JACK__) + +class MidiInJack: public MidiInApi +{ + public: + MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInJack( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + std::string clientName; + + void connect( void ); + void initialize( const std::string& clientName ); +}; + +class MidiOutJack: public MidiOutApi +{ + public: + MidiOutJack( const std::string &clientName ); + ~MidiOutJack( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + std::string clientName; + + void connect( void ); + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__LINUX_ALSA__) + +class MidiInAlsa: public MidiInApi +{ + public: + MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInAlsa( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + void initialize( const std::string& clientName ); +}; + +class MidiOutAlsa: public MidiOutApi +{ + public: + MidiOutAlsa( const std::string &clientName ); + ~MidiOutAlsa( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__WINDOWS_MM__) + +class MidiInWinMM: public MidiInApi +{ + public: + MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInWinMM( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + void initialize( const std::string& clientName ); +}; + +class MidiOutWinMM: public MidiOutApi +{ + public: + MidiOutWinMM( const std::string &clientName ); + ~MidiOutWinMM( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__WEB_MIDI_API__) + +class MidiInWeb : public MidiInApi +{ + std::string client_name{}; + std::string web_midi_id{}; + int open_port_number{-1}; + + public: + MidiInWeb(const std::string &/*clientName*/, unsigned int queueSizeLimit ); + ~MidiInWeb( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::WEB_MIDI_API; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + void onMidiMessage( uint8_t* data, double domHishResTimeStamp ); + + protected: + void initialize( const std::string& clientName ); +}; + +class MidiOutWeb: public MidiOutApi +{ + std::string client_name{}; + std::string web_midi_id{}; + int open_port_number{-1}; + + public: + MidiOutWeb( const std::string &clientName ); + ~MidiOutWeb( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::WEB_MIDI_API; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__RTMIDI_DUMMY__) + +class MidiInDummy: public MidiInApi +{ + public: + MidiInDummy( const std::string &/*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } + RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} + void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + + protected: + void initialize( const std::string& /*clientName*/ ) {} +}; + +class MidiOutDummy: public MidiOutApi +{ + public: + MidiOutDummy( const std::string &/*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } + RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} + void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} + + protected: + void initialize( const std::string& /*clientName*/ ) {} +}; + +#endif + +//*********************************************************************// +// RtMidi Definitions +//*********************************************************************// + +RtMidi :: RtMidi() + : rtapi_(0) +{ +} + +RtMidi :: ~RtMidi() +{ + delete rtapi_; + rtapi_ = 0; +} + +RtMidi::RtMidi(RtMidi&& other) noexcept { + rtapi_ = other.rtapi_; + other.rtapi_ = nullptr; +} + +std::string RtMidi :: getVersion( void ) throw() +{ + return std::string( RTMIDI_VERSION ); +} + +// Define API names and display names. +// Must be in same order as API enum. +extern "C" { +const char* rtmidi_api_names[][2] = { + { "unspecified" , "Unknown" }, + { "core" , "CoreMidi" }, + { "alsa" , "ALSA" }, + { "jack" , "Jack" }, + { "winmm" , "Windows MultiMedia" }, + { "web" , "Web MIDI API" }, + { "dummy" , "Dummy" }, +}; +const unsigned int rtmidi_num_api_names = + sizeof(rtmidi_api_names)/sizeof(rtmidi_api_names[0]); + +// The order here will control the order of RtMidi's API search in +// the constructor. +extern "C" const RtMidi::Api rtmidi_compiled_apis[] = { +#if defined(__MACOSX_CORE__) + RtMidi::MACOSX_CORE, +#endif +#if defined(__LINUX_ALSA__) + RtMidi::LINUX_ALSA, +#endif +#if defined(__UNIX_JACK__) + RtMidi::UNIX_JACK, +#endif +#if defined(__WINDOWS_MM__) + RtMidi::WINDOWS_MM, +#endif +#if defined(__WEB_MIDI_API__) + RtMidi::WEB_MIDI_API, +#endif +#if defined(__RTMIDI_DUMMY__) + RtMidi::RTMIDI_DUMMY, +#endif + RtMidi::UNSPECIFIED, +}; +extern "C" const unsigned int rtmidi_num_compiled_apis = + sizeof(rtmidi_compiled_apis)/sizeof(rtmidi_compiled_apis[0])-1; +} + +void RtMidi :: getCompiledApi( std::vector &apis ) throw() +{ + apis = std::vector(rtmidi_compiled_apis, + rtmidi_compiled_apis + rtmidi_num_compiled_apis); +} + +std::string RtMidi :: getApiName( RtMidi::Api api ) +{ + if (api < RtMidi::UNSPECIFIED || api >= RtMidi::NUM_APIS) + return ""; + return rtmidi_api_names[api][0]; +} + +std::string RtMidi :: getApiDisplayName( RtMidi::Api api ) +{ + if (api < RtMidi::UNSPECIFIED || api >= RtMidi::NUM_APIS) + return "Unknown"; + return rtmidi_api_names[api][1]; +} + +RtMidi::Api RtMidi :: getCompiledApiByName( const std::string &name ) +{ + unsigned int i=0; + for (i = 0; i < rtmidi_num_compiled_apis; ++i) + if (name == rtmidi_api_names[rtmidi_compiled_apis[i]][0]) + return rtmidi_compiled_apis[i]; + return RtMidi::UNSPECIFIED; +} + +void RtMidi :: setClientName( const std::string &clientName ) +{ + rtapi_->setClientName( clientName ); +} + +void RtMidi :: setPortName( const std::string &portName ) +{ + rtapi_->setPortName( portName ); +} + + +//*********************************************************************// +// RtMidiIn Definitions +//*********************************************************************// + +void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) +{ + delete rtapi_; + rtapi_ = 0; + +#if defined(__UNIX_JACK__) + if ( api == UNIX_JACK ) + rtapi_ = new MidiInJack( clientName, queueSizeLimit ); +#endif +#if defined(__LINUX_ALSA__) + if ( api == LINUX_ALSA ) + rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); +#endif +#if defined(__WINDOWS_MM__) + if ( api == WINDOWS_MM ) + rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); +#endif +#if defined(__MACOSX_CORE__) + if ( api == MACOSX_CORE ) + rtapi_ = new MidiInCore( clientName, queueSizeLimit ); +#endif +#if defined(__WEB_MIDI_API__) + if ( api == WEB_MIDI_API ) + rtapi_ = new MidiInWeb( clientName, queueSizeLimit ); +#endif +#if defined(__RTMIDI_DUMMY__) + if ( api == RTMIDI_DUMMY ) + rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); +#endif +} + +RTMIDI_DLL_PUBLIC RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) + : RtMidi() +{ + if ( api != UNSPECIFIED ) { + // Attempt to open the specified API. + openMidiApi( api, clientName, queueSizeLimit ); + if ( rtapi_ ) return; + + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nRtMidiIn: no compiled support for specified API argument!\n\n" << std::endl; + } + + // Iterate through the compiled APIs and return as soon as we find + // one with at least one port or we reach the end of the list. + std::vector< RtMidi::Api > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; igetPortCount() ) break; + } + + if ( rtapi_ ) return; + + // It should not be possible to get here because the preprocessor + // definition __RTMIDI_DUMMY__ is automatically defined if no + // API-specific definitions are passed to the compiler. But just in + // case something weird happens, we'll throw an error. + std::string errorText = "RtMidiIn: no compiled API support found ... critical error!!"; + throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); +} + +RtMidiIn :: ~RtMidiIn() throw() +{ +} + + +//*********************************************************************// +// RtMidiOut Definitions +//*********************************************************************// + +void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string &clientName ) +{ + delete rtapi_; + rtapi_ = 0; + +#if defined(__UNIX_JACK__) + if ( api == UNIX_JACK ) + rtapi_ = new MidiOutJack( clientName ); +#endif +#if defined(__LINUX_ALSA__) + if ( api == LINUX_ALSA ) + rtapi_ = new MidiOutAlsa( clientName ); +#endif +#if defined(__WINDOWS_MM__) + if ( api == WINDOWS_MM ) + rtapi_ = new MidiOutWinMM( clientName ); +#endif +#if defined(__MACOSX_CORE__) + if ( api == MACOSX_CORE ) + rtapi_ = new MidiOutCore( clientName ); +#endif +#if defined(__WEB_MIDI_API__) + if ( api == WEB_MIDI_API ) + rtapi_ = new MidiOutWeb( clientName ); +#endif +#if defined(__RTMIDI_DUMMY__) + if ( api == RTMIDI_DUMMY ) + rtapi_ = new MidiOutDummy( clientName ); +#endif +} + +RTMIDI_DLL_PUBLIC RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName) +{ + if ( api != UNSPECIFIED ) { + // Attempt to open the specified API. + openMidiApi( api, clientName ); + if ( rtapi_ ) return; + + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nRtMidiOut: no compiled support for specified API argument!\n\n" << std::endl; + } + + // Iterate through the compiled APIs and return as soon as we find + // one with at least one port or we reach the end of the list. + std::vector< RtMidi::Api > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; igetPortCount() ) break; + } + + if ( rtapi_ ) return; + + // It should not be possible to get here because the preprocessor + // definition __RTMIDI_DUMMY__ is automatically defined if no + // API-specific definitions are passed to the compiler. But just in + // case something weird happens, we'll thrown an error. + std::string errorText = "RtMidiOut: no compiled API support found ... critical error!!"; + throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); +} + +RtMidiOut :: ~RtMidiOut() throw() +{ +} + +//*********************************************************************// +// Common MidiApi Definitions +//*********************************************************************// + +MidiApi :: MidiApi( void ) + : apiData_( 0 ), connected_( false ), errorCallback_(0), firstErrorOccurred_(false), errorCallbackUserData_(0) +{ +} + +MidiApi :: ~MidiApi( void ) +{ +} + +void MidiApi :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData = 0 ) +{ + errorCallback_ = errorCallback; + errorCallbackUserData_ = userData; +} + +void MidiApi :: error( RtMidiError::Type type, std::string errorString ) +{ + if ( errorCallback_ ) { + + if ( firstErrorOccurred_ ) + return; + + firstErrorOccurred_ = true; + const std::string errorMessage = errorString; + + errorCallback_( type, errorMessage, errorCallbackUserData_ ); + firstErrorOccurred_ = false; + return; + } + + if ( type == RtMidiError::WARNING ) { + std::cerr << '\n' << errorString << "\n\n"; + } + else if ( type == RtMidiError::DEBUG_WARNING ) { +#if defined(__RTMIDI_DEBUG__) + std::cerr << '\n' << errorString << "\n\n"; +#endif + } + else { + std::cerr << '\n' << errorString << "\n\n"; + throw RtMidiError( errorString, type ); + } +} + +//*********************************************************************// +// Common MidiInApi Definitions +//*********************************************************************// + +MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) + : MidiApi() +{ + // Allocate the MIDI queue. + inputData_.queue.ringSize = queueSizeLimit; + if ( inputData_.queue.ringSize > 0 ) + inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ]; +} + +MidiInApi :: ~MidiInApi( void ) +{ + // Delete the MIDI queue. + if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring; +} + +void MidiInApi :: setCallback( RtMidiIn::RtMidiCallback callback, void *userData ) +{ + if ( inputData_.usingCallback ) { + errorString_ = "MidiInApi::setCallback: a callback function is already set!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + if ( !callback ) { + errorString_ = "RtMidiIn::setCallback: callback function value is invalid!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + inputData_.userCallback = callback; + inputData_.userData = userData; + inputData_.usingCallback = true; +} + +void MidiInApi :: cancelCallback() +{ + if ( !inputData_.usingCallback ) { + errorString_ = "RtMidiIn::cancelCallback: no callback function was set!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + inputData_.userCallback = 0; + inputData_.userData = 0; + inputData_.usingCallback = false; +} + +void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) +{ + inputData_.ignoreFlags = 0; + if ( midiSysex ) inputData_.ignoreFlags = 0x01; + if ( midiTime ) inputData_.ignoreFlags |= 0x02; + if ( midiSense ) inputData_.ignoreFlags |= 0x04; +} + +double MidiInApi :: getMessage( std::vector *message ) +{ + message->clear(); + + if ( inputData_.usingCallback ) { + errorString_ = "RtMidiIn::getNextMessage: a user callback is currently set for this port."; + error( RtMidiError::WARNING, errorString_ ); + return 0.0; + } + + double timeStamp; + if ( !inputData_.queue.pop( message, &timeStamp ) ) + return 0.0; + + return timeStamp; +} + +void MidiInApi :: setBufferSize( unsigned int size, unsigned int count ) +{ + inputData_.bufferSize = size; + inputData_.bufferCount = count; +} + +unsigned int MidiInApi::MidiQueue::size( unsigned int *__back, + unsigned int *__front ) +{ + // Access back/front members exactly once and make stack copies for + // size calculation + unsigned int _back = back, _front = front, _size; + if ( _back >= _front ) + _size = _back - _front; + else + _size = ringSize - _front + _back; + + // Return copies of back/front so no new and unsynchronized accesses + // to member variables are needed. + if ( __back ) *__back = _back; + if ( __front ) *__front = _front; + return _size; +} + +// As long as we haven't reached our queue size limit, push the message. +bool MidiInApi::MidiQueue::push( const MidiInApi::MidiMessage& msg ) +{ + // Local stack copies of front/back + unsigned int _back, _front, _size; + + // Get back/front indexes exactly once and calculate current size + _size = size( &_back, &_front ); + + if ( _size < ringSize-1 ) + { + ring[_back] = msg; + back = (back+1)%ringSize; + return true; + } + + return false; +} + +bool MidiInApi::MidiQueue::pop( std::vector *msg, double* timeStamp ) +{ + // Local stack copies of front/back + unsigned int _back, _front, _size; + + // Get back/front indexes exactly once and calculate current size + _size = size( &_back, &_front ); + + if ( _size == 0 ) + return false; + + // Copy queued message to the vector pointer argument and then "pop" it. + msg->assign( ring[_front].bytes.begin(), ring[_front].bytes.end() ); + *timeStamp = ring[_front].timeStamp; + + // Update front + front = (front+1)%ringSize; + return true; +} + +//*********************************************************************// +// Common MidiOutApi Definitions +//*********************************************************************// + +MidiOutApi :: MidiOutApi( void ) + : MidiApi() +{ +} + +MidiOutApi :: ~MidiOutApi( void ) +{ +} + +// *************************************************** // +// +// OS/API-specific methods. +// +// *************************************************** // + +#if defined(__MACOSX_CORE__) + +// The CoreMIDI API is based on the use of a callback function for +// MIDI input. We convert the system specific time stamps to delta +// time values. + +// These are not available on iOS. +#if (TARGET_OS_IPHONE == 0) + #include + #include +#endif + +// A structure to hold variables related to the CoreMIDI API +// implementation. +struct CoreMidiData { + MIDIClientRef client; + MIDIPortRef port; + MIDIEndpointRef endpoint; + MIDIEndpointRef destinationId; + unsigned long long lastTime; + MIDISysexSendRequest sysexreq; +}; + +static MIDIClientRef CoreMidiClientSingleton = 0; + +void RtMidi_setCoreMidiClientSingleton(MIDIClientRef client){ + CoreMidiClientSingleton = client; +} + +void RtMidi_disposeCoreMidiClientSingleton(){ + if (CoreMidiClientSingleton == 0){ + return; + } + MIDIClientDispose( CoreMidiClientSingleton ); + CoreMidiClientSingleton = 0; +} + +//*********************************************************************// +// API: OS-X +// Class Definitions: MidiInCore +//*********************************************************************// + +static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ) +{ + MidiInApi::RtMidiInData *data = static_cast (procRef); + CoreMidiData *apiData = static_cast (data->apiData); + + unsigned char status; + unsigned short nBytes, iByte, size; + unsigned long long time; + + bool& continueSysex = data->continueSysex; + MidiInApi::MidiMessage& message = data->message; + + const MIDIPacket *packet = &list->packet[0]; + for ( unsigned int i=0; inumPackets; ++i ) { + + // My interpretation of the CoreMIDI documentation: all message + // types, except sysex, are complete within a packet and there may + // be several of them in a single packet. Sysex messages can be + // broken across multiple packets and PacketLists but are bundled + // alone within each packet (these packets do not contain other + // message types). If sysex messages are split across multiple + // MIDIPacketLists, they must be handled by multiple calls to this + // function. + + nBytes = packet->length; + if ( nBytes == 0 ) { + packet = MIDIPacketNext( packet ); + continue; + } + + // Calculate time stamp. + if ( data->firstMessage ) { + message.timeStamp = 0.0; + data->firstMessage = false; + } + else { + time = packet->timeStamp; + if ( time == 0 ) { // this happens when receiving asynchronous sysex messages + time = AudioGetCurrentHostTime(); + } + time -= apiData->lastTime; + time = AudioConvertHostTimeToNanos( time ); + if ( !continueSysex ) + message.timeStamp = time * 0.000000001; + } + + // Track whether any non-filtered messages were found in this + // packet for timestamp calculation + bool foundNonFiltered = false; + + iByte = 0; + if ( continueSysex ) { + // We have a continuing, segmented sysex message. + if ( !( data->ignoreFlags & 0x01 ) ) { + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); + } + continueSysex = packet->data[nBytes-1] != 0xF7; + + if ( !( data->ignoreFlags & 0x01 ) && !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->usingCallback ) { + RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( !data->queue.push( message ) ) + std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + } + message.bytes.clear(); + } + } + else { + while ( iByte < nBytes ) { + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + foundNonFiltered = true; + message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] ); + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->usingCallback ) { + RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( !data->queue.push( message ) ) + std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + } + message.bytes.clear(); + } + iByte += size; + } + } + } + + // Save the time of the last non-filtered message + if ( foundNonFiltered ) { + apiData->lastTime = packet->timeStamp; + if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages + apiData->lastTime = AudioGetCurrentHostTime(); + } + } + + packet = MIDIPacketNext(packet); + } +} + +MidiInCore :: MidiInCore( const std::string &clientName, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) +{ + MidiInCore::initialize( clientName ); +} + +MidiInCore :: ~MidiInCore( void ) +{ + // Close a connection if it exists. + MidiInCore::closePort(); + + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); + delete data; +} + +MIDIClientRef MidiInCore::getCoreMidiClientSingleton(const std::string& clientName) throw() { + + if (CoreMidiClientSingleton == 0){ + // Set up our client. + MIDIClientRef client; + + CFStringRef name = CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDIClientCreate(name, NULL, NULL, &client ); + if ( result != noErr ) { + std::ostringstream ost; + ost << "MidiInCore::initialize: error creating OS-X MIDI client object (" << result << ")."; + errorString_ = ost.str(); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return 0; + } + CFRelease( name ); + + CoreMidiClientSingleton = client; + } + + return CoreMidiClientSingleton; +} + +void MidiInCore :: initialize( const std::string& clientName ) +{ + // Set up our client. + MIDIClientRef client = getCoreMidiClientSingleton(clientName); + + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData; + data->client = client; + data->endpoint = 0; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; +} + +void MidiInCore :: openPort( unsigned int portNumber, const std::string &portName ) +{ + if ( connected_ ) { + errorString_ = "MidiInCore::openPort: a valid connection already exists!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nSrc = MIDIGetNumberOfSources(); + if ( nSrc < 1 ) { + errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nSrc ) { + std::ostringstream ost; + ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDIInputPortCreate( data->client, + portNameRef, + midiInputCallback, (void *)&inputData_, &port ); + CFRelease( portNameRef ); + + if ( result != noErr ) { + errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Get the desired input source identifier. + MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); + if ( endpoint == 0 ) { + MIDIPortDispose( port ); + errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Make the connection. + result = MIDIPortConnectSource( port, endpoint, NULL ); + if ( result != noErr ) { + MIDIPortDispose( port ); + errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific port information. + data->port = port; + + connected_ = true; +} + +void MidiInCore :: openVirtualPort( const std::string &portName ) +{ + CoreMidiData *data = static_cast (apiData_); + + // Create a virtual MIDI input destination. + MIDIEndpointRef endpoint; + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDIDestinationCreate( data->client, + portNameRef, + midiInputCallback, (void *)&inputData_, &endpoint ); + CFRelease( portNameRef ); + + if ( result != noErr ) { + errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->endpoint = endpoint; +} + +void MidiInCore :: closePort( void ) +{ + CoreMidiData *data = static_cast (apiData_); + + if ( data->endpoint ) { + MIDIEndpointDispose( data->endpoint ); + data->endpoint = 0; + } + + if ( data->port ) { + MIDIPortDispose( data->port ); + data->port = 0; + } + + connected_ = false; +} + +void MidiInCore :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiInCore::setClientName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiInCore :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiInCore::setPortName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +unsigned int MidiInCore :: getPortCount() +{ + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfSources(); +} + +// This function was submitted by Douglas Casey Tucker and apparently +// derived largely from PortMidi. +CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) +{ + CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); + CFStringRef str; + + // Begin with the endpoint's name. + str = NULL; + MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); + } + + // some MIDI devices have a leading space in endpoint name. trim + CFStringRef space = CFStringCreateWithCString(NULL, " ", kCFStringEncodingUTF8); + CFStringTrim(result, space); + CFRelease(space); + + MIDIEntityRef entity = 0; + MIDIEndpointGetEntity( endpoint, &entity ); + if ( entity == 0 ) + // probably virtual + return result; + + if ( CFStringGetLength( result ) == 0 ) { + // endpoint name has zero length -- try the entity + str = NULL; + MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); + } + } + // now consider the device's name + MIDIDeviceRef device = 0; + MIDIEntityGetDevice( entity, &device ); + if ( device == 0 ) + return result; + + str = NULL; + MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str ); + if ( CFStringGetLength( result ) == 0 ) { + CFRelease( result ); + return str; + } + if ( str != NULL ) { + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) { + CFRelease( result ); + return str; + } else { + if ( CFStringGetLength( str ) == 0 ) { + CFRelease( str ); + return result; + } + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend + if ( CFStringCompareWithOptions( result, /* endpoint name */ + str /* device name */, + CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { + // prepend the device name to the entity name + if ( CFStringGetLength( result ) > 0 ) + CFStringInsert( result, 0, CFSTR(" ") ); + + CFStringInsert( result, 0, str ); + } + CFRelease( str ); + } + } + return result; +} + +// This function was submitted by Douglas Casey Tucker and apparently +// derived largely from PortMidi. +static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) +{ + CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); + CFStringRef str; + OSStatus err; + int i; + + // Does the endpoint have connections? + CFDataRef connections = NULL; + int nConnected = 0; + bool anyStrings = false; + err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections ); + if ( connections != NULL ) { + // It has connections, follow them + // Concatenate the names of all connected devices + nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); + if ( nConnected ) { + const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); + for ( i=0; i= MIDIGetNumberOfSources() ) { + std::ostringstream ost; + ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::WARNING, errorString_ ); + return stringName; + } + + portRef = MIDIGetSource( portNumber ); + nameRef = ConnectedEndpointName( portRef ); + CFStringGetCString( nameRef, name, sizeof(name), kCFStringEncodingUTF8 ); + CFRelease( nameRef ); + + return stringName = name; +} + +//*********************************************************************// +// API: OS-X +// Class Definitions: MidiOutCore +//*********************************************************************// + +MidiOutCore :: MidiOutCore( const std::string &clientName ) + : MidiOutApi() +{ + MidiOutCore::initialize( clientName ); +} + +MidiOutCore :: ~MidiOutCore( void ) +{ + // Close a connection if it exists. + MidiOutCore::closePort(); + + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); + delete data; +} + +MIDIClientRef MidiOutCore::getCoreMidiClientSingleton(const std::string& clientName) throw() { + + if (CoreMidiClientSingleton == 0){ + // Set up our client. + MIDIClientRef client; + + CFStringRef name = CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDIClientCreate(name, NULL, NULL, &client ); + if ( result != noErr ) { + std::ostringstream ost; + ost << "MidiInCore::initialize: error creating OS-X MIDI client object (" << result << ")."; + errorString_ = ost.str(); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return 0; + } + CFRelease( name ); + + CoreMidiClientSingleton = client; + } + + return CoreMidiClientSingleton; +} + +void MidiOutCore :: initialize( const std::string& clientName ) +{ + // Set up our client. + MIDIClientRef client = getCoreMidiClientSingleton(clientName); + + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData; + data->client = client; + data->endpoint = 0; + apiData_ = (void *) data; +} + +unsigned int MidiOutCore :: getPortCount() +{ + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfDestinations(); +} + +std::string MidiOutCore :: getPortName( unsigned int portNumber ) +{ + CFStringRef nameRef; + MIDIEndpointRef portRef; + char name[128]; + + std::string stringName; + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + if ( portNumber >= MIDIGetNumberOfDestinations() ) { + std::ostringstream ost; + ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::WARNING, errorString_ ); + return stringName; + } + + portRef = MIDIGetDestination( portNumber ); + nameRef = ConnectedEndpointName(portRef); + CFStringGetCString( nameRef, name, sizeof(name), kCFStringEncodingUTF8 ); + CFRelease( nameRef ); + + return stringName = name; +} + +void MidiOutCore :: openPort( unsigned int portNumber, const std::string &portName ) +{ + if ( connected_ ) { + errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nDest = MIDIGetNumberOfDestinations(); + if (nDest < 1) { + errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDest ) { + std::ostringstream ost; + ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDIOutputPortCreate( data->client, portNameRef, &port ); + CFRelease( portNameRef ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Get the desired output port identifier. + MIDIEndpointRef destination = MIDIGetDestination( portNumber ); + if ( destination == 0 ) { + MIDIPortDispose( port ); + errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->port = port; + data->destinationId = destination; + connected_ = true; +} + +void MidiOutCore :: closePort( void ) +{ + CoreMidiData *data = static_cast (apiData_); + + if ( data->endpoint ) { + MIDIEndpointDispose( data->endpoint ); + data->endpoint = 0; + } + + if ( data->port ) { + MIDIPortDispose( data->port ); + data->port = 0; + } + + connected_ = false; +} + +void MidiOutCore :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiOutCore::setClientName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiOutCore :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiOutCore::setPortName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiOutCore :: openVirtualPort( const std::string &portName ) +{ + CoreMidiData *data = static_cast (apiData_); + + if ( data->endpoint ) { + errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + // Create a virtual MIDI output source. + MIDIEndpointRef endpoint; + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDISourceCreate( data->client, portNameRef, &endpoint ); + CFRelease( portNameRef ); + + if ( result != noErr ) { + errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->endpoint = endpoint; +} + +void MidiOutCore :: sendMessage( const unsigned char *message, size_t size ) +{ + // We use the MIDISendSysex() function to asynchronously send sysex + // messages. Otherwise, we use a single CoreMidi MIDIPacket. + unsigned int nBytes = static_cast (size); + if ( nBytes == 0 ) { + errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + if ( message[0] != 0xF0 && nBytes > 3 ) { + errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); + CoreMidiData *data = static_cast (apiData_); + OSStatus result; + + ByteCount bufsize = nBytes > 65535 ? 65535 : nBytes; + Byte buffer[bufsize+16]; // pad for other struct members + ByteCount listSize = sizeof( buffer ); + MIDIPacketList *packetList = (MIDIPacketList*)buffer; + + ByteCount remainingBytes = nBytes; + while ( remainingBytes ) { + MIDIPacket *packet = MIDIPacketListInit( packetList ); + // A MIDIPacketList can only contain a maximum of 64K of data, so if our message is longer, + // break it up into chunks of 64K or less and send out as a MIDIPacketList with only one + // MIDIPacket. Here, we reuse the memory allocated above on the stack for all. + ByteCount bytesForPacket = remainingBytes > 65535 ? 65535 : remainingBytes; + const Byte* dataStartPtr = (const Byte *) &message[nBytes - remainingBytes]; + packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr ); + remainingBytes -= bytesForPacket; + + if ( !packet ) { + errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Send to any destinations that may have connected to us. + if ( data->endpoint ) { + result = MIDIReceived( data->endpoint, packetList ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; + error( RtMidiError::WARNING, errorString_ ); + } + } + + // And send to an explicit destination port if we're connected. + if ( connected_ ) { + result = MIDISend( data->port, data->destinationId, packetList ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; + error( RtMidiError::WARNING, errorString_ ); + } + } + } +} + +#endif // __MACOSX_CORE__ + + +//*********************************************************************// +// API: LINUX ALSA SEQUENCER +//*********************************************************************// + +// API information found at: +// - http://www.alsa-project.org/documentation.php#Library + +#if defined(__LINUX_ALSA__) + +// The ALSA Sequencer API is based on the use of a callback function for +// MIDI input. +// +// Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer +// time stamps and other assorted fixes!!! + +// If you don't need timestamping for incoming MIDI events, define the +// preprocessor definition AVOID_TIMESTAMPING to save resources +// associated with the ALSA sequencer queues. + +#include +#include + +// ALSA header file. +#include + +// A structure to hold variables related to the ALSA API +// implementation. +struct AlsaMidiData { + snd_seq_t *seq; + unsigned int portNum; + int vport; + snd_seq_port_subscribe_t *subscription; + snd_midi_event_t *coder; + unsigned int bufferSize; + unsigned int requestedBufferSize; + unsigned char *buffer; + pthread_t thread; + pthread_t dummy_thread_id; + snd_seq_real_time_t lastTime; + int queue_id; // an input queue is needed to get timestamped events + int trigger_fds[2]; +}; + +#define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) + +//*********************************************************************// +// API: LINUX ALSA +// Class Definitions: MidiInAlsa +//*********************************************************************// + +static void *alsaMidiHandler( void *ptr ) +{ + MidiInApi::RtMidiInData *data = static_cast (ptr); + AlsaMidiData *apiData = static_cast (data->apiData); + + long nBytes; + double time; + bool continueSysex = false; + bool doDecode = false; + MidiInApi::MidiMessage message; + int poll_fd_count; + struct pollfd *poll_fds; + + snd_seq_event_t *ev; + int result; + result = snd_midi_event_new( 0, &apiData->coder ); + if ( result < 0 ) { + data->doInput = false; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n"; + return 0; + } + unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + snd_midi_event_free( apiData->coder ); + apiData->coder = 0; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n"; + return 0; + } + snd_midi_event_init( apiData->coder ); + snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages + + poll_fd_count = snd_seq_poll_descriptors_count( apiData->seq, POLLIN ) + 1; + poll_fds = (struct pollfd*)alloca( poll_fd_count * sizeof( struct pollfd )); + snd_seq_poll_descriptors( apiData->seq, poll_fds + 1, poll_fd_count - 1, POLLIN ); + poll_fds[0].fd = apiData->trigger_fds[0]; + poll_fds[0].events = POLLIN; + + while ( data->doInput ) { + + if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { + // No data pending + if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { + if ( poll_fds[0].revents & POLLIN ) { + bool dummy; + int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); + (void) res; + } + } + continue; + } + + // If here, there should be data. + result = snd_seq_event_input( apiData->seq, &ev ); + if ( result == -ENOSPC ) { + std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n"; + continue; + } + else if ( result <= 0 ) { + std::cerr << "\nMidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n"; + perror("System reports"); + continue; + } + + // This is a bit weird, but we now have to decode an ALSA MIDI + // event (back) into MIDI bytes. We'll ignore non-MIDI types. + if ( !continueSysex ) message.bytes.clear(); + + doDecode = false; + switch ( ev->type ) { + + case SND_SEQ_EVENT_PORT_SUBSCRIBED: +#if defined(__RTMIDI_DEBUG__) + std::cout << "MidiInAlsa::alsaMidiHandler: port connection made!\n"; +#endif + break; + + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: +#if defined(__RTMIDI_DEBUG__) + std::cerr << "MidiInAlsa::alsaMidiHandler: port connection has closed!\n"; + std::cout << "sender = " << (int) ev->data.connect.sender.client << ":" + << (int) ev->data.connect.sender.port + << ", dest = " << (int) ev->data.connect.dest.client << ":" + << (int) ev->data.connect.dest.port + << std::endl; +#endif + break; + + case SND_SEQ_EVENT_QFRAME: // MIDI time code + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_TICK: // 0xF9 ... MIDI timing tick + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_CLOCK: // 0xF8 ... MIDI timing (clock) tick + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_SENSING: // Active sensing + if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_SYSEX: + if ( (data->ignoreFlags & 0x01) ) break; + if ( ev->data.ext.len > apiData->bufferSize ) { + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n"; + break; + } + } + doDecode = true; + break; + + default: + doDecode = true; + } + + if ( doDecode ) { + + nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); + if ( nBytes > 0 ) { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + + // Using method from: + // https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html + + // Perform the carry for the later subtraction by updating y. + // Temp var y is timespec because computation requires signed types, + // while snd_seq_real_time_t has unsigned types. + snd_seq_real_time_t &x( ev->time.time ); + struct timespec y; + y.tv_nsec = apiData->lastTime.tv_nsec; + y.tv_sec = apiData->lastTime.tv_sec; + if ( x.tv_nsec < y.tv_nsec ) { + int nsec = (y.tv_nsec - (int)x.tv_nsec) / 1000000000 + 1; + y.tv_nsec -= 1000000000 * nsec; + y.tv_sec += nsec; + } + if ( x.tv_nsec - y.tv_nsec > 1000000000 ) { + int nsec = ((int)x.tv_nsec - y.tv_nsec) / 1000000000; + y.tv_nsec += 1000000000 * nsec; + y.tv_sec -= nsec; + } + + // Compute the time difference. + time = (int)x.tv_sec - y.tv_sec + ((int)x.tv_nsec - y.tv_nsec)*1e-9; + + apiData->lastTime = ev->time.time; + + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time; + } + else { +#if defined(__RTMIDI_DEBUG__) + std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; +#endif + } + } + } + + snd_seq_free_event( ev ); + if ( message.bytes.size() == 0 || continueSysex ) continue; + + if ( data->usingCallback ) { + RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( !data->queue.push( message ) ) + std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; + } + } + + if ( buffer ) free( buffer ); + snd_midi_event_free( apiData->coder ); + apiData->coder = 0; + apiData->thread = apiData->dummy_thread_id; + return 0; +} + +MidiInAlsa :: MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) +{ + MidiInAlsa::initialize( clientName ); +} + +MidiInAlsa :: ~MidiInAlsa() +{ + // Close a connection if it exists. + MidiInAlsa::closePort(); + + // Shutdown the input thread. + AlsaMidiData *data = static_cast (apiData_); + if ( inputData_.doInput ) { + inputData_.doInput = false; + int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof( inputData_.doInput ) ); + (void) res; + if ( !pthread_equal(data->thread, data->dummy_thread_id) ) + pthread_join( data->thread, NULL ); + } + + // Cleanup. + close ( data->trigger_fds[0] ); + close ( data->trigger_fds[1] ); + if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); +#ifndef AVOID_TIMESTAMPING + snd_seq_free_queue( data->seq, data->queue_id ); +#endif + snd_seq_close( data->seq ); + delete data; +} + +void MidiInAlsa :: initialize( const std::string& clientName ) +{ + // Set up the ALSA sequencer client. + snd_seq_t *seq; + int result = snd_seq_open( &seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK ); + if ( result < 0 ) { + errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); + + // Save our api-specific connection information. + AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; + data->seq = seq; + data->portNum = -1; + data->vport = -1; + data->subscription = 0; + data->dummy_thread_id = pthread_self(); + data->thread = data->dummy_thread_id; + data->trigger_fds[0] = -1; + data->trigger_fds[1] = -1; + data->bufferSize = inputData_.bufferSize; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + + if ( pipe(data->trigger_fds) == -1 ) { + errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Create the input queue +#ifndef AVOID_TIMESTAMPING + data->queue_id = snd_seq_alloc_named_queue( seq, "RtMidi Queue" ); + // Set arbitrary tempo (mm=100) and resolution (240) + snd_seq_queue_tempo_t *qtempo; + snd_seq_queue_tempo_alloca( &qtempo ); + snd_seq_queue_tempo_set_tempo( qtempo, 600000 ); + snd_seq_queue_tempo_set_ppq( qtempo, 240 ); + snd_seq_set_queue_tempo( data->seq, data->queue_id, qtempo ); + snd_seq_drain_output( data->seq ); +#endif +} + +// This function is used to count or get the pinfo structure for a given port number. +unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber ) +{ + snd_seq_client_info_t *cinfo; + int client; + int count = 0; + snd_seq_client_info_alloca( &cinfo ); + + snd_seq_client_info_set_client( cinfo, -1 ); + while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) { + client = snd_seq_client_info_get_client( cinfo ); + if ( client == 0 ) continue; + // Reset query info + snd_seq_port_info_set_client( pinfo, client ); + snd_seq_port_info_set_port( pinfo, -1 ); + while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { + unsigned int atyp = snd_seq_port_info_get_type( pinfo ); + if ( ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) && + ( ( atyp & SND_SEQ_PORT_TYPE_SYNTH ) == 0 ) && + ( ( atyp & SND_SEQ_PORT_TYPE_APPLICATION ) == 0 ) ) continue; + + unsigned int caps = snd_seq_port_info_get_capability( pinfo ); + if ( ( caps & type ) != type ) continue; + if ( count == portNumber ) return 1; + ++count; + } + } + + // If a negative portNumber was used, return the port count. + if ( portNumber < 0 ) return count; + return 0; +} + +unsigned int MidiInAlsa :: getPortCount() +{ + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + + AlsaMidiData *data = static_cast (apiData_); + return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 ); +} + +std::string MidiInAlsa :: getPortName( unsigned int portNumber ) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + std::string stringName; + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) { + int cnum = snd_seq_port_info_get_client( pinfo ); + snd_seq_get_any_client_info( data->seq, cnum, cinfo ); + std::ostringstream os; + os << snd_seq_client_info_get_name( cinfo ); + os << ":"; + os << snd_seq_port_info_get_name( pinfo ); + os << " "; // These lines added to make sure devices are listed + os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names + os << ":"; + os << snd_seq_port_info_get_port( pinfo ); + stringName = os.str(); + return stringName; + } + + // If we get here, we didn't find a match. + errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; + error( RtMidiError::WARNING, errorString_ ); + return stringName; +} + +void MidiInAlsa :: openPort( unsigned int portNumber, const std::string &portName ) +{ + if ( connected_ ) { + errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + unsigned int nSrc = this->getPortCount(); + if ( nSrc < 1 ) { + errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; + } + + snd_seq_port_info_t *src_pinfo; + snd_seq_port_info_alloca( &src_pinfo ); + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, src_pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { + std::ostringstream ost; + ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; + } + + snd_seq_addr_t sender, receiver; + sender.client = snd_seq_port_info_get_client( src_pinfo ); + sender.port = snd_seq_port_info_get_port( src_pinfo ); + receiver.client = snd_seq_client_id( data->seq ); + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + if ( data->vport < 0 ) { + snd_seq_port_info_set_client( pinfo, 0 ); + snd_seq_port_info_set_port( pinfo, 0 ); + snd_seq_port_info_set_capability( pinfo, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE ); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels(pinfo, 16); +#ifndef AVOID_TIMESTAMPING + snd_seq_port_info_set_timestamping( pinfo, 1 ); + snd_seq_port_info_set_timestamp_real( pinfo, 1 ); + snd_seq_port_info_set_timestamp_queue( pinfo, data->queue_id ); +#endif + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + data->vport = snd_seq_create_port( data->seq, pinfo ); + + if ( data->vport < 0 ) { + errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + data->vport = snd_seq_port_info_get_port( pinfo ); + } + + receiver.port = data->vport; + + if ( !data->subscription ) { + // Make subscription + if ( snd_seq_port_subscribe_malloc( &data->subscription ) < 0 ) { + errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + snd_seq_port_subscribe_set_sender( data->subscription, &sender ); + snd_seq_port_subscribe_set_dest( data->subscription, &receiver ); + if ( snd_seq_subscribe_port( data->seq, data->subscription ) ) { + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + } + + if ( inputData_.doInput == false ) { + // Start the input queue +#ifndef AVOID_TIMESTAMPING + snd_seq_start_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); +#endif + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init( &attr ); + pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); + + inputData_.doInput = true; + int err = pthread_create( &data->thread, &attr, alsaMidiHandler, &inputData_ ); + pthread_attr_destroy( &attr ); + if ( err ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + inputData_.doInput = false; + errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; + error( RtMidiError::THREAD_ERROR, errorString_ ); + return; + } + } + + connected_ = true; +} + +void MidiInAlsa :: openVirtualPort( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport < 0 ) { + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_port_info_set_capability( pinfo, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE ); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels( pinfo, 16 ); +#ifndef AVOID_TIMESTAMPING + snd_seq_port_info_set_timestamping( pinfo, 1 ); + snd_seq_port_info_set_timestamp_real( pinfo, 1 ); + snd_seq_port_info_set_timestamp_queue( pinfo, data->queue_id ); +#endif + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + data->vport = snd_seq_create_port( data->seq, pinfo ); + + if ( data->vport < 0 ) { + errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + data->vport = snd_seq_port_info_get_port( pinfo ); + } + + if ( inputData_.doInput == false ) { + // Wait for old thread to stop, if still running + if ( !pthread_equal( data->thread, data->dummy_thread_id ) ) + pthread_join( data->thread, NULL ); + + // Start the input queue +#ifndef AVOID_TIMESTAMPING + snd_seq_start_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); +#endif + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init( &attr ); + pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); + pthread_attr_setschedpolicy( &attr, SCHED_OTHER ); + + inputData_.doInput = true; + int err = pthread_create( &data->thread, &attr, alsaMidiHandler, &inputData_ ); + pthread_attr_destroy( &attr ); + if ( err ) { + if ( data->subscription ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + } + inputData_.doInput = false; + errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; + error( RtMidiError::THREAD_ERROR, errorString_ ); + return; + } + } +} + +void MidiInAlsa :: closePort( void ) +{ + AlsaMidiData *data = static_cast (apiData_); + + if ( connected_ ) { + if ( data->subscription ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + } + // Stop the input queue +#ifndef AVOID_TIMESTAMPING + snd_seq_stop_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); +#endif + connected_ = false; + } + + // Stop thread to avoid triggering the callback, while the port is intended to be closed + if ( inputData_.doInput ) { + inputData_.doInput = false; + int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof( inputData_.doInput ) ); + (void) res; + if ( !pthread_equal( data->thread, data->dummy_thread_id ) ) + pthread_join( data->thread, NULL ); + } +} + +void MidiInAlsa :: setClientName( const std::string &clientName ) +{ + + AlsaMidiData *data = static_cast ( apiData_ ); + snd_seq_set_client_name( data->seq, clientName.c_str() ); + +} + +void MidiInAlsa :: setPortName( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_get_port_info( data->seq, data->vport, pinfo ); + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + snd_seq_set_port_info( data->seq, data->vport, pinfo ); +} + +//*********************************************************************// +// API: LINUX ALSA +// Class Definitions: MidiOutAlsa +//*********************************************************************// + +MidiOutAlsa :: MidiOutAlsa( const std::string &clientName ) : MidiOutApi() +{ + MidiOutAlsa::initialize( clientName ); +} + +MidiOutAlsa :: ~MidiOutAlsa() +{ + // Close a connection if it exists. + MidiOutAlsa::closePort(); + + // Cleanup. + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); + if ( data->coder ) snd_midi_event_free( data->coder ); + if ( data->buffer ) free( data->buffer ); + snd_seq_close( data->seq ); + delete data; +} + +void MidiOutAlsa :: initialize( const std::string& clientName ) +{ + // Set up the ALSA sequencer client. + snd_seq_t *seq; + int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); + if ( result1 < 0 ) { + errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); + + // Save our api-specific connection information. + AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; + data->seq = seq; + data->portNum = -1; + data->vport = -1; + data->bufferSize = 32; + data->coder = 0; + data->buffer = 0; + int result = snd_midi_event_new( data->bufferSize, &data->coder ); + if ( result < 0 ) { + delete data; + errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + data->buffer = (unsigned char *) malloc( data->bufferSize ); + if ( data->buffer == NULL ) { + delete data; + errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; + error( RtMidiError::MEMORY_ERROR, errorString_ ); + return; + } + snd_midi_event_init( data->coder ); + apiData_ = (void *) data; +} + +unsigned int MidiOutAlsa :: getPortCount() +{ + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + + AlsaMidiData *data = static_cast (apiData_); + return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 ); +} + +std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + std::string stringName; + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) { + int cnum = snd_seq_port_info_get_client( pinfo ); + snd_seq_get_any_client_info( data->seq, cnum, cinfo ); + std::ostringstream os; + os << snd_seq_client_info_get_name( cinfo ); + os << ":"; + os << snd_seq_port_info_get_name( pinfo ); + os << " "; // These lines added to make sure devices are listed + os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names + os << ":"; + os << snd_seq_port_info_get_port( pinfo ); + stringName = os.str(); + return stringName; + } + + // If we get here, we didn't find a match. + errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; + error( RtMidiError::WARNING, errorString_ ); + return stringName; +} + +void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string &portName ) +{ + if ( connected_ ) { + errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + unsigned int nSrc = this->getPortCount(); + if ( nSrc < 1 ) { + errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { + std::ostringstream ost; + ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; + } + + snd_seq_addr_t sender, receiver; + receiver.client = snd_seq_port_info_get_client( pinfo ); + receiver.port = snd_seq_port_info_get_port( pinfo ); + sender.client = snd_seq_client_id( data->seq ); + + if ( data->vport < 0 ) { + data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + if ( data->vport < 0 ) { + errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + } + + sender.port = data->vport; + + // Make subscription + if ( snd_seq_port_subscribe_malloc( &data->subscription ) < 0 ) { + snd_seq_port_subscribe_free( data->subscription ); + errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + snd_seq_port_subscribe_set_sender( data->subscription, &sender ); + snd_seq_port_subscribe_set_dest( data->subscription, &receiver ); + snd_seq_port_subscribe_set_time_update( data->subscription, 1 ); + snd_seq_port_subscribe_set_time_real( data->subscription, 1 ); + if ( snd_seq_subscribe_port( data->seq, data->subscription ) ) { + snd_seq_port_subscribe_free( data->subscription ); + errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; +} + +void MidiOutAlsa :: closePort( void ) +{ + if ( connected_ ) { + AlsaMidiData *data = static_cast (apiData_); + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + connected_ = false; + } +} + +void MidiOutAlsa :: setClientName( const std::string &clientName ) +{ + + AlsaMidiData *data = static_cast ( apiData_ ); + snd_seq_set_client_name( data->seq, clientName.c_str() ); + +} + +void MidiOutAlsa :: setPortName( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_get_port_info( data->seq, data->vport, pinfo ); + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + snd_seq_set_port_info( data->seq, data->vport, pinfo ); +} + +void MidiOutAlsa :: openVirtualPort( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport < 0 ) { + data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + + if ( data->vport < 0 ) { + errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + } + } +} + +void MidiOutAlsa :: sendMessage( const unsigned char *message, size_t size ) +{ + long result; + AlsaMidiData *data = static_cast (apiData_); + unsigned int nBytes = static_cast (size); + if ( nBytes > data->bufferSize ) { + data->bufferSize = nBytes; + result = snd_midi_event_resize_buffer( data->coder, nBytes ); + if ( result != 0 ) { + errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + free (data->buffer); + data->buffer = (unsigned char *) malloc( data->bufferSize ); + if ( data->buffer == NULL ) { + errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; + error( RtMidiError::MEMORY_ERROR, errorString_ ); + return; + } + } + + for ( unsigned int i=0; ibuffer[i] = message[i]; + + unsigned int offset = 0; + while (offset < nBytes) { + snd_seq_event_t ev; + snd_seq_ev_clear( &ev ); + snd_seq_ev_set_source( &ev, data->vport ); + snd_seq_ev_set_subs( &ev ); + snd_seq_ev_set_direct( &ev ); + result = snd_midi_event_encode( data->coder, data->buffer + offset, + (long)(nBytes - offset), &ev ); + if ( result < 0 ) { + errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + if ( ev.type == SND_SEQ_EVENT_NONE ) { + errorString_ = "MidiOutAlsa::sendMessage: incomplete message!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + offset += result; + + // Send the event. + result = snd_seq_event_output( data->seq, &ev ); + if ( result < 0 ) { + errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; + error( RtMidiError::WARNING, errorString_ ); + return; + } + } + snd_seq_drain_output( data->seq ); +} + +#endif // __LINUX_ALSA__ + + +//*********************************************************************// +// API: Windows Multimedia Library (MM) +//*********************************************************************// + +// API information deciphered from: +// - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp + +// Thanks to Jean-Baptiste Berruchon for the sysex code. + +#if defined(__WINDOWS_MM__) + +// The Windows MM API is based on the use of a callback function for +// MIDI input. We convert the system specific time stamps to delta +// time values. + +// Windows MM MIDI header files. +#include +#include + +// Convert a null-terminated wide string or ANSI-encoded string to UTF-8. +static std::string ConvertToUTF8(const TCHAR *str) +{ + std::string u8str; + const WCHAR *wstr = L""; +#if defined( UNICODE ) || defined( _UNICODE ) + wstr = str; +#else + // Convert from ANSI encoding to wide string + int wlength = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + std::wstring wstrtemp; + if ( wlength ) + { + wstrtemp.assign( wlength - 1, 0 ); + MultiByteToWideChar( CP_ACP, 0, str, -1, &wstrtemp[0], wlength ); + wstr = &wstrtemp[0]; + } +#endif + // Convert from wide string to UTF-8 + int length = WideCharToMultiByte( CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL ); + if ( length ) + { + u8str.assign( length - 1, 0 ); + length = WideCharToMultiByte( CP_UTF8, 0, wstr, -1, &u8str[0], length, NULL, NULL ); + } + return u8str; +} + +// A structure to hold variables related to the CoreMIDI API +// implementation. +struct WinMidiData { + HMIDIIN inHandle; // Handle to Midi Input Device + HMIDIOUT outHandle; // Handle to Midi Output Device + DWORD lastTime; + MidiInApi::MidiMessage message; + std::vector sysexBuffer; + CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo +}; + +//*********************************************************************// +// API: Windows MM +// Class Definitions: MidiInWinMM +//*********************************************************************// + +static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, + UINT inputStatus, + DWORD_PTR instancePtr, + DWORD_PTR midiMessage, + DWORD timestamp ) +{ + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; + + //MidiInApi::RtMidiInData *data = static_cast (instancePtr); + MidiInApi::RtMidiInData *data = (MidiInApi::RtMidiInData *)instancePtr; + WinMidiData *apiData = static_cast (data->apiData); + + // Calculate time stamp. + if ( data->firstMessage == true ) { + apiData->message.timeStamp = 0.0; + data->firstMessage = false; + } + else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; + + if ( inputStatus == MIM_DATA ) { // Channel or system message + + // Make sure the first byte is a status byte. + unsigned char status = (unsigned char) (midiMessage & 0x000000FF); + if ( !(status & 0x80) ) return; + + // Determine the number of bytes in the MIDI message. + unsigned short nBytes = 1; + if ( status < 0xC0 ) nBytes = 3; + else if ( status < 0xE0 ) nBytes = 2; + else if ( status < 0xF0 ) nBytes = 3; + else if ( status == 0xF1 ) { + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; + } + else if ( status == 0xF2 ) nBytes = 3; + else if ( status == 0xF3 ) nBytes = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + return; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + return; + } + + // Copy bytes to our MIDI message. + unsigned char *ptr = (unsigned char *) &midiMessage; + for ( int i=0; imessage.bytes.push_back( *ptr++ ); + } + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) + MIDIHDR *sysex = ( MIDIHDR *) midiMessage; + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); + } + + // The WinMM API requires that the sysex buffer be requeued after + // input of each sysex message. Even if we are ignoring sysex + // messages, we still need to requeue the buffer in case the user + // decides to not ignore sysex messages in the future. However, + // it seems that WinMM calls this function with an empty sysex + // buffer when an application closes and in this case, we should + // avoid requeueing it, else the computer suddenly reboots after + // one or two minutes. + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ) + std::cerr << "\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; + + if ( data->ignoreFlags & 0x01 ) return; + } + else return; + } + + // Save the time of the last non-filtered message + apiData->lastTime = timestamp; + + if ( data->usingCallback ) { + RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; + callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( !data->queue.push( apiData->message ) ) + std::cerr << "\nMidiInWinMM: message queue limit reached!!\n\n"; + } + + // Clear the vector for the next input message. + apiData->message.bytes.clear(); +} + +MidiInWinMM :: MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) +{ + MidiInWinMM::initialize( clientName ); +} + +MidiInWinMM :: ~MidiInWinMM() +{ + // Close a connection if it exists. + MidiInWinMM::closePort(); + + WinMidiData *data = static_cast (apiData_); + DeleteCriticalSection( &(data->_mutex) ); + + // Cleanup. + delete data; +} + +void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) +{ + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plugin something later. + unsigned int nDevices = midiInGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; + error( RtMidiError::WARNING, errorString_ ); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + data->message.bytes.clear(); // needs to be empty for first input message + + if ( !InitializeCriticalSectionAndSpinCount( &(data->_mutex), 0x00000400 ) ) { + errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; + error( RtMidiError::WARNING, errorString_ ); + } +} + +void MidiInWinMM :: openPort( unsigned int portNumber, const std::string &/*portName*/ ) +{ + if ( connected_ ) { + errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + unsigned int nDevices = midiInGetNumDevs(); + if (nDevices == 0) { + errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiInOpen( &data->inHandle, + portNumber, + (DWORD_PTR)&midiInputCallback, + (DWORD_PTR)&inputData_, + CALLBACK_FUNCTION ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Allocate and init the sysex buffers. + data->sysexBuffer.resize( inputData_.bufferCount ); + for ( unsigned int i=0; i < inputData_.bufferCount; ++i ) { + data->sysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; + data->sysexBuffer[i]->lpData = new char[ inputData_.bufferSize ]; + data->sysexBuffer[i]->dwBufferLength = inputData_.bufferSize; + data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator + data->sysexBuffer[i]->dwFlags = 0; + + result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Register the buffer. + result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + } + + result = midiInStart( data->inHandle ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; +} + +void MidiInWinMM :: openVirtualPort( const std::string &/*portName*/ ) +{ + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( RtMidiError::WARNING, errorString_ ); +} + +void MidiInWinMM :: closePort( void ) +{ + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + EnterCriticalSection( &(data->_mutex) ); + midiInReset( data->inHandle ); + midiInStop( data->inHandle ); + + for ( size_t i=0; i < data->sysexBuffer.size(); ++i ) { + int result = midiInUnprepareHeader(data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); + delete [] data->sysexBuffer[i]->lpData; + delete [] data->sysexBuffer[i]; + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + } + + midiInClose( data->inHandle ); + data->inHandle = 0; + connected_ = false; + LeaveCriticalSection( &(data->_mutex) ); + } +} + +void MidiInWinMM :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiInWinMM::setClientName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiInWinMM :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiInWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +unsigned int MidiInWinMM :: getPortCount() +{ + return midiInGetNumDevs(); +} + +std::string MidiInWinMM :: getPortName( unsigned int portNumber ) +{ + std::string stringName; + unsigned int nDevices = midiInGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::WARNING, errorString_ ); + return stringName; + } + + MIDIINCAPS deviceCaps; + midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); + stringName = ConvertToUTF8( deviceCaps.szPname ); + + // Next lines added to add the portNumber to the name so that + // the device's names are sure to be listed with individual names + // even when they have the same brand name +#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES + std::ostringstream os; + os << " "; + os << portNumber; + stringName += os.str(); +#endif + + return stringName; +} + +//*********************************************************************// +// API: Windows MM +// Class Definitions: MidiOutWinMM +//*********************************************************************// + +MidiOutWinMM :: MidiOutWinMM( const std::string &clientName ) : MidiOutApi() +{ + MidiOutWinMM::initialize( clientName ); +} + +MidiOutWinMM :: ~MidiOutWinMM() +{ + // Close a connection if it exists. + MidiOutWinMM::closePort(); + + // Cleanup. + WinMidiData *data = static_cast (apiData_); + delete data; +} + +void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) +{ + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plug something in later. + unsigned int nDevices = midiOutGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; + error( RtMidiError::WARNING, errorString_ ); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; +} + +unsigned int MidiOutWinMM :: getPortCount() +{ + return midiOutGetNumDevs(); +} + +std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) +{ + std::string stringName; + unsigned int nDevices = midiOutGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::WARNING, errorString_ ); + return stringName; + } + + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( portNumber, &deviceCaps, sizeof( MIDIOUTCAPS ) ); + stringName = ConvertToUTF8( deviceCaps.szPname ); + + // Next lines added to add the portNumber to the name so that + // the device's names are sure to be listed with individual names + // even when they have the same brand name + std::ostringstream os; +#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES + os << " "; + os << portNumber; + stringName += os.str(); +#endif + + return stringName; +} + +void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string &/*portName*/ ) +{ + if ( connected_ ) { + errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + unsigned int nDevices = midiOutGetNumDevs(); + if ( nDevices < 1 ) { + errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiOutOpen( &data->outHandle, + portNumber, + (DWORD)NULL, + (DWORD)NULL, + CALLBACK_NULL ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; +} + +void MidiOutWinMM :: closePort( void ) +{ + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + // Disabled because midiOutReset triggers 0x7b (if any note was ON) and 0x79 "Reset All + // Controllers" (to all 16 channels) CC messages which is undesirable (see issue #222) + // midiOutReset( data->outHandle ); + + midiOutClose( data->outHandle ); + data->outHandle = 0; + connected_ = false; + } +} + +void MidiOutWinMM :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiOutWinMM::setClientName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiOutWinMM :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiOutWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiOutWinMM :: openVirtualPort( const std::string &/*portName*/ ) +{ + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( RtMidiError::WARNING, errorString_ ); +} + +void MidiOutWinMM :: sendMessage( const unsigned char *message, size_t size ) +{ + if ( !connected_ ) return; + + unsigned int nBytes = static_cast(size); + if ( nBytes == 0 ) { + errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + MMRESULT result; + WinMidiData *data = static_cast (apiData_); + if ( message[0] == 0xF0 ) { // Sysex message + + // Allocate buffer for sysex data. + char *buffer = (char *) malloc( nBytes ); + if ( buffer == NULL ) { + errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; + error( RtMidiError::MEMORY_ERROR, errorString_ ); + return; + } + + // Copy data to buffer. + for ( unsigned int i=0; ioutHandle, &sysex, sizeof( MIDIHDR ) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Send the message. + result = midiOutLongMsg( data->outHandle, &sysex, sizeof( MIDIHDR ) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Unprepare the buffer and MIDIHDR. + while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof ( MIDIHDR ) ) ) Sleep( 1 ); + free( buffer ); + } + else { // Channel or system message. + + // Make sure the message size isn't too big. + if ( nBytes > 3 ) { + errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + // Pack MIDI bytes into double word. + DWORD packet; + unsigned char *ptr = (unsigned char *) &packet; + for ( unsigned int i=0; ioutHandle, packet ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + } + } +} + +#endif // __WINDOWS_MM__ + + +//*********************************************************************// +// API: UNIX JACK +// +// Written primarily by Alexander Svetalkin, with updates for delta +// time by Gary Scavone, April 2011. +// +// *********************************************************************// + +#if defined(__UNIX_JACK__) + +// JACK header files +#include +#include +#include +#include +#include +#ifdef HAVE_SEMAPHORE + #include +#endif + +#define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer + +struct JackMidiData { + jack_client_t *client; + jack_port_t *port; + jack_ringbuffer_t *buff; + int buffMaxWrite; // actual writable size, usually 1 less than ringbuffer + jack_time_t lastTime; +#ifdef HAVE_SEMAPHORE + sem_t sem_cleanup; + sem_t sem_needpost; +#endif + MidiInApi :: RtMidiInData *rtMidiIn; + }; + +//*********************************************************************// +// API: JACK +// Class Definitions: MidiInJack +//*********************************************************************// + +static int jackProcessIn( jack_nframes_t nframes, void *arg ) +{ + JackMidiData *jData = (JackMidiData *) arg; + MidiInApi :: RtMidiInData *rtData = jData->rtMidiIn; + jack_midi_event_t event; + jack_time_t time; + + // Is port created? + if ( jData->port == NULL ) return 0; + + void *buff = jack_port_get_buffer( jData->port, nframes ); + bool& continueSysex = rtData->continueSysex; + unsigned char& ignoreFlags = rtData->ignoreFlags; + + // We have midi events in buffer + int evCount = jack_midi_get_event_count( buff ); + for (int j = 0; j < evCount; j++) { + MidiInApi::MidiMessage& message = rtData->message; + jack_midi_event_get( &event, buff, j ); + + // Compute the delta time. + time = jack_get_time(); + if ( rtData->firstMessage == true ) { + message.timeStamp = 0.0; + rtData->firstMessage = false; + } else + message.timeStamp = ( time - jData->lastTime ) * 0.000001; + + jData->lastTime = time; + + if ( !continueSysex ) + message.bytes.clear(); + + if ( !( ( continueSysex || event.buffer[0] == 0xF0 ) && ( ignoreFlags & 0x01 ) ) ) { + // Unless this is a (possibly continued) SysEx message and we're ignoring SysEx, + // copy the event buffer into the MIDI message struct. + for ( unsigned int i = 0; i < event.size; i++ ) + message.bytes.push_back( event.buffer[i] ); + } + + switch ( event.buffer[0] ) { + case 0xF0: + // Start of a SysEx message + continueSysex = event.buffer[event.size - 1] != 0xF7; + if ( ignoreFlags & 0x01 ) continue; + break; + case 0xF1: + case 0xF8: + // MIDI Time Code or Timing Clock message + if ( ignoreFlags & 0x02 ) continue; + break; + case 0xFE: + // Active Sensing message + if ( ignoreFlags & 0x04 ) continue; + break; + default: + if ( continueSysex ) { + // Continuation of a SysEx message + continueSysex = event.buffer[event.size - 1] != 0xF7; + if ( ignoreFlags & 0x01 ) continue; + } + // All other MIDI messages + } + + if ( !continueSysex ) { + // If not a continuation of a SysEx message, + // invoke the user callback function or queue the message. + if ( rtData->usingCallback ) { + RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback; + callback( message.timeStamp, &message.bytes, rtData->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( !rtData->queue.push( message ) ) + std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; + } + } + } + + return 0; +} + +MidiInJack :: MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) +{ + MidiInJack::initialize( clientName ); +} + +void MidiInJack :: initialize( const std::string& clientName ) +{ + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; + + data->rtMidiIn = &inputData_; + data->port = NULL; + data->client = NULL; + this->clientName = clientName; + + connect(); +} + +void MidiInJack :: connect() +{ + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; + + // Initialize JACK client + if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + errorString_ = "MidiInJack::initialize: JACK server not running?"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + jack_set_process_callback( data->client, jackProcessIn, data ); + jack_activate( data->client ); +} + +MidiInJack :: ~MidiInJack() +{ + JackMidiData *data = static_cast (apiData_); + MidiInJack::closePort(); + + if ( data->client ) + jack_client_close( data->client ); + delete data; +} + +void MidiInJack :: openPort( unsigned int portNumber, const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + + connect(); + + // Creating new port + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + + if ( data->port == NULL ) { + errorString_ = "MidiInJack::openPort: JACK error creating port"; + if (portName.size() >= (size_t)jack_port_name_size()) + errorString_ += " (port name too long?)"; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); + + connected_ = true; +} + +void MidiInJack :: openVirtualPort( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + + if ( data->port == NULL ) { + errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; + if (portName.size() >= (size_t)jack_port_name_size()) + errorString_ += " (port name too long?)"; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + } +} + +unsigned int MidiInJack :: getPortCount() +{ + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; + + free( ports ); + + return count; +} + +std::string MidiInJack :: getPortName( unsigned int portNumber ) +{ + JackMidiData *data = static_cast (apiData_); + std::string retStr( "" ); + + connect(); + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + + // Check port validity + if ( ports == NULL ) { + errorString_ = "MidiInJack::getPortName: no ports available!"; + error( RtMidiError::WARNING, errorString_ ); + return retStr; + } + + unsigned int i; + for ( i=0; i (apiData_); + + if ( data->port == NULL ) return; + jack_port_unregister( data->client, data->port ); + data->port = NULL; + + connected_ = false; +} + +void MidiInJack:: setClientName( const std::string& ) +{ + + errorString_ = "MidiInJack::setClientName: this function is not implemented for the UNIX_JACK API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiInJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); +#ifdef JACK_HAS_PORT_RENAME + jack_port_rename( data->client, data->port, portName.c_str() ); +#else + jack_port_set_name( data->port, portName.c_str() ); +#endif +} + +//*********************************************************************// +// API: JACK +// Class Definitions: MidiOutJack +//*********************************************************************// + +// Jack process callback +static int jackProcessOut( jack_nframes_t nframes, void *arg ) +{ + JackMidiData *data = (JackMidiData *) arg; + jack_midi_data_t *midiData; + int space; + + // Is port created? + if ( data->port == NULL ) return 0; + + void *buff = jack_port_get_buffer( data->port, nframes ); + jack_midi_clear_buffer( buff ); + + while ( jack_ringbuffer_peek( data->buff, (char *) &space, sizeof( space ) ) == sizeof(space) && + jack_ringbuffer_read_space( data->buff ) >= sizeof(space) + space ) { + jack_ringbuffer_read_advance( data->buff, sizeof(space) ); + + midiData = jack_midi_event_reserve( buff, 0, space ); + if ( midiData ) + jack_ringbuffer_read( data->buff, (char *) midiData, (size_t) space ); + else + jack_ringbuffer_read_advance( data->buff, (size_t) space ); + } + +#ifdef HAVE_SEMAPHORE + if ( !sem_trywait( &data->sem_needpost ) ) + sem_post( &data->sem_cleanup ); +#endif + + return 0; +} + +MidiOutJack :: MidiOutJack( const std::string &clientName ) : MidiOutApi() +{ + MidiOutJack::initialize( clientName ); +} + +void MidiOutJack :: initialize( const std::string& clientName ) +{ + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; + + data->port = NULL; + data->client = NULL; +#ifdef HAVE_SEMAPHORE + sem_init( &data->sem_cleanup, 0, 0 ); + sem_init( &data->sem_needpost, 0, 0 ); +#endif + this->clientName = clientName; + + connect(); +} + +void MidiOutJack :: connect() +{ + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; + + // Initialize output ringbuffers + data->buff = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + data->buffMaxWrite = (int) jack_ringbuffer_write_space( data->buff ); + + // Initialize JACK client + if ( ( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL ) ) == 0 ) { + errorString_ = "MidiOutJack::initialize: JACK server not running?"; + error( RtMidiError::WARNING, errorString_ ); + return; + } + + jack_set_process_callback( data->client, jackProcessOut, data ); + jack_activate( data->client ); +} + +MidiOutJack :: ~MidiOutJack() +{ + JackMidiData *data = static_cast (apiData_); + MidiOutJack::closePort(); + + // Cleanup + jack_ringbuffer_free( data->buff ); + if ( data->client ) { + jack_client_close( data->client ); + } + +#ifdef HAVE_SEMAPHORE + sem_destroy( &data->sem_cleanup ); + sem_destroy( &data->sem_needpost ); +#endif + + delete data; +} + +void MidiOutJack :: openPort( unsigned int portNumber, const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + + connect(); + + // Creating new port + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openPort: JACK error creating port"; + if (portName.size() >= (size_t)jack_port_name_size()) + errorString_ += " (port name too long?)"; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; + } + + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); + + connected_ = true; +} + +void MidiOutJack :: openVirtualPort( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; + if (portName.size() >= (size_t)jack_port_name_size()) + errorString_ += " (port name too long?)"; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + } +} + +unsigned int MidiOutJack :: getPortCount() +{ + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; + + free( ports ); + + return count; +} + +std::string MidiOutJack :: getPortName( unsigned int portNumber ) +{ + JackMidiData *data = static_cast (apiData_); + std::string retStr(""); + + connect(); + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + + // Check port validity + if ( ports == NULL ) { + errorString_ = "MidiOutJack::getPortName: no ports available!"; + error( RtMidiError::WARNING, errorString_ ); + return retStr; + } + + if ( ports[portNumber] == NULL ) { + std::ostringstream ost; + ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( RtMidiError::WARNING, errorString_ ); + } + else retStr.assign( ports[portNumber] ); + + free( ports ); + return retStr; +} + +void MidiOutJack :: closePort() +{ + JackMidiData *data = static_cast (apiData_); + + if ( data->port == NULL ) return; + +#ifdef HAVE_SEMAPHORE + struct timespec ts; + if ( clock_gettime( CLOCK_REALTIME, &ts ) != -1 ) { + ts.tv_sec += 1; // wait max one second + sem_post( &data->sem_needpost ); + sem_timedwait( &data->sem_cleanup, &ts ); + } +#endif + + jack_port_unregister( data->client, data->port ); + data->port = NULL; + + connected_ = false; +} + +void MidiOutJack:: setClientName( const std::string& ) +{ + + errorString_ = "MidiOutJack::setClientName: this function is not implemented for the UNIX_JACK API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiOutJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); +#ifdef JACK_HAS_PORT_RENAME + jack_port_rename( data->client, data->port, portName.c_str() ); +#else + jack_port_set_name( data->port, portName.c_str() ); +#endif +} + +void MidiOutJack :: sendMessage( const unsigned char *message, size_t size ) +{ + int nBytes = static_cast(size); + JackMidiData *data = static_cast (apiData_); + + if ( size + sizeof(nBytes) > (size_t) data->buffMaxWrite ) + return; + + while ( jack_ringbuffer_write_space(data->buff) < sizeof(nBytes) + size ) + sched_yield(); + + // Write full message to buffer + jack_ringbuffer_write( data->buff, ( char * ) &nBytes, sizeof( nBytes ) ); + jack_ringbuffer_write( data->buff, ( const char * ) message, nBytes ); +} + +#endif // __UNIX_JACK__ + +//*********************************************************************// +// API: Web MIDI +// +// Written primarily by Atsushi Eno, February 2020. +// +// *********************************************************************// + +#if defined(__WEB_MIDI_API__) + +#include + +//*********************************************************************// +// API: WEB MIDI +// Class Definitions: WebMidiAccessShim +//*********************************************************************// + +class WebMidiAccessShim +{ +public: + WebMidiAccessShim(); + ~WebMidiAccessShim(); + std::string getPortName( unsigned int portNumber, bool isInput ); +}; + +std::unique_ptr shim{nullptr}; + +void ensureShim() +{ + if ( shim.get() != nullptr ) + return; + shim.reset( new WebMidiAccessShim() ); +} + +bool checkWebMidiAvailability() +{ + ensureShim(); + + return MAIN_THREAD_EM_ASM_INT( { + if ( typeof window._rtmidi_internals_waiting === "undefined" ) { + console.log ( "Attempted to use Web MIDI API without trying to open it." ); + return false; + } + if ( window._rtmidi_internals_waiting ) { + console.log ( "Attempted to use Web MIDI API while it is being queried." ); + return false; + } + if ( _rtmidi_internals_midi_access == null ) { + console.log ( "Attempted to use Web MIDI API while it already turned out to be unavailable." ); + return false; + } + return true; + } ); +} + +WebMidiAccessShim::WebMidiAccessShim() +{ + MAIN_THREAD_ASYNC_EM_ASM( { + if( typeof window._rtmidi_internals_midi_access !== "undefined" ) + return; + if( typeof window._rtmidi_internals_waiting !== "undefined" ) { + console.log( "MIDI Access was requested while another request is in progress." ); + return; + } + + // define functions + window._rtmidi_internals_get_port_by_number = function( portNumber, isInput ) { + var midi = window._rtmidi_internals_midi_access; + var devices = isInput ? midi.inputs : midi.outputs; + var i = 0; + for (var device of devices.values()) { + if ( i == portNumber ) + return device; + i++; + } + console.log( "MIDI " + (isInput ? "input" : "output") + " device of portNumber " + portNumber + " is not found."); + return null; + }; + + window._rtmidi_internals_waiting = true; + window.navigator.requestMIDIAccess( {"sysex": true} ).then( (midiAccess) => { + window._rtmidi_internals_midi_access = midiAccess; + window._rtmidi_internals_latest_message_timestamp = 0.0; + window._rtmidi_internals_waiting = false; + if( midiAccess == null ) { + console.log ( "Could not get access to MIDI API" ); + } + } ); + } ); +} + +WebMidiAccessShim::~WebMidiAccessShim() +{ +} + +std::string WebMidiAccessShim::getPortName( unsigned int portNumber, bool isInput ) +{ + if( !checkWebMidiAvailability() ) + return ""; + char *ret = (char*) MAIN_THREAD_EM_ASM_INT( { + var port = window._rtmidi_internals_get_port_by_number($0, $1); + if( port == null) + return null; + var length = lengthBytesUTF8(port.name) + 1; + var ret = _malloc(length); + stringToUTF8(port.name, ret, length); + return ret; + }, portNumber, isInput); + if (ret == nullptr) + return ""; + std::string s = ret; + free(ret); + return s; +} + +//*********************************************************************// +// API: WEB MIDI +// Class Definitions: MidiInWeb +//*********************************************************************// + +MidiInWeb::MidiInWeb( const std::string &clientName, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) +{ + initialize( clientName ); +} + +MidiInWeb::~MidiInWeb( void ) +{ + closePort(); +} + +extern "C" void EMSCRIPTEN_KEEPALIVE rtmidi_onMidiMessageProc( MidiInApi::RtMidiInData* data, uint8_t* inputBytes, int32_t length, double domHighResTimeStamp ) +{ + auto &message = data->message; + message.bytes.resize(message.bytes.size() + length); + memcpy(message.bytes.data(), inputBytes, length); + // FIXME: handle timestamp + if ( data->usingCallback ) { + RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } +} + +void MidiInWeb::openPort( unsigned int portNumber, const std::string &portName ) +{ + if( !checkWebMidiAvailability() ) + return; + if (open_port_number >= 0) + return; + + MAIN_THREAD_EM_ASM( { + // In Web MIDI API world, there is no step to open a port, but we have to register the input callback instead. + var input = window._rtmidi_internals_get_port_by_number($0, true); + input.onmidimessage = function(e) { + // In RtMidi world, timestamps are delta time from previous message, while in Web MIDI world + // timestamps are relative to window creation time (i.e. kind of absolute time with window "epoch" time). + var rtmidiTimestamp = window._rtmidi_internals_latest_message_timestamp == 0.0 ? 0.0 : e.timeStamp - window._rtmidi_internals_latest_message_timestamp; + window._rtmidi_internals_latest_message_timestamp = e.timeStamp; + Module.ccall( 'rtmidi_onMidiMessageProc', 'void', ['number', 'array', 'number', 'number'], [$1, e.data, e.data.length, rtmidiTimestamp] ); + }; + }, portNumber, &inputData_ ); + open_port_number = portNumber; +} + +void MidiInWeb::openVirtualPort( const std::string &portName ) +{ + + errorString_ = "MidiInWeb::openVirtualPort: this function is not implemented for the Web MIDI API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiInWeb::closePort( void ) +{ + if( open_port_number < 0 ) + return; + + MAIN_THREAD_EM_ASM( { + var input = _rtmidi_internals_get_port_by_number($0, true); + if( input == null ) { + console.log( "Port #" + $0 + " could not be found."); + return; + } + // unregister event handler + input.onmidimessage = null; + }, open_port_number ); + open_port_number = -1; +} + +void MidiInWeb::setClientName( const std::string &clientName ) +{ + client_name = clientName; +} + +void MidiInWeb::setPortName( const std::string &portName ) +{ + + errorString_ = "MidiInWeb::setPortName: this function is not implemented for the Web MIDI API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +unsigned int MidiInWeb::getPortCount( void ) +{ + if( !checkWebMidiAvailability() ) + return 0; + return MAIN_THREAD_EM_ASM_INT( { return _rtmidi_internals_midi_access.inputs.size; } ); +} + +std::string MidiInWeb::getPortName( unsigned int portNumber ) +{ + if( !checkWebMidiAvailability() ) + return ""; + return shim->getPortName( portNumber, true ); +} + +void MidiInWeb::initialize( const std::string& clientName ) +{ + ensureShim(); + setClientName( clientName ); +} + +//*********************************************************************// +// API: WEB MIDI +// Class Definitions: MidiOutWeb +//*********************************************************************// + +MidiOutWeb::MidiOutWeb( const std::string &clientName ) +{ + initialize( clientName ); +} + +MidiOutWeb::~MidiOutWeb( void ) +{ + closePort(); +} + +void MidiOutWeb::openPort( unsigned int portNumber, const std::string &portName ) +{ + if( !checkWebMidiAvailability() ) + return; + if (open_port_number >= 0) + return; + // In Web MIDI API world, there is no step to open a port. + + open_port_number = portNumber; +} + +void MidiOutWeb::openVirtualPort( const std::string &portName ) +{ + + errorString_ = "MidiOutWeb::openVirtualPort: this function is not implemented for the Web MIDI API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +void MidiOutWeb::closePort( void ) +{ + // there is really nothing to do for output at JS side. + open_port_number = -1; +} + +void MidiOutWeb::setClientName( const std::string &clientName ) +{ + client_name = clientName; +} + +void MidiOutWeb::setPortName( const std::string &portName ) +{ + + errorString_ = "MidiOutWeb::setPortName: this function is not implemented for the Web MIDI API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + +unsigned int MidiOutWeb::getPortCount( void ) +{ + if( !checkWebMidiAvailability() ) + return 0; + return MAIN_THREAD_EM_ASM_INT( { return _rtmidi_internals_midi_access.outputs.size; } ); +} + +std::string MidiOutWeb::getPortName( unsigned int portNumber ) +{ + if( !checkWebMidiAvailability() ) + return ""; + return shim->getPortName( portNumber, false ); +} + +void MidiOutWeb::sendMessage( const unsigned char *message, size_t size ) +{ + if( open_port_number < 0 ) + return; + + MAIN_THREAD_EM_ASM( { + var output = _rtmidi_internals_get_port_by_number( $0, false ); + if( output == null ) { + console.log( "Port #" + $0 + " could not be found."); + return; + } + var buf = new ArrayBuffer ($2); + var msg = new Uint8Array( buf ); + msg.set( new Uint8Array( Module.HEAPU8.buffer.slice( $1, $1 + $2 ) ) ); + output.send( msg ); + }, open_port_number, message, size ); +} + +void MidiOutWeb::initialize( const std::string& clientName ) +{ + if ( shim.get() != nullptr ) + return; + shim.reset( new WebMidiAccessShim() ); + setClientName( clientName ); +} + +#endif // __WEB_MIDI_API__ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtmidi/RtMidi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/jackbridge/rtmidi/RtMidi.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,658 @@ +/**********************************************************************/ +/*! \class RtMidi + \brief An abstract base class for realtime MIDI input/output. + + This class implements some common functionality for the realtime + MIDI input/output subclasses RtMidiIn and RtMidiOut. + + RtMidi GitHub site: https://github.com/thestk/rtmidi + RtMidi WWW site: http://www.music.mcgill.ca/~gary/rtmidi/ + + RtMidi: realtime MIDI i/o C++ classes + Copyright (c) 2003-2021 Gary P. Scavone + + 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. + + Any person wishing to distribute modifications to the Software is + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + 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. +*/ +/**********************************************************************/ + +/*! + \file RtMidi.h + */ + +#ifndef RTMIDI_H +#define RTMIDI_H + +#if defined _WIN32 || defined __CYGWIN__ + #if defined(RTMIDI_EXPORT) + #define RTMIDI_DLL_PUBLIC __declspec(dllexport) + #else + #define RTMIDI_DLL_PUBLIC + #endif +#else + #if __GNUC__ >= 4 + #define RTMIDI_DLL_PUBLIC __attribute__( (visibility( "default" )) ) + #else + #define RTMIDI_DLL_PUBLIC + #endif +#endif + +#define RTMIDI_VERSION "5.0.0" + +#include +#include +#include +#include + + +/************************************************************************/ +/*! \class RtMidiError + \brief Exception handling class for RtMidi. + + The RtMidiError class is quite simple but it does allow errors to be + "caught" by RtMidiError::Type. See the RtMidi documentation to know + which methods can throw an RtMidiError. +*/ +/************************************************************************/ + +class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception +{ + public: + //! Defined RtMidiError types. + enum Type { + WARNING, /*!< A non-critical error. */ + DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ + UNSPECIFIED, /*!< The default, unspecified error type. */ + NO_DEVICES_FOUND, /*!< No devices found on system. */ + INVALID_DEVICE, /*!< An invalid device ID was specified. */ + MEMORY_ERROR, /*!< An error occured during memory allocation. */ + INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ + INVALID_USE, /*!< The function was called incorrectly. */ + DRIVER_ERROR, /*!< A system driver error occured. */ + SYSTEM_ERROR, /*!< A system error occured. */ + THREAD_ERROR /*!< A thread error occured. */ + }; + + //! The constructor. + RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() + : message_(message), type_(type) {} + + //! The destructor. + virtual ~RtMidiError( void ) throw() {} + + //! Prints thrown error message to stderr. + virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType( void ) const throw() { return type_; } + + //! Returns the thrown error message string. + virtual const std::string& getMessage( void ) const throw() { return message_; } + + //! Returns the thrown error message as a c-style string. + virtual const char* what( void ) const throw() { return message_.c_str(); } + + protected: + std::string message_; + Type type_; +}; + +//! RtMidi error callback function prototype. +/*! + \param type Type of error. + \param errorText Error description. + + Note that class behaviour is undefined after a critical error (not + a warning) is reported. + */ +typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText, void *userData ); + +class MidiApi; + +class RTMIDI_DLL_PUBLIC RtMidi +{ + public: + + RtMidi(RtMidi&& other) noexcept; + //! MIDI API specifier arguments. + enum Api { + UNSPECIFIED, /*!< Search for a working compiled API. */ + MACOSX_CORE, /*!< Macintosh OS-X CoreMIDI API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ + WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + RTMIDI_DUMMY, /*!< A compilable but non-functional API. */ + WEB_MIDI_API, /*!< W3C Web MIDI API. */ + NUM_APIS /*!< Number of values in this enum. */ + }; + + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ) throw(); + + //! Return the name of a specified compiled MIDI API. + /*! + This obtains a short lower-case name used for identification purposes. + This value is guaranteed to remain identical across library versions. + If the API is unknown, this function will return the empty string. + */ + static std::string getApiName( RtMidi::Api api ); + + //! Return the display name of a specified compiled MIDI API. + /*! + This obtains a long name used for display purposes. + If the API is unknown, this function will return the empty string. + */ + static std::string getApiDisplayName( RtMidi::Api api ); + + //! Return the compiled MIDI API having the given name. + /*! + A case insensitive comparison will check the specified name + against the list of compiled APIs, and return the one which + matches. On failure, the function returns UNSPECIFIED. + */ + static RtMidi::Api getCompiledApiByName( const std::string &name ); + + //! Pure virtual openPort() function. + virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual openVirtualPort() function. + virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual getPortCount() function. + virtual unsigned int getPortCount() = 0; + + //! Pure virtual getPortName() function. + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual closePort() function. + virtual void closePort( void ) = 0; + + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + + //! Returns true if a port is open and false if not. + /*! + Note that this only applies to connections made with the openPort() + function, not to virtual ports. + */ + virtual bool isPortOpen( void ) const = 0; + + //! Set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0; + + protected: + RtMidi(); + virtual ~RtMidi(); + MidiApi *rtapi_; + + /* Make the class non-copyable */ + RtMidi(RtMidi& other) = delete; + RtMidi& operator=(RtMidi& other) = delete; +}; + +/**********************************************************************/ +/*! \class RtMidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also + possible to open a virtual input port to which other MIDI software + clients can connect. +*/ +/**********************************************************************/ + +// **************************************************************** // +// +// RtMidiIn and RtMidiOut class declarations. +// +// RtMidiIn / RtMidiOut are "controllers" used to select an available +// MIDI input or output interface. They present common APIs for the +// user to call but all functionality is implemented by the classes +// MidiInApi, MidiOutApi and their subclasses. RtMidiIn and RtMidiOut +// each create an instance of a MidiInApi or MidiOutApi subclass based +// on the user's API choice. If no choice is made, they attempt to +// make a "logical" API selection. +// +// **************************************************************** // + +class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi +{ + public: + //! User callback function type definition. + typedef void (*RtMidiCallback)( double timeStamp, std::vector *message, void *userData ); + + //! Default constructor that allows an optional api, client name and queue size. + /*! + An exception will be thrown if a MIDI system initialization + error occurs. The queue size defines the maximum number of + messages that can be held in the MIDI queue (when not using a + callback function). If the queue size limit is reached, + incoming messages will be ignored. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is ALSA, JACK (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + */ + RtMidiIn( RtMidi::Api api=UNSPECIFIED, + const std::string& clientName = "RtMidi Input Client", + unsigned int queueSizeLimit = 100 ); + + RtMidiIn(RtMidiIn&& other) noexcept : RtMidi(std::move(other)) { } + + //! If a MIDI connection is still open, it will be closed by the destructor. + ~RtMidiIn ( void ) throw(); + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + RtMidi::Api getCurrentApi( void ) throw(); + + //! Open a MIDI input connection given by enumeration number. + /*! + \param portNumber An optional port number greater than 0 can be specified. + Otherwise, the default or first port found is opened. + \param portName An optional name for the application port that is used to connect to portId can be specified. + */ + void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) ); + + //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only). + /*! + This function creates a virtual MIDI input port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the application port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) ); + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Optionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( RtMidiCallback callback, void *userData = 0 ); + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback(); + + //! Close an open MIDI connection (if one exists). + void closePort( void ); + + //! Returns true if a port is open and false if not. + /*! + Note that this only applies to connections made with the openPort() + function, not to virtual ports. + */ + virtual bool isPortOpen() const; + + //! Return the number of available MIDI input ports. + /*! + \return This function returns the number of MIDI ports of the selected API. + */ + unsigned int getPortCount(); + + //! Return a string identifier for the specified MIDI input port number. + /*! + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier + is provided. User code should assume a UTF-8 encoding. + */ + std::string getPortName( unsigned int portNumber = 0 ); + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true ); + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector *message ); + + //! Set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); + + //! Set maximum expected incoming message size. + /*! + For APIs that require manual buffer management, it can be useful to set the buffer + size and buffer count when expecting to receive large SysEx messages. Note that + currently this function has no effect when called after openPort(). The default + buffer size is 1024 with a count of 4 buffers, which should be sufficient for most + cases; as mentioned, this does not affect all API backends, since most either support + dynamically scalable buffers or take care of buffer handling themselves. It is + principally intended for users of the Windows MM backend who must support receiving + especially large messages. + */ + virtual void setBufferSize( unsigned int size, unsigned int count ); + + protected: + void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ); +}; + +/**********************************************************************/ +/*! \class RtMidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. +*/ +/**********************************************************************/ + +class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi +{ + public: + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is ALSA, JACK (Linux) and CORE, + JACK (OS-X). + */ + RtMidiOut( RtMidi::Api api=UNSPECIFIED, + const std::string& clientName = "RtMidi Output Client" ); + + RtMidiOut(RtMidiOut&& other) noexcept : RtMidi(std::move(other)) { } + + //! The destructor closes any open MIDI connections. + ~RtMidiOut( void ) throw(); + + //! Returns the MIDI API specifier for the current instance of RtMidiOut. + RtMidi::Api getCurrentApi( void ) throw(); + + //! Open a MIDI output connection. + /*! + An optional port number greater than 0 can be specified. + Otherwise, the default or first port found is opened. An + exception is thrown if an error occurs while attempting to make + the port connection. + */ + void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Output" ) ); + + //! Close an open MIDI connection (if one exists). + void closePort( void ); + + //! Returns true if a port is open and false if not. + /*! + Note that this only applies to connections made with the openPort() + function, not to virtual ports. + */ + virtual bool isPortOpen() const; + + //! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only). + /*! + This function creates a virtual MIDI output port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, Linux ALSA + and JACK APIs (the function does nothing with the other APIs). + An exception is thrown if an error occurs while attempting to + create the virtual port. + */ + void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) ); + + //! Return the number of available MIDI output ports. + unsigned int getPortCount( void ); + + //! Return a string identifier for the specified MIDI port type and number. + /*! + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier + is provided. User code should assume a UTF-8 encoding. + */ + std::string getPortName( unsigned int portNumber = 0 ); + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + */ + void sendMessage( const std::vector *message ); + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \param message A pointer to the MIDI message as raw bytes + \param size Length of the MIDI message in bytes + */ + void sendMessage( const unsigned char *message, size_t size ); + + //! Set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); + + protected: + void openMidiApi( RtMidi::Api api, const std::string &clientName ); +}; + + +// **************************************************************** // +// +// MidiInApi / MidiOutApi class declarations. +// +// Subclasses of MidiInApi and MidiOutApi contain all API- and +// OS-specific code necessary to fully implement the RtMidi API. +// +// Note that MidiInApi and MidiOutApi are abstract base classes and +// cannot be explicitly instantiated. RtMidiIn and RtMidiOut will +// create instances of a MidiInApi or MidiOutApi subclass. +// +// **************************************************************** // + +class RTMIDI_DLL_PUBLIC MidiApi +{ + public: + + MidiApi(); + virtual ~MidiApi(); + virtual RtMidi::Api getCurrentApi( void ) = 0; + virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0; + virtual void openVirtualPort( const std::string &portName ) = 0; + virtual void closePort( void ) = 0; + virtual void setClientName( const std::string &clientName ) = 0; + virtual void setPortName( const std::string &portName ) = 0; + + virtual unsigned int getPortCount( void ) = 0; + virtual std::string getPortName( unsigned int portNumber ) = 0; + + inline bool isPortOpen() const { return connected_; } + void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ); + + //! A basic error reporting function for RtMidi classes. + void error( RtMidiError::Type type, std::string errorString ); + +protected: + virtual void initialize( const std::string& clientName ) = 0; + + void *apiData_; + bool connected_; + std::string errorString_; + RtMidiErrorCallback errorCallback_; + bool firstErrorOccurred_; + void *errorCallbackUserData_; + +}; + +class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi +{ + public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( RtMidiIn::RtMidiCallback callback, void *userData ); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + double getMessage( std::vector *message ); + virtual void setBufferSize( unsigned int size, unsigned int count ); + + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + + //! Time in seconds elapsed since the previous message + double timeStamp; + + // Default constructor. + MidiMessage() + : bytes(0), timeStamp(0.0) {} + }; + + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int ringSize; + MidiMessage *ring; + + // Default constructor. + MidiQueue() + : front(0), back(0), ringSize(0), ring(0) {} + bool push( const MidiMessage& ); + bool pop( std::vector*, double* ); + unsigned int size( unsigned int *back=0, unsigned int *front=0 ); + }; + + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + struct RtMidiInData { + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + void *apiData; + bool usingCallback; + RtMidiIn::RtMidiCallback userCallback; + void *userData; + bool continueSysex; + unsigned int bufferSize; + unsigned int bufferCount; + + // Default constructor. + RtMidiInData() + : ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false), + userCallback(0), userData(0), continueSysex(false), bufferSize(1024), bufferCount(4) {} + }; + + protected: + RtMidiInData inputData_; +}; + +class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi +{ + public: + + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + virtual void sendMessage( const unsigned char *message, size_t size ) = 0; +}; + +// **************************************************************** // +// +// Inline RtMidiIn and RtMidiOut definitions. +// +// **************************************************************** // + +inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } +inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); } +inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); } +inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); } +inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); } +inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast(rtapi_)->setCallback( callback, userData ); } +inline void RtMidiIn :: cancelCallback( void ) { static_cast(rtapi_)->cancelCallback(); } +inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); } +inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } +inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { static_cast(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); } +inline double RtMidiIn :: getMessage( std::vector *message ) { return static_cast(rtapi_)->getMessage( message ); } +inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } +inline void RtMidiIn :: setBufferSize( unsigned int size, unsigned int count ) { static_cast(rtapi_)->setBufferSize(size, count); } + +inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } +inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); } +inline void RtMidiOut :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); } +inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); } +inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); } +inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); } +inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } +inline void RtMidiOut :: sendMessage( const std::vector *message ) { static_cast(rtapi_)->sendMessage( &message->at(0), message->size() ); } +inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { static_cast(rtapi_)->sendMessage( message, size ); } +inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/ladspa/ladspa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/ladspa/ladspa.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,611 @@ +/* ladspa.h + + Linux Audio Developer's Simple Plugin API Version 1.1[LGPL]. + Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, + Stefan Westerfeld. + + 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.1 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. */ + +#ifndef LADSPA_INCLUDED +#define LADSPA_INCLUDED + +#define LADSPA_VERSION "1.1" +#define LADSPA_VERSION_MAJOR 1 +#define LADSPA_VERSION_MINOR 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LADSPA_PLUGIN_EXPORT +# ifdef _WIN32 +# define LADSPA_PLUGIN_EXPORT __declspec(dllexport) +# else +# define LADSPA_PLUGIN_EXPORT __attribute__((visibility("default"))) +# endif +#endif + +/*****************************************************************************/ + +/* Overview: + + There is a large number of synthesis packages in use or development + on the Linux platform at this time. This API (`The Linux Audio + Developer's Simple Plugin API') attempts to give programmers the + ability to write simple `plugin' audio processors in C/C++ and link + them dynamically (`plug') into a range of these packages (`hosts'). + It should be possible for any host and any plugin to communicate + completely through this interface. + + This API is deliberately short and simple. To achieve compatibility + with a range of promising Linux sound synthesis packages it + attempts to find the `greatest common divisor' in their logical + behaviour. Having said this, certain limiting decisions are + implicit, notably the use of a fixed type (LADSPA_Data) for all + data transfer and absence of a parameterised `initialisation' + phase. See below for the LADSPA_Data typedef. + + Plugins are expected to distinguish between control and audio + data. Plugins have `ports' that are inputs or outputs for audio or + control data and each plugin is `run' for a `block' corresponding + to a short time interval measured in samples. Audio data is + communicated using arrays of LADSPA_Data, allowing a block of audio + to be processed by the plugin in a single pass. Control data is + communicated using single LADSPA_Data values. Control data has a + single value at the start of a call to the `run()' or `run_adding()' + function, and may be considered to remain this value for its + duration. The plugin may assume that all its input and output ports + have been connected to the relevant data location (see the + `connect_port()' function below) before it is asked to run. + + Plugins will reside in shared object files suitable for dynamic + linking by dlopen() and family. The file will provide a number of + `plugin types' that can be used to instantiate actual plugins + (sometimes known as `plugin instances') that can be connected + together to perform tasks. + + This API contains very limited error-handling. */ + +/*****************************************************************************/ + +/* Fundamental data type passed in and out of plugin. This data type + is used to communicate audio samples and control values. It is + assumed that the plugin will work sensibly given any numeric input + value although it may have a preferred range (see hints below). + + For audio it is generally assumed that 1.0f is the `0dB' reference + amplitude and is a `normal' signal level. */ + +typedef float LADSPA_Data; + +/*****************************************************************************/ + +/* Special Plugin Properties: + + Optional features of the plugin type are encapsulated in the + LADSPA_Properties type. This is assembled by ORing individual + properties together. */ + +typedef int LADSPA_Properties; + +/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a + real-time dependency (e.g. listens to a MIDI device) and so its + output must not be cached or subject to significant latency. */ +#define LADSPA_PROPERTY_REALTIME 0x1 + +/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin + may cease to work correctly if the host elects to use the same data + location for both input and output (see connect_port()). This + should be avoided as enabling this flag makes it impossible for + hosts to use the plugin to process audio `in-place.' */ +#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2 + +/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin + is capable of running not only in a conventional host but also in a + `hard real-time' environment. To qualify for this the plugin must + satisfy all of the following: + + (1) The plugin must not use malloc(), free() or other heap memory + management within its run() or run_adding() functions. All new + memory used in run() must be managed via the stack. These + restrictions only apply to the run() function. + + (2) The plugin will not attempt to make use of any library + functions with the exceptions of functions in the ANSI standard C + and C maths libraries, which the host is expected to provide. + + (3) The plugin will not access files, devices, pipes, sockets, IPC + or any other mechanism that might result in process or thread + blocking. + + (4) The plugin will take an amount of time to execute a run() or + run_adding() call approximately of form (A+B*SampleCount) where A + and B depend on the machine and host in use. This amount of time + may not depend on input signals or plugin state. The host is left + the responsibility to perform timings to estimate upper bounds for + A and B. */ +#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4 + +#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME) +#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN) +#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE) + +/*****************************************************************************/ + +/* Plugin Ports: + + Plugins have `ports' that are inputs or outputs for audio or + data. Ports can communicate arrays of LADSPA_Data (for audio + inputs/outputs) or single LADSPA_Data values (for control + input/outputs). This information is encapsulated in the + LADSPA_PortDescriptor type which is assembled by ORing individual + properties together. + + Note that a port must be an input or an output port but not both + and that a port must be a control or audio port but not both. */ + +typedef int LADSPA_PortDescriptor; + +/* Property LADSPA_PORT_INPUT indicates that the port is an input. */ +#define LADSPA_PORT_INPUT 0x1 + +/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */ +#define LADSPA_PORT_OUTPUT 0x2 + +/* Property LADSPA_PORT_CONTROL indicates that the port is a control + port. */ +#define LADSPA_PORT_CONTROL 0x4 + +/* Property LADSPA_PORT_AUDIO indicates that the port is a audio + port. */ +#define LADSPA_PORT_AUDIO 0x8 + +#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT) +#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT) +#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL) +#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO) + +/*****************************************************************************/ + +/* Plugin Port Range Hints: + + The host may wish to provide a representation of data entering or + leaving a plugin (e.g. to generate a GUI automatically). To make + this more meaningful, the plugin should provide `hints' to the host + describing the usual values taken by the data. + + Note that these are only hints. The host may ignore them and the + plugin must not assume that data supplied to it is meaningful. If + the plugin receives invalid input data it is expected to continue + to run without failure and, where possible, produce a sensible + output (e.g. a high-pass filter given a negative cutoff frequency + might switch to an all-pass mode). + + Hints are meaningful for all input and output ports but hints for + input control ports are expected to be particularly useful. + + More hint information is encapsulated in the + LADSPA_PortRangeHintDescriptor type which is assembled by ORing + individual hint types together. Hints may require further + LowerBound and UpperBound information. + + All the hint information for a particular port is aggregated in the + LADSPA_PortRangeHint structure. */ + +typedef int LADSPA_PortRangeHintDescriptor; + +/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) lower + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of LowerBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_BELOW 0x1 + +/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) upper + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of UpperBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_ABOVE 0x2 + +/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be + considered a Boolean toggle. Data less than or equal to zero should + be considered `off' or `false,' and data above zero should be + considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in + conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or + LADSPA_HINT_DEFAULT_1. */ +#define LADSPA_HINT_TOGGLED 0x4 + +/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified + should be interpreted as multiples of the sample rate. For + instance, a frequency range from 0Hz to the Nyquist frequency (half + the sample rate) could be requested by this hint in conjunction + with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds + at all must support this hint to retain meaning. */ +#define LADSPA_HINT_SAMPLE_RATE 0x8 + +/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the + user will find it more intuitive to view values using a logarithmic + scale. This is particularly useful for frequencies and gains. */ +#define LADSPA_HINT_LOGARITHMIC 0x10 + +/* Hint LADSPA_HINT_INTEGER indicates that a user interface would + probably wish to provide a stepped control taking only integer + values. Any bounds set should be slightly wider than the actual + integer range required to avoid floating point rounding errors. For + instance, the integer set {0,1,2,3} might be described as [-0.1, + 3.1]. */ +#define LADSPA_HINT_INTEGER 0x20 + +/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal' + value for the port that is sensible as a default. For instance, + this value is suitable for use as an initial value in a user + interface or as a value the host might assign to a control port + when the user has not provided one. Defaults are encoded using a + mask so only one default may be specified for a port. Some of the + hints make use of lower and upper bounds, in which case the + relevant bound or bounds must be available and + LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting + default must be rounded if LADSPA_HINT_INTEGER is present. Default + values were introduced in LADSPA v1.1. */ +#define LADSPA_HINT_DEFAULT_MASK 0x3C0 + +/* This default values indicates that no default is provided. */ +#define LADSPA_HINT_DEFAULT_NONE 0x0 + +/* This default hint indicates that the suggested lower bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MINIMUM 0x40 + +/* This default hint indicates that a low value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 + + log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper + * 0.25). */ +#define LADSPA_HINT_DEFAULT_LOW 0x80 + +/* This default hint indicates that a middle value between the + suggested lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 + + log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper * + 0.5). */ +#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0 + +/* This default hint indicates that a high value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 + + log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper + * 0.75). */ +#define LADSPA_HINT_DEFAULT_HIGH 0x100 + +/* This default hint indicates that the suggested upper bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140 + +/* This default hint indicates that the number 0 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_0 0x200 + +/* This default hint indicates that the number 1 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_1 0x240 + +/* This default hint indicates that the number 100 should be used. */ +#define LADSPA_HINT_DEFAULT_100 0x280 + +/* This default hint indicates that the Hz frequency of `concert A' + should be used. This will be 440 unless the host uses an unusual + tuning convention, in which case it may be within a few Hz. */ +#define LADSPA_HINT_DEFAULT_440 0x2C0 + +#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW) +#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE) +#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED) +#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE) +#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC) +#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER) + +#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK) +#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MINIMUM) +#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_LOW) +#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MIDDLE) +#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_HIGH) +#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MAXIMUM) +#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_0) +#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_1) +#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_100) +#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_440) + +typedef struct _LADSPA_PortRangeHint { + + /* Hints about the port. */ + LADSPA_PortRangeHintDescriptor HintDescriptor; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data LowerBound; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data UpperBound; + +} LADSPA_PortRangeHint; + +/*****************************************************************************/ + +/* Plugin Handles: + + This plugin handle indicates a particular instance of the plugin + concerned. It is valid to compare this to NULL (0 for C++) but + otherwise the host should not attempt to interpret it. The plugin + may use it to reference internal instance data. */ + +typedef void * LADSPA_Handle; + +/*****************************************************************************/ + +/* Descriptor for a Type of Plugin: + + This structure is used to describe a plugin type. It provides a + number of functions to examine the type, instantiate it, link it to + buffers and workspaces and to run it. */ + +typedef struct _LADSPA_Descriptor { + + /* This numeric identifier indicates the plugin type + uniquely. Plugin programmers may reserve ranges of IDs from a + central body to avoid clashes. Hosts may assume that IDs are + below 0x1000000. */ + unsigned long UniqueID; + + /* This identifier can be used as a unique, case-sensitive + identifier for the plugin type within the plugin file. Plugin + types should be identified by file and label rather than by index + or plugin name, which may be changed in new plugin + versions. Labels must not contain white-space characters. */ + const char * Label; + + /* This indicates a number of properties of the plugin. */ + LADSPA_Properties Properties; + + /* This member points to the null-terminated name of the plugin + (e.g. "Sine Oscillator"). */ + const char * Name; + + /* This member points to the null-terminated string indicating the + maker of the plugin. This can be an empty string but not NULL. */ + const char * Maker; + + /* This member points to the null-terminated string indicating any + copyright applying to the plugin. If no Copyright applies the + string "None" should be used. */ + const char * Copyright; + + /* This indicates the number of ports (input AND output) present on + the plugin. */ + unsigned long PortCount; + + /* This member indicates an array of port descriptors. Valid indices + vary from 0 to PortCount-1. */ + const LADSPA_PortDescriptor * PortDescriptors; + + /* This member indicates an array of null-terminated strings + describing ports (e.g. "Frequency (Hz)"). Valid indices vary from + 0 to PortCount-1. */ + const char * const * PortNames; + + /* This member indicates an array of range hints for each port (see + above). Valid indices vary from 0 to PortCount-1. */ + const LADSPA_PortRangeHint * PortRangeHints; + + /* This may be used by the plugin developer to pass any custom + implementation data into an instantiate call. It must not be used + or interpreted by the host. It is expected that most plugin + writers will not use this facility as LADSPA_Handle should be + used to hold instance data. */ + void * ImplementationData; + + /* This member is a function pointer that instantiates a plugin. A + handle is returned indicating the new plugin instance. The + instantiation function accepts a sample rate as a parameter. The + plugin descriptor from which this instantiate function was found + must also be passed. This function must return NULL if + instantiation fails. + + Note that instance initialisation should generally occur in + activate() rather than here. */ + LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, + unsigned long SampleRate); + + /* This member is a function pointer that connects a port on an + instantiated plugin to a memory location at which a block of data + for the port will be read/written. The data location is expected + to be an array of LADSPA_Data for audio ports or a single + LADSPA_Data value for control ports. Memory issues will be + managed by the host. The plugin must read/write the data at these + locations every time run() or run_adding() is called and the data + present at the time of this connection call should not be + considered meaningful. + + connect_port() may be called more than once for a plugin instance + to allow the host to change the buffers that the plugin is + reading or writing. These calls may be made before or after + activate() or deactivate() calls. + + connect_port() must be called at least once for each port before + run() or run_adding() is called. When working with blocks of + LADSPA_Data the plugin should pay careful attention to the block + size passed to the run function as the block allocated may only + just be large enough to contain the block of samples. + + Plugin writers should be aware that the host may elect to use the + same buffer for more than one port and even use the same buffer + for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). + However, overlapped buffers or use of a single buffer for both + audio and control data may result in unexpected behaviour. */ + void (*connect_port)(LADSPA_Handle Instance, + unsigned long Port, + LADSPA_Data * DataLocation); + + /* This member is a function pointer that initialises a plugin + instance and activates it for use. This is separated from + instantiate() to aid real-time support and so that hosts can + reinitialise a plugin instance by calling deactivate() and then + activate(). In this case the plugin instance must reset all state + information dependent on the history of the plugin instance + except for any data locations provided by connect_port() and any + gain set by set_run_adding_gain(). If there is nothing for + activate() to do then the plugin writer may provide a NULL rather + than an empty function. + + When present, hosts must call this function once before run() (or + run_adding()) is called for the first time. This call should be + made as close to the run() call as possible and indicates to + real-time plugins that they are now live. Plugins should not rely + on a prompt call to run() after activate(). activate() may not be + called again unless deactivate() is called first. Note that + connect_port() may be called before or after a call to + activate(). */ + void (*activate)(LADSPA_Handle Instance); + + /* This method is a function pointer that runs an instance of a + plugin for a block. Two parameters are required: the first is a + handle to the particular instance to be run and the second + indicates the block size (in samples) for which the plugin + instance may run. + + Note that if an activate() function exists then it must be called + before run() or run_adding(). If deactivate() is called for a + plugin instance then the plugin instance may not be reused until + activate() has been called again. + + If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE + then there are various things that the plugin should not do + within the run() or run_adding() functions (see above). */ + void (*run)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that runs an instance of a + plugin for a block. This has identical behaviour to run() except + in the way data is output from the plugin. When run() is used, + values are written directly to the memory areas associated with + the output ports. However when run_adding() is called, values + must be added to the values already present in the memory + areas. Furthermore, output values written must be scaled by the + current gain set by set_run_adding_gain() (see below) before + addition. + + run_adding() is optional. When it is not provided by a plugin, + this function pointer must be set to NULL. When it is provided, + the function set_run_adding_gain() must be provided also. */ + void (*run_adding)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that sets the output gain for + use when run_adding() is called (see above). If this function is + never called the gain is assumed to default to 1. Gain + information should be retained when activate() or deactivate() + are called. + + This function should be provided by the plugin if and only if the + run_adding() function is provided. When it is absent this + function pointer must be set to NULL. */ + void (*set_run_adding_gain)(LADSPA_Handle Instance, + LADSPA_Data Gain); + + /* This is the counterpart to activate() (see above). If there is + nothing for deactivate() to do then the plugin writer may provide + a NULL rather than an empty function. + + Hosts must deactivate all activated units after they have been + run() (or run_adding()) for the last time. This call should be + made as close to the last run() call as possible and indicates to + real-time plugins that they are no longer live. Plugins should + not rely on prompt deactivation. Note that connect_port() may be + called before or after a call to deactivate(). + + Deactivation is not similar to pausing as the plugin instance + will be reinitialised when activate() is called to reuse it. */ + void (*deactivate)(LADSPA_Handle Instance); + + /* Once an instance of a plugin has been finished with it can be + deleted using the following function. The instance handle passed + ceases to be valid after this call. + + If activate() was called for a plugin instance then a + corresponding call to deactivate() must be made before cleanup() + is called. */ + void (*cleanup)(LADSPA_Handle Instance); + +} LADSPA_Descriptor; + +/**********************************************************************/ + +/* Accessing a Plugin: */ + +/* The exact mechanism by which plugins are loaded is host-dependent, + however all most hosts will need to know is the name of shared + object file containing the plugin types. To allow multiple hosts to + share plugin types, hosts may wish to check for environment + variable LADSPA_PATH. If present, this should contain a + colon-separated path indicating directories that should be searched + (in order) when loading plugin types. + + A plugin programmer must include a function called + "ladspa_descriptor" with the following function prototype within + the shared object file. This function will have C-style linkage (if + you are using C++ this is taken care of by the `extern "C"' clause + at the top of the file). + + A host will find the plugin shared object file by one means or + another, find the ladspa_descriptor() function, call it, and + proceed from there. + + Plugin types are accessed by index (not ID) using values from 0 + upwards. Out of range indexes must result in this function + returning NULL, so the plugin count can be determined by checking + for the least index that results in NULL being returned. */ + +LADSPA_PLUGIN_EXPORT const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); + +/* Datatype corresponding to the ladspa_descriptor() function. */ +typedef const LADSPA_Descriptor * +(*LADSPA_Descriptor_Function)(unsigned long Index); + +/**********************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* LADSPA_INCLUDED */ + +/* EOF */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/atom-forge.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/atom-forge.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,710 @@ +/* + Copyright 2008-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file forge.h An API for constructing LV2 atoms. + + This file provides an API for constructing Atoms which makes it relatively + simple to build nested atoms of arbitrary complexity without requiring + dynamic memory allocation. + + The API is based on successively appending the appropriate pieces to build a + complete Atom. The size of containers is automatically updated. Functions + that begin a container return (via their frame argument) a stack frame which + must be popped when the container is finished. + + All output is written to a user-provided buffer or sink function. This + makes it popssible to create create atoms on the stack, on the heap, in LV2 + port buffers, in a ringbuffer, or elsewhere, all using the same API. + + This entire API is realtime safe if used with a buffer or a realtime safe + sink, except lv2_atom_forge_init() which is only realtime safe if the URI + map function is. + + Note these functions are all static inline, do not take their address. + + This header is non-normative, it is provided for convenience. +*/ + +/** + @defgroup forge Forge + @ingroup atom + @{ +*/ + +#ifndef LV2_ATOM_FORGE_H +#define LV2_ATOM_FORGE_H + +#include + +#include "atom.h" +#include "atom-util.h" +#include "urid.h" + +#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define LV2_ATOM_FORGE_DEPRECATED __attribute__((__deprecated__)) +#else +# define LV2_ATOM_FORGE_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#else +# include +#endif + +// Disable deprecation warnings for Blank and Resource +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +/** Handle for LV2_Atom_Forge_Sink. */ +typedef void* LV2_Atom_Forge_Sink_Handle; + +/** A reference to a chunk of written output. */ +typedef intptr_t LV2_Atom_Forge_Ref; + +/** Sink function for writing output. See lv2_atom_forge_set_sink(). */ +typedef LV2_Atom_Forge_Ref +(*LV2_Atom_Forge_Sink)(LV2_Atom_Forge_Sink_Handle handle, + const void* buf, + uint32_t size); + +/** Function for resolving a reference. See lv2_atom_forge_set_sink(). */ +typedef LV2_Atom* +(*LV2_Atom_Forge_Deref_Func)(LV2_Atom_Forge_Sink_Handle handle, + LV2_Atom_Forge_Ref ref); + +/** A stack frame used for keeping track of nested Atom containers. */ +typedef struct _LV2_Atom_Forge_Frame { + struct _LV2_Atom_Forge_Frame* parent; + LV2_Atom_Forge_Ref ref; +} LV2_Atom_Forge_Frame; + +/** A "forge" for creating atoms by appending to a buffer. */ +typedef struct { + uint8_t* buf; + uint32_t offset; + uint32_t size; + + LV2_Atom_Forge_Sink sink; + LV2_Atom_Forge_Deref_Func deref; + LV2_Atom_Forge_Sink_Handle handle; + + LV2_Atom_Forge_Frame* stack; + + LV2_URID Blank LV2_ATOM_FORGE_DEPRECATED; + LV2_URID Bool; + LV2_URID Chunk; + LV2_URID Double; + LV2_URID Float; + LV2_URID Int; + LV2_URID Long; + LV2_URID Literal; + LV2_URID Object; + LV2_URID Path; + LV2_URID Property; + LV2_URID Resource LV2_ATOM_FORGE_DEPRECATED; + LV2_URID Sequence; + LV2_URID String; + LV2_URID Tuple; + LV2_URID URI; + LV2_URID URID; + LV2_URID Vector; +} LV2_Atom_Forge; + +static inline void +lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size); + +/** + Initialise `forge`. + + URIs will be mapped using `map` and stored, a reference to `map` itself is + not held. +*/ +static inline void +lv2_atom_forge_init(LV2_Atom_Forge* forge, const LV2_URID_Map* map) +{ + lv2_atom_forge_set_buffer(forge, NULL, 0); + forge->Blank = map->map(map->handle, LV2_ATOM__Blank); + forge->Bool = map->map(map->handle, LV2_ATOM__Bool); + forge->Chunk = map->map(map->handle, LV2_ATOM__Chunk); + forge->Double = map->map(map->handle, LV2_ATOM__Double); + forge->Float = map->map(map->handle, LV2_ATOM__Float); + forge->Int = map->map(map->handle, LV2_ATOM__Int); + forge->Long = map->map(map->handle, LV2_ATOM__Long); + forge->Literal = map->map(map->handle, LV2_ATOM__Literal); + forge->Object = map->map(map->handle, LV2_ATOM__Object); + forge->Path = map->map(map->handle, LV2_ATOM__Path); + forge->Property = map->map(map->handle, LV2_ATOM__Property); + forge->Resource = map->map(map->handle, LV2_ATOM__Resource); + forge->Sequence = map->map(map->handle, LV2_ATOM__Sequence); + forge->String = map->map(map->handle, LV2_ATOM__String); + forge->Tuple = map->map(map->handle, LV2_ATOM__Tuple); + forge->URI = map->map(map->handle, LV2_ATOM__URI); + forge->URID = map->map(map->handle, LV2_ATOM__URID); + forge->Vector = map->map(map->handle, LV2_ATOM__Vector); +} + +/** Access the Atom pointed to by a reference. */ +static inline LV2_Atom* +lv2_atom_forge_deref(LV2_Atom_Forge* forge, LV2_Atom_Forge_Ref ref) +{ + if (forge->buf) { + return (LV2_Atom*)ref; + } else { + return forge->deref(forge->handle, ref); + } +} + +/** + @name Object Stack + @{ +*/ + +/** + Push a stack frame. + This is done automatically by container functions (which take a stack frame + pointer), but may be called by the user to push the top level container when + writing to an existing Atom. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_push(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + LV2_Atom_Forge_Ref ref) +{ + frame->parent = forge->stack; + frame->ref = ref; + forge->stack = frame; + return ref; +} + +/** Pop a stack frame. This must be called when a container is finished. */ +static inline void +lv2_atom_forge_pop(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) +{ + assert(frame == forge->stack); + forge->stack = frame->parent; +} + +/** Return true iff the top of the stack has the given type. */ +static inline bool +lv2_atom_forge_top_is(LV2_Atom_Forge* forge, uint32_t type) +{ + return forge->stack && forge->stack->ref && + (lv2_atom_forge_deref(forge, forge->stack->ref)->type == type); +} + +/** Return true iff `type` is an atom:Object. */ +static inline bool +lv2_atom_forge_is_object_type(const LV2_Atom_Forge* forge, uint32_t type) +{ + return (type == forge->Object || + type == forge->Blank || + type == forge->Resource); +} + +/** Return true iff `type` is an atom:Object with a blank ID. */ +static inline bool +lv2_atom_forge_is_blank(const LV2_Atom_Forge* forge, + uint32_t type, + const LV2_Atom_Object_Body* body) +{ + return (type == forge->Blank || + (type == forge->Object && body->id == 0)); +} + +/** + @} + @name Output Configuration + @{ +*/ + +/** Set the output buffer where `forge` will write atoms. */ +static inline void +lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size) +{ + forge->buf = buf; + forge->size = (uint32_t)size; + forge->offset = 0; + forge->deref = NULL; + forge->sink = NULL; + forge->handle = NULL; + forge->stack = NULL; +} + +/** + Set the sink function where `forge` will write output. + + The return value of forge functions is an LV2_Atom_Forge_Ref which is an + integer type safe to use as a pointer but is otherwise opaque. The sink + function must return a ref that can be dereferenced to access as least + sizeof(LV2_Atom) bytes of the written data, so sizes can be updated. For + ringbuffers, this should be possible as long as the size of the buffer is a + multiple of sizeof(LV2_Atom), since atoms are always aligned. + + Note that 0 is an invalid reference, so if you are using a buffer offset be + sure to offset it such that 0 is never a valid reference. You will get + confusing errors otherwise. +*/ +static inline void +lv2_atom_forge_set_sink(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Sink sink, + LV2_Atom_Forge_Deref_Func deref, + LV2_Atom_Forge_Sink_Handle handle) +{ + forge->buf = NULL; + forge->size = forge->offset = 0; + forge->deref = deref; + forge->sink = sink; + forge->handle = handle; + forge->stack = NULL; +} + +/** + @} + @name Low Level Output + @{ +*/ + +/** + Write raw output. This is used internally, but is also useful for writing + atom types not explicitly supported by the forge API. Note the caller is + responsible for ensuring the output is approriately padded. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size) +{ + LV2_Atom_Forge_Ref out = 0; + if (forge->sink) { + out = forge->sink(forge->handle, data, size); + } else { + out = (LV2_Atom_Forge_Ref)forge->buf + (LV2_Atom_Forge_Ref)forge->offset; + uint8_t* mem = forge->buf + forge->offset; + if (forge->offset + size > forge->size) { + return 0; + } + forge->offset += size; + memcpy(mem, data, size); + } + for (LV2_Atom_Forge_Frame* f = forge->stack; f; f = f->parent) { + lv2_atom_forge_deref(forge, f->ref)->size += size; + } + return out; +} + +/** Pad output accordingly so next write is 64-bit aligned. */ +static inline void +lv2_atom_forge_pad(LV2_Atom_Forge* forge, uint32_t written) +{ + const uint64_t pad = 0; + const uint32_t pad_size = lv2_atom_pad_size(written) - written; + lv2_atom_forge_raw(forge, &pad, pad_size); +} + +/** Write raw output, padding to 64-bits as necessary. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_write(LV2_Atom_Forge* forge, const void* data, uint32_t size) +{ + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, data, size); + if (out) { + lv2_atom_forge_pad(forge, size); + } + return out; +} + +/** Write a null-terminated string body. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_string_body(LV2_Atom_Forge* forge, + const char* str, + uint32_t len) +{ + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, str, len); + if (out && (out = lv2_atom_forge_raw(forge, "", 1))) { + lv2_atom_forge_pad(forge, len + 1); + } + return out; +} + +/** + @} + @name Atom Output + @{ +*/ + +/** Write an atom:Atom header. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_atom(LV2_Atom_Forge* forge, uint32_t size, uint32_t type) +{ + const LV2_Atom a = { size, type }; + return lv2_atom_forge_raw(forge, &a, sizeof(a)); +} + +/** Write a primitive (fixed-size) atom. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_primitive(LV2_Atom_Forge* forge, const LV2_Atom* a) +{ + if (lv2_atom_forge_top_is(forge, forge->Vector)) { + return lv2_atom_forge_raw(forge, LV2_ATOM_BODY_CONST(a), a->size); + } else { + return lv2_atom_forge_write( + forge, a, (uint32_t)sizeof(LV2_Atom) + a->size); + } +} + +/** Write an atom:Int. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_int(LV2_Atom_Forge* forge, int32_t val) +{ + const LV2_Atom_Int a = { { sizeof(val), forge->Int }, val }; + return lv2_atom_forge_primitive(forge, &a.atom); +} + +/** Write an atom:Long. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_long(LV2_Atom_Forge* forge, int64_t val) +{ + const LV2_Atom_Long a = { { sizeof(val), forge->Long }, val }; + return lv2_atom_forge_primitive(forge, &a.atom); +} + +/** Write an atom:Float. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_float(LV2_Atom_Forge* forge, float val) +{ + const LV2_Atom_Float a = { { sizeof(val), forge->Float }, val }; + return lv2_atom_forge_primitive(forge, &a.atom); +} + +/** Write an atom:Double. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_double(LV2_Atom_Forge* forge, double val) +{ + const LV2_Atom_Double a = { { sizeof(val), forge->Double }, val }; + return lv2_atom_forge_primitive(forge, &a.atom); +} + +/** Write an atom:Bool. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_bool(LV2_Atom_Forge* forge, bool val) +{ + const LV2_Atom_Bool a = { { sizeof(int32_t), forge->Bool }, val ? 1 : 0 }; + return lv2_atom_forge_primitive(forge, &a.atom); +} + +/** Write an atom:URID. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_urid(LV2_Atom_Forge* forge, LV2_URID id) +{ + const LV2_Atom_URID a = { { sizeof(id), forge->URID }, id }; + return lv2_atom_forge_primitive(forge, &a.atom); +} + +/** Write an atom compatible with atom:String. Used internally. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_typed_string(LV2_Atom_Forge* forge, + uint32_t type, + const char* str, + uint32_t len) +{ + const LV2_Atom_String a = { { len + 1, type } }; + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a)); + if (out) { + if (!lv2_atom_forge_string_body(forge, str, len)) { + LV2_Atom* atom = lv2_atom_forge_deref(forge, out); + atom->size = atom->type = 0; + out = 0; + } + } + return out; +} + +/** Write an atom:String. Note that `str` need not be NULL terminated. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_string(LV2_Atom_Forge* forge, const char* str, uint32_t len) +{ + return lv2_atom_forge_typed_string(forge, forge->String, str, len); +} + +/** + Write an atom:URI. Note that `uri` need not be NULL terminated. + This does not map the URI, but writes the complete URI string. To write + a mapped URI, use lv2_atom_forge_urid(). +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_uri(LV2_Atom_Forge* forge, const char* uri, uint32_t len) +{ + return lv2_atom_forge_typed_string(forge, forge->URI, uri, len); +} + +/** Write an atom:Path. Note that `path` need not be NULL terminated. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_path(LV2_Atom_Forge* forge, const char* path, uint32_t len) +{ + return lv2_atom_forge_typed_string(forge, forge->Path, path, len); +} + +/** Write an atom:Literal. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_literal(LV2_Atom_Forge* forge, + const char* str, + uint32_t len, + uint32_t datatype, + uint32_t lang) +{ + const LV2_Atom_Literal a = { + { (uint32_t)(sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1), + forge->Literal }, + { datatype, + lang } + }; + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a)); + if (out) { + if (!lv2_atom_forge_string_body(forge, str, len)) { + LV2_Atom* atom = lv2_atom_forge_deref(forge, out); + atom->size = atom->type = 0; + out = 0; + } + } + return out; +} + +/** Start an atom:Vector. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_vector_head(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + uint32_t child_size, + uint32_t child_type) +{ + const LV2_Atom_Vector a = { + { sizeof(LV2_Atom_Vector_Body), forge->Vector }, + { child_size, child_type } + }; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** Write a complete atom:Vector. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_vector(LV2_Atom_Forge* forge, + uint32_t child_size, + uint32_t child_type, + uint32_t n_elems, + const void* elems) +{ + const LV2_Atom_Vector a = { + { (uint32_t)(sizeof(LV2_Atom_Vector_Body) + n_elems * child_size), + forge->Vector }, + { child_size, child_type } + }; + LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); + if (out) { + lv2_atom_forge_write(forge, elems, child_size * n_elems); + } + return out; +} + +/** + Write the header of an atom:Tuple. + + The passed frame will be initialised to represent this tuple. To complete + the tuple, write a sequence of atoms, then pop the frame with + lv2_atom_forge_pop(). + + For example: + @code + // Write tuple (1, 2.0) + LV2_Atom_Forge_Frame frame; + LV2_Atom* tup = (LV2_Atom*)lv2_atom_forge_tuple(forge, &frame); + lv2_atom_forge_int32(forge, 1); + lv2_atom_forge_float(forge, 2.0); + lv2_atom_forge_pop(forge, &frame); + @endcode +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) +{ + const LV2_Atom_Tuple a = { { 0, forge->Tuple } }; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + Write the header of an atom:Object. + + The passed frame will be initialised to represent this object. To complete + the object, write a sequence of properties, then pop the frame with + lv2_atom_forge_pop(). + + For example: + @code + LV2_URID eg_Cat = map("http://example.org/Cat"); + LV2_URID eg_name = map("http://example.org/name"); + + // Start object with type eg_Cat and blank ID + LV2_Atom_Forge_Frame frame; + lv2_atom_forge_object(forge, &frame, 0, eg_Cat); + + // Append property eg:name = "Hobbes" + lv2_atom_forge_key(forge, eg_name); + lv2_atom_forge_string(forge, "Hobbes", strlen("Hobbes")); + + // Finish object + lv2_atom_forge_pop(forge, &frame); + @endcode +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_object(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + LV2_URID id, + LV2_URID otype) +{ + const LV2_Atom_Object a = { + { (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Object }, + { id, otype } + }; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + The same as lv2_atom_forge_object(), but for object:Resource. + + This function is deprecated and should not be used in new code. + Use lv2_atom_forge_object() directly instead. +*/ +LV2_ATOM_FORGE_DEPRECATED +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_resource(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + LV2_URID id, + LV2_URID otype) +{ + const LV2_Atom_Object a = { + { (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Resource }, + { id, otype } + }; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + The same as lv2_atom_forge_object(), but for object:Blank. + + This function is deprecated and should not be used in new code. + Use lv2_atom_forge_object() directly instead. +*/ +LV2_ATOM_FORGE_DEPRECATED +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_blank(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + uint32_t id, + LV2_URID otype) +{ + const LV2_Atom_Object a = { + { (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Blank }, + { id, otype } + }; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + Write a property key in an Object, to be followed by the value. + + See lv2_atom_forge_object() documentation for an example. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_key(LV2_Atom_Forge* forge, + LV2_URID key) +{ + const LV2_Atom_Property_Body a = { key, 0, { 0, 0 } }; + return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t)); +} + +/** + Write the header for a property body in an object, with context. + + If you do not need the context, which is almost certainly the case, + use the simpler lv2_atom_forge_key() instead. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_property_head(LV2_Atom_Forge* forge, + LV2_URID key, + LV2_URID context) +{ + const LV2_Atom_Property_Body a = { key, context, { 0, 0 } }; + return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t)); +} + +/** + Write the header for a Sequence. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + uint32_t unit) +{ + const LV2_Atom_Sequence a = { + { (uint32_t)sizeof(LV2_Atom_Sequence_Body), forge->Sequence }, + { unit, 0 } + }; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + Write the time stamp header of an Event (in a Sequence) in audio frames. + After this, call the appropriate forge method(s) to write the body. Note + the returned reference is to an LV2_Event which is NOT an Atom. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames) +{ + return lv2_atom_forge_write(forge, &frames, sizeof(frames)); +} + +/** + Write the time stamp header of an Event (in a Sequence) in beats. After + this, call the appropriate forge method(s) to write the body. Note the + returned reference is to an LV2_Event which is NOT an Atom. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats) +{ + return lv2_atom_forge_write(forge, &beats, sizeof(beats)); +} + +/** + @} + @} +*/ + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic pop +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_ATOM_FORGE_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/atom-util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/atom-util.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,518 @@ +/* + Copyright 2008-2015 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file util.h Helper functions for the LV2 Atom extension. + + Note these functions are all static inline, do not take their address. + + This header is non-normative, it is provided for convenience. +*/ + +/** + @defgroup util Utilities + @ingroup atom + @{ +*/ + +#ifndef LV2_ATOM_UTIL_H +#define LV2_ATOM_UTIL_H + +#include +#include +#include + +#include "atom.h" + +#ifdef __cplusplus +extern "C" { +#else +# include +#endif + +/** Pad a size to 64 bits. */ +static inline uint32_t +lv2_atom_pad_size(uint32_t size) +{ + return (size + 7U) & (~7U); +} + +/** Return the total size of `atom`, including the header. */ +static inline uint32_t +lv2_atom_total_size(const LV2_Atom* atom) +{ + return (uint32_t)sizeof(LV2_Atom) + atom->size; +} + +/** Return true iff `atom` is null. */ +static inline bool +lv2_atom_is_null(const LV2_Atom* atom) +{ + return !atom || (atom->type == 0 && atom->size == 0); +} + +/** Return true iff `a` is equal to `b`. */ +static inline bool +lv2_atom_equals(const LV2_Atom* a, const LV2_Atom* b) +{ + return (a == b) || ((a->type == b->type) && + (a->size == b->size) && + !memcmp(a + 1, b + 1, a->size)); +} + +/** + @name Sequence Iterator + @{ +*/ + +/** Get an iterator pointing to the first event in a Sequence body. */ +static inline const LV2_Atom_Event* +lv2_atom_sequence_begin(const LV2_Atom_Sequence_Body* body) +{ + return (const LV2_Atom_Event*)(body + 1); +} + +/** Get an iterator pointing to the end of a Sequence body. */ +static inline const LV2_Atom_Event* +lv2_atom_sequence_end(const LV2_Atom_Sequence_Body* body, uint32_t size) +{ + return (const LV2_Atom_Event*)((const uint8_t*)body + lv2_atom_pad_size(size)); +} + +/** Get an iterator pointing to the end of a Sequence body. */ +static inline LV2_Atom_Event* +lv2_atom_sequence_end2(LV2_Atom_Sequence_Body* body, uint32_t size) +{ + return (LV2_Atom_Event*)((uint8_t*)body + lv2_atom_pad_size(size)); +} + +/** Return true iff `i` has reached the end of `body`. */ +static inline bool +lv2_atom_sequence_is_end(const LV2_Atom_Sequence_Body* body, + uint32_t size, + const LV2_Atom_Event* i) +{ + return (const uint8_t*)i >= ((const uint8_t*)body + size); +} + +/** Return an iterator to the element following `i`. */ +static inline const LV2_Atom_Event* +lv2_atom_sequence_next(const LV2_Atom_Event* i) +{ + return (const LV2_Atom_Event*)((const uint8_t*)i + + sizeof(LV2_Atom_Event) + + lv2_atom_pad_size(i->body.size)); +} + +/** + A macro for iterating over all events in a Sequence. + @param seq The sequence to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), e.g.: + @code + LV2_ATOM_SEQUENCE_FOREACH(sequence, ev) { + // Do something with ev (an LV2_Atom_Event*) here... + } + @endcode +*/ +#define LV2_ATOM_SEQUENCE_FOREACH(seq, iter) \ + for (const LV2_Atom_Event* iter = lv2_atom_sequence_begin(&(seq)->body); \ + !lv2_atom_sequence_is_end(&(seq)->body, (seq)->atom.size, (iter)); \ + iter = lv2_atom_sequence_next(iter)) + +/** Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. */ +#define LV2_ATOM_SEQUENCE_BODY_FOREACH(body, size, iter) \ + for (const LV2_Atom_Event* iter = lv2_atom_sequence_begin(body); \ + !lv2_atom_sequence_is_end(body, size, (iter)); \ + iter = lv2_atom_sequence_next(iter)) + +/** + @} + @name Sequence Utilities + @{ +*/ + +/** + Clear all events from `sequence`. + + This simply resets the size field, the other fields are left untouched. +*/ +static inline void +lv2_atom_sequence_clear(LV2_Atom_Sequence* seq) +{ + seq->atom.size = sizeof(LV2_Atom_Sequence_Body); +} + +/** + Append an event at the end of `sequence`. + + @param seq Sequence to append to. + @param capacity Total capacity of the sequence atom + (e.g. as set by the host for sequence output ports). + @param event Event to write. + + @return A pointer to the newly written event in `seq`, + or NULL on failure (insufficient space). +*/ +static inline LV2_Atom_Event* +lv2_atom_sequence_append_event(LV2_Atom_Sequence* seq, + uint32_t capacity, + const LV2_Atom_Event* event) +{ + const uint32_t total_size = (uint32_t)sizeof(*event) + event->body.size; + if (capacity - seq->atom.size < total_size) { + return NULL; + } + + LV2_Atom_Event* e = lv2_atom_sequence_end2(&seq->body, seq->atom.size); + memcpy(e, event, total_size); + + seq->atom.size += lv2_atom_pad_size(total_size); + + return e; +} + +/** + @} + @name Tuple Iterator + @{ +*/ + +/** Get an iterator pointing to the first element in `tup`. */ +static inline const LV2_Atom* +lv2_atom_tuple_begin(const LV2_Atom_Tuple* tup) +{ + return (const LV2_Atom*)(LV2_ATOM_BODY_CONST(tup)); +} + +/** Return true iff `i` has reached the end of `body`. */ +static inline bool +lv2_atom_tuple_is_end(const void* body, uint32_t size, const LV2_Atom* i) +{ + return (const uint8_t*)i >= ((const uint8_t*)body + size); +} + +/** Return an iterator to the element following `i`. */ +static inline const LV2_Atom* +lv2_atom_tuple_next(const LV2_Atom* i) +{ + return (const LV2_Atom*)( + (const uint8_t*)i + sizeof(LV2_Atom) + lv2_atom_pad_size(i->size)); +} + +/** + A macro for iterating over all properties of a Tuple. + @param tuple The tuple to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), e.g.: + @code + LV2_ATOM_TUPLE_FOREACH(tuple, elem) { + // Do something with elem (an LV2_Atom*) here... + } + @endcode +*/ +#define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \ + for (const LV2_Atom* iter = lv2_atom_tuple_begin(tuple); \ + !lv2_atom_tuple_is_end(LV2_ATOM_BODY_CONST(tuple), (tuple)->atom.size, (iter)); \ + iter = lv2_atom_tuple_next(iter)) + +/** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */ +#define LV2_ATOM_TUPLE_BODY_FOREACH(body, size, iter) \ + for (const LV2_Atom* iter = (const LV2_Atom*)body; \ + !lv2_atom_tuple_is_end(body, size, (iter)); \ + iter = lv2_atom_tuple_next(iter)) + +/** + @} + @name Object Iterator + @{ +*/ + +/** Return a pointer to the first property in `body`. */ +static inline const LV2_Atom_Property_Body* +lv2_atom_object_begin(const LV2_Atom_Object_Body* body) +{ + return (const LV2_Atom_Property_Body*)(body + 1); +} + +/** Return true iff `i` has reached the end of `obj`. */ +static inline bool +lv2_atom_object_is_end(const LV2_Atom_Object_Body* body, + uint32_t size, + const LV2_Atom_Property_Body* i) +{ + return (const uint8_t*)i >= ((const uint8_t*)body + size); +} + +/** Return an iterator to the property following `i`. */ +static inline const LV2_Atom_Property_Body* +lv2_atom_object_next(const LV2_Atom_Property_Body* i) +{ + const LV2_Atom* const value = (const LV2_Atom*)( + (const uint8_t*)i + 2 * sizeof(uint32_t)); + return (const LV2_Atom_Property_Body*)( + (const uint8_t*)i + lv2_atom_pad_size( + (uint32_t)sizeof(LV2_Atom_Property_Body) + value->size)); +} + +/** + A macro for iterating over all properties of an Object. + @param obj The object to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), e.g.: + @code + LV2_ATOM_OBJECT_FOREACH(object, i) { + // Do something with prop (an LV2_Atom_Property_Body*) here... + } + @endcode +*/ +#define LV2_ATOM_OBJECT_FOREACH(obj, iter) \ + for (const LV2_Atom_Property_Body* iter = lv2_atom_object_begin(&(obj)->body); \ + !lv2_atom_object_is_end(&(obj)->body, (obj)->atom.size, (iter)); \ + iter = lv2_atom_object_next(iter)) + +/** Like LV2_ATOM_OBJECT_FOREACH but for a headerless object body. */ +#define LV2_ATOM_OBJECT_BODY_FOREACH(body, size, iter) \ + for (const LV2_Atom_Property_Body* iter = lv2_atom_object_begin(body); \ + !lv2_atom_object_is_end(body, size, (iter)); \ + iter = lv2_atom_object_next(iter)) + +/** + @} + @name Object Query + @{ +*/ + +/** A single entry in an Object query. */ +typedef struct { + uint32_t key; /**< Key to query (input set by user) */ + const LV2_Atom** value; /**< Found value (output set by query function) */ +} LV2_Atom_Object_Query; + +static const LV2_Atom_Object_Query LV2_ATOM_OBJECT_QUERY_END = { 0, NULL }; + +/** + Get an object's values for various keys. + + The value pointer of each item in `query` will be set to the location of + the corresponding value in `object`. Every value pointer in `query` MUST + be initialised to NULL. This function reads `object` in a single linear + sweep. By allocating `query` on the stack, objects can be "queried" + quickly without allocating any memory. This function is realtime safe. + + This function can only do "flat" queries, it is not smart enough to match + variables in nested objects. + + For example: + @code + const LV2_Atom* name = NULL; + const LV2_Atom* age = NULL; + LV2_Atom_Object_Query q[] = { + { urids.eg_name, &name }, + { urids.eg_age, &age }, + LV2_ATOM_OBJECT_QUERY_END + }; + lv2_atom_object_query(obj, q); + // name and age are now set to the appropriate values in obj, or NULL. + @endcode +*/ +static inline int +lv2_atom_object_query(const LV2_Atom_Object* object, + LV2_Atom_Object_Query* query) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of query keys so we can short-circuit when done */ + for (LV2_Atom_Object_Query* q = query; q->key; ++q) { + ++n_queries; + } + + LV2_ATOM_OBJECT_FOREACH(object, prop) { + for (LV2_Atom_Object_Query* q = query; q->key; ++q) { + if (q->key == prop->key && !*q->value) { + *q->value = &prop->value; + if (++matches == n_queries) { + return matches; + } + break; + } + } + } + return matches; +} + +/** + Body only version of lv2_atom_object_get(). +*/ +static inline int +lv2_atom_object_body_get(uint32_t size, const LV2_Atom_Object_Body* body, ...) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of keys so we can short-circuit when done */ + va_list args; + va_start(args, body); + for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { + if (!va_arg(args, const LV2_Atom**)) { + va_end(args); + return -1; + } + } + va_end(args); + + LV2_ATOM_OBJECT_BODY_FOREACH(body, size, prop) { + va_start(args, body); + for (int i = 0; i < n_queries; ++i) { + uint32_t qkey = va_arg(args, uint32_t); + const LV2_Atom** qval = va_arg(args, const LV2_Atom**); + if (qkey == prop->key && !*qval) { + *qval = &prop->value; + if (++matches == n_queries) { + va_end(args); + return matches; + } + break; + } + } + va_end(args); + } + return matches; +} + +/** + Variable argument version of lv2_atom_object_query(). + + This is nicer-looking in code, but a bit more error-prone since it is not + type safe and the argument list must be terminated. + + The arguments should be a series of uint32_t key and const LV2_Atom** value + pairs, terminated by a zero key. The value pointers MUST be initialized to + NULL. For example: + + @code + const LV2_Atom* name = NULL; + const LV2_Atom* age = NULL; + lv2_atom_object_get(obj, + uris.name_key, &name, + uris.age_key, &age, + 0); + @endcode +*/ +static inline int +lv2_atom_object_get(const LV2_Atom_Object* object, ...) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of keys so we can short-circuit when done */ + va_list args; + va_start(args, object); + for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { + if (!va_arg(args, const LV2_Atom**)) { + return -1; + } + } + va_end(args); + + LV2_ATOM_OBJECT_FOREACH(object, prop) { + va_start(args, object); + for (int i = 0; i < n_queries; ++i) { + uint32_t qkey = va_arg(args, uint32_t); + const LV2_Atom** qval = va_arg(args, const LV2_Atom**); + if (qkey == prop->key && !*qval) { + *qval = &prop->value; + if (++matches == n_queries) { + return matches; + } + break; + } + } + va_end(args); + } + return matches; +} + +/** + Variable argument version of lv2_atom_object_query() with types. + + This is like lv2_atom_object_get(), but each entry has an additional + parameter to specify the required type. Only atoms with a matching type + will be selected. + + The arguments should be a series of uint32_t key, const LV2_Atom**, uint32_t + type triples, terminated by a zero key. The value pointers MUST be + initialized to NULL. For example: + + @code + const LV2_Atom_String* name = NULL; + const LV2_Atom_Int* age = NULL; + lv2_atom_object_get(obj, + uris.name_key, &name, uris.atom_String, + uris.age_key, &age, uris.atom_Int + 0); + @endcode +*/ +static inline int +lv2_atom_object_get_typed(const LV2_Atom_Object* object, ...) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of keys so we can short-circuit when done */ + va_list args; + va_start(args, object); + for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { + if (!va_arg(args, const LV2_Atom**) || + !va_arg(args, uint32_t)) { + return -1; + } + } + va_end(args); + + LV2_ATOM_OBJECT_FOREACH(object, prop) { + va_start(args, object); + for (int i = 0; i < n_queries; ++i) { + const uint32_t qkey = va_arg(args, uint32_t); + const LV2_Atom** qval = va_arg(args, const LV2_Atom**); + const uint32_t qtype = va_arg(args, uint32_t); + if (!*qval && qkey == prop->key && qtype == prop->value.type) { + *qval = &prop->value; + if (++matches == n_queries) { + return matches; + } + break; + } + } + va_end(args); + } + return matches; +} + +/** + @} + @} +*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_ATOM_UTIL_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/atom.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/atom.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,256 @@ +/* + Copyright 2008-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup atom Atom + + A generic value container and several data types, see + for details. + + @{ +*/ + +#ifndef LV2_ATOM_H +#define LV2_ATOM_H + +#include +#include + +#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom" ///< http://lv2plug.in/ns/ext/atom +#define LV2_ATOM_PREFIX LV2_ATOM_URI "#" ///< http://lv2plug.in/ns/ext/atom# + +#define LV2_ATOM__Atom LV2_ATOM_PREFIX "Atom" ///< http://lv2plug.in/ns/ext/atom#Atom +#define LV2_ATOM__AtomPort LV2_ATOM_PREFIX "AtomPort" ///< http://lv2plug.in/ns/ext/atom#AtomPort +#define LV2_ATOM__Blank LV2_ATOM_PREFIX "Blank" ///< http://lv2plug.in/ns/ext/atom#Blank +#define LV2_ATOM__Bool LV2_ATOM_PREFIX "Bool" ///< http://lv2plug.in/ns/ext/atom#Bool +#define LV2_ATOM__Chunk LV2_ATOM_PREFIX "Chunk" ///< http://lv2plug.in/ns/ext/atom#Chunk +#define LV2_ATOM__Double LV2_ATOM_PREFIX "Double" ///< http://lv2plug.in/ns/ext/atom#Double +#define LV2_ATOM__Event LV2_ATOM_PREFIX "Event" ///< http://lv2plug.in/ns/ext/atom#Event +#define LV2_ATOM__Float LV2_ATOM_PREFIX "Float" ///< http://lv2plug.in/ns/ext/atom#Float +#define LV2_ATOM__Int LV2_ATOM_PREFIX "Int" ///< http://lv2plug.in/ns/ext/atom#Int +#define LV2_ATOM__Literal LV2_ATOM_PREFIX "Literal" ///< http://lv2plug.in/ns/ext/atom#Literal +#define LV2_ATOM__Long LV2_ATOM_PREFIX "Long" ///< http://lv2plug.in/ns/ext/atom#Long +#define LV2_ATOM__Number LV2_ATOM_PREFIX "Number" ///< http://lv2plug.in/ns/ext/atom#Number +#define LV2_ATOM__Object LV2_ATOM_PREFIX "Object" ///< http://lv2plug.in/ns/ext/atom#Object +#define LV2_ATOM__Path LV2_ATOM_PREFIX "Path" ///< http://lv2plug.in/ns/ext/atom#Path +#define LV2_ATOM__Property LV2_ATOM_PREFIX "Property" ///< http://lv2plug.in/ns/ext/atom#Property +#define LV2_ATOM__Resource LV2_ATOM_PREFIX "Resource" ///< http://lv2plug.in/ns/ext/atom#Resource +#define LV2_ATOM__Sequence LV2_ATOM_PREFIX "Sequence" ///< http://lv2plug.in/ns/ext/atom#Sequence +#define LV2_ATOM__Sound LV2_ATOM_PREFIX "Sound" ///< http://lv2plug.in/ns/ext/atom#Sound +#define LV2_ATOM__String LV2_ATOM_PREFIX "String" ///< http://lv2plug.in/ns/ext/atom#String +#define LV2_ATOM__Tuple LV2_ATOM_PREFIX "Tuple" ///< http://lv2plug.in/ns/ext/atom#Tuple +#define LV2_ATOM__URI LV2_ATOM_PREFIX "URI" ///< http://lv2plug.in/ns/ext/atom#URI +#define LV2_ATOM__URID LV2_ATOM_PREFIX "URID" ///< http://lv2plug.in/ns/ext/atom#URID +#define LV2_ATOM__Vector LV2_ATOM_PREFIX "Vector" ///< http://lv2plug.in/ns/ext/atom#Vector +#define LV2_ATOM__atomTransfer LV2_ATOM_PREFIX "atomTransfer" ///< http://lv2plug.in/ns/ext/atom#atomTransfer +#define LV2_ATOM__beatTime LV2_ATOM_PREFIX "beatTime" ///< http://lv2plug.in/ns/ext/atom#beatTime +#define LV2_ATOM__bufferType LV2_ATOM_PREFIX "bufferType" ///< http://lv2plug.in/ns/ext/atom#bufferType +#define LV2_ATOM__childType LV2_ATOM_PREFIX "childType" ///< http://lv2plug.in/ns/ext/atom#childType +#define LV2_ATOM__eventTransfer LV2_ATOM_PREFIX "eventTransfer" ///< http://lv2plug.in/ns/ext/atom#eventTransfer +#define LV2_ATOM__frameTime LV2_ATOM_PREFIX "frameTime" ///< http://lv2plug.in/ns/ext/atom#frameTime +#define LV2_ATOM__supports LV2_ATOM_PREFIX "supports" ///< http://lv2plug.in/ns/ext/atom#supports +#define LV2_ATOM__timeUnit LV2_ATOM_PREFIX "timeUnit" ///< http://lv2plug.in/ns/ext/atom#timeUnit + +#define LV2_ATOM_REFERENCE_TYPE 0 ///< The special type for a reference atom + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond */ +/** This expression will fail to compile if double does not fit in 64 bits. */ +typedef char lv2_atom_assert_double_fits_in_64_bits[ + ((sizeof(double) <= sizeof(uint64_t)) * 2) - 1]; +/** @endcond */ + +/** + Return a pointer to the contents of an Atom. The "contents" of an atom + is the data past the complete type-specific header. + @param type The type of the atom, e.g. LV2_Atom_String. + @param atom A variable-sized atom. +*/ +#define LV2_ATOM_CONTENTS(type, atom) \ + ((uint8_t*)(atom) + sizeof(type)) + +/** + Const version of LV2_ATOM_CONTENTS. +*/ +#define LV2_ATOM_CONTENTS_CONST(type, atom) \ + ((const uint8_t*)(atom) + sizeof(type)) + +/** + Return a pointer to the body of an Atom. The "body" of an atom is the + data just past the LV2_Atom head (i.e. the same offset for all types). +*/ +#define LV2_ATOM_BODY(atom) LV2_ATOM_CONTENTS(LV2_Atom, atom) + +/** + Const version of LV2_ATOM_BODY. +*/ +#define LV2_ATOM_BODY_CONST(atom) LV2_ATOM_CONTENTS_CONST(LV2_Atom, atom) + +/** The header of an atom:Atom. */ +typedef struct { + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t type; /**< Type of this atom (mapped URI). */ +} LV2_Atom; + +/** An atom:Int or atom:Bool. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + int32_t body; /**< Integer value. */ +} LV2_Atom_Int; + +/** An atom:Long. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + int64_t body; /**< Integer value. */ +} LV2_Atom_Long; + +/** An atom:Float. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + float body; /**< Floating point value. */ +} LV2_Atom_Float; + +/** An atom:Double. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + double body; /**< Floating point value. */ +} LV2_Atom_Double; + +/** An atom:Bool. May be cast to LV2_Atom. */ +typedef LV2_Atom_Int LV2_Atom_Bool; + +/** An atom:URID. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + uint32_t body; /**< URID. */ +} LV2_Atom_URID; + +/** An atom:String. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + /* Contents (a null-terminated UTF-8 string) follow here. */ +} LV2_Atom_String; + +/** The body of an atom:Literal. */ +typedef struct { + uint32_t datatype; /**< Datatype URID. */ + uint32_t lang; /**< Language URID. */ + /* Contents (a null-terminated UTF-8 string) follow here. */ +} LV2_Atom_Literal_Body; + +/** An atom:Literal. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Literal_Body body; /**< Body. */ +} LV2_Atom_Literal; + +/** An atom:Tuple. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + /* Contents (a series of complete atoms) follow here. */ +} LV2_Atom_Tuple; + +/** The body of an atom:Vector. */ +typedef struct { + uint32_t child_size; /**< The size of each element in the vector. */ + uint32_t child_type; /**< The type of each element in the vector. */ + /* Contents (a series of packed atom bodies) follow here. */ +} LV2_Atom_Vector_Body; + +/** An atom:Vector. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Vector_Body body; /**< Body. */ +} LV2_Atom_Vector; + +/** The body of an atom:Property (e.g. in an atom:Object). */ +typedef struct { + uint32_t key; /**< Key (predicate) (mapped URI). */ + uint32_t context; /**< Context URID (may be, and generally is, 0). */ + LV2_Atom value; /**< Value atom header. */ + /* Value atom body follows here. */ +} LV2_Atom_Property_Body; + +/** An atom:Property. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Property_Body body; /**< Body. */ +} LV2_Atom_Property; + +/** The body of an atom:Object. May be cast to LV2_Atom. */ +typedef struct { + uint32_t id; /**< URID, or 0 for blank. */ + uint32_t otype; /**< Type URID (same as rdf:type, for fast dispatch). */ + /* Contents (a series of property bodies) follow here. */ +} LV2_Atom_Object_Body; + +/** An atom:Object. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Object_Body body; /**< Body. */ +} LV2_Atom_Object; + +/** The header of an atom:Event. Note this type is NOT an LV2_Atom. */ +typedef struct { + /** Time stamp. Which type is valid is determined by context. */ + union { + int64_t frames; /**< Time in audio frames. */ + double beats; /**< Time in beats. */ + } time; + LV2_Atom body; /**< Event body atom header. */ + /* Body atom contents follow here. */ +} LV2_Atom_Event; + +/** + The body of an atom:Sequence (a sequence of events). + + The unit field is either a URID that described an appropriate time stamp + type, or may be 0 where a default stamp type is known. For + LV2_Descriptor::run(), the default stamp type is audio frames. + + The contents of a sequence is a series of LV2_Atom_Event, each aligned + to 64-bits, e.g.: +
+   | Event 1 (size 6)                              | Event 2
+   |       |       |       |       |       |       |       |       |
+   | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   |FRAMES |SUBFRMS|TYPE   |SIZE   |DATADATADATAPAD|FRAMES |SUBFRMS|...
+   
+*/ +typedef struct { + uint32_t unit; /**< URID of unit of event time stamps. */ + uint32_t pad; /**< Currently unused. */ + /* Contents (a series of events) follow here. */ +} LV2_Atom_Sequence_Body; + +/** An atom:Sequence. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Sequence_Body body; /**< Body. */ +} LV2_Atom_Sequence; + +/** + @} +*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_ATOM_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/buf-size.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/buf-size.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,44 @@ +/* + Copyright 2007-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef LV2_BUF_SIZE_H +#define LV2_BUF_SIZE_H + +/** + @defgroup buf-size Buffer Size + + Access to, and restrictions on, buffer sizes; see + for details. + + @{ +*/ + +#define LV2_BUF_SIZE_URI "http://lv2plug.in/ns/ext/buf-size" ///< http://lv2plug.in/ns/ext/buf-size +#define LV2_BUF_SIZE_PREFIX LV2_BUF_SIZE_URI "#" ///< http://lv2plug.in/ns/ext/buf-size# + +#define LV2_BUF_SIZE__boundedBlockLength LV2_BUF_SIZE_PREFIX "boundedBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#boundedBlockLength +#define LV2_BUF_SIZE__fixedBlockLength LV2_BUF_SIZE_PREFIX "fixedBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#fixedBlockLength +#define LV2_BUF_SIZE__maxBlockLength LV2_BUF_SIZE_PREFIX "maxBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#maxBlockLength +#define LV2_BUF_SIZE__minBlockLength LV2_BUF_SIZE_PREFIX "minBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#minBlockLength +#define LV2_BUF_SIZE__nominalBlockLength LV2_BUF_SIZE_PREFIX "nominalBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#nominalBlockLength +#define LV2_BUF_SIZE__powerOf2BlockLength LV2_BUF_SIZE_PREFIX "powerOf2BlockLength" ///< http://lv2plug.in/ns/ext/buf-size#powerOf2BlockLength +#define LV2_BUF_SIZE__sequenceSize LV2_BUF_SIZE_PREFIX "sequenceSize" ///< http://lv2plug.in/ns/ext/buf-size#sequenceSize + +/** + @} +*/ + +#endif /* LV2_BUF_SIZE_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/control-input-port-change-request.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/control-input-port-change-request.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,84 @@ +/* + LV2 ControlInputPort change request extension + Copyright 2020 Filipe Coelho + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file control-input-port-change-request.h + C header for the LV2 ControlInputPort change request extension . +*/ + +#ifndef LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H +#define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H + +#include "lv2.h" + +#define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI "http://kx.studio/ns/lv2ext/control-input-port-change-request" +#define LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_PREFIX LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI "#" + +#include + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +/** A status code for LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI functions. */ +typedef enum { + LV2_CONTROL_INPUT_PORT_CHANGE_SUCCESS = 0, /**< Completed successfully. */ + LV2_CONTROL_INPUT_PORT_CHANGE_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_CONTROL_INPUT_PORT_CHANGE_ERR_INVALID_INDEX = 2 /**< Failed due to invalid port index. */ +} LV2_ControlInputPort_Change_Status; + +/** + * Opaque handle for LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI feature. + */ +typedef void* LV2_ControlInputPort_Change_Request_Handle; + +/** + * On instantiation, host must supply LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI feature. + * LV2_Feature::data must be pointer to LV2_ControlInputPort_Change_Request. +*/ +typedef struct _LV2_ControlInputPort_Change_Request { + /** + * Opaque host data. + */ + LV2_ControlInputPort_Change_Request_Handle handle; + + /** + * request_change() + * + * Ask the host to change a plugin's control input port value. + * Parameter handle MUST be the 'handle' member of this struct. + * Parameter index is port index to change. + * Parameter value is the requested value to change the control port input to. + * + * Returns status of the request. + * The host may decline this request, if e.g. it is currently automating this port. + * + * The plugin MUST call this function during run(). + */ + LV2_ControlInputPort_Change_Status (*request_change)(LV2_ControlInputPort_Change_Request_Handle handle, + uint32_t index, + float value); + +} LV2_ControlInputPort_Change_Request; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/data-access.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/data-access.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,68 @@ +/* + LV2 Data Access Extension + Copyright 2008-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup data-access Data Access + + Access to plugin extension_data() for UIs, see + for details. + + @{ +*/ + +#ifndef LV2_DATA_ACCESS_H +#define LV2_DATA_ACCESS_H + +#define LV2_DATA_ACCESS_URI "http://lv2plug.in/ns/ext/data-access" ///< http://lv2plug.in/ns/ext/data-access +#define LV2_DATA_ACCESS_PREFIX LV2_DATA_ACCESS_URI "#" ///< http://lv2plug.in/ns/ext/data-access# + +#ifdef __cplusplus +extern "C" { +#endif + +/** + The data field of the LV2_Feature for this extension. + + To support this feature the host must pass an LV2_Feature struct to the + instantiate method with URI "http://lv2plug.in/ns/ext/data-access" + and data pointed to an instance of this struct. +*/ +typedef struct { + /** + A pointer to a method the UI can call to get data (of a type specified + by some other extension) from the plugin. + + This call never is never guaranteed to return anything, UIs should + degrade gracefully if direct access to the plugin data is not possible + (in which case this function will return NULL). + + This is for access to large data that can only possibly work if the UI + and plugin are running in the same process. For all other things, use + the normal LV2 UI communication system. + */ + const void* (*data_access)(const char* uri); +} LV2_Extension_Data_Feature; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_DATA_ACCESS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/dynmanifest.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/dynmanifest.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,151 @@ +/* + Dynamic manifest specification for LV2 + Copyright 2008-2011 Stefano D'Angelo + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup dynmanifest Dynamic Manifest + + Support for dynamic data generation, see + for details. + + @{ +*/ + +#ifndef LV2_DYN_MANIFEST_H_INCLUDED +#define LV2_DYN_MANIFEST_H_INCLUDED + +#include + +#include "lv2.h" + +#define LV2_DYN_MANIFEST_URI "http://lv2plug.in/ns/ext/dynmanifest" ///< http://lv2plug.in/ns/ext/dynmanifest +#define LV2_DYN_MANIFEST_PREFIX LV2_DYN_MANIFEST_URI "#" ///< http://lv2plug.in/ns/ext/dynmanifest# + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Dynamic manifest generator handle. + + This handle indicates a particular status of a dynamic manifest generator. + The host MUST NOT attempt to interpret it and, unlikely LV2_Handle, it is + NOT even valid to compare this to NULL. The dynamic manifest generator MAY + use it to reference internal data. +*/ +typedef void * LV2_Dyn_Manifest_Handle; + +/** + Generate the dynamic manifest. + + @param handle Pointer to an uninitialized dynamic manifest generator handle. + + @param features NULL terminated array of LV2_Feature structs which represent + the features the host supports. The dynamic manifest generator may refuse to + (re)generate the dynamic manifest if required features are not found here + (however hosts SHOULD NOT use this as a discovery mechanism, instead of + reading the static manifest file). This array must always exist; if a host + has no features, it MUST pass a single element array containing NULL. + + @return 0 on success, otherwise a non-zero error code. The host SHOULD + evaluate the result of the operation by examining the returned value and + MUST NOT try to interpret the value of handle. +*/ +int lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle * handle, + const LV2_Feature *const * features); + +/** + Fetch a "list" of subject URIs described in the dynamic manifest. + + The dynamic manifest generator has to fill the resource only with the needed + triples to make the host aware of the "objects" it wants to expose. For + example, if the plugin library exposes a regular LV2 plugin, it should + output only a triple like the following: + + a lv2:Plugin . + + The objects that are elegible for exposure are those that would need to be + represented by a subject node in a static manifest. + + @param handle Dynamic manifest generator handle. + + @param fp FILE * identifying the resource the host has to set up for the + dynamic manifest generator. The host MUST pass a writable, empty resource to + this function, and the dynamic manifest generator MUST ONLY perform write + operations on it at the end of the stream (e.g., using only fprintf(), + fwrite() and similar). + + @return 0 on success, otherwise a non-zero error code. +*/ +int lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle, + FILE * fp); + +/** + Function that fetches data related to a specific URI. + + The dynamic manifest generator has to fill the resource with data related to + object represented by the given URI. For example, if the library exposes a + regular LV2 plugin whose URI, as retrieved by the host using + lv2_dyn_manifest_get_subjects() is http://www.example.com/plugin/uri, it + should output something like: + +
+   
+       a lv2:Plugin ;
+       doap:name "My Plugin" ;
+       lv2:binary  ;
+       etc:etc "..." .
+   
+ + @param handle Dynamic manifest generator handle. + + @param fp FILE * identifying the resource the host has to set up for the + dynamic manifest generator. The host MUST pass a writable resource to this + function, and the dynamic manifest generator MUST ONLY perform write + operations on it at the current position of the stream (e.g. using only + fprintf(), fwrite() and similar). + + @param uri URI to get data about (in the "plain" form, i.e., absolute URI + without Turtle prefixes). + + @return 0 on success, otherwise a non-zero error code. +*/ +int lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle, + FILE * fp, + const char * uri); + +/** + Function that ends the operations on the dynamic manifest generator. + + This function SHOULD be used by the dynamic manifest generator to perform + cleanup operations, etc. + + Once this function is called, referring to handle will cause undefined + behavior. + + @param handle Dynamic manifest generator handle. +*/ +void lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle); + +#ifdef __cplusplus +} +#endif + +#endif /* LV2_DYN_MANIFEST_H_INCLUDED */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/event-helpers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/event-helpers.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,265 @@ +/* + Copyright 2008-2015 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file event-helpers.h Helper functions for the LV2 Event extension + . +*/ + +#ifndef LV2_EVENT_HELPERS_H +#define LV2_EVENT_HELPERS_H + +#include +#include +#include + +#include "event.h" + +#ifdef __cplusplus +extern "C" { +#else +# include +#endif + +/** @file + * Helper functions for the LV2 Event extension + * . + * + * These functions are provided for convenience only, use of them is not + * required for supporting lv2ev (i.e. the events extension is defined by the + * raw buffer format described in lv2_event.h and NOT by this API). + * + * Note that these functions are all static inline which basically means: + * do not take the address of these functions. */ + + +/** Pad a size to 64 bits (for event sizes) */ +static inline uint16_t +lv2_event_pad_size(uint16_t size) +{ + return (uint16_t)(size + 7U) & (uint16_t)(~7U); +} + + +/** Initialize (empty, reset..) an existing event buffer. + * The contents of buf are ignored entirely and overwritten, except capacity + * which is unmodified. */ +static inline void +lv2_event_buffer_reset(LV2_Event_Buffer* buf, + uint16_t stamp_type, + uint8_t* data) +{ + buf->data = data; + buf->header_size = sizeof(LV2_Event_Buffer); + buf->stamp_type = stamp_type; + buf->event_count = 0; + buf->size = 0; +} + + +/** Allocate a new, empty event buffer. */ +static inline LV2_Event_Buffer* +lv2_event_buffer_new(uint32_t capacity, uint16_t stamp_type) +{ + const size_t size = sizeof(LV2_Event_Buffer) + capacity; + LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(size); + if (buf != NULL) { + buf->capacity = capacity; + lv2_event_buffer_reset(buf, stamp_type, (uint8_t *)(buf + 1)); + return buf; + } else { + return NULL; + } +} + + +/** An iterator over an LV2_Event_Buffer. + * + * Multiple simultaneous read iterators over a single buffer is fine, + * but changing the buffer invalidates all iterators (e.g. RW Lock). */ +typedef struct { + LV2_Event_Buffer* buf; + uint32_t offset; +} LV2_Event_Iterator; + + +/** Reset an iterator to point to the start of `buf`. + * @return True if `iter` is valid, otherwise false (buffer is empty) */ +static inline bool +lv2_event_begin(LV2_Event_Iterator* iter, + LV2_Event_Buffer* buf) +{ + iter->buf = buf; + iter->offset = 0; + return (buf->size > 0); +} + + +/** Check if `iter` is valid. + * @return True if `iter` is valid, otherwise false (past end of buffer) */ +static inline bool +lv2_event_is_valid(LV2_Event_Iterator* iter) +{ + return (iter->buf && (iter->offset < iter->buf->size)); +} + + +/** Advance `iter` forward one event. + * `iter` must be valid. + * @return True if `iter` is valid, otherwise false (reached end of buffer) */ +static inline bool +lv2_event_increment(LV2_Event_Iterator* iter) +{ + if (!lv2_event_is_valid(iter)) { + return false; + } + + LV2_Event* const ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + iter->offset += lv2_event_pad_size( + (uint16_t)((uint16_t)sizeof(LV2_Event) + ev->size)); + + return true; +} + + +/** Dereference an event iterator (get the event currently pointed at). + * `iter` must be valid. + * `data` if non-NULL, will be set to point to the contents of the event + * returned. + * @return A Pointer to the event `iter` is currently pointing at, or NULL + * if the end of the buffer is reached (in which case `data` is + * also set to NULL). */ +static inline LV2_Event* +lv2_event_get(LV2_Event_Iterator* iter, + uint8_t** data) +{ + if (!lv2_event_is_valid(iter)) { + return NULL; + } + + LV2_Event* const ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + if (data) + *data = (uint8_t*)ev + sizeof(LV2_Event); + + return ev; +} + + +/** Write an event at `iter`. + * The event (if any) pointed to by `iter` will be overwritten, and `iter` + * incremented to point to the following event (i.e. several calls to this + * function can be done in sequence without twiddling iter in-between). + * @return True if event was written, otherwise false (buffer is full). */ +static inline bool +lv2_event_write(LV2_Event_Iterator* iter, + uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size, + const uint8_t* data) +{ + if (!iter->buf) + return false; + + if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) + return false; + + LV2_Event* const ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + ev->frames = frames; + ev->subframes = subframes; + ev->type = type; + ev->size = size; + memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size); + ++iter->buf->event_count; + + size = lv2_event_pad_size((uint16_t)(sizeof(LV2_Event) + size)); + iter->buf->size += size; + iter->offset += size; + + return true; +} + + +/** Reserve space for an event in the buffer and return a pointer to + the memory where the caller can write the event data, or NULL if there + is not enough room in the buffer. */ +static inline uint8_t* +lv2_event_reserve(LV2_Event_Iterator* iter, + uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size) +{ + const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + size); + if (iter->buf->capacity - iter->buf->size < total_size) + return NULL; + + LV2_Event* const ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + ev->frames = frames; + ev->subframes = subframes; + ev->type = type; + ev->size = size; + ++iter->buf->event_count; + + const uint16_t padded_size = lv2_event_pad_size(total_size); + iter->buf->size += padded_size; + iter->offset += padded_size; + + return (uint8_t*)ev + sizeof(LV2_Event); +} + + +/** Write an event at `iter`. + * The event (if any) pointed to by `iter` will be overwritten, and `iter` + * incremented to point to the following event (i.e. several calls to this + * function can be done in sequence without twiddling iter in-between). + * @return True if event was written, otherwise false (buffer is full). */ +static inline bool +lv2_event_write_event(LV2_Event_Iterator* iter, + const LV2_Event* ev, + const uint8_t* data) +{ + const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + ev->size); + if (iter->buf->capacity - iter->buf->size < total_size) + return false; + + LV2_Event* const write_ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + *write_ev = *ev; + memcpy((uint8_t*)write_ev + sizeof(LV2_Event), data, ev->size); + ++iter->buf->event_count; + + const uint16_t padded_size = lv2_event_pad_size(total_size); + iter->buf->size += padded_size; + iter->offset += padded_size; + + return true; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_EVENT_HELPERS_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/event.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/event.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,292 @@ +/* + Copyright 2008-2016 David Robillard + Copyright 2006-2007 Lars Luthman + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup event Event + + Generic time-stamped events, see for + details. + + @{ +*/ + +#ifndef LV2_EVENT_H +#define LV2_EVENT_H + +#define LV2_EVENT_URI "http://lv2plug.in/ns/ext/event" ///< http://lv2plug.in/ns/ext/event +#define LV2_EVENT_PREFIX LV2_EVENT_URI "#" ///< http://lv2plug.in/ns/ext/event# + +#define LV2_EVENT__Event LV2_EVENT_PREFIX "Event" ///< http://lv2plug.in/ns/ext/event#Event +#define LV2_EVENT__EventPort LV2_EVENT_PREFIX "EventPort" ///< http://lv2plug.in/ns/ext/event#EventPort +#define LV2_EVENT__FrameStamp LV2_EVENT_PREFIX "FrameStamp" ///< http://lv2plug.in/ns/ext/event#FrameStamp +#define LV2_EVENT__TimeStamp LV2_EVENT_PREFIX "TimeStamp" ///< http://lv2plug.in/ns/ext/event#TimeStamp +#define LV2_EVENT__generatesTimeStamp LV2_EVENT_PREFIX "generatesTimeStamp" ///< http://lv2plug.in/ns/ext/event#generatesTimeStamp +#define LV2_EVENT__generic LV2_EVENT_PREFIX "generic" ///< http://lv2plug.in/ns/ext/event#generic +#define LV2_EVENT__inheritsEvent LV2_EVENT_PREFIX "inheritsEvent" ///< http://lv2plug.in/ns/ext/event#inheritsEvent +#define LV2_EVENT__inheritsTimeStamp LV2_EVENT_PREFIX "inheritsTimeStamp" ///< http://lv2plug.in/ns/ext/event#inheritsTimeStamp +#define LV2_EVENT__supportsEvent LV2_EVENT_PREFIX "supportsEvent" ///< http://lv2plug.in/ns/ext/event#supportsEvent +#define LV2_EVENT__supportsTimeStamp LV2_EVENT_PREFIX "supportsTimeStamp" ///< http://lv2plug.in/ns/ext/event#supportsTimeStamp + +#define LV2_EVENT_AUDIO_STAMP 0 ///< Special timestamp type for audio frames + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + The best Pulses Per Quarter Note for tempo-based uint32_t timestamps. + Equal to 2^12 * 5 * 7 * 9 * 11 * 13 * 17, which is evenly divisble + by all integers from 1 through 18 inclusive, and powers of 2 up to 2^12. +*/ +static const uint32_t LV2_EVENT_PPQN = 3136573440U; + +/** + An LV2 event (header only). + + LV2 events are generic time-stamped containers for any type of event. + The type field defines the format of a given event's contents. + + This struct defines the header of an LV2 event. An LV2 event is a single + chunk of POD (plain old data), usually contained in a flat buffer (see + LV2_EventBuffer below). Unless a required feature says otherwise, hosts may + assume a deep copy of an LV2 event can be created safely using a simple: + + memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size); (or equivalent) +*/ +typedef struct { + /** + The frames portion of timestamp. The units used here can optionally be + set for a port (with the lv2ev:timeUnits property), otherwise this is + audio frames, corresponding to the sample_count parameter of the LV2 run + method (e.g. frame 0 is the first frame for that call to run). + */ + uint32_t frames; + + /** + The sub-frames portion of timestamp. The units used here can optionally + be set for a port (with the lv2ev:timeUnits property), otherwise this is + 1/(2^32) of an audio frame. + */ + uint32_t subframes; + + /** + The type of this event, as a number which represents some URI + defining an event type. This value MUST be some value previously + returned from a call to the uri_to_id function defined in the LV2 + URI map extension (see lv2_uri_map.h). + There are special rules which must be followed depending on the type + of an event. If the plugin recognizes an event type, the definition + of that event type will describe how to interpret the event, and + any required behaviour. Otherwise, if the type is 0, this event is a + non-POD event and lv2_event_unref MUST be called if the event is + 'dropped' (see above). Even if the plugin does not understand an event, + it may pass the event through to an output by simply copying (and NOT + calling lv2_event_unref). These rules are designed to allow for generic + event handling plugins and large non-POD events, but with minimal hassle + on simple plugins that "don't care" about these more advanced features. + */ + uint16_t type; + + /** + The size of the data portion of this event in bytes, which immediately + follows. The header size (12 bytes) is not included in this value. + */ + uint16_t size; + + /* size bytes of data follow here */ +} LV2_Event; + + +/** + A buffer of LV2 events (header only). + + Like events (which this contains) an event buffer is a single chunk of POD: + the entire buffer (including contents) can be copied with a single memcpy. + The first contained event begins sizeof(LV2_EventBuffer) bytes after the + start of this struct. + + After this header, the buffer contains an event header (defined by struct + LV2_Event), followed by that event's contents (padded to 64 bits), followed + by another header, etc: + + | | | | | | | + | | | | | | | | | | | | | | | | | | | | | | | | | + |FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ... +*/ +typedef struct { + /** + The contents of the event buffer. This may or may not reside in the + same block of memory as this header, plugins must not assume either. + The host guarantees this points to at least capacity bytes of allocated + memory (though only size bytes of that are valid events). + */ + uint8_t* data; + + /** + The size of this event header in bytes (including everything). + + This is to allow for extending this header in the future without + breaking binary compatibility. Whenever this header is copied, + it MUST be done using this field (and NOT the sizeof this struct). + */ + uint16_t header_size; + + /** + The type of the time stamps for events in this buffer. + As a special exception, '0' always means audio frames and subframes + (1/UINT32_MAX'th of a frame) in the sample rate passed to instantiate. + + INPUTS: The host must set this field to the numeric ID of some URI + defining the meaning of the frames/subframes fields of contained events + (obtained by the LV2 URI Map uri_to_id function with the URI of this + extension as the 'map' argument, see lv2_uri_map.h). The host must + never pass a plugin a buffer which uses a stamp type the plugin does not + 'understand'. The value of this field must never change, except when + connect_port is called on the input port, at which time the host MUST + have set the stamp_type field to the value that will be used for all + subsequent run calls. + + OUTPUTS: The plugin may set this to any value that has been returned + from uri_to_id with the URI of this extension for a 'map' argument. + When connected to a buffer with connect_port, output ports MUST set this + field to the type of time stamp they will be writing. On any call to + connect_port on an event input port, the plugin may change this field on + any output port, it is the responsibility of the host to check if any of + these values have changed and act accordingly. + */ + uint16_t stamp_type; + + /** + The number of events in this buffer. + + INPUTS: The host must set this field to the number of events contained + in the data buffer before calling run(). The plugin must not change + this field. + + OUTPUTS: The plugin must set this field to the number of events it has + written to the buffer before returning from run(). Any initial value + should be ignored by the plugin. + */ + uint32_t event_count; + + /** + The size of the data buffer in bytes. + This is set by the host and must not be changed by the plugin. + The host is allowed to change this between run() calls. + */ + uint32_t capacity; + + /** + The size of the initial portion of the data buffer containing data. + + INPUTS: The host must set this field to the number of bytes used + by all events it has written to the buffer (including headers) + before calling the plugin's run(). + The plugin must not change this field. + + OUTPUTS: The plugin must set this field to the number of bytes + used by all events it has written to the buffer (including headers) + before returning from run(). + Any initial value should be ignored by the plugin. + */ + uint32_t size; +} LV2_Event_Buffer; + + +/** + Opaque pointer to host data. +*/ +typedef void* LV2_Event_Callback_Data; + + +/** + Non-POD events feature. + + To support this feature the host must pass an LV2_Feature struct to the + plugin's instantiate method with URI "http://lv2plug.in/ns/ext/event" + and data pointed to an instance of this struct. Note this feature + is not mandatory to support the event extension. +*/ +typedef struct { + /** + Opaque pointer to host data. + + The plugin MUST pass this to any call to functions in this struct. + Otherwise, it must not be interpreted in any way. + */ + LV2_Event_Callback_Data callback_data; + + /** + Take a reference to a non-POD event. + + If a plugin receives an event with type 0, it means the event is a + pointer to some object in memory and not a flat sequence of bytes + in the buffer. When receiving a non-POD event, the plugin already + has an implicit reference to the event. If the event is stored AND + passed to an output, lv2_event_ref MUST be called on that event. + If the event is only stored OR passed through, this is not necessary + (as the plugin already has 1 implicit reference). + + @param event An event received at an input that will not be copied to + an output or stored in any way. + + @param context The calling context. Like event types, this is a mapped + URI, see lv2_context.h. Simple plugin with just a run() method should + pass 0 here (the ID of the 'standard' LV2 run context). The host + guarantees that this function is realtime safe iff the context is + realtime safe. + + PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS. + */ + uint32_t (*lv2_event_ref)(LV2_Event_Callback_Data callback_data, + LV2_Event* event); + + /** + Drop a reference to a non-POD event. + + If a plugin receives an event with type 0, it means the event is a + pointer to some object in memory and not a flat sequence of bytes + in the buffer. If the plugin does not pass the event through to + an output or store it internally somehow, it MUST call this function + on the event (more information on using non-POD events below). + + @param event An event received at an input that will not be copied to an + output or stored in any way. + + @param context The calling context. Like event types, this is a mapped + URI, see lv2_context.h. Simple plugin with just a run() method should + pass 0 here (the ID of the 'standard' LV2 run context). The host + guarantees that this function is realtime safe iff the context is + realtime safe. + + PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS. + */ + uint32_t (*lv2_event_unref)(LV2_Event_Callback_Data callback_data, + LV2_Event* event); +} LV2_Event_Feature; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_EVENT_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/instance-access.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/instance-access.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,36 @@ +/* + LV2 Instance Access Extension + Copyright 2008-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup instance-access Instance Access + + Access to the LV2_Handle of a plugin for UIs; see + for details. + + @{ +*/ + +#ifndef LV2_INSTANCE_ACCESS_H +#define LV2_INSTANCE_ACCESS_H + +#define LV2_INSTANCE_ACCESS_URI "http://lv2plug.in/ns/ext/instance-access" ///< http://lv2plug.in/ns/ext/instance-access + +#endif /* LV2_INSTANCE_ACCESS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/log.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/log.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,109 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup log Log + + Interface for plugins to log via the host; see + for details. + + @{ +*/ + +#ifndef LV2_LOG_H +#define LV2_LOG_H + +#define LV2_LOG_URI "http://lv2plug.in/ns/ext/log" ///< http://lv2plug.in/ns/ext/log +#define LV2_LOG_PREFIX LV2_LOG_URI "#" ///< http://lv2plug.in/ns/ext/log# + +#define LV2_LOG__Entry LV2_LOG_PREFIX "Entry" ///< http://lv2plug.in/ns/ext/log#Entry +#define LV2_LOG__Error LV2_LOG_PREFIX "Error" ///< http://lv2plug.in/ns/ext/log#Error +#define LV2_LOG__Note LV2_LOG_PREFIX "Note" ///< http://lv2plug.in/ns/ext/log#Note +#define LV2_LOG__Trace LV2_LOG_PREFIX "Trace" ///< http://lv2plug.in/ns/ext/log#Trace +#define LV2_LOG__Warning LV2_LOG_PREFIX "Warning" ///< http://lv2plug.in/ns/ext/log#Warning +#define LV2_LOG__log LV2_LOG_PREFIX "log" ///< http://lv2plug.in/ns/ext/log#log + +#include + +#include "urid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond */ +#ifdef __GNUC__ +/** Allow type checking of printf-like functions. */ +# define LV2_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) +#else +# define LV2_LOG_FUNC(fmt, arg1) +#endif +/** @endcond */ + +/** + Opaque data to host data for LV2_Log_Log. +*/ +typedef void* LV2_Log_Handle; + +/** + Log feature (LV2_LOG__log) +*/ +typedef struct _LV2_Log { + /** + Opaque pointer to host data. + + This MUST be passed to methods in this struct whenever they are called. + Otherwise, it must not be interpreted in any way. + */ + LV2_Log_Handle handle; + + /** + Log a message, passing format parameters directly. + + The API of this function matches that of the standard C printf function, + except for the addition of the first two parameters. This function may + be called from any non-realtime context, or from any context if `type` + is @ref LV2_LOG__Trace. + */ + LV2_LOG_FUNC(3, 4) + int (*printf)(LV2_Log_Handle handle, + LV2_URID type, + const char* fmt, ...); + + /** + Log a message, passing format parameters in a va_list. + + The API of this function matches that of the standard C vprintf + function, except for the addition of the first two parameters. This + function may be called from any non-realtime context, or from any + context if `type` is @ref LV2_LOG__Trace. + */ + LV2_LOG_FUNC(3, 0) + int (*vprintf)(LV2_Log_Handle handle, + LV2_URID type, + const char* fmt, + va_list ap); +} LV2_Log_Log; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_LOG_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/logger.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/logger.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,160 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup logger Logger + @ingroup log + + Convenience API for easy logging in plugin code. This API provides simple + wrappers for logging from a plugin, which automatically fall back to + printing to stderr if host support is unavailabe. + + @{ +*/ + +#ifndef LV2_ATOM_LOGGER_H +#define LV2_ATOM_LOGGER_H + +#include +#include + +#include "log.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Logger convenience API state. +*/ +typedef struct { + LV2_Log_Log* log; + + LV2_URID Error; + LV2_URID Note; + LV2_URID Trace; + LV2_URID Warning; +} LV2_Log_Logger; + +/** + Set `map` as the URI map for `logger`. + + This affects the message type URIDs (Error, Warning, etc) which are passed + to the log's print functions. +*/ +static inline void +lv2_log_logger_set_map(LV2_Log_Logger* logger, LV2_URID_Map* map) +{ + if (map) { + logger->Error = map->map(map->handle, LV2_LOG__Error); + logger->Note = map->map(map->handle, LV2_LOG__Note); + logger->Trace = map->map(map->handle, LV2_LOG__Trace); + logger->Warning = map->map(map->handle, LV2_LOG__Warning); + } else { + logger->Error = logger->Note = logger->Trace = logger->Warning = 0; + } +} + +/** + Initialise `logger`. + + URIs will be mapped using `map` and stored, a reference to `map` itself is + not held. Both `map` and `log` may be NULL when unsupported by the host, + in which case the implementation will fall back to printing to stderr. +*/ +static inline void +lv2_log_logger_init(LV2_Log_Logger* logger, + LV2_URID_Map* map, + LV2_Log_Log* log) +{ + logger->log = log; + lv2_log_logger_set_map(logger, map); +} + +/** + Log a message to the host, or stderr if support is unavailable. +*/ +LV2_LOG_FUNC(3, 0) +static inline int +lv2_log_vprintf(LV2_Log_Logger* logger, + LV2_URID type, + const char* fmt, + va_list args) +{ + if (logger && logger->log) { + return logger->log->vprintf(logger->log->handle, type, fmt, args); + } else { + return vfprintf(stderr, fmt, args); + } +} + +/** Log an error via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_error(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Error, fmt, args); + va_end(args); + return ret; +} + +/** Log a note via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_note(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Note, fmt, args); + va_end(args); + return ret; +} + +/** Log a trace via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_trace(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Trace, fmt, args); + va_end(args); + return ret; +} + +/** Log a warning via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_warning(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Warning, fmt, args); + va_end(args); + return ret; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_LOG_LOGGER_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,476 @@ +/* + LV2 - An audio plugin interface specification. + Copyright 2006-2012 Steve Harris, David Robillard. + + Based on LADSPA, Copyright 2000-2002 Richard W.E. Furse, + Paul Barton-Davis, Stefan Westerfeld. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup lv2core LV2 Core + + Core LV2 specification, see for details. + + @{ +*/ + +#ifndef LV2_H_INCLUDED +#define LV2_H_INCLUDED + +#include + +#define LV2_CORE_URI "http://lv2plug.in/ns/lv2core" ///< http://lv2plug.in/ns/lv2core +#define LV2_CORE_PREFIX LV2_CORE_URI "#" ///< http://lv2plug.in/ns/lv2core# + +#define LV2_CORE__AllpassPlugin LV2_CORE_PREFIX "AllpassPlugin" ///< http://lv2plug.in/ns/lv2core#AllpassPlugin +#define LV2_CORE__AmplifierPlugin LV2_CORE_PREFIX "AmplifierPlugin" ///< http://lv2plug.in/ns/lv2core#AmplifierPlugin +#define LV2_CORE__AnalyserPlugin LV2_CORE_PREFIX "AnalyserPlugin" ///< http://lv2plug.in/ns/lv2core#AnalyserPlugin +#define LV2_CORE__AudioPort LV2_CORE_PREFIX "AudioPort" ///< http://lv2plug.in/ns/lv2core#AudioPort +#define LV2_CORE__BandpassPlugin LV2_CORE_PREFIX "BandpassPlugin" ///< http://lv2plug.in/ns/lv2core#BandpassPlugin +#define LV2_CORE__CVPort LV2_CORE_PREFIX "CVPort" ///< http://lv2plug.in/ns/lv2core#CVPort +#define LV2_CORE__ChorusPlugin LV2_CORE_PREFIX "ChorusPlugin" ///< http://lv2plug.in/ns/lv2core#ChorusPlugin +#define LV2_CORE__CombPlugin LV2_CORE_PREFIX "CombPlugin" ///< http://lv2plug.in/ns/lv2core#CombPlugin +#define LV2_CORE__CompressorPlugin LV2_CORE_PREFIX "CompressorPlugin" ///< http://lv2plug.in/ns/lv2core#CompressorPlugin +#define LV2_CORE__ConstantPlugin LV2_CORE_PREFIX "ConstantPlugin" ///< http://lv2plug.in/ns/lv2core#ConstantPlugin +#define LV2_CORE__ControlPort LV2_CORE_PREFIX "ControlPort" ///< http://lv2plug.in/ns/lv2core#ControlPort +#define LV2_CORE__ConverterPlugin LV2_CORE_PREFIX "ConverterPlugin" ///< http://lv2plug.in/ns/lv2core#ConverterPlugin +#define LV2_CORE__DelayPlugin LV2_CORE_PREFIX "DelayPlugin" ///< http://lv2plug.in/ns/lv2core#DelayPlugin +#define LV2_CORE__DistortionPlugin LV2_CORE_PREFIX "DistortionPlugin" ///< http://lv2plug.in/ns/lv2core#DistortionPlugin +#define LV2_CORE__DynamicsPlugin LV2_CORE_PREFIX "DynamicsPlugin" ///< http://lv2plug.in/ns/lv2core#DynamicsPlugin +#define LV2_CORE__EQPlugin LV2_CORE_PREFIX "EQPlugin" ///< http://lv2plug.in/ns/lv2core#EQPlugin +#define LV2_CORE__EnvelopePlugin LV2_CORE_PREFIX "EnvelopePlugin" ///< http://lv2plug.in/ns/lv2core#EnvelopePlugin +#define LV2_CORE__ExpanderPlugin LV2_CORE_PREFIX "ExpanderPlugin" ///< http://lv2plug.in/ns/lv2core#ExpanderPlugin +#define LV2_CORE__ExtensionData LV2_CORE_PREFIX "ExtensionData" ///< http://lv2plug.in/ns/lv2core#ExtensionData +#define LV2_CORE__Feature LV2_CORE_PREFIX "Feature" ///< http://lv2plug.in/ns/lv2core#Feature +#define LV2_CORE__FilterPlugin LV2_CORE_PREFIX "FilterPlugin" ///< http://lv2plug.in/ns/lv2core#FilterPlugin +#define LV2_CORE__FlangerPlugin LV2_CORE_PREFIX "FlangerPlugin" ///< http://lv2plug.in/ns/lv2core#FlangerPlugin +#define LV2_CORE__FunctionPlugin LV2_CORE_PREFIX "FunctionPlugin" ///< http://lv2plug.in/ns/lv2core#FunctionPlugin +#define LV2_CORE__GatePlugin LV2_CORE_PREFIX "GatePlugin" ///< http://lv2plug.in/ns/lv2core#GatePlugin +#define LV2_CORE__GeneratorPlugin LV2_CORE_PREFIX "GeneratorPlugin" ///< http://lv2plug.in/ns/lv2core#GeneratorPlugin +#define LV2_CORE__HighpassPlugin LV2_CORE_PREFIX "HighpassPlugin" ///< http://lv2plug.in/ns/lv2core#HighpassPlugin +#define LV2_CORE__InputPort LV2_CORE_PREFIX "InputPort" ///< http://lv2plug.in/ns/lv2core#InputPort +#define LV2_CORE__InstrumentPlugin LV2_CORE_PREFIX "InstrumentPlugin" ///< http://lv2plug.in/ns/lv2core#InstrumentPlugin +#define LV2_CORE__LimiterPlugin LV2_CORE_PREFIX "LimiterPlugin" ///< http://lv2plug.in/ns/lv2core#LimiterPlugin +#define LV2_CORE__LowpassPlugin LV2_CORE_PREFIX "LowpassPlugin" ///< http://lv2plug.in/ns/lv2core#LowpassPlugin +#define LV2_CORE__MixerPlugin LV2_CORE_PREFIX "MixerPlugin" ///< http://lv2plug.in/ns/lv2core#MixerPlugin +#define LV2_CORE__ModulatorPlugin LV2_CORE_PREFIX "ModulatorPlugin" ///< http://lv2plug.in/ns/lv2core#ModulatorPlugin +#define LV2_CORE__MultiEQPlugin LV2_CORE_PREFIX "MultiEQPlugin" ///< http://lv2plug.in/ns/lv2core#MultiEQPlugin +#define LV2_CORE__OscillatorPlugin LV2_CORE_PREFIX "OscillatorPlugin" ///< http://lv2plug.in/ns/lv2core#OscillatorPlugin +#define LV2_CORE__OutputPort LV2_CORE_PREFIX "OutputPort" ///< http://lv2plug.in/ns/lv2core#OutputPort +#define LV2_CORE__ParaEQPlugin LV2_CORE_PREFIX "ParaEQPlugin" ///< http://lv2plug.in/ns/lv2core#ParaEQPlugin +#define LV2_CORE__PhaserPlugin LV2_CORE_PREFIX "PhaserPlugin" ///< http://lv2plug.in/ns/lv2core#PhaserPlugin +#define LV2_CORE__PitchPlugin LV2_CORE_PREFIX "PitchPlugin" ///< http://lv2plug.in/ns/lv2core#PitchPlugin +#define LV2_CORE__Plugin LV2_CORE_PREFIX "Plugin" ///< http://lv2plug.in/ns/lv2core#Plugin +#define LV2_CORE__PluginBase LV2_CORE_PREFIX "PluginBase" ///< http://lv2plug.in/ns/lv2core#PluginBase +#define LV2_CORE__Point LV2_CORE_PREFIX "Point" ///< http://lv2plug.in/ns/lv2core#Point +#define LV2_CORE__Port LV2_CORE_PREFIX "Port" ///< http://lv2plug.in/ns/lv2core#Port +#define LV2_CORE__PortProperty LV2_CORE_PREFIX "PortProperty" ///< http://lv2plug.in/ns/lv2core#PortProperty +#define LV2_CORE__Resource LV2_CORE_PREFIX "Resource" ///< http://lv2plug.in/ns/lv2core#Resource +#define LV2_CORE__ReverbPlugin LV2_CORE_PREFIX "ReverbPlugin" ///< http://lv2plug.in/ns/lv2core#ReverbPlugin +#define LV2_CORE__ScalePoint LV2_CORE_PREFIX "ScalePoint" ///< http://lv2plug.in/ns/lv2core#ScalePoint +#define LV2_CORE__SimulatorPlugin LV2_CORE_PREFIX "SimulatorPlugin" ///< http://lv2plug.in/ns/lv2core#SimulatorPlugin +#define LV2_CORE__SpatialPlugin LV2_CORE_PREFIX "SpatialPlugin" ///< http://lv2plug.in/ns/lv2core#SpatialPlugin +#define LV2_CORE__Specification LV2_CORE_PREFIX "Specification" ///< http://lv2plug.in/ns/lv2core#Specification +#define LV2_CORE__SpectralPlugin LV2_CORE_PREFIX "SpectralPlugin" ///< http://lv2plug.in/ns/lv2core#SpectralPlugin +#define LV2_CORE__UtilityPlugin LV2_CORE_PREFIX "UtilityPlugin" ///< http://lv2plug.in/ns/lv2core#UtilityPlugin +#define LV2_CORE__WaveshaperPlugin LV2_CORE_PREFIX "WaveshaperPlugin" ///< http://lv2plug.in/ns/lv2core#WaveshaperPlugin +#define LV2_CORE__appliesTo LV2_CORE_PREFIX "appliesTo" ///< http://lv2plug.in/ns/lv2core#appliesTo +#define LV2_CORE__binary LV2_CORE_PREFIX "binary" ///< http://lv2plug.in/ns/lv2core#binary +#define LV2_CORE__connectionOptional LV2_CORE_PREFIX "connectionOptional" ///< http://lv2plug.in/ns/lv2core#connectionOptional +#define LV2_CORE__control LV2_CORE_PREFIX "control" ///< http://lv2plug.in/ns/lv2core#control +#define LV2_CORE__default LV2_CORE_PREFIX "default" ///< http://lv2plug.in/ns/lv2core#default +#define LV2_CORE__designation LV2_CORE_PREFIX "designation" ///< http://lv2plug.in/ns/lv2core#designation +#define LV2_CORE__documentation LV2_CORE_PREFIX "documentation" ///< http://lv2plug.in/ns/lv2core#documentation +#define LV2_CORE__enumeration LV2_CORE_PREFIX "enumeration" ///< http://lv2plug.in/ns/lv2core#enumeration +#define LV2_CORE__extensionData LV2_CORE_PREFIX "extensionData" ///< http://lv2plug.in/ns/lv2core#extensionData +#define LV2_CORE__freeWheeling LV2_CORE_PREFIX "freeWheeling" ///< http://lv2plug.in/ns/lv2core#freeWheeling +#define LV2_CORE__hardRTCapable LV2_CORE_PREFIX "hardRTCapable" ///< http://lv2plug.in/ns/lv2core#hardRTCapable +#define LV2_CORE__inPlaceBroken LV2_CORE_PREFIX "inPlaceBroken" ///< http://lv2plug.in/ns/lv2core#inPlaceBroken +#define LV2_CORE__index LV2_CORE_PREFIX "index" ///< http://lv2plug.in/ns/lv2core#index +#define LV2_CORE__integer LV2_CORE_PREFIX "integer" ///< http://lv2plug.in/ns/lv2core#integer +#define LV2_CORE__isLive LV2_CORE_PREFIX "isLive" ///< http://lv2plug.in/ns/lv2core#isLive +#define LV2_CORE__latency LV2_CORE_PREFIX "latency" ///< http://lv2plug.in/ns/lv2core#latency +#define LV2_CORE__maximum LV2_CORE_PREFIX "maximum" ///< http://lv2plug.in/ns/lv2core#maximum +#define LV2_CORE__microVersion LV2_CORE_PREFIX "microVersion" ///< http://lv2plug.in/ns/lv2core#microVersion +#define LV2_CORE__minimum LV2_CORE_PREFIX "minimum" ///< http://lv2plug.in/ns/lv2core#minimum +#define LV2_CORE__minorVersion LV2_CORE_PREFIX "minorVersion" ///< http://lv2plug.in/ns/lv2core#minorVersion +#define LV2_CORE__name LV2_CORE_PREFIX "name" ///< http://lv2plug.in/ns/lv2core#name +#define LV2_CORE__optionalFeature LV2_CORE_PREFIX "optionalFeature" ///< http://lv2plug.in/ns/lv2core#optionalFeature +#define LV2_CORE__port LV2_CORE_PREFIX "port" ///< http://lv2plug.in/ns/lv2core#port +#define LV2_CORE__portProperty LV2_CORE_PREFIX "portProperty" ///< http://lv2plug.in/ns/lv2core#portProperty +#define LV2_CORE__project LV2_CORE_PREFIX "project" ///< http://lv2plug.in/ns/lv2core#project +#define LV2_CORE__prototype LV2_CORE_PREFIX "prototype" ///< http://lv2plug.in/ns/lv2core#prototype +#define LV2_CORE__reportsLatency LV2_CORE_PREFIX "reportsLatency" ///< http://lv2plug.in/ns/lv2core#reportsLatency +#define LV2_CORE__requiredFeature LV2_CORE_PREFIX "requiredFeature" ///< http://lv2plug.in/ns/lv2core#requiredFeature +#define LV2_CORE__sampleRate LV2_CORE_PREFIX "sampleRate" ///< http://lv2plug.in/ns/lv2core#sampleRate +#define LV2_CORE__scalePoint LV2_CORE_PREFIX "scalePoint" ///< http://lv2plug.in/ns/lv2core#scalePoint +#define LV2_CORE__symbol LV2_CORE_PREFIX "symbol" ///< http://lv2plug.in/ns/lv2core#symbol +#define LV2_CORE__toggled LV2_CORE_PREFIX "toggled" ///< http://lv2plug.in/ns/lv2core#toggled + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Plugin Instance Handle. + + This is a handle for one particular instance of a plugin. It is valid to + compare to NULL (or 0 for C++) but otherwise the host MUST NOT attempt to + interpret it. +*/ +typedef void * LV2_Handle; + +/** + Feature. + + Features allow hosts to make additional functionality available to plugins + without requiring modification to the LV2 API. Extensions may define new + features and specify the `URI` and `data` to be used if necessary. + Some features, such as lv2:isLive, do not require the host to pass data. +*/ +typedef struct _LV2_Feature { + /** + A globally unique, case-sensitive identifier (URI) for this feature. + + This MUST be a valid URI string as defined by RFC 3986. + */ + const char * URI; + + /** + Pointer to arbitrary data. + + The format of this data is defined by the extension which describes the + feature with the given `URI`. + */ + void * data; +} LV2_Feature; + +/** + Plugin Descriptor. + + This structure provides the core functions necessary to instantiate and use + a plugin. +*/ +typedef struct _LV2_Descriptor { + /** + A globally unique, case-sensitive identifier for this plugin. + + This MUST be a valid URI string as defined by RFC 3986. All plugins with + the same URI MUST be compatible to some degree, see + http://lv2plug.in/ns/lv2core for details. + */ + const char * URI; + + /** + Instantiate the plugin. + + Note that instance initialisation should generally occur in activate() + rather than here. If a host calls instantiate(), it MUST call cleanup() + at some point in the future. + + @param descriptor Descriptor of the plugin to instantiate. + + @param sample_rate Sample rate, in Hz, for the new plugin instance. + + @param bundle_path Path to the LV2 bundle which contains this plugin + binary. It MUST include the trailing directory separator (e.g. '/') so + that simply appending a filename will yield the path to that file in the + bundle. + + @param features A NULL terminated array of LV2_Feature structs which + represent the features the host supports. Plugins may refuse to + instantiate if required features are not found here. However, hosts MUST + NOT use this as a discovery mechanism: instead, use the RDF data to + determine which features are required and do not attempt to instantiate + unsupported plugins at all. This parameter MUST NOT be NULL, i.e. a host + that supports no features MUST pass a single element array containing + NULL. + + @return A handle for the new plugin instance, or NULL if instantiation + has failed. + */ + LV2_Handle (*instantiate)(const struct _LV2_Descriptor * descriptor, + double sample_rate, + const char * bundle_path, + const LV2_Feature *const * features); + + /** + Connect a port on a plugin instance to a memory location. + + Plugin writers should be aware that the host may elect to use the same + buffer for more than one port and even use the same buffer for both + input and output (see lv2:inPlaceBroken in lv2.ttl). + + If the plugin has the feature lv2:hardRTCapable then there are various + things that the plugin MUST NOT do within the connect_port() function; + see lv2core.ttl for details. + + connect_port() MUST be called at least once for each port before run() + is called, unless that port is lv2:connectionOptional. The plugin must + pay careful attention to the block size passed to run() since the block + allocated may only just be large enough to contain the data, and is not + guaranteed to remain constant between run() calls. + + connect_port() may be called more than once for a plugin instance to + allow the host to change the buffers that the plugin is reading or + writing. These calls may be made before or after activate() or + deactivate() calls. + + @param instance Plugin instance containing the port. + + @param port Index of the port to connect. The host MUST NOT try to + connect a port index that is not defined in the plugin's RDF data. If + it does, the plugin's behaviour is undefined (a crash is likely). + + @param data_location Pointer to data of the type defined by the port + type in the plugin's RDF data (e.g. an array of float for an + lv2:AudioPort). This pointer must be stored by the plugin instance and + used to read/write data when run() is called. Data present at the time + of the connect_port() call MUST NOT be considered meaningful. + */ + void (*connect_port)(LV2_Handle instance, + uint32_t port, + void * data_location); + + /** + Initialise a plugin instance and activate it for use. + + This is separated from instantiate() to aid real-time support and so + that hosts can reinitialise a plugin instance by calling deactivate() + and then activate(). In this case the plugin instance MUST reset all + state information dependent on the history of the plugin instance except + for any data locations provided by connect_port(). If there is nothing + for activate() to do then this field may be NULL. + + When present, hosts MUST call this function once before run() is called + for the first time. This call SHOULD be made as close to the run() call + as possible and indicates to real-time plugins that they are now live, + however plugins MUST NOT rely on a prompt call to run() after + activate(). + + The host MUST NOT call activate() again until deactivate() has been + called first. If a host calls activate(), it MUST call deactivate() at + some point in the future. Note that connect_port() may be called before + or after activate(). + */ + void (*activate)(LV2_Handle instance); + + /** + Run a plugin instance for a block. + + Note that if an activate() function exists then it must be called before + run(). If deactivate() is called for a plugin instance then run() may + not be called until activate() has been called again. + + If the plugin has the feature lv2:hardRTCapable then there are various + things that the plugin MUST NOT do within the run() function (see + lv2core.ttl for details). + + As a special case, when `sample_count` is 0, the plugin should update + any output ports that represent a single instant in time (e.g. control + ports, but not audio ports). This is particularly useful for latent + plugins, which should update their latency output port so hosts can + pre-roll plugins to compute latency. Plugins MUST NOT crash when + `sample_count` is 0. + + @param instance Instance to be run. + + @param sample_count The block size (in samples) for which the plugin + instance must run. + */ + void (*run)(LV2_Handle instance, + uint32_t sample_count); + + /** + Deactivate a plugin instance (counterpart to activate()). + + Hosts MUST deactivate all activated instances after they have been run() + for the last time. This call SHOULD be made as close to the last run() + call as possible and indicates to real-time plugins that they are no + longer live, however plugins MUST NOT rely on prompt deactivation. If + there is nothing for deactivate() to do then this field may be NULL + + Deactivation is not similar to pausing since the plugin instance will be + reinitialised by activate(). However, deactivate() itself MUST NOT fully + reset plugin state. For example, the host may deactivate a plugin, then + store its state (using some extension to do so). + + Hosts MUST NOT call deactivate() unless activate() was previously + called. Note that connect_port() may be called before or after + deactivate(). + */ + void (*deactivate)(LV2_Handle instance); + + /** + Clean up a plugin instance (counterpart to instantiate()). + + Once an instance of a plugin has been finished with it must be deleted + using this function. The instance handle passed ceases to be valid after + this call. + + If activate() was called for a plugin instance then a corresponding call + to deactivate() MUST be made before cleanup() is called. Hosts MUST NOT + call cleanup() unless instantiate() was previously called. + */ + void (*cleanup)(LV2_Handle instance); + + /** + Return additional plugin data defined by some extenion. + + A typical use of this facility is to return a struct containing function + pointers to extend the LV2_Descriptor API. + + The actual type and meaning of the returned object MUST be specified + precisely by the extension. This function MUST return NULL for any + unsupported URI. If a plugin does not support any extension data, this + field may be NULL. + + The host is never responsible for freeing the returned value. + */ + const void * (*extension_data)(const char * uri); +} LV2_Descriptor; + +/** + Helper macro needed for LV2_SYMBOL_EXPORT when using C++. +*/ +#ifdef __cplusplus +# define LV2_SYMBOL_EXTERN extern "C" +#else +# define LV2_SYMBOL_EXTERN +#endif + +/** + Put this (LV2_SYMBOL_EXPORT) before any functions that are to be loaded + by the host as a symbol from the dynamic library. +*/ +#if defined(__EMSCRIPTEN__) +# define LV2_SYMBOL_EXPORT LV2_SYMBOL_EXTERN __attribute__((used)) +#elif defined(_WIN32) +# define LV2_SYMBOL_EXPORT LV2_SYMBOL_EXTERN __declspec(dllexport) +#else +# define LV2_SYMBOL_EXPORT LV2_SYMBOL_EXTERN __attribute__((visibility("default"))) +#endif + +/** + Prototype for plugin accessor function. + + Plugins are discovered by hosts using RDF data (not by loading libraries). + See http://lv2plug.in for details on the discovery process, though most + hosts should use an existing library to implement this functionality. + + This is the simple plugin discovery API, suitable for most statically + defined plugins. Advanced plugins that need access to their bundle during + discovery can use lv2_lib_descriptor() instead. Plugin libraries MUST + include a function called "lv2_descriptor" or "lv2_lib_descriptor" with + C-style linkage, but SHOULD provide "lv2_descriptor" wherever possible. + + When it is time to load a plugin (designated by its URI), the host loads the + plugin's library, gets the lv2_descriptor() function from it, and uses this + function to find the LV2_Descriptor for the desired plugin. Plugins are + accessed by index using values from 0 upwards. This function MUST return + NULL for out of range indices, so the host can enumerate plugins by + increasing `index` until NULL is returned. + + Note that `index` has no meaning, hosts MUST NOT depend on it remaining + consistent between loads of the plugin library. +*/ +LV2_SYMBOL_EXPORT +const LV2_Descriptor * lv2_descriptor(uint32_t index); + +/** + Type of the lv2_descriptor() function in a library (old discovery API). +*/ +typedef const LV2_Descriptor * +(*LV2_Descriptor_Function)(uint32_t index); + +/** + Handle for a library descriptor. +*/ +typedef void* LV2_Lib_Handle; + +/** + Descriptor for a plugin library. + + To access a plugin library, the host creates an LV2_Lib_Descriptor via the + lv2_lib_descriptor() function in the shared object. +*/ +typedef struct { + /** + Opaque library data which must be passed as the first parameter to all + the methods of this struct. + */ + LV2_Lib_Handle handle; + + /** + The total size of this struct. This allows for this struct to be + expanded in the future if necessary. This MUST be set by the library to + sizeof(LV2_Lib_Descriptor). The host MUST NOT access any fields of this + struct beyond get_plugin() unless this field indicates they are present. + */ + uint32_t size; + + /** + Destroy this library descriptor and free all related resources. + */ + void (*cleanup)(LV2_Lib_Handle handle); + + /** + Plugin accessor. + + Plugins are accessed by index using values from 0 upwards. Out of range + indices MUST result in this function returning NULL, so the host can + enumerate plugins by increasing `index` until NULL is returned. + */ + const LV2_Descriptor * (*get_plugin)(LV2_Lib_Handle handle, + uint32_t index); +} LV2_Lib_Descriptor; + +/** + Prototype for library accessor function. + + This is the more advanced discovery API, which allows plugin libraries to + access their bundles during discovery, which makes it possible for plugins to + be dynamically defined by files in their bundle. This API also has an + explicit cleanup function, removing any need for non-portable shared library + destructors. Simple plugins that do not require these features may use + lv2_descriptor() instead. + + This is the entry point for a plugin library. Hosts load this symbol from + the library and call this function to obtain a library descriptor which can + be used to access all the contained plugins. The returned object must not + be destroyed (using LV2_Lib_Descriptor::cleanup()) until all plugins loaded + from that library have been destroyed. +*/ +LV2_SYMBOL_EXPORT +const LV2_Lib_Descriptor * +lv2_lib_descriptor(const char * bundle_path, + const LV2_Feature *const * features); + +/** + Type of the lv2_lib_descriptor() function in an LV2 library. +*/ +typedef const LV2_Lib_Descriptor * +(*LV2_Lib_Descriptor_Function)(const char * bundle_path, + const LV2_Feature *const * features); + +#ifdef __cplusplus +} +#endif + +#endif /* LV2_H_INCLUDED */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_external_ui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_external_ui.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,109 @@ +/* + LV2 External UI extension + This work is in public domain. + + This file 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. + + If you have questions, contact Filipe Coelho (aka falkTX) + or ask in #lad channel, FreeNode IRC network. +*/ + +/** + @file lv2_external_ui.h + C header for the LV2 External UI extension . +*/ + +#ifndef LV2_EXTERNAL_UI_H +#define LV2_EXTERNAL_UI_H + +#include "ui.h" + +#define LV2_EXTERNAL_UI_URI "http://kxstudio.sf.net/ns/lv2ext/external-ui" +#define LV2_EXTERNAL_UI_PREFIX LV2_EXTERNAL_UI_URI "#" + +#define LV2_EXTERNAL_UI__Host LV2_EXTERNAL_UI_PREFIX "Host" +#define LV2_EXTERNAL_UI__Widget LV2_EXTERNAL_UI_PREFIX "Widget" + +/** This extension used to be defined by a lv2plug.in URI */ +#define LV2_EXTERNAL_UI_DEPRECATED_URI "http://lv2plug.in/ns/extensions/ui#external" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * When LV2_EXTERNAL_UI__Widget UI is instantiated, the returned + * LV2UI_Widget handle must be cast to pointer to LV2_External_UI_Widget. + * UI is created in invisible state. + */ +typedef struct _LV2_External_UI_Widget { + /** + * Host calls this function regulary. UI library implementing the + * callback may do IPC or redraw the UI. + * + * @param _this_ the UI context + */ + void (*run)(struct _LV2_External_UI_Widget * _this_); + + /** + * Host calls this function to make the plugin UI visible. + * + * @param _this_ the UI context + */ + void (*show)(struct _LV2_External_UI_Widget * _this_); + + /** + * Host calls this function to make the plugin UI invisible again. + * + * @param _this_ the UI context + */ + void (*hide)(struct _LV2_External_UI_Widget * _this_); + +} LV2_External_UI_Widget; + +#define LV2_EXTERNAL_UI_RUN(ptr) (ptr)->run(ptr) +#define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr) +#define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr) + +/** + * On UI instantiation, host must supply LV2_EXTERNAL_UI__Host feature. + * LV2_Feature::data must be pointer to LV2_External_UI_Host. + */ +typedef struct _LV2_External_UI_Host { + /** + * Callback that plugin UI will call when UI (GUI window) is closed by user. + * This callback will be called during execution of LV2_External_UI_Widget::run() + * (i.e. not from background thread). + * + * After this callback is called, UI is defunct. Host must call LV2UI_Descriptor::cleanup(). + * If host wants to make the UI visible again, the UI must be reinstantiated. + * + * @note When using the depreated URI LV2_EXTERNAL_UI_DEPRECATED_URI, + * some hosts will not call LV2UI_Descriptor::cleanup() as they should, + * and may call show() again without re-initialization. + * + * @param controller Host context associated with plugin UI, as + * supplied to LV2UI_Descriptor::instantiate(). + */ + void (*ui_closed)(LV2UI_Controller controller); + + /** + * Optional (may be NULL) "user friendly" identifier which the UI + * may display to allow a user to easily associate this particular + * UI instance with the correct plugin instance as it is represented + * by the host (e.g. "track 1" or "channel 4"). + * + * If supplied by host, the string will be referenced only during + * LV2UI_Descriptor::instantiate() + */ + const char * plugin_human_id; + +} LV2_External_UI_Host; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_EXTERNAL_UI_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_kxstudio_properties.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_kxstudio_properties.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,33 @@ +/* + LV2 KXStudio Properties Extension + Copyright 2014-2021 Filipe Coelho + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file lv2_kxstudio_properties.h + C header for the LV2 KXStudio Properties extension . +*/ + +#ifndef LV2_KXSTUDIO_PROPERTIES_H +#define LV2_KXSTUDIO_PROPERTIES_H + +#define LV2_KXSTUDIO_PROPERTIES_URI "http://kxstudio.sf.net/ns/lv2ext/props" +#define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#" + +#define LV2_KXSTUDIO_PROPERTIES__NonAutomatable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomatable" +#define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat" +#define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId" + +#endif /* LV2_KXSTUDIO_PROPERTIES_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_programs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_programs.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,174 @@ +/* + LV2 Programs Extension + Copyright 2012 Filipe Coelho + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file lv2_programs.h + C header for the LV2 programs extension . +*/ + +#ifndef LV2_PROGRAMS_H +#define LV2_PROGRAMS_H + +#include "lv2.h" +#include "ui.h" + +#define LV2_PROGRAMS_URI "http://kxstudio.sf.net/ns/lv2ext/programs" +#define LV2_PROGRAMS_PREFIX LV2_PROGRAMS_URI "#" + +#define LV2_PROGRAMS__Host LV2_PROGRAMS_PREFIX "Host" +#define LV2_PROGRAMS__Interface LV2_PROGRAMS_PREFIX "Interface" +#define LV2_PROGRAMS__UIInterface LV2_PROGRAMS_PREFIX "UIInterface" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* LV2_Programs_Handle; + +typedef struct _LV2_Program_Descriptor { + + /** Bank number for this program. Note that this extension does not + support MIDI-style separation of bank LSB and MSB values. There is + no restriction on the set of available banks: the numbers do not + need to be contiguous, there does not need to be a bank 0, etc. */ + uint32_t bank; + + /** Program number (unique within its bank) for this program. There is + no restriction on the set of available programs: the numbers do not + need to be contiguous, there does not need to be a program 0, etc. */ + uint32_t program; + + /** Name of the program. */ + const char * name; + +} LV2_Program_Descriptor; + +/** + Programs extension, plugin data. + + When the plugin's extension_data is called with argument LV2_PROGRAMS__Interface, + the plugin MUST return an LV2_Programs_Instance structure, which remains valid + for the lifetime of the plugin. +*/ +typedef struct _LV2_Programs_Interface { + /** + * get_program() + * + * This member is a function pointer that provides a description + * of a program (named preset sound) available on this plugin. + * + * The index argument is an index into the plugin's list of + * programs, not a program number as represented by the Program + * field of the LV2_Program_Descriptor. (This distinction is + * needed to support plugins that use non-contiguous program or + * bank numbers.) + * + * This function returns a LV2_Program_Descriptor pointer that is + * guaranteed to be valid only until the next call to get_program + * or deactivate, on the same plugin instance. This function must + * return NULL if passed an index argument out of range, so that + * the host can use it to query the number of programs as well as + * their properties. + */ + const LV2_Program_Descriptor *(*get_program)(LV2_Handle handle, + uint32_t index); + + /** + * select_program() + * + * This member is a function pointer that selects a new program + * for this plugin. The program change should take effect + * immediately at the start of the next run() call. (This + * means that a host providing the capability of changing programs + * between any two notes on a track must vary the block size so as + * to place the program change at the right place. A host that + * wanted to avoid this would probably just instantiate a plugin + * for each program.) + * + * Plugins should ignore a select_program() call with an invalid + * bank or program. + * + * A plugin is not required to select any particular default + * program on activate(): it's the host's duty to set a program + * explicitly. + * + * A plugin is permitted to re-write the values of its input + * control ports when select_program is called. The host should + * re-read the input control port values and update its own + * records appropriately. (This is the only circumstance in which + * a LV2 plugin is allowed to modify its own control-input ports.) + */ + void (*select_program)(LV2_Handle handle, + uint32_t bank, + uint32_t program); + +} LV2_Programs_Interface; + +/** + Programs extension, UI data. + + When the UI's extension_data is called with argument LV2_PROGRAMS__UIInterface, + the UI MUST return an LV2_Programs_UI_Interface structure, which remains valid + for the lifetime of the UI. +*/ +typedef struct _LV2_Programs_UI_Interface { + /** + * select_program() + * + * This is exactly the same as select_program in LV2_Programs_Instance, + * but this struct relates to the UI instead of the plugin. + * + * When called, UIs should update their state to match the selected program. + */ + void (*select_program)(LV2UI_Handle handle, + uint32_t bank, + uint32_t program); + +} LV2_Programs_UI_Interface; + +/** + Feature data for LV2_PROGRAMS__Host. +*/ +typedef struct _LV2_Programs_Host { + /** + * Opaque host data. + */ + LV2_Programs_Handle handle; + + /** + * program_changed() + * + * Tell the host to reload a plugin's program. + * Parameter handle MUST be the 'handle' member of this struct. + * Parameter index is program index to change. + * When index is -1, host should reload all the programs. + * + * The plugin MUST NEVER call this function on a RT context or during run(). + * + * NOTE: This call is to inform the host about a program's bank, program or name change. + * It DOES NOT change the current selected program. + */ + void (*program_changed)(LV2_Programs_Handle handle, + int32_t index); + +} LV2_Programs_Host; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_PROGRAMS_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_rtmempool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/lv2_rtmempool.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,119 @@ +/* + LV2 realtime safe memory pool extension definition + This work is in public domain. + + This file 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. + + If you have questions, contact Filipe Coelho (aka falkTX) + or ask in #lad channel, FreeNode IRC network. +*/ + +/** + * @file lv2_rtmempool.h + * C header for the LV2 rtmempool extension . + * + */ + +#ifndef LV2_RTMEMPOOL_H +#define LV2_RTMEMPOOL_H + +#define LV2_RTSAFE_MEMORY_POOL_URI "http://kxstudio.sf.net/ns/lv2ext/rtmempool" +#define LV2_RTSAFE_MEMORY_POOL_PREFIX LV2_RTSAFE_MEMORY_POOL_URI "#" + +#define LV2_RTSAFE_MEMORY_POOL__Pool LV2_RTSAFE_MEMORY_POOL_URI "Pool" + +/** max size of memory pool name, in chars, including terminating zero char */ +#define LV2_RTSAFE_MEMORY_POOL_NAME_MAX 128 + +/** This extension used to be defined by a different URI */ +#define LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI "http://home.gna.org/lv2dynparam/rtmempool/v1" + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +/** + * Opaque data to host data for LV2_RtMemPool_Pool. + */ +typedef void* LV2_RtMemPool_Handle; + +/** + * On instantiation, host must supply LV2_RTSAFE_MEMORY_POOL__Pool feature. + * LV2_Feature::data must be pointer to LV2_RtMemPool_Pool. + */ +typedef struct _LV2_RtMemPool_Pool { + /** + * This function is called when plugin wants to create memory pool + * + * may/will sleep + * + * @param pool_name pool name, for debug purposes, max RTSAFE_MEMORY_POOL_NAME_MAX chars, including terminating zero char. May be NULL. + * @param data_size memory chunk size + * @param min_preallocated min chunks preallocated + * @param max_preallocated max chunks preallocated + * + * @return Success status, true if successful + */ + bool (*create)(LV2_RtMemPool_Handle * handle_ptr, + const char * pool_name, + size_t data_size, + size_t min_preallocated, + size_t max_preallocated); + + /** + * This function is called when plugin wants to destroy previously created memory pool + * + * may/will sleep + */ + void (*destroy)(LV2_RtMemPool_Handle handle); + + /** + * This function is called when plugin wants to allocate memory in context where sleeping is not allowed + * + * will not sleep + * + * @return Pointer to allocated memory or NULL if memory no memory is available + */ + void * (*allocate_atomic)(LV2_RtMemPool_Handle handle); + + /** + * This function is called when plugin wants to allocate memory in context where sleeping is allowed + * + * may/will sleep + * + * @return Pointer to allocated memory or NULL if memory no memory is available (should not happen under normal conditions) + */ + void * (*allocate_sleepy)(LV2_RtMemPool_Handle handle); + + /** + * This function is called when plugin wants to deallocate previously allocated memory + * + * will not sleep + * + * @param memory_ptr pointer to previously allocated memory chunk + */ + void (*deallocate)(LV2_RtMemPool_Handle handle, + void * memory_ptr); + +} LV2_RtMemPool_Pool; + +/** + * Deprecated feature for backwards compatibility. + */ +typedef struct _LV2_RtMemPool_Pool_Deprecated { + unsigned char (*create)(const char*,size_t,size_t,size_t,LV2_RtMemPool_Handle*); + void (*destroy)(LV2_RtMemPool_Handle); + void* (*allocate_atomic)(LV2_RtMemPool_Handle); + void* (*allocate_sleepy)(LV2_RtMemPool_Handle); + void (*deallocate)(LV2_RtMemPool_Handle,void*); +} LV2_RtMemPool_Pool_Deprecated; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_RTMEMPOOL_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/midi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/midi.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,234 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup midi MIDI + + Definitions of standard MIDI messages, see + for details. + + @{ +*/ + +#ifndef LV2_MIDI_H +#define LV2_MIDI_H + +#include + +#ifdef __cplusplus +extern "C" { +#else +# include +#endif + +#define LV2_MIDI_URI "http://lv2plug.in/ns/ext/midi" ///< http://lv2plug.in/ns/ext/midi +#define LV2_MIDI_PREFIX LV2_MIDI_URI "#" ///< http://lv2plug.in/ns/ext/midi# + +#define LV2_MIDI__ActiveSense LV2_MIDI_PREFIX "ActiveSense" ///< http://lv2plug.in/ns/ext/midi#ActiveSense +#define LV2_MIDI__Aftertouch LV2_MIDI_PREFIX "Aftertouch" ///< http://lv2plug.in/ns/ext/midi#Aftertouch +#define LV2_MIDI__Bender LV2_MIDI_PREFIX "Bender" ///< http://lv2plug.in/ns/ext/midi#Bender +#define LV2_MIDI__ChannelPressure LV2_MIDI_PREFIX "ChannelPressure" ///< http://lv2plug.in/ns/ext/midi#ChannelPressure +#define LV2_MIDI__Chunk LV2_MIDI_PREFIX "Chunk" ///< http://lv2plug.in/ns/ext/midi#Chunk +#define LV2_MIDI__Clock LV2_MIDI_PREFIX "Clock" ///< http://lv2plug.in/ns/ext/midi#Clock +#define LV2_MIDI__Continue LV2_MIDI_PREFIX "Continue" ///< http://lv2plug.in/ns/ext/midi#Continue +#define LV2_MIDI__Controller LV2_MIDI_PREFIX "Controller" ///< http://lv2plug.in/ns/ext/midi#Controller +#define LV2_MIDI__MidiEvent LV2_MIDI_PREFIX "MidiEvent" ///< http://lv2plug.in/ns/ext/midi#MidiEvent +#define LV2_MIDI__NoteOff LV2_MIDI_PREFIX "NoteOff" ///< http://lv2plug.in/ns/ext/midi#NoteOff +#define LV2_MIDI__NoteOn LV2_MIDI_PREFIX "NoteOn" ///< http://lv2plug.in/ns/ext/midi#NoteOn +#define LV2_MIDI__ProgramChange LV2_MIDI_PREFIX "ProgramChange" ///< http://lv2plug.in/ns/ext/midi#ProgramChange +#define LV2_MIDI__QuarterFrame LV2_MIDI_PREFIX "QuarterFrame" ///< http://lv2plug.in/ns/ext/midi#QuarterFrame +#define LV2_MIDI__Reset LV2_MIDI_PREFIX "Reset" ///< http://lv2plug.in/ns/ext/midi#Reset +#define LV2_MIDI__SongPosition LV2_MIDI_PREFIX "SongPosition" ///< http://lv2plug.in/ns/ext/midi#SongPosition +#define LV2_MIDI__SongSelect LV2_MIDI_PREFIX "SongSelect" ///< http://lv2plug.in/ns/ext/midi#SongSelect +#define LV2_MIDI__Start LV2_MIDI_PREFIX "Start" ///< http://lv2plug.in/ns/ext/midi#Start +#define LV2_MIDI__Stop LV2_MIDI_PREFIX "Stop" ///< http://lv2plug.in/ns/ext/midi#Stop +#define LV2_MIDI__SystemCommon LV2_MIDI_PREFIX "SystemCommon" ///< http://lv2plug.in/ns/ext/midi#SystemCommon +#define LV2_MIDI__SystemExclusive LV2_MIDI_PREFIX "SystemExclusive" ///< http://lv2plug.in/ns/ext/midi#SystemExclusive +#define LV2_MIDI__SystemMessage LV2_MIDI_PREFIX "SystemMessage" ///< http://lv2plug.in/ns/ext/midi#SystemMessage +#define LV2_MIDI__SystemRealtime LV2_MIDI_PREFIX "SystemRealtime" ///< http://lv2plug.in/ns/ext/midi#SystemRealtime +#define LV2_MIDI__Tick LV2_MIDI_PREFIX "Tick" ///< http://lv2plug.in/ns/ext/midi#Tick +#define LV2_MIDI__TuneRequest LV2_MIDI_PREFIX "TuneRequest" ///< http://lv2plug.in/ns/ext/midi#TuneRequest +#define LV2_MIDI__VoiceMessage LV2_MIDI_PREFIX "VoiceMessage" ///< http://lv2plug.in/ns/ext/midi#VoiceMessage +#define LV2_MIDI__benderValue LV2_MIDI_PREFIX "benderValue" ///< http://lv2plug.in/ns/ext/midi#benderValue +#define LV2_MIDI__binding LV2_MIDI_PREFIX "binding" ///< http://lv2plug.in/ns/ext/midi#binding +#define LV2_MIDI__byteNumber LV2_MIDI_PREFIX "byteNumber" ///< http://lv2plug.in/ns/ext/midi#byteNumber +#define LV2_MIDI__channel LV2_MIDI_PREFIX "channel" ///< http://lv2plug.in/ns/ext/midi#channel +#define LV2_MIDI__chunk LV2_MIDI_PREFIX "chunk" ///< http://lv2plug.in/ns/ext/midi#chunk +#define LV2_MIDI__controllerNumber LV2_MIDI_PREFIX "controllerNumber" ///< http://lv2plug.in/ns/ext/midi#controllerNumber +#define LV2_MIDI__controllerValue LV2_MIDI_PREFIX "controllerValue" ///< http://lv2plug.in/ns/ext/midi#controllerValue +#define LV2_MIDI__noteNumber LV2_MIDI_PREFIX "noteNumber" ///< http://lv2plug.in/ns/ext/midi#noteNumber +#define LV2_MIDI__pressure LV2_MIDI_PREFIX "pressure" ///< http://lv2plug.in/ns/ext/midi#pressure +#define LV2_MIDI__programNumber LV2_MIDI_PREFIX "programNumber" ///< http://lv2plug.in/ns/ext/midi#programNumber +#define LV2_MIDI__property LV2_MIDI_PREFIX "property" ///< http://lv2plug.in/ns/ext/midi#property +#define LV2_MIDI__songNumber LV2_MIDI_PREFIX "songNumber" ///< http://lv2plug.in/ns/ext/midi#songNumber +#define LV2_MIDI__songPosition LV2_MIDI_PREFIX "songPosition" ///< http://lv2plug.in/ns/ext/midi#songPosition +#define LV2_MIDI__status LV2_MIDI_PREFIX "status" ///< http://lv2plug.in/ns/ext/midi#status +#define LV2_MIDI__statusMask LV2_MIDI_PREFIX "statusMask" ///< http://lv2plug.in/ns/ext/midi#statusMask +#define LV2_MIDI__velocity LV2_MIDI_PREFIX "velocity" ///< http://lv2plug.in/ns/ext/midi#velocity + +/** + MIDI Message Type. + + This includes both voice messages (which have a channel) and system messages + (which do not), as well as a sentinel value for invalid messages. To get + the type of a message suitable for use in a switch statement, use + lv2_midi_get_type() on the status byte. +*/ +typedef enum { + LV2_MIDI_MSG_INVALID = 0, /**< Invalid Message */ + LV2_MIDI_MSG_NOTE_OFF = 0x80, /**< Note Off */ + LV2_MIDI_MSG_NOTE_ON = 0x90, /**< Note On */ + LV2_MIDI_MSG_NOTE_PRESSURE = 0xA0, /**< Note Pressure */ + LV2_MIDI_MSG_CONTROLLER = 0xB0, /**< Controller */ + LV2_MIDI_MSG_PGM_CHANGE = 0xC0, /**< Program Change */ + LV2_MIDI_MSG_CHANNEL_PRESSURE = 0xD0, /**< Channel Pressure */ + LV2_MIDI_MSG_BENDER = 0xE0, /**< Pitch Bender */ + LV2_MIDI_MSG_SYSTEM_EXCLUSIVE = 0xF0, /**< System Exclusive Begin */ + LV2_MIDI_MSG_MTC_QUARTER = 0xF1, /**< MTC Quarter Frame */ + LV2_MIDI_MSG_SONG_POS = 0xF2, /**< Song Position */ + LV2_MIDI_MSG_SONG_SELECT = 0xF3, /**< Song Select */ + LV2_MIDI_MSG_TUNE_REQUEST = 0xF6, /**< Tune Request */ + LV2_MIDI_MSG_CLOCK = 0xF8, /**< Clock */ + LV2_MIDI_MSG_START = 0xFA, /**< Start */ + LV2_MIDI_MSG_CONTINUE = 0xFB, /**< Continue */ + LV2_MIDI_MSG_STOP = 0xFC, /**< Stop */ + LV2_MIDI_MSG_ACTIVE_SENSE = 0xFE, /**< Active Sensing */ + LV2_MIDI_MSG_RESET = 0xFF /**< Reset */ +} LV2_Midi_Message_Type; + +/** + Standard MIDI Controller Numbers. +*/ +typedef enum { + LV2_MIDI_CTL_MSB_BANK = 0x00, /**< Bank Selection */ + LV2_MIDI_CTL_MSB_MODWHEEL = 0x01, /**< Modulation */ + LV2_MIDI_CTL_MSB_BREATH = 0x02, /**< Breath */ + LV2_MIDI_CTL_MSB_FOOT = 0x04, /**< Foot */ + LV2_MIDI_CTL_MSB_PORTAMENTO_TIME = 0x05, /**< Portamento Time */ + LV2_MIDI_CTL_MSB_DATA_ENTRY = 0x06, /**< Data Entry */ + LV2_MIDI_CTL_MSB_MAIN_VOLUME = 0x07, /**< Main Volume */ + LV2_MIDI_CTL_MSB_BALANCE = 0x08, /**< Balance */ + LV2_MIDI_CTL_MSB_PAN = 0x0A, /**< Panpot */ + LV2_MIDI_CTL_MSB_EXPRESSION = 0x0B, /**< Expression */ + LV2_MIDI_CTL_MSB_EFFECT1 = 0x0C, /**< Effect1 */ + LV2_MIDI_CTL_MSB_EFFECT2 = 0x0D, /**< Effect2 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE1 = 0x10, /**< General Purpose 1 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE2 = 0x11, /**< General Purpose 2 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE3 = 0x12, /**< General Purpose 3 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE4 = 0x13, /**< General Purpose 4 */ + LV2_MIDI_CTL_LSB_BANK = 0x20, /**< Bank Selection */ + LV2_MIDI_CTL_LSB_MODWHEEL = 0x21, /**< Modulation */ + LV2_MIDI_CTL_LSB_BREATH = 0x22, /**< Breath */ + LV2_MIDI_CTL_LSB_FOOT = 0x24, /**< Foot */ + LV2_MIDI_CTL_LSB_PORTAMENTO_TIME = 0x25, /**< Portamento Time */ + LV2_MIDI_CTL_LSB_DATA_ENTRY = 0x26, /**< Data Entry */ + LV2_MIDI_CTL_LSB_MAIN_VOLUME = 0x27, /**< Main Volume */ + LV2_MIDI_CTL_LSB_BALANCE = 0x28, /**< Balance */ + LV2_MIDI_CTL_LSB_PAN = 0x2A, /**< Panpot */ + LV2_MIDI_CTL_LSB_EXPRESSION = 0x2B, /**< Expression */ + LV2_MIDI_CTL_LSB_EFFECT1 = 0x2C, /**< Effect1 */ + LV2_MIDI_CTL_LSB_EFFECT2 = 0x2D, /**< Effect2 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE1 = 0x30, /**< General Purpose 1 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE2 = 0x31, /**< General Purpose 2 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE3 = 0x32, /**< General Purpose 3 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE4 = 0x33, /**< General Purpose 4 */ + LV2_MIDI_CTL_SUSTAIN = 0x40, /**< Sustain Pedal */ + LV2_MIDI_CTL_PORTAMENTO = 0x41, /**< Portamento */ + LV2_MIDI_CTL_SOSTENUTO = 0x42, /**< Sostenuto */ + LV2_MIDI_CTL_SOFT_PEDAL = 0x43, /**< Soft Pedal */ + LV2_MIDI_CTL_LEGATO_FOOTSWITCH = 0x44, /**< Legato Foot Switch */ + LV2_MIDI_CTL_HOLD2 = 0x45, /**< Hold2 */ + LV2_MIDI_CTL_SC1_SOUND_VARIATION = 0x46, /**< SC1 Sound Variation */ + LV2_MIDI_CTL_SC2_TIMBRE = 0x47, /**< SC2 Timbre */ + LV2_MIDI_CTL_SC3_RELEASE_TIME = 0x48, /**< SC3 Release Time */ + LV2_MIDI_CTL_SC4_ATTACK_TIME = 0x49, /**< SC4 Attack Time */ + LV2_MIDI_CTL_SC5_BRIGHTNESS = 0x4A, /**< SC5 Brightness */ + LV2_MIDI_CTL_SC6 = 0x4B, /**< SC6 */ + LV2_MIDI_CTL_SC7 = 0x4C, /**< SC7 */ + LV2_MIDI_CTL_SC8 = 0x4D, /**< SC8 */ + LV2_MIDI_CTL_SC9 = 0x4E, /**< SC9 */ + LV2_MIDI_CTL_SC10 = 0x4F, /**< SC10 */ + LV2_MIDI_CTL_GENERAL_PURPOSE5 = 0x50, /**< General Purpose 5 */ + LV2_MIDI_CTL_GENERAL_PURPOSE6 = 0x51, /**< General Purpose 6 */ + LV2_MIDI_CTL_GENERAL_PURPOSE7 = 0x52, /**< General Purpose 7 */ + LV2_MIDI_CTL_GENERAL_PURPOSE8 = 0x53, /**< General Purpose 8 */ + LV2_MIDI_CTL_PORTAMENTO_CONTROL = 0x54, /**< Portamento Control */ + LV2_MIDI_CTL_E1_REVERB_DEPTH = 0x5B, /**< E1 Reverb Depth */ + LV2_MIDI_CTL_E2_TREMOLO_DEPTH = 0x5C, /**< E2 Tremolo Depth */ + LV2_MIDI_CTL_E3_CHORUS_DEPTH = 0x5D, /**< E3 Chorus Depth */ + LV2_MIDI_CTL_E4_DETUNE_DEPTH = 0x5E, /**< E4 Detune Depth */ + LV2_MIDI_CTL_E5_PHASER_DEPTH = 0x5F, /**< E5 Phaser Depth */ + LV2_MIDI_CTL_DATA_INCREMENT = 0x60, /**< Data Increment */ + LV2_MIDI_CTL_DATA_DECREMENT = 0x61, /**< Data Decrement */ + LV2_MIDI_CTL_NRPN_LSB = 0x62, /**< Non-registered Parameter Number */ + LV2_MIDI_CTL_NRPN_MSB = 0x63, /**< Non-registered Parameter Number */ + LV2_MIDI_CTL_RPN_LSB = 0x64, /**< Registered Parameter Number */ + LV2_MIDI_CTL_RPN_MSB = 0x65, /**< Registered Parameter Number */ + LV2_MIDI_CTL_ALL_SOUNDS_OFF = 0x78, /**< All Sounds Off */ + LV2_MIDI_CTL_RESET_CONTROLLERS = 0x79, /**< Reset Controllers */ + LV2_MIDI_CTL_LOCAL_CONTROL_SWITCH = 0x7A, /**< Local Control Switch */ + LV2_MIDI_CTL_ALL_NOTES_OFF = 0x7B, /**< All Notes Off */ + LV2_MIDI_CTL_OMNI_OFF = 0x7C, /**< Omni Off */ + LV2_MIDI_CTL_OMNI_ON = 0x7D, /**< Omni On */ + LV2_MIDI_CTL_MONO1 = 0x7E, /**< Mono1 */ + LV2_MIDI_CTL_MONO2 = 0x7F /**< Mono2 */ +} LV2_Midi_Controller; + +/** + Return true iff `msg` is a MIDI voice message (which has a channel). +*/ +static inline bool +lv2_midi_is_voice_message(const uint8_t* msg) { + return msg[0] >= 0x80 && msg[0] < 0xF0; +} + +/** + Return true iff `msg` is a MIDI system message (which has no channel). +*/ +static inline bool +lv2_midi_is_system_message(const uint8_t* msg) { + switch (msg[0]) { + case 0xF4: case 0xF5: case 0xF7: case 0xF9: case 0xFD: + return false; + default: + return (msg[0] & 0xF0) == 0xF0; + } +} + +/** + Return the type of a MIDI message. + @param msg Pointer to the start (status byte) of a MIDI message. +*/ +static inline LV2_Midi_Message_Type +lv2_midi_message_type(const uint8_t* msg) { + if (lv2_midi_is_voice_message(msg)) { + return (LV2_Midi_Message_Type)(msg[0] & 0xF0); + } else if (lv2_midi_is_system_message(msg)) { + return (LV2_Midi_Message_Type)msg[0]; + } else { + return LV2_MIDI_MSG_INVALID; + } +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_MIDI_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/morph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/morph.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,42 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup morph Morph + + Ports that can dynamically change type, see + for details. + + @{ +*/ + +#ifndef LV2_MORPH_H +#define LV2_MORPH_H + +#define LV2_MORPH_URI "http://lv2plug.in/ns/ext/morph" ///< http://lv2plug.in/ns/ext/morph +#define LV2_MORPH_PREFIX LV2_MORPH_URI "#" ///< http://lv2plug.in/ns/ext/morph# + +#define LV2_MORPH__AutoMorphPort LV2_MORPH_PREFIX "AutoMorphPort" ///< http://lv2plug.in/ns/ext/morph#AutoMorphPort +#define LV2_MORPH__MorphPort LV2_MORPH_PREFIX "MorphPort" ///< http://lv2plug.in/ns/ext/morph#MorphPort +#define LV2_MORPH__interface LV2_MORPH_PREFIX "interface" ///< http://lv2plug.in/ns/ext/morph#interface +#define LV2_MORPH__supportsType LV2_MORPH_PREFIX "supportsType" ///< http://lv2plug.in/ns/ext/morph#supportsType +#define LV2_MORPH__currentType LV2_MORPH_PREFIX "currentType" ///< http://lv2plug.in/ns/ext/morph#currentType + +#endif /* LV2_MORPH_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/options.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/options.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,145 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup options Options + + Instantiation time options, see for + details. + + @{ +*/ + +#ifndef LV2_OPTIONS_H +#define LV2_OPTIONS_H + +#include + +#include "urid.h" +#include "lv2.h" + +#define LV2_OPTIONS_URI "http://lv2plug.in/ns/ext/options" ///< http://lv2plug.in/ns/ext/options +#define LV2_OPTIONS_PREFIX LV2_OPTIONS_URI "#" ///< http://lv2plug.in/ns/ext/options# + +#define LV2_OPTIONS__Option LV2_OPTIONS_PREFIX "Option" ///< http://lv2plug.in/ns/ext/options#Option +#define LV2_OPTIONS__interface LV2_OPTIONS_PREFIX "interface" ///< http://lv2plug.in/ns/ext/options#interface +#define LV2_OPTIONS__options LV2_OPTIONS_PREFIX "options" ///< http://lv2plug.in/ns/ext/options#options +#define LV2_OPTIONS__requiredOption LV2_OPTIONS_PREFIX "requiredOption" ///< http://lv2plug.in/ns/ext/options#requiredOption +#define LV2_OPTIONS__supportedOption LV2_OPTIONS_PREFIX "supportedOption" ///< http://lv2plug.in/ns/ext/options#supportedOption + +#ifdef __cplusplus +extern "C" { +#endif + +/** + The context of an Option, which defines the subject it applies to. +*/ +typedef enum { + /** + This option applies to the instance itself. The subject must be + ignored. + */ + LV2_OPTIONS_INSTANCE, + + /** + This option applies to some named resource. The subject is a URI mapped + to an integer (a LV2_URID, like the key) + */ + LV2_OPTIONS_RESOURCE, + + /** + This option applies to some blank node. The subject is a blank node + identifier, which is valid only within the current local scope. + */ + LV2_OPTIONS_BLANK, + + /** + This option applies to a port on the instance. The subject is the + port's index. + */ + LV2_OPTIONS_PORT +} LV2_Options_Context; + +/** + An option. + + This is a property with a subject, also known as a triple or statement. + + This struct is useful anywhere a statement needs to be passed where no + memory ownership issues are present (since the value is a const pointer). + + Options can be passed to an instance via the feature LV2_OPTIONS__options + with data pointed to an array of options terminated by a zeroed option, or + accessed/manipulated using LV2_Options_Interface. +*/ +typedef struct _LV2_Options_Option { + LV2_Options_Context context; /**< Context (type of subject). */ + uint32_t subject; /**< Subject. */ + LV2_URID key; /**< Key (property). */ + uint32_t size; /**< Size of value in bytes. */ + LV2_URID type; /**< Type of value (datatype). */ + const void* value; /**< Pointer to value (object). */ +} LV2_Options_Option; + +/** A status code for option functions. */ +typedef enum { + LV2_OPTIONS_SUCCESS = 0, /**< Completed successfully. */ + LV2_OPTIONS_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_OPTIONS_ERR_BAD_SUBJECT = 1 << 1, /**< Invalid/unsupported subject. */ + LV2_OPTIONS_ERR_BAD_KEY = 1 << 2, /**< Invalid/unsupported key. */ + LV2_OPTIONS_ERR_BAD_VALUE = 1 << 3 /**< Invalid/unsupported value. */ +} LV2_Options_Status; + +/** + Interface for dynamically setting options (LV2_OPTIONS__interface). +*/ +typedef struct _LV2_Options_Interface { + /** + Get the given options. + + Each element of the passed options array MUST have type, subject, and + key set. All other fields (size, type, value) MUST be initialised to + zero, and are set to the option value if such an option is found. + + This function is in the "instantiation" LV2 threading class, so no other + instance functions may be called concurrently. + + @return Bitwise OR of LV2_Options_Status values. + */ + uint32_t (*get)(LV2_Handle instance, + LV2_Options_Option* options); + + /** + Set the given options. + + This function is in the "instantiation" LV2 threading class, so no other + instance functions may be called concurrently. + + @return Bitwise OR of LV2_Options_Status values. + */ + uint32_t (*set)(LV2_Handle instance, + const LV2_Options_Option* options); +} LV2_Options_Interface; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_OPTIONS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/parameters.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/parameters.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,62 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup parameters Parameters + + Common parameters for audio processing, see + . + + @{ +*/ + +#ifndef LV2_PARAMETERS_H +#define LV2_PARAMETERS_H + +#define LV2_PARAMETERS_URI "http://lv2plug.in/ns/ext/parameters" ///< http://lv2plug.in/ns/ext/parameters +#define LV2_PARAMETERS_PREFIX LV2_PARAMETERS_URI "#" ///< http://lv2plug.in/ns/ext/parameters# + +#define LV2_PARAMETERS__CompressorControls LV2_PARAMETERS_PREFIX "CompressorControls" ///< http://lv2plug.in/ns/ext/parameters#CompressorControls +#define LV2_PARAMETERS__ControlGroup LV2_PARAMETERS_PREFIX "ControlGroup" ///< http://lv2plug.in/ns/ext/parameters#ControlGroup +#define LV2_PARAMETERS__EnvelopeControls LV2_PARAMETERS_PREFIX "EnvelopeControls" ///< http://lv2plug.in/ns/ext/parameters#EnvelopeControls +#define LV2_PARAMETERS__FilterControls LV2_PARAMETERS_PREFIX "FilterControls" ///< http://lv2plug.in/ns/ext/parameters#FilterControls +#define LV2_PARAMETERS__OscillatorControls LV2_PARAMETERS_PREFIX "OscillatorControls" ///< http://lv2plug.in/ns/ext/parameters#OscillatorControls +#define LV2_PARAMETERS__amplitude LV2_PARAMETERS_PREFIX "amplitude" ///< http://lv2plug.in/ns/ext/parameters#amplitude +#define LV2_PARAMETERS__attack LV2_PARAMETERS_PREFIX "attack" ///< http://lv2plug.in/ns/ext/parameters#attack +#define LV2_PARAMETERS__bypass LV2_PARAMETERS_PREFIX "bypass" ///< http://lv2plug.in/ns/ext/parameters#bypass +#define LV2_PARAMETERS__cutoffFrequency LV2_PARAMETERS_PREFIX "cutoffFrequency" ///< http://lv2plug.in/ns/ext/parameters#cutoffFrequency +#define LV2_PARAMETERS__decay LV2_PARAMETERS_PREFIX "decay" ///< http://lv2plug.in/ns/ext/parameters#decay +#define LV2_PARAMETERS__delay LV2_PARAMETERS_PREFIX "delay" ///< http://lv2plug.in/ns/ext/parameters#delay +#define LV2_PARAMETERS__dryLevel LV2_PARAMETERS_PREFIX "dryLevel" ///< http://lv2plug.in/ns/ext/parameters#dryLevel +#define LV2_PARAMETERS__frequency LV2_PARAMETERS_PREFIX "frequency" ///< http://lv2plug.in/ns/ext/parameters#frequency +#define LV2_PARAMETERS__gain LV2_PARAMETERS_PREFIX "gain" ///< http://lv2plug.in/ns/ext/parameters#gain +#define LV2_PARAMETERS__hold LV2_PARAMETERS_PREFIX "hold" ///< http://lv2plug.in/ns/ext/parameters#hold +#define LV2_PARAMETERS__pulseWidth LV2_PARAMETERS_PREFIX "pulseWidth" ///< http://lv2plug.in/ns/ext/parameters#pulseWidth +#define LV2_PARAMETERS__ratio LV2_PARAMETERS_PREFIX "ratio" ///< http://lv2plug.in/ns/ext/parameters#ratio +#define LV2_PARAMETERS__release LV2_PARAMETERS_PREFIX "release" ///< http://lv2plug.in/ns/ext/parameters#release +#define LV2_PARAMETERS__resonance LV2_PARAMETERS_PREFIX "resonance" ///< http://lv2plug.in/ns/ext/parameters#resonance +#define LV2_PARAMETERS__sampleRate LV2_PARAMETERS_PREFIX "sampleRate" ///< http://lv2plug.in/ns/ext/parameters#sampleRate +#define LV2_PARAMETERS__sustain LV2_PARAMETERS_PREFIX "sustain" ///< http://lv2plug.in/ns/ext/parameters#sustain +#define LV2_PARAMETERS__threshold LV2_PARAMETERS_PREFIX "threshold" ///< http://lv2plug.in/ns/ext/parameters#threshold +#define LV2_PARAMETERS__waveform LV2_PARAMETERS_PREFIX "waveform" ///< http://lv2plug.in/ns/ext/parameters#waveform +#define LV2_PARAMETERS__wetDryRatio LV2_PARAMETERS_PREFIX "wetDryRatio" ///< http://lv2plug.in/ns/ext/parameters#wetDryRatio +#define LV2_PARAMETERS__wetLevel LV2_PARAMETERS_PREFIX "wetLevel" ///< http://lv2plug.in/ns/ext/parameters#wetLevel + +#endif /* LV2_PARAMETERS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/patch.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/patch.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,66 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup patch Patch + + Messages for accessing and manipulating properties, see + for details. + + Note the patch extension is purely data, this header merely defines URIs for + convenience. + + @{ +*/ + +#ifndef LV2_PATCH_H +#define LV2_PATCH_H + +#define LV2_PATCH_URI "http://lv2plug.in/ns/ext/patch" ///< http://lv2plug.in/ns/ext/patch +#define LV2_PATCH_PREFIX LV2_PATCH_URI "#" ///< http://lv2plug.in/ns/ext/patch# + +#define LV2_PATCH__Ack LV2_PATCH_PREFIX "Ack" ///< http://lv2plug.in/ns/ext/patch#Ack +#define LV2_PATCH__Delete LV2_PATCH_PREFIX "Delete" ///< http://lv2plug.in/ns/ext/patch#Delete +#define LV2_PATCH__Copy LV2_PATCH_PREFIX "Copy" ///< http://lv2plug.in/ns/ext/patch#Copy +#define LV2_PATCH__Error LV2_PATCH_PREFIX "Error" ///< http://lv2plug.in/ns/ext/patch#Error +#define LV2_PATCH__Get LV2_PATCH_PREFIX "Get" ///< http://lv2plug.in/ns/ext/patch#Get +#define LV2_PATCH__Message LV2_PATCH_PREFIX "Message" ///< http://lv2plug.in/ns/ext/patch#Message +#define LV2_PATCH__Move LV2_PATCH_PREFIX "Move" ///< http://lv2plug.in/ns/ext/patch#Move +#define LV2_PATCH__Patch LV2_PATCH_PREFIX "Patch" ///< http://lv2plug.in/ns/ext/patch#Patch +#define LV2_PATCH__Post LV2_PATCH_PREFIX "Post" ///< http://lv2plug.in/ns/ext/patch#Post +#define LV2_PATCH__Put LV2_PATCH_PREFIX "Put" ///< http://lv2plug.in/ns/ext/patch#Put +#define LV2_PATCH__Request LV2_PATCH_PREFIX "Request" ///< http://lv2plug.in/ns/ext/patch#Request +#define LV2_PATCH__Response LV2_PATCH_PREFIX "Response" ///< http://lv2plug.in/ns/ext/patch#Response +#define LV2_PATCH__Set LV2_PATCH_PREFIX "Set" ///< http://lv2plug.in/ns/ext/patch#Set +#define LV2_PATCH__accept LV2_PATCH_PREFIX "accept" ///< http://lv2plug.in/ns/ext/patch#accept +#define LV2_PATCH__add LV2_PATCH_PREFIX "add" ///< http://lv2plug.in/ns/ext/patch#add +#define LV2_PATCH__body LV2_PATCH_PREFIX "body" ///< http://lv2plug.in/ns/ext/patch#body +#define LV2_PATCH__destination LV2_PATCH_PREFIX "destination" ///< http://lv2plug.in/ns/ext/patch#destination +#define LV2_PATCH__property LV2_PATCH_PREFIX "property" ///< http://lv2plug.in/ns/ext/patch#property +#define LV2_PATCH__readable LV2_PATCH_PREFIX "readable" ///< http://lv2plug.in/ns/ext/patch#readable +#define LV2_PATCH__remove LV2_PATCH_PREFIX "remove" ///< http://lv2plug.in/ns/ext/patch#remove +#define LV2_PATCH__request LV2_PATCH_PREFIX "request" ///< http://lv2plug.in/ns/ext/patch#request +#define LV2_PATCH__subject LV2_PATCH_PREFIX "subject" ///< http://lv2plug.in/ns/ext/patch#subject +#define LV2_PATCH__sequenceNumber LV2_PATCH_PREFIX "sequenceNumber" ///< http://lv2plug.in/ns/ext/patch#sequenceNumber +#define LV2_PATCH__value LV2_PATCH_PREFIX "value" ///< http://lv2plug.in/ns/ext/patch#value +#define LV2_PATCH__wildcard LV2_PATCH_PREFIX "wildcard" ///< http://lv2plug.in/ns/ext/patch#wildcard +#define LV2_PATCH__writable LV2_PATCH_PREFIX "writable" ///< http://lv2plug.in/ns/ext/patch#writable + +#endif /* LV2_PATCH_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/port-groups.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/port-groups.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,71 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup port-groups Port Groups + + Multi-channel groups of LV2 ports, see + for details. + + @{ +*/ + +#ifndef LV2_PORT_GROUPS_H +#define LV2_PORT_GROUPS_H + +#define LV2_PORT_GROUPS_URI "http://lv2plug.in/ns/ext/port-groups" ///< http://lv2plug.in/ns/ext/port-groups +#define LV2_PORT_GROUPS_PREFIX LV2_PORT_GROUPS_URI "#" ///< http://lv2plug.in/ns/ext/port-groups# + +#define LV2_PORT_GROUPS__DiscreteGroup LV2_PORT_GROUPS_PREFIX "DiscreteGroup" ///< http://lv2plug.in/ns/ext/port-groups#DiscreteGroup +#define LV2_PORT_GROUPS__Element LV2_PORT_GROUPS_PREFIX "Element" ///< http://lv2plug.in/ns/ext/port-groups#Element +#define LV2_PORT_GROUPS__FivePointOneGroup LV2_PORT_GROUPS_PREFIX "FivePointOneGroup" ///< http://lv2plug.in/ns/ext/port-groups#FivePointOneGroup +#define LV2_PORT_GROUPS__FivePointZeroGroup LV2_PORT_GROUPS_PREFIX "FivePointZeroGroup" ///< http://lv2plug.in/ns/ext/port-groups#FivePointZeroGroup +#define LV2_PORT_GROUPS__FourPointZeroGroup LV2_PORT_GROUPS_PREFIX "FourPointZeroGroup" ///< http://lv2plug.in/ns/ext/port-groups#FourPointZeroGroup +#define LV2_PORT_GROUPS__Group LV2_PORT_GROUPS_PREFIX "Group" ///< http://lv2plug.in/ns/ext/port-groups#Group +#define LV2_PORT_GROUPS__InputGroup LV2_PORT_GROUPS_PREFIX "InputGroup" ///< http://lv2plug.in/ns/ext/port-groups#InputGroup +#define LV2_PORT_GROUPS__MidSideGroup LV2_PORT_GROUPS_PREFIX "MidSideGroup" ///< http://lv2plug.in/ns/ext/port-groups#MidSideGroup +#define LV2_PORT_GROUPS__MonoGroup LV2_PORT_GROUPS_PREFIX "MonoGroup" ///< http://lv2plug.in/ns/ext/port-groups#MonoGroup +#define LV2_PORT_GROUPS__OutputGroup LV2_PORT_GROUPS_PREFIX "OutputGroup" ///< http://lv2plug.in/ns/ext/port-groups#OutputGroup +#define LV2_PORT_GROUPS__SevenPointOneGroup LV2_PORT_GROUPS_PREFIX "SevenPointOneGroup" ///< http://lv2plug.in/ns/ext/port-groups#SevenPointOneGroup +#define LV2_PORT_GROUPS__SevenPointOneWideGroup LV2_PORT_GROUPS_PREFIX "SevenPointOneWideGroup" ///< http://lv2plug.in/ns/ext/port-groups#SevenPointOneWideGroup +#define LV2_PORT_GROUPS__SixPointOneGroup LV2_PORT_GROUPS_PREFIX "SixPointOneGroup" ///< http://lv2plug.in/ns/ext/port-groups#SixPointOneGroup +#define LV2_PORT_GROUPS__StereoGroup LV2_PORT_GROUPS_PREFIX "StereoGroup" ///< http://lv2plug.in/ns/ext/port-groups#StereoGroup +#define LV2_PORT_GROUPS__ThreePointZeroGroup LV2_PORT_GROUPS_PREFIX "ThreePointZeroGroup" ///< http://lv2plug.in/ns/ext/port-groups#ThreePointZeroGroup +#define LV2_PORT_GROUPS__center LV2_PORT_GROUPS_PREFIX "center" ///< http://lv2plug.in/ns/ext/port-groups#center +#define LV2_PORT_GROUPS__centerLeft LV2_PORT_GROUPS_PREFIX "centerLeft" ///< http://lv2plug.in/ns/ext/port-groups#centerLeft +#define LV2_PORT_GROUPS__centerRight LV2_PORT_GROUPS_PREFIX "centerRight" ///< http://lv2plug.in/ns/ext/port-groups#centerRight +#define LV2_PORT_GROUPS__element LV2_PORT_GROUPS_PREFIX "element" ///< http://lv2plug.in/ns/ext/port-groups#element +#define LV2_PORT_GROUPS__group LV2_PORT_GROUPS_PREFIX "group" ///< http://lv2plug.in/ns/ext/port-groups#group +#define LV2_PORT_GROUPS__left LV2_PORT_GROUPS_PREFIX "left" ///< http://lv2plug.in/ns/ext/port-groups#left +#define LV2_PORT_GROUPS__lowFrequencyEffects LV2_PORT_GROUPS_PREFIX "lowFrequencyEffects" ///< http://lv2plug.in/ns/ext/port-groups#lowFrequencyEffects +#define LV2_PORT_GROUPS__mainInput LV2_PORT_GROUPS_PREFIX "mainInput" ///< http://lv2plug.in/ns/ext/port-groups#mainInput +#define LV2_PORT_GROUPS__mainOutput LV2_PORT_GROUPS_PREFIX "mainOutput" ///< http://lv2plug.in/ns/ext/port-groups#mainOutput +#define LV2_PORT_GROUPS__rearCenter LV2_PORT_GROUPS_PREFIX "rearCenter" ///< http://lv2plug.in/ns/ext/port-groups#rearCenter +#define LV2_PORT_GROUPS__rearLeft LV2_PORT_GROUPS_PREFIX "rearLeft" ///< http://lv2plug.in/ns/ext/port-groups#rearLeft +#define LV2_PORT_GROUPS__rearRight LV2_PORT_GROUPS_PREFIX "rearRight" ///< http://lv2plug.in/ns/ext/port-groups#rearRight +#define LV2_PORT_GROUPS__right LV2_PORT_GROUPS_PREFIX "right" ///< http://lv2plug.in/ns/ext/port-groups#right +#define LV2_PORT_GROUPS__side LV2_PORT_GROUPS_PREFIX "side" ///< http://lv2plug.in/ns/ext/port-groups#side +#define LV2_PORT_GROUPS__sideChainOf LV2_PORT_GROUPS_PREFIX "sideChainOf" ///< http://lv2plug.in/ns/ext/port-groups#sideChainOf +#define LV2_PORT_GROUPS__sideLeft LV2_PORT_GROUPS_PREFIX "sideLeft" ///< http://lv2plug.in/ns/ext/port-groups#sideLeft +#define LV2_PORT_GROUPS__sideRight LV2_PORT_GROUPS_PREFIX "sideRight" ///< http://lv2plug.in/ns/ext/port-groups#sideRight +#define LV2_PORT_GROUPS__source LV2_PORT_GROUPS_PREFIX "source" ///< http://lv2plug.in/ns/ext/port-groups#source +#define LV2_PORT_GROUPS__subGroupOf LV2_PORT_GROUPS_PREFIX "subGroupOf" ///< http://lv2plug.in/ns/ext/port-groups#subGroupOf + +#endif /* LV2_PORT_GROUPS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/port-props.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/port-props.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,48 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup port-props Port Properties + + Various port properties. + + @{ +*/ + +#ifndef LV2_PORT_PROPS_H +#define LV2_PORT_PROPS_H + +#define LV2_PORT_PROPS_URI "http://lv2plug.in/ns/ext/port-props" ///< http://lv2plug.in/ns/ext/port-props +#define LV2_PORT_PROPS_PREFIX LV2_PORT_PROPS_URI "#" ///< http://lv2plug.in/ns/ext/port-props# + +#define LV2_PORT_PROPS__causesArtifacts LV2_PORT_PROPS_PREFIX "causesArtifacts" ///< http://lv2plug.in/ns/ext/port-props#causesArtifacts +#define LV2_PORT_PROPS__continuousCV LV2_PORT_PROPS_PREFIX "continuousCV" ///< http://lv2plug.in/ns/ext/port-props#continuousCV +#define LV2_PORT_PROPS__discreteCV LV2_PORT_PROPS_PREFIX "discreteCV" ///< http://lv2plug.in/ns/ext/port-props#discreteCV +#define LV2_PORT_PROPS__displayPriority LV2_PORT_PROPS_PREFIX "displayPriority" ///< http://lv2plug.in/ns/ext/port-props#displayPriority +#define LV2_PORT_PROPS__expensive LV2_PORT_PROPS_PREFIX "expensive" ///< http://lv2plug.in/ns/ext/port-props#expensive +#define LV2_PORT_PROPS__hasStrictBounds LV2_PORT_PROPS_PREFIX "hasStrictBounds" ///< http://lv2plug.in/ns/ext/port-props#hasStrictBounds +#define LV2_PORT_PROPS__logarithmic LV2_PORT_PROPS_PREFIX "logarithmic" ///< http://lv2plug.in/ns/ext/port-props#logarithmic +#define LV2_PORT_PROPS__notAutomatic LV2_PORT_PROPS_PREFIX "notAutomatic" ///< http://lv2plug.in/ns/ext/port-props#notAutomatic +#define LV2_PORT_PROPS__notOnGUI LV2_PORT_PROPS_PREFIX "notOnGUI" ///< http://lv2plug.in/ns/ext/port-props#notOnGUI +#define LV2_PORT_PROPS__rangeSteps LV2_PORT_PROPS_PREFIX "rangeSteps" ///< http://lv2plug.in/ns/ext/port-props#rangeSteps +#define LV2_PORT_PROPS__supportsStrictBounds LV2_PORT_PROPS_PREFIX "supportsStrictBounds" ///< http://lv2plug.in/ns/ext/port-props#supportsStrictBounds +#define LV2_PORT_PROPS__trigger LV2_PORT_PROPS_PREFIX "trigger" ///< http://lv2plug.in/ns/ext/port-props#trigger + +#endif /* LV2_PORT_PROPS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/presets.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/presets.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,41 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup presets Presets + + Presets for plugins, see for details. + + @{ +*/ + +#ifndef LV2_PRESETS_H +#define LV2_PRESETS_H + +#define LV2_PRESETS_URI "http://lv2plug.in/ns/ext/presets" ///< http://lv2plug.in/ns/ext/presets +#define LV2_PRESETS_PREFIX LV2_PRESETS_URI "#" ///< http://lv2plug.in/ns/ext/presets# + +#define LV2_PRESETS__Bank LV2_PRESETS_PREFIX "Bank" ///< http://lv2plug.in/ns/ext/presets#Bank +#define LV2_PRESETS__Preset LV2_PRESETS_PREFIX "Preset" ///< http://lv2plug.in/ns/ext/presets#Preset +#define LV2_PRESETS__bank LV2_PRESETS_PREFIX "bank" ///< http://lv2plug.in/ns/ext/presets#bank +#define LV2_PRESETS__preset LV2_PRESETS_PREFIX "preset" ///< http://lv2plug.in/ns/ext/presets#preset +#define LV2_PRESETS__value LV2_PRESETS_PREFIX "value" ///< http://lv2plug.in/ns/ext/presets#value + +#endif /* LV2_PRESETS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/resize-port.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/resize-port.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,86 @@ +/* + Copyright 2007-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup resize-port Resize Port + + Dynamically sized LV2 port buffers. + + @{ +*/ + +#ifndef LV2_RESIZE_PORT_H +#define LV2_RESIZE_PORT_H + +#include +#include + +#define LV2_RESIZE_PORT_URI "http://lv2plug.in/ns/ext/resize-port" ///< http://lv2plug.in/ns/ext/resize-port +#define LV2_RESIZE_PORT_PREFIX LV2_RESIZE_PORT_URI "#" ///< http://lv2plug.in/ns/ext/resize-port# + +#define LV2_RESIZE_PORT__asLargeAs LV2_RESIZE_PORT_PREFIX "asLargeAs" ///< http://lv2plug.in/ns/ext/port#asLargeAs +#define LV2_RESIZE_PORT__minimumSize LV2_RESIZE_PORT_PREFIX "minimumSize" ///< http://lv2plug.in/ns/ext/port#minimumSize +#define LV2_RESIZE_PORT__resize LV2_RESIZE_PORT_PREFIX "resize" ///< http://lv2plug.in/ns/ext/port#resize + +#ifdef __cplusplus +extern "C" { +#else +# include +#endif + +/** A status code for state functions. */ +typedef enum { + LV2_RESIZE_PORT_SUCCESS = 0, /**< Completed successfully. */ + LV2_RESIZE_PORT_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_RESIZE_PORT_ERR_NO_SPACE = 2 /**< Insufficient space. */ +} LV2_Resize_Port_Status; + +/** Opaque data for resize method. */ +typedef void* LV2_Resize_Port_Feature_Data; + +/** Host feature to allow plugins to resize their port buffers. */ +typedef struct { + /** Opaque data for resize method. */ + LV2_Resize_Port_Feature_Data data; + + /** + Resize a port buffer to at least `size` bytes. + + This function MAY return an error, in which case the port buffer was not + resized and the port is still connected to the same location. Plugins + MUST gracefully handle this situation. + + This function is in the audio threading class. + + The host MUST preserve the contents of the port buffer when resizing. + + Plugins MAY resize a port many times in a single run callback. Hosts + SHOULD make this as inexpensive as possible. + */ + LV2_Resize_Port_Status (*resize)(LV2_Resize_Port_Feature_Data data, + uint32_t index, + size_t size); +} LV2_Resize_Port_Resize; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_RESIZE_PORT_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/state.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/state.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,389 @@ +/* + Copyright 2010-2016 David Robillard + Copyright 2010 Leonard Ritter + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup state State + @ingroup lv2 + + An interface for LV2 plugins to save and restore state, see + for details. + + @{ +*/ + +#ifndef LV2_STATE_H +#define LV2_STATE_H + +#include "lv2.h" + +#include +#include +#include + +#define LV2_STATE_URI "http://lv2plug.in/ns/ext/state" ///< http://lv2plug.in/ns/ext/state +#define LV2_STATE_PREFIX LV2_STATE_URI "#" ///< http://lv2plug.in/ns/ext/state# + +#define LV2_STATE__State LV2_STATE_PREFIX "State" ///< http://lv2plug.in/ns/ext/state#State +#define LV2_STATE__interface LV2_STATE_PREFIX "interface" ///< http://lv2plug.in/ns/ext/state#interface +#define LV2_STATE__loadDefaultState LV2_STATE_PREFIX "loadDefaultState" ///< http://lv2plug.in/ns/ext/state#loadDefaultState +#define LV2_STATE__freePath LV2_STATE_PREFIX "freePath" ///< http://lv2plug.in/ns/ext/state#freePath +#define LV2_STATE__makePath LV2_STATE_PREFIX "makePath" ///< http://lv2plug.in/ns/ext/state#makePath +#define LV2_STATE__mapPath LV2_STATE_PREFIX "mapPath" ///< http://lv2plug.in/ns/ext/state#mapPath +#define LV2_STATE__state LV2_STATE_PREFIX "state" ///< http://lv2plug.in/ns/ext/state#state +#define LV2_STATE__threadSafeRestore LV2_STATE_PREFIX "threadSafeRestore" ///< http://lv2plug.in/ns/ext/state#threadSafeRestore +#define LV2_STATE__StateChanged LV2_STATE_PREFIX "StateChanged" ///< http://lv2plug.in/ns/ext/state#StateChanged + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* LV2_State_Handle; ///< Opaque handle for state save/restore +typedef void* LV2_State_Free_Path_Handle; ///< Opaque handle for state:freePath feature +typedef void* LV2_State_Map_Path_Handle; ///< Opaque handle for state:mapPath feature +typedef void* LV2_State_Make_Path_Handle; ///< Opaque handle for state:makePath feature + +/** + Flags describing value characteristics. + + These flags are used along with the value's type URI to determine how to + (de-)serialise the value data, or whether it is even possible to do so. +*/ +typedef enum { + /** + Plain Old Data. + + Values with this flag contain no pointers or references to other areas + of memory. It is safe to copy POD values with a simple memcpy and store + them for the duration of the process. A POD value is not necessarily + safe to trasmit between processes or machines (for example, filenames + are POD), see LV2_STATE_IS_PORTABLE for details. + + Implementations MUST NOT attempt to copy or serialise a non-POD value if + they do not understand its type (and thus know how to correctly do so). + */ + LV2_STATE_IS_POD = 1, + + /** + Portable (architecture independent) data. + + Values with this flag are in a format that is usable on any + architecture. A portable value saved on one machine can be restored on + another machine regardless of architecture. The format of portable + values MUST NOT depend on architecture-specific properties like + endianness or alignment. Portable values MUST NOT contain filenames. + */ + LV2_STATE_IS_PORTABLE = 1 << 1, + + /** + Native data. + + This flag is used by the host to indicate that the saved data is only + going to be used locally in the currently running process (for things + like instance duplication or snapshots), so the plugin should use the + most efficient representation possible and not worry about serialisation + and portability. + */ + LV2_STATE_IS_NATIVE = 1 << 2 +} LV2_State_Flags; + +/** A status code for state functions. */ +typedef enum { + LV2_STATE_SUCCESS = 0, /**< Completed successfully. */ + LV2_STATE_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_STATE_ERR_BAD_TYPE = 2, /**< Failed due to unsupported type. */ + LV2_STATE_ERR_BAD_FLAGS = 3, /**< Failed due to unsupported flags. */ + LV2_STATE_ERR_NO_FEATURE = 4, /**< Failed due to missing features. */ + LV2_STATE_ERR_NO_PROPERTY = 5, /**< Failed due to missing property. */ + LV2_STATE_ERR_NO_SPACE = 6 /**< Failed due to insufficient space. */ +} LV2_State_Status; + +/** + A host-provided function to store a property. + @param handle Must be the handle passed to LV2_State_Interface.save(). + @param key The key to store `value` under (URID). + @param value Pointer to the value to be stored. + @param size The size of `value` in bytes. + @param type The type of `value` (URID). + @param flags LV2_State_Flags for `value`. + @return 0 on success, otherwise a non-zero error code. + + The host passes a callback of this type to LV2_State_Interface.save(). This + callback is called repeatedly by the plugin to store all the properties that + describe its current state. + + DO NOT INVENT NONSENSE URI SCHEMES FOR THE KEY. Best is to use keys from + existing vocabularies. If nothing appropriate is available, use http URIs + that point to somewhere you can host documents so documentation can be made + resolvable (typically a child of the plugin or project URI). If this is not + possible, invent a URN scheme, e.g. urn:myproj:whatever. The plugin MUST + NOT pass an invalid URI key. + + The host MAY fail to store a property for whatever reason, but SHOULD + store any property that is LV2_STATE_IS_POD and LV2_STATE_IS_PORTABLE. + Implementations SHOULD use the types from the LV2 Atom extension + (http://lv2plug.in/ns/ext/atom) wherever possible. The plugin SHOULD + attempt to fall-back and avoid the error if possible. + + Note that `size` MUST be > 0, and `value` MUST point to a valid region of + memory `size` bytes long (this is required to make restore unambiguous). + + The plugin MUST NOT attempt to use this function outside of the + LV2_State_Interface.restore() context. +*/ +typedef LV2_State_Status (*LV2_State_Store_Function)( + LV2_State_Handle handle, + uint32_t key, + const void* value, + size_t size, + uint32_t type, + uint32_t flags); + +/** + A host-provided function to retrieve a property. + @param handle Must be the handle passed to LV2_State_Interface.restore(). + @param key The key of the property to retrieve (URID). + @param size (Output) If non-NULL, set to the size of the restored value. + @param type (Output) If non-NULL, set to the type of the restored value. + @param flags (Output) If non-NULL, set to the flags for the restored value. + @return A pointer to the restored value (object), or NULL if no value + has been stored under `key`. + + A callback of this type is passed by the host to + LV2_State_Interface.restore(). This callback is called repeatedly by the + plugin to retrieve any properties it requires to restore its state. + + The returned value MUST remain valid until LV2_State_Interface.restore() + returns. The plugin MUST NOT attempt to use this function, or any value + returned from it, outside of the LV2_State_Interface.restore() context. +*/ +typedef const void* (*LV2_State_Retrieve_Function)( + LV2_State_Handle handle, + uint32_t key, + size_t* size, + uint32_t* type, + uint32_t* flags); + +/** + LV2 Plugin State Interface. + + When the plugin's extension_data is called with argument + LV2_STATE__interface, the plugin MUST return an LV2_State_Interface + structure, which remains valid for the lifetime of the plugin. + + The host can use the contained function pointers to save and restore the + state of a plugin instance at any time, provided the threading restrictions + of the functions are met. + + Stored data is only guaranteed to be compatible between instances of plugins + with the same URI (i.e. if a change to a plugin would cause a fatal error + when restoring state saved by a previous version of that plugin, the plugin + URI MUST change just as it must when ports change incompatibly). Plugin + authors should consider this possibility, and always store sensible data + with meaningful types to avoid such problems in the future. +*/ +typedef struct { + /** + Save plugin state using a host-provided `store` callback. + + @param instance The instance handle of the plugin. + @param store The host-provided store callback. + @param handle An opaque pointer to host data which MUST be passed as the + handle parameter to `store` if it is called. + @param flags Flags describing desired properties of this save. These + flags may be used to determine the most appropriate values to store. + @param features Extensible parameter for passing any additional + features to be used for this save. + + The plugin is expected to store everything necessary to completely + restore its state later. Plugins SHOULD store simple POD data whenever + possible, and consider the possibility of state being restored much + later on a different machine. + + The `handle` pointer and `store` function MUST NOT be used + beyond the scope of save(). + + This function has its own special threading class: it may not be called + concurrently with any "Instantiation" function, but it may be called + concurrently with functions in any other class, unless the definition of + that class prohibits it (for example, it may not be called concurrently + with a "Discovery" function, but it may be called concurrently with an + "Audio" function. The plugin is responsible for any locking or + lock-free techniques necessary to make this possible. + + Note that in the simple case where state is only modified by restore(), + there are no synchronization issues since save() is never called + concurrently with restore() (though run() may read it during a save). + + Plugins that dynamically modify state while running, however, must take + care to do so in such a way that a concurrent call to save() will save a + consistent representation of plugin state for a single instant in time. + */ + LV2_State_Status (*save)(LV2_Handle instance, + LV2_State_Store_Function store, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature *const * features); + + /** + Restore plugin state using a host-provided `retrieve` callback. + + @param instance The instance handle of the plugin. + @param retrieve The host-provided retrieve callback. + @param handle An opaque pointer to host data which MUST be passed as the + handle parameter to `retrieve` if it is called. + @param flags Currently unused. + @param features Extensible parameter for passing any additional + features to be used for this restore. + + The plugin MAY assume a restored value was set by a previous call to + LV2_State_Interface.save() by a plugin with the same URI. + + The plugin MUST gracefully fall back to a default value when a value can + not be retrieved. This allows the host to reset the plugin state with + an empty map. + + The `handle` pointer and `store` function MUST NOT be used + beyond the scope of restore(). + + This function is in the "Instantiation" threading class as defined by + LV2. This means it MUST NOT be called concurrently with any other + function on the same plugin instance. + */ + LV2_State_Status (*restore)(LV2_Handle instance, + LV2_State_Retrieve_Function retrieve, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature *const * features); +} LV2_State_Interface; + +/** + Feature data for state:mapPath (@ref LV2_STATE__mapPath). +*/ +typedef struct { + /** + Opaque host data. + */ + LV2_State_Map_Path_Handle handle; + + /** + Map an absolute path to an abstract path for use in plugin state. + @param handle MUST be the `handle` member of this struct. + @param absolute_path The absolute path of a file. + @return An abstract path suitable for use in plugin state. + + The plugin MUST use this function to map any paths that will be stored + in plugin state. The returned value is an abstract path which MAY not + be an actual file system path; absolute_path() MUST be used to map + it to an actual path in order to use the file. + + Plugins MUST NOT make any assumptions about abstract paths except that + they can be mapped back to the absolute path of the "same" file (though + not necessarily the same original path) using absolute_path(). + + This function may only be called within the context of + LV2_State_Interface methods. The caller must free the returned value + with LV2_State_Free_Path.free_path(). + */ + char* (*abstract_path)(LV2_State_Map_Path_Handle handle, + const char* absolute_path); + + /** + Map an abstract path from plugin state to an absolute path. + @param handle MUST be the `handle` member of this struct. + @param abstract_path An abstract path (typically from plugin state). + @return An absolute file system path. + + The plugin MUST use this function in order to actually open or otherwise + use any paths loaded from plugin state. + + This function may only be called within the context of + LV2_State_Interface methods. The caller must free the returned value + with LV2_State_Free_Path.free_path(). + */ + char* (*absolute_path)(LV2_State_Map_Path_Handle handle, + const char* abstract_path); +} LV2_State_Map_Path; + +/** + Feature data for state:makePath (@ref LV2_STATE__makePath). +*/ +typedef struct { + /** + Opaque host data. + */ + LV2_State_Make_Path_Handle handle; + + /** + Return a path the plugin may use to create a new file. + @param handle MUST be the `handle` member of this struct. + @param path The path of the new file within a namespace unique to this + plugin instance. + @return The absolute path to use for the new file. + + This function can be used by plugins to create files and directories, + either at state saving time (if this feature is passed to + LV2_State_Interface.save()) or any time (if this feature is passed to + LV2_Descriptor.instantiate()). + + The host MUST do whatever is necessary for the plugin to be able to + create a file at the returned path (for example, using fopen()), + including creating any leading directories. + + If this function is passed to LV2_Descriptor.instantiate(), it may be + called from any non-realtime context. If it is passed to + LV2_State_Interface.save(), it may only be called within the dynamic + scope of that function call. + + The caller must free the returned value with + LV2_State_Free_Path.free_path(). + */ + char* (*path)(LV2_State_Make_Path_Handle handle, + const char* path); +} LV2_State_Make_Path; + +/** + Feature data for state:freePath (@ref LV2_STATE__freePath). +*/ +typedef struct { + /** + Opaque host data. + */ + LV2_State_Free_Path_Handle handle; + + /** + Free a path returned by a state feature. + + @param handle MUST be the `handle` member of this struct. + @param path The path previously returned by a state feature. + + This function can be used by plugins to free paths allocated by the host + and returned by state features (LV2_State_Map_Path.abstract_path(), + LV2_State_Map_Path.absolute_path(), and LV2_State_Make_Path.path()). + */ + void (*free_path)(LV2_State_Free_Path_Handle handle, + char* path); +} LV2_State_Free_Path; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_STATE_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/time.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/time.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,53 @@ +/* + Copyright 2011-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup time Time + + Properties for describing time, see for + details. + + Note the time extension is purely data, this header merely defines URIs for + convenience. + + @{ +*/ + +#ifndef LV2_TIME_H +#define LV2_TIME_H + +#define LV2_TIME_URI "http://lv2plug.in/ns/ext/time" ///< http://lv2plug.in/ns/ext/time +#define LV2_TIME_PREFIX LV2_TIME_URI "#" ///< http://lv2plug.in/ns/ext/time# + +#define LV2_TIME__Time LV2_TIME_PREFIX "Time" ///< http://lv2plug.in/ns/ext/time#Time +#define LV2_TIME__Position LV2_TIME_PREFIX "Position" ///< http://lv2plug.in/ns/ext/time#Position +#define LV2_TIME__Rate LV2_TIME_PREFIX "Rate" ///< http://lv2plug.in/ns/ext/time#Rate +#define LV2_TIME__position LV2_TIME_PREFIX "position" ///< http://lv2plug.in/ns/ext/time#position +#define LV2_TIME__barBeat LV2_TIME_PREFIX "barBeat" ///< http://lv2plug.in/ns/ext/time#barBeat +#define LV2_TIME__bar LV2_TIME_PREFIX "bar" ///< http://lv2plug.in/ns/ext/time#bar +#define LV2_TIME__beat LV2_TIME_PREFIX "beat" ///< http://lv2plug.in/ns/ext/time#beat +#define LV2_TIME__beatUnit LV2_TIME_PREFIX "beatUnit" ///< http://lv2plug.in/ns/ext/time#beatUnit +#define LV2_TIME__beatsPerBar LV2_TIME_PREFIX "beatsPerBar" ///< http://lv2plug.in/ns/ext/time#beatsPerBar +#define LV2_TIME__beatsPerMinute LV2_TIME_PREFIX "beatsPerMinute" ///< http://lv2plug.in/ns/ext/time#beatsPerMinute +#define LV2_TIME__frame LV2_TIME_PREFIX "frame" ///< http://lv2plug.in/ns/ext/time#frame +#define LV2_TIME__framesPerSecond LV2_TIME_PREFIX "framesPerSecond" ///< http://lv2plug.in/ns/ext/time#framesPerSecond +#define LV2_TIME__speed LV2_TIME_PREFIX "speed" ///< http://lv2plug.in/ns/ext/time#speed + +/** + @} +*/ + +#endif /* LV2_TIME_H */ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/ui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/ui.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,539 @@ +/* + LV2 UI Extension + Copyright 2009-2016 David Robillard + Copyright 2006-2011 Lars Luthman + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup ui User Interfaces + + User interfaces of any type for plugins, + for details. + + @{ +*/ + +#ifndef LV2_UI_H +#define LV2_UI_H + +#include + +#include "lv2.h" +#include "urid.h" + +#define LV2_UI_URI "http://lv2plug.in/ns/extensions/ui" ///< http://lv2plug.in/ns/extensions/ui +#define LV2_UI_PREFIX LV2_UI_URI "#" ///< http://lv2plug.in/ns/extensions/ui# + +#define LV2_UI__CocoaUI LV2_UI_PREFIX "CocoaUI" ///< http://lv2plug.in/ns/extensions/ui#CocoaUI +#define LV2_UI__Gtk3UI LV2_UI_PREFIX "Gtk3UI" ///< http://lv2plug.in/ns/extensions/ui#Gtk3UI +#define LV2_UI__GtkUI LV2_UI_PREFIX "GtkUI" ///< http://lv2plug.in/ns/extensions/ui#GtkUI +#define LV2_UI__PortNotification LV2_UI_PREFIX "PortNotification" ///< http://lv2plug.in/ns/extensions/ui#PortNotification +#define LV2_UI__PortProtocol LV2_UI_PREFIX "PortProtocol" ///< http://lv2plug.in/ns/extensions/ui#PortProtocol +#define LV2_UI__Qt4UI LV2_UI_PREFIX "Qt4UI" ///< http://lv2plug.in/ns/extensions/ui#Qt4UI +#define LV2_UI__Qt5UI LV2_UI_PREFIX "Qt5UI" ///< http://lv2plug.in/ns/extensions/ui#Qt5UI +#define LV2_UI__UI LV2_UI_PREFIX "UI" ///< http://lv2plug.in/ns/extensions/ui#UI +#define LV2_UI__WindowsUI LV2_UI_PREFIX "WindowsUI" ///< http://lv2plug.in/ns/extensions/ui#WindowsUI +#define LV2_UI__X11UI LV2_UI_PREFIX "X11UI" ///< http://lv2plug.in/ns/extensions/ui#X11UI +#define LV2_UI__backgroundColor LV2_UI_PREFIX "backgroundColor" ///< http://lv2plug.in/ns/extensions/ui#backgroundColor +#define LV2_UI__binary LV2_UI_PREFIX "binary" ///< http://lv2plug.in/ns/extensions/ui#binary +#define LV2_UI__fixedSize LV2_UI_PREFIX "fixedSize" ///< http://lv2plug.in/ns/extensions/ui#fixedSize +#define LV2_UI__foregroundColor LV2_UI_PREFIX "foregroundColor" ///< http://lv2plug.in/ns/extensions/ui#foregroundColor +#define LV2_UI__idleInterface LV2_UI_PREFIX "idleInterface" ///< http://lv2plug.in/ns/extensions/ui#idleInterface +#define LV2_UI__noUserResize LV2_UI_PREFIX "noUserResize" ///< http://lv2plug.in/ns/extensions/ui#noUserResize +#define LV2_UI__notifyType LV2_UI_PREFIX "notifyType" ///< http://lv2plug.in/ns/extensions/ui#notifyType +#define LV2_UI__parent LV2_UI_PREFIX "parent" ///< http://lv2plug.in/ns/extensions/ui#parent +#define LV2_UI__plugin LV2_UI_PREFIX "plugin" ///< http://lv2plug.in/ns/extensions/ui#plugin +#define LV2_UI__portIndex LV2_UI_PREFIX "portIndex" ///< http://lv2plug.in/ns/extensions/ui#portIndex +#define LV2_UI__portMap LV2_UI_PREFIX "portMap" ///< http://lv2plug.in/ns/extensions/ui#portMap +#define LV2_UI__portNotification LV2_UI_PREFIX "portNotification" ///< http://lv2plug.in/ns/extensions/ui#portNotification +#define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe" ///< http://lv2plug.in/ns/extensions/ui#portSubscribe +#define LV2_UI__protocol LV2_UI_PREFIX "protocol" ///< http://lv2plug.in/ns/extensions/ui#protocol +#define LV2_UI__floatProtocol LV2_UI_PREFIX "floatProtocol" ///< http://lv2plug.in/ns/extensions/ui#floatProtocol +#define LV2_UI__peakProtocol LV2_UI_PREFIX "peakProtocol" ///< http://lv2plug.in/ns/extensions/ui#peakProtocol +#define LV2_UI__requestValue LV2_UI_PREFIX "requestValue" ///< http://lv2plug.in/ns/extensions/ui#requestValue +#define LV2_UI__resize LV2_UI_PREFIX "resize" ///< http://lv2plug.in/ns/extensions/ui#resize +#define LV2_UI__scaleFactor LV2_UI_PREFIX "scaleFactor" ///< http://lv2plug.in/ns/extensions/ui#scaleFactor +#define LV2_UI__showInterface LV2_UI_PREFIX "showInterface" ///< http://lv2plug.in/ns/extensions/ui#showInterface +#define LV2_UI__touch LV2_UI_PREFIX "touch" ///< http://lv2plug.in/ns/extensions/ui#touch +#define LV2_UI__ui LV2_UI_PREFIX "ui" ///< http://lv2plug.in/ns/extensions/ui#ui +#define LV2_UI__updateRate LV2_UI_PREFIX "updateRate" ///< http://lv2plug.in/ns/extensions/ui#updateRate +#define LV2_UI__windowTitle LV2_UI_PREFIX "windowTitle" ///< http://lv2plug.in/ns/extensions/ui#windowTitle + +/** + The index returned by LV2UI_Port_Map::port_index() for unknown ports. +*/ +#define LV2UI_INVALID_PORT_INDEX ((uint32_t)-1) + +#ifdef __cplusplus +extern "C" { +#else +# include +#endif + +/** + A pointer to some widget or other type of UI handle. + + The actual type is defined by the type of the UI. +*/ +typedef void* LV2UI_Widget; + +/** + A pointer to UI instance internals. + + The host may compare this to NULL, but otherwise MUST NOT interpret it. +*/ +typedef void* LV2UI_Handle; + +/** + A pointer to a controller provided by the host. + + The UI may compare this to NULL, but otherwise MUST NOT interpret it. +*/ +typedef void* LV2UI_Controller; + +/** + A pointer to opaque data for a feature. +*/ +typedef void* LV2UI_Feature_Handle; + +/** + A host-provided function that sends data to a plugin's input ports. + + @param controller The opaque controller pointer passed to + LV2UI_Descriptor::instantiate(). + + @param port_index Index of the port to update. + + @param buffer Buffer containing `buffer_size` bytes of data. + + @param buffer_size Size of `buffer` in bytes. + + @param port_protocol Either 0 or the URID for a ui:PortProtocol. If 0, the + protocol is implicitly ui:floatProtocol, the port MUST be an lv2:ControlPort + input, `buffer` MUST point to a single float value, and `buffer_size` MUST + be sizeof(float). The UI SHOULD NOT use a protocol not supported by the + host, but the host MUST gracefully ignore any protocol it does not + understand. +*/ +typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller, + uint32_t port_index, + uint32_t buffer_size, + uint32_t port_protocol, + const void* buffer); + +/** + A plugin UI. + + A pointer to an object of this type is returned by the lv2ui_descriptor() + function. +*/ +typedef struct _LV2UI_Descriptor { + /** + The URI for this UI (not for the plugin it controls). + */ + const char* URI; + + /** + Create a new UI and return a handle to it. This function works + similarly to LV2_Descriptor::instantiate(). + + @param descriptor The descriptor for the UI to instantiate. + + @param plugin_uri The URI of the plugin that this UI will control. + + @param bundle_path The path to the bundle containing this UI, including + the trailing directory separator. + + @param write_function A function that the UI can use to send data to the + plugin's input ports. + + @param controller A handle for the UI instance to be passed as the + first parameter of UI methods. + + @param widget (output) widget pointer. The UI points this at its main + widget, which has the type defined by the UI type in the data file. + + @param features An array of LV2_Feature pointers. The host must pass + all feature URIs that it and the UI supports and any additional data, as + in LV2_Descriptor::instantiate(). Note that UI features and plugin + features are not necessarily the same. + + */ + LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor, + const char* plugin_uri, + const char* bundle_path, + LV2UI_Write_Function write_function, + LV2UI_Controller controller, + LV2UI_Widget* widget, + const LV2_Feature* const* features); + + + /** + Destroy the UI. The host must not try to access the widget after + calling this function. + */ + void (*cleanup)(LV2UI_Handle ui); + + /** + Tell the UI that something interesting has happened at a plugin port. + + What is "interesting" and how it is written to `buffer` is defined by + `format`, which has the same meaning as in LV2UI_Write_Function(). + Format 0 is a special case for lv2:ControlPort, where this function + should be called when the port value changes (but not necessarily for + every change), `buffer_size` must be sizeof(float), and `buffer` + points to a single IEEE-754 float. + + By default, the host should only call this function for lv2:ControlPort + inputs. However, the UI can request updates for other ports statically + with ui:portNotification or dynamicaly with ui:portSubscribe. + + The UI MUST NOT retain any reference to `buffer` after this function + returns, it is only valid for the duration of the call. + + This member may be NULL if the UI is not interested in any port events. + */ + void (*port_event)(LV2UI_Handle ui, + uint32_t port_index, + uint32_t buffer_size, + uint32_t format, + const void* buffer); + + /** + Return a data structure associated with an extension URI, typically an + interface struct with additional function pointers + + This member may be set to NULL if the UI is not interested in supporting + any extensions. This is similar to LV2_Descriptor::extension_data(). + + */ + const void* (*extension_data)(const char* uri); +} LV2UI_Descriptor; + +/** + Feature/interface for resizable UIs (LV2_UI__resize). + + This structure is used in two ways: as a feature passed by the host via + LV2UI_Descriptor::instantiate(), or as an interface provided by a UI via + LV2UI_Descriptor::extension_data()). +*/ +typedef struct _LV2UI_Resize { + /** + Pointer to opaque data which must be passed to ui_resize(). + */ + LV2UI_Feature_Handle handle; + + /** + Request/advertise a size change. + + When provided by the host, the UI may call this function to inform the + host about the size of the UI. + + When provided by the UI, the host may call this function to notify the + UI that it should change its size accordingly. In this case, the host + must pass the LV2UI_Handle to provide access to the UI instance. + + @return 0 on success. + */ + int (*ui_resize)(LV2UI_Feature_Handle handle, int width, int height); +} LV2UI_Resize; + +/** + Feature to map port symbols to UIs. + + This can be used by the UI to get the index for a port with the given + symbol. This makes it possible to implement and distribute a UI separately + from the plugin (since symbol, unlike index, is a stable port identifier). +*/ +typedef struct _LV2UI_Port_Map { + /** + Pointer to opaque data which must be passed to port_index(). + */ + LV2UI_Feature_Handle handle; + + /** + Get the index for the port with the given `symbol`. + + @return The index of the port, or LV2UI_INVALID_PORT_INDEX if no such + port is found. + */ + uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol); +} LV2UI_Port_Map; + +/** + Feature to subscribe to port updates (LV2_UI__portSubscribe). +*/ +typedef struct _LV2UI_Port_Subscribe { + /** + Pointer to opaque data which must be passed to subscribe() and + unsubscribe(). + */ + LV2UI_Feature_Handle handle; + + /** + Subscribe to updates for a port. + + This means that the host will call the UI's port_event() function when + the port value changes (as defined by protocol). + + Calling this function with the same `port_index` and `port_protocol` + as an already active subscription has no effect. + + @param handle The handle field of this struct. + @param port_index The index of the port. + @param port_protocol The URID of the ui:PortProtocol. + @param features Features for this subscription. + @return 0 on success. + */ + uint32_t (*subscribe)(LV2UI_Feature_Handle handle, + uint32_t port_index, + uint32_t port_protocol, + const LV2_Feature* const* features); + + /** + Unsubscribe from updates for a port. + + This means that the host will cease calling calling port_event() when + the port value changes. + + Calling this function with a `port_index` and `port_protocol` that + does not refer to an active port subscription has no effect. + + @param handle The handle field of this struct. + @param port_index The index of the port. + @param port_protocol The URID of the ui:PortProtocol. + @param features Features for this subscription. + @return 0 on success. + */ + uint32_t (*unsubscribe)(LV2UI_Feature_Handle handle, + uint32_t port_index, + uint32_t port_protocol, + const LV2_Feature* const* features); +} LV2UI_Port_Subscribe; + +/** + A feature to notify the host that the user has grabbed a UI control. +*/ +typedef struct _LV2UI_Touch { + /** + Pointer to opaque data which must be passed to ui_resize(). + */ + LV2UI_Feature_Handle handle; + + /** + Notify the host that a control has been grabbed or released. + + The host should cease automating the port or otherwise manipulating the + port value until the control has been ungrabbed. + + @param handle The handle field of this struct. + @param port_index The index of the port associated with the control. + @param grabbed If true, the control has been grabbed, otherwise the + control has been released. + */ + void (*touch)(LV2UI_Feature_Handle handle, + uint32_t port_index, + bool grabbed); +} LV2UI_Touch; + +/** + A status code for LV2UI_Request_Value::request. +*/ +typedef enum { + /** + Completed successfully. + + The host will set the parameter later if the user choses a new value. + */ + LV2UI_REQUEST_VALUE_SUCCESS, + + /** + Parameter already being requested. + + The host is already requesting a parameter from the user (for example, a + dialog is visible), or the UI is otherwise busy and can not make this + request. + */ + LV2UI_REQUEST_VALUE_BUSY, + + /** + Unknown parameter. + + The host is not aware of this parameter, and is not able to set a new + value for it. + */ + LV2UI_REQUEST_VALUE_ERR_UNKNOWN, + + /** + Unsupported parameter. + + The host knows about this parameter, but does not support requesting a + new value for it from the user. This is likely because the host does + not have UI support for choosing a value with the appropriate type. + */ + LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED +} LV2UI_Request_Value_Status; + +/** + A feature to request a new parameter value from the host. +*/ +typedef struct { + /** + Pointer to opaque data which must be passed to request(). + */ + LV2UI_Feature_Handle handle; + + /** + Request a value for a parameter from the host. + + This is mainly used by UIs to request values for complex parameters that + don't change often, such as file paths, but it may be used to request + any parameter value. + + This function returns immediately, and the return value indicates + whether the host can fulfill the request. The host may notify the + plugin about the new parameter value, for example when a file is + selected by the user, via the usual mechanism. Typically, the host will + send a message to the plugin that sets the new parameter value, and the + plugin will notify the UI via a message as usual for any other parameter + change. + + To provide an appropriate UI, the host can determine details about the + parameter from the plugin data as usual. The additional parameters of + this function provide support for more advanced use cases, but in the + simple common case, the plugin will simply pass the key of the desired + parameter and zero for everything else. + + @param handle The handle field of this struct. + + @param key The URID of the parameter. + + @param type The optional type of the value to request. This can be used + to request a specific value type for parameters that support several. + If non-zero, it must be the URID of an instance of rdfs:Class or + rdfs:Datatype. + + @param features Additional features for this request, or NULL. + + @return A status code which is 0 on success. + */ + LV2UI_Request_Value_Status (*request)(LV2UI_Feature_Handle handle, + LV2_URID key, + LV2_URID type, + const LV2_Feature* const* features); + +} LV2UI_Request_Value; + +/** + UI Idle Interface (LV2_UI__idleInterface) + + UIs can provide this interface to have an idle() callback called by the host + rapidly to update the UI. +*/ +typedef struct _LV2UI_Idle_Interface { + /** + Run a single iteration of the UI's idle loop. + + This will be called rapidly in the UI thread at a rate appropriate + for a toolkit main loop. There are no precise timing guarantees, but + the host should attempt to call idle() at a high enough rate for smooth + animation, at least 30Hz. + + @return non-zero if the UI has been closed, in which case the host + should stop calling idle(), and can either completely destroy the UI, or + re-show it and resume calling idle(). + */ + int (*idle)(LV2UI_Handle ui); +} LV2UI_Idle_Interface; + +/** + UI Show Interface (LV2_UI__showInterface) + + UIs can provide this interface to show and hide a window, which allows them + to function in hosts unable to embed their widget. This allows any UI to + provide a fallback for embedding that works in any host. + + If used: + - The host MUST use LV2UI_Idle_Interface to drive the UI. + - The UI MUST return non-zero from LV2UI_Idle_Interface::idle() when it has been closed. + - If idle() returns non-zero, the host MUST call hide() and stop calling + idle(). It MAY later call show() then resume calling idle(). +*/ +typedef struct _LV2UI_Show_Interface { + /** + Show a window for this UI. + + The window title MAY have been passed by the host to + LV2UI_Descriptor::instantiate() as an LV2_Options_Option with key + LV2_UI__windowTitle. + + @return 0 on success, or anything else to stop being called. + */ + int (*show)(LV2UI_Handle ui); + + /** + Hide the window for this UI. + + @return 0 on success, or anything else to stop being called. + */ + int (*hide)(LV2UI_Handle ui); +} LV2UI_Show_Interface; + +/** + Peak data for a slice of time, the update format for ui:peakProtocol. +*/ +typedef struct _LV2UI_Peak_Data { + /** + The start of the measurement period. This is just a running counter + that is only meaningful in comparison to previous values and must not be + interpreted as an absolute time. + */ + uint32_t period_start; + + /** + The size of the measurement period, in the same units as period_start. + */ + uint32_t period_size; + + /** + The peak value for the measurement period. This should be the maximal + value for abs(sample) over all the samples in the period. + */ + float peak; +} LV2UI_Peak_Data; + +/** + Prototype for UI accessor function. + + This is the entry point to a UI library, which works in the same way as + lv2_descriptor() but for UIs rather than plugins. +*/ +LV2_SYMBOL_EXPORT +const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index); + +/** + The type of the lv2ui_descriptor() function. +*/ +typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index); + +#ifdef __cplusplus +} +#endif + +#endif /* LV2_UI_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/units.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/units.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,69 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup units Units + + Units for LV2 values, see for + details. + + @{ +*/ + +#ifndef LV2_UNITS_H +#define LV2_UNITS_H + +#define LV2_UNITS_URI "http://lv2plug.in/ns/extensions/units" ///< http://lv2plug.in/ns/extensions/units +#define LV2_UNITS_PREFIX LV2_UNITS_URI "#" ///< http://lv2plug.in/ns/extensions/units# + +#define LV2_UNITS__Conversion LV2_UNITS_PREFIX "Conversion" ///< http://lv2plug.in/ns/ext/units#Conversion +#define LV2_UNITS__Unit LV2_UNITS_PREFIX "Unit" ///< http://lv2plug.in/ns/ext/units#Unit +#define LV2_UNITS__bar LV2_UNITS_PREFIX "bar" ///< http://lv2plug.in/ns/ext/units#bar +#define LV2_UNITS__beat LV2_UNITS_PREFIX "beat" ///< http://lv2plug.in/ns/ext/units#beat +#define LV2_UNITS__bpm LV2_UNITS_PREFIX "bpm" ///< http://lv2plug.in/ns/ext/units#bpm +#define LV2_UNITS__cent LV2_UNITS_PREFIX "cent" ///< http://lv2plug.in/ns/ext/units#cent +#define LV2_UNITS__cm LV2_UNITS_PREFIX "cm" ///< http://lv2plug.in/ns/ext/units#cm +#define LV2_UNITS__coef LV2_UNITS_PREFIX "coef" ///< http://lv2plug.in/ns/ext/units#coef +#define LV2_UNITS__conversion LV2_UNITS_PREFIX "conversion" ///< http://lv2plug.in/ns/ext/units#conversion +#define LV2_UNITS__db LV2_UNITS_PREFIX "db" ///< http://lv2plug.in/ns/ext/units#db +#define LV2_UNITS__degree LV2_UNITS_PREFIX "degree" ///< http://lv2plug.in/ns/ext/units#degree +#define LV2_UNITS__frame LV2_UNITS_PREFIX "frame" ///< http://lv2plug.in/ns/ext/units#frame +#define LV2_UNITS__hz LV2_UNITS_PREFIX "hz" ///< http://lv2plug.in/ns/ext/units#hz +#define LV2_UNITS__inch LV2_UNITS_PREFIX "inch" ///< http://lv2plug.in/ns/ext/units#inch +#define LV2_UNITS__khz LV2_UNITS_PREFIX "khz" ///< http://lv2plug.in/ns/ext/units#khz +#define LV2_UNITS__km LV2_UNITS_PREFIX "km" ///< http://lv2plug.in/ns/ext/units#km +#define LV2_UNITS__m LV2_UNITS_PREFIX "m" ///< http://lv2plug.in/ns/ext/units#m +#define LV2_UNITS__mhz LV2_UNITS_PREFIX "mhz" ///< http://lv2plug.in/ns/ext/units#mhz +#define LV2_UNITS__midiNote LV2_UNITS_PREFIX "midiNote" ///< http://lv2plug.in/ns/ext/units#midiNote +#define LV2_UNITS__mile LV2_UNITS_PREFIX "mile" ///< http://lv2plug.in/ns/ext/units#mile +#define LV2_UNITS__min LV2_UNITS_PREFIX "min" ///< http://lv2plug.in/ns/ext/units#min +#define LV2_UNITS__mm LV2_UNITS_PREFIX "mm" ///< http://lv2plug.in/ns/ext/units#mm +#define LV2_UNITS__ms LV2_UNITS_PREFIX "ms" ///< http://lv2plug.in/ns/ext/units#ms +#define LV2_UNITS__name LV2_UNITS_PREFIX "name" ///< http://lv2plug.in/ns/ext/units#name +#define LV2_UNITS__oct LV2_UNITS_PREFIX "oct" ///< http://lv2plug.in/ns/ext/units#oct +#define LV2_UNITS__pc LV2_UNITS_PREFIX "pc" ///< http://lv2plug.in/ns/ext/units#pc +#define LV2_UNITS__prefixConversion LV2_UNITS_PREFIX "prefixConversion" ///< http://lv2plug.in/ns/ext/units#prefixConversion +#define LV2_UNITS__render LV2_UNITS_PREFIX "render" ///< http://lv2plug.in/ns/ext/units#render +#define LV2_UNITS__s LV2_UNITS_PREFIX "s" ///< http://lv2plug.in/ns/ext/units#s +#define LV2_UNITS__semitone12TET LV2_UNITS_PREFIX "semitone12TET" ///< http://lv2plug.in/ns/ext/units#semitone12TET +#define LV2_UNITS__symbol LV2_UNITS_PREFIX "symbol" ///< http://lv2plug.in/ns/ext/units#symbol +#define LV2_UNITS__unit LV2_UNITS_PREFIX "unit" ///< http://lv2plug.in/ns/ext/units#unit + +#endif /* LV2_UNITS_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/uri-map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/uri-map.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,106 @@ +/* + Copyright 2008-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup uri-map URI Map + + C API for the LV2 URI Map extension . + + This extension defines a simple mechanism for plugins to map URIs to + integers, usually for performance reasons (e.g. processing events typed by + URIs in real time). The expected use case is for plugins to map URIs to + integers for things they 'understand' at instantiation time, and store those + values for use in the audio thread without doing any string comparison. + This allows the extensibility of RDF with the performance of integers (or + centrally defined enumerations). + + @{ +*/ + +#ifndef LV2_URI_MAP_H +#define LV2_URI_MAP_H + +#define LV2_URI_MAP_URI "http://lv2plug.in/ns/ext/uri-map" ///< http://lv2plug.in/ns/ext/uri-map +#define LV2_URI_MAP_PREFIX LV2_URI_MAP_URI "#" ///< http://lv2plug.in/ns/ext/uri-map# + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Opaque pointer to host data. +*/ +typedef void* LV2_URI_Map_Callback_Data; + +/** + URI Map Feature. + + To support this feature the host must pass an LV2_Feature struct to the + plugin's instantiate method with URI "http://lv2plug.in/ns/ext/uri-map" + and data pointed to an instance of this struct. +*/ +typedef struct { + /** + Opaque pointer to host data. + + The plugin MUST pass this to any call to functions in this struct. + Otherwise, it must not be interpreted in any way. + */ + LV2_URI_Map_Callback_Data callback_data; + + /** + Get the numeric ID of a URI from the host. + + @param callback_data Must be the callback_data member of this struct. + @param map The 'context' of this URI. Certain extensions may define a + URI that must be passed here with certain restrictions on the return + value (e.g. limited range). This value may be NULL if the plugin needs + an ID for a URI in general. Extensions SHOULD NOT define a context + unless there is a specific need to do so, e.g. to restrict the range of + the returned value. + @param uri The URI to be mapped to an integer ID. + + This function is referentially transparent; any number of calls with the + same arguments is guaranteed to return the same value over the life of a + plugin instance (though the same URI may return different values with a + different map parameter). However, this function is not necessarily very + fast: plugins SHOULD cache any IDs they might need in performance + critical situations. + + The return value 0 is reserved and indicates that an ID for that URI + could not be created for whatever reason. Extensions MAY define more + precisely what this means in a certain context, but in general plugins + SHOULD handle this situation as gracefully as possible. However, hosts + SHOULD NOT return 0 from this function in non-exceptional circumstances + (e.g. the URI map SHOULD be dynamic). Hosts that statically support only + a fixed set of URIs should not expect plugins to function correctly. + */ + uint32_t (*uri_to_id)(LV2_URI_Map_Callback_Data callback_data, + const char* map, + const char* uri); +} LV2_URI_Map_Feature; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_URI_MAP_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/urid.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/urid.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,136 @@ +/* + Copyright 2008-2016 David Robillard + Copyright 2011 Gabriel M. Beddingfield + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup urid URID + + Features for mapping URIs to and from integers, see + for details. + + @{ +*/ + +#ifndef LV2_URID_H +#define LV2_URID_H + +#define LV2_URID_URI "http://lv2plug.in/ns/ext/urid" ///< http://lv2plug.in/ns/ext/urid +#define LV2_URID_PREFIX LV2_URID_URI "#" ///< http://lv2plug.in/ns/ext/urid# + +#define LV2_URID__map LV2_URID_PREFIX "map" ///< http://lv2plug.in/ns/ext/urid#map +#define LV2_URID__unmap LV2_URID_PREFIX "unmap" ///< http://lv2plug.in/ns/ext/urid#unmap + +#define LV2_URID_MAP_URI LV2_URID__map ///< Legacy +#define LV2_URID_UNMAP_URI LV2_URID__unmap ///< Legacy + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Opaque pointer to host data for LV2_URID_Map. +*/ +typedef void* LV2_URID_Map_Handle; + +/** + Opaque pointer to host data for LV2_URID_Unmap. +*/ +typedef void* LV2_URID_Unmap_Handle; + +/** + URI mapped to an integer. +*/ +typedef uint32_t LV2_URID; + +/** + URID Map Feature (LV2_URID__map) +*/ +typedef struct _LV2_URID_Map { + /** + Opaque pointer to host data. + + This MUST be passed to map_uri() whenever it is called. + Otherwise, it must not be interpreted in any way. + */ + LV2_URID_Map_Handle handle; + + /** + Get the numeric ID of a URI. + + If the ID does not already exist, it will be created. + + This function is referentially transparent; any number of calls with the + same arguments is guaranteed to return the same value over the life of a + plugin instance. Note, however, that several URIs MAY resolve to the + same ID if the host considers those URIs equivalent. + + This function is not necessarily very fast or RT-safe: plugins SHOULD + cache any IDs they might need in performance critical situations. + + The return value 0 is reserved and indicates that an ID for that URI + could not be created for whatever reason. However, hosts SHOULD NOT + return 0 from this function in non-exceptional circumstances (i.e. the + URI map SHOULD be dynamic). + + @param handle Must be the callback_data member of this struct. + @param uri The URI to be mapped to an integer ID. + */ + LV2_URID (*map)(LV2_URID_Map_Handle handle, + const char* uri); +} LV2_URID_Map; + +/** + URI Unmap Feature (LV2_URID__unmap) +*/ +typedef struct _LV2_URID_Unmap { + /** + Opaque pointer to host data. + + This MUST be passed to unmap() whenever it is called. + Otherwise, it must not be interpreted in any way. + */ + LV2_URID_Unmap_Handle handle; + + /** + Get the URI for a previously mapped numeric ID. + + Returns NULL if `urid` is not yet mapped. Otherwise, the corresponding + URI is returned in a canonical form. This MAY not be the exact same + string that was originally passed to LV2_URID_Map::map(), but it MUST be + an identical URI according to the URI syntax specification (RFC3986). A + non-NULL return for a given `urid` will always be the same for the life + of the plugin. Plugins that intend to perform string comparison on + unmapped URIs SHOULD first canonicalise URI strings with a call to + map_uri() followed by a call to unmap_uri(). + + @param handle Must be the callback_data member of this struct. + @param urid The ID to be mapped back to the URI string. + */ + const char* (*unmap)(LV2_URID_Unmap_Handle handle, + LV2_URID urid); +} LV2_URID_Unmap; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_URID_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/lv2/worker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/worker.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,177 @@ +/* + Copyright 2012-2016 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @defgroup worker Worker + + Support for non-realtime plugin operations, see + for details. + + @{ +*/ + +#ifndef LV2_WORKER_H +#define LV2_WORKER_H + +#include + +#include "lv2.h" + +#define LV2_WORKER_URI "http://lv2plug.in/ns/ext/worker" ///< http://lv2plug.in/ns/ext/worker +#define LV2_WORKER_PREFIX LV2_WORKER_URI "#" ///< http://lv2plug.in/ns/ext/worker# + +#define LV2_WORKER__interface LV2_WORKER_PREFIX "interface" ///< http://lv2plug.in/ns/ext/worker#interface +#define LV2_WORKER__schedule LV2_WORKER_PREFIX "schedule" ///< http://lv2plug.in/ns/ext/worker#schedule + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Status code for worker functions. +*/ +typedef enum { + LV2_WORKER_SUCCESS = 0, /**< Completed successfully. */ + LV2_WORKER_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_WORKER_ERR_NO_SPACE = 2 /**< Failed due to lack of space. */ +} LV2_Worker_Status; + +/** Opaque handle for LV2_Worker_Interface::work(). */ +typedef void* LV2_Worker_Respond_Handle; + +/** + A function to respond to run() from the worker method. + + The `data` MUST be safe for the host to copy and later pass to + work_response(), and the host MUST guarantee that it will be eventually + passed to work_response() if this function returns LV2_WORKER_SUCCESS. +*/ +typedef LV2_Worker_Status (*LV2_Worker_Respond_Function)( + LV2_Worker_Respond_Handle handle, + uint32_t size, + const void* data); + +/** + Plugin Worker Interface. + + This is the interface provided by the plugin to implement a worker method. + The plugin's extension_data() method should return an LV2_Worker_Interface + when called with LV2_WORKER__interface as its argument. +*/ +typedef struct _LV2_Worker_Interface { + /** + The worker method. This is called by the host in a non-realtime context + as requested, possibly with an arbitrary message to handle. + + A response can be sent to run() using `respond`. The plugin MUST NOT + make any assumptions about which thread calls this method, except that + there are no real-time requirements and only one call may be executed at + a time. That is, the host MAY call this method from any non-real-time + thread, but MUST NOT make concurrent calls to this method from several + threads. + + @param instance The LV2 instance this is a method on. + @param respond A function for sending a response to run(). + @param handle Must be passed to `respond` if it is called. + @param size The size of `data`. + @param data Data from run(), or NULL. + */ + LV2_Worker_Status (*work)(LV2_Handle instance, + LV2_Worker_Respond_Function respond, + LV2_Worker_Respond_Handle handle, + uint32_t size, + const void* data); + + /** + Handle a response from the worker. This is called by the host in the + run() context when a response from the worker is ready. + + @param instance The LV2 instance this is a method on. + @param size The size of `body`. + @param body Message body, or NULL. + */ + LV2_Worker_Status (*work_response)(LV2_Handle instance, + uint32_t size, + const void* body); + + /** + Called when all responses for this cycle have been delivered. + + Since work_response() may be called after run() finished, this provides + a hook for code that must run after the cycle is completed. + + This field may be NULL if the plugin has no use for it. Otherwise, the + host MUST call it after every run(), regardless of whether or not any + responses were sent that cycle. + */ + LV2_Worker_Status (*end_run)(LV2_Handle instance); +} LV2_Worker_Interface; + +/** Opaque handle for LV2_Worker_Schedule. */ +typedef void* LV2_Worker_Schedule_Handle; + +/** + Schedule Worker Host Feature. + + The host passes this feature to provide a schedule_work() function, which + the plugin can use to schedule a worker call from run(). +*/ +typedef struct _LV2_Worker_Schedule { + /** + Opaque host data. + */ + LV2_Worker_Schedule_Handle handle; + + /** + Request from run() that the host call the worker. + + This function is in the audio threading class. It should be called from + run() to request that the host call the work() method in a non-realtime + context with the given arguments. + + This function is always safe to call from run(), but it is not + guaranteed that the worker is actually called from a different thread. + In particular, when free-wheeling (e.g. for offline rendering), the + worker may be executed immediately. This allows single-threaded + processing with sample accuracy and avoids timing problems when run() is + executing much faster or slower than real-time. + + Plugins SHOULD be written in such a way that if the worker runs + immediately, and responses from the worker are delivered immediately, + the effect of the work takes place immediately with sample accuracy. + + The `data` MUST be safe for the host to copy and later pass to work(), + and the host MUST guarantee that it will be eventually passed to work() + if this function returns LV2_WORKER_SUCCESS. + + @param handle The handle field of this struct. + @param size The size of `data`. + @param data Message to pass to work(), or NULL. + */ + LV2_Worker_Status (*schedule_work)(LV2_Worker_Schedule_Handle handle, + uint32_t size, + const void* data); +} LV2_Worker_Schedule; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_WORKER_H */ + +/** + @} +*/ diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/README.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,9 @@ +This folder contains a pure C VST3-compatible interface, codenamed "travesty". +Name is a play on words from morphing "vestige" (the good old free VST2 reverse-engineered header file) and "three". + +The main target is to be able to create VST3-compatible plugins without a bloated SDK. +Everything that is required for plugins fits in a few small header files as presented here. +Also being able to build VST3-compatible plugins in pure C code, something not possible with the original SDK. + +Please note this project is still a work in progress. +Use at your own risk, and please report any issues to https://github.com/DISTRHO/DPF/. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/align_pop.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/align_pop.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,38 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if defined(__APPLE__) +# if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpragma-pack" +# elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunknown-warning-option" +# pragma GCC diagnostic ignored "-Wpragma-pack" +# endif +#endif + +#if defined(__APPLE__) || defined(_WIN32) +# pragma pack(pop) +#endif + +#if defined(__APPLE__) +# if defined(__clang__) +# pragma clang diagnostic pop +# elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460 +# pragma GCC diagnostic pop +# endif +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/align_push.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/align_push.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,44 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if defined(__APPLE__) + +# if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunknown-warning-option" +# pragma clang diagnostic ignored "-Wpragma-pack" +# elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunknown-warning-option" +# pragma GCC diagnostic ignored "-Wpragma-pack" +# endif + +# if defined(__LP64__) || defined(_LP64) +# pragma pack(push, 16) +# else +# pragma pack(push, 1) +# endif + +#elif defined(_WIN32) + +# pragma pack(push) +# if defined(_WIN64) || defined(_M_ARM64) +# pragma pack(16) +# else +# pragma pack(8) +# endif + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/audio_processor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/audio_processor.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,286 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" +#include "events.h" + +#include "align_push.h" + +/** + * speakers + */ + +typedef uint64_t v3_speaker_arrangement; + +enum { + V3_SPEAKER_L = 1 << 0, + V3_SPEAKER_R = 1 << 1, + V3_SPEAKER_C = 1 << 2, + V3_SPEAKER_LFE = 1 << 3, + V3_SPEAKER_LS = 1 << 4, + V3_SPEAKER_RS = 1 << 5, + V3_SPEAKER_LC = 1 << 6, + V3_SPEAKER_RC = 1 << 7, + V3_SPEAKER_S = 1 << 8, + V3_SPEAKER_SL = 1 << 9, + V3_SPEAKER_SR = 1 << 10, + V3_SPEAKER_TC = 1 << 11, + V3_SPEAKER_TFL = 1 << 12, + V3_SPEAKER_TFC = 1 << 13, + V3_SPEAKER_TFR = 1 << 14, + V3_SPEAKER_TRL = 1 << 15, + V3_SPEAKER_TRC = 1 << 16, + V3_SPEAKER_TRR = 1 << 17, + V3_SPEAKER_LFE2 = 1 << 18, + V3_SPEAKER_M = 1 << 19 +}; + +/** + * process setup + */ + +enum v3_process_mode { + V3_REALTIME, + V3_PREFETCH, + V3_OFFLINE +}; + +static inline +const char* v3_process_mode_str(int32_t d) +{ + switch (d) + { + case V3_REALTIME: + return "V3_REALTIME"; + case V3_PREFETCH: + return "V3_PREFETCH"; + case V3_OFFLINE: + return "V3_OFFLINE"; + default: + return "[unknown]"; + } +} + +enum { + V3_SAMPLE_32, + V3_SAMPLE_64 +}; + +static inline +const char* v3_sample_size_str(int32_t d) +{ + switch (d) + { + case V3_SAMPLE_32: + return "V3_SAMPLE_32"; + case V3_SAMPLE_64: + return "V3_SAMPLE_64"; + default: + return "[unknown]"; + } +} + +struct v3_process_setup { + int32_t process_mode; + int32_t symbolic_sample_size; + int32_t max_block_size; + double sample_rate; +}; + +/** + * param changes + */ + +struct v3_param_value_queue { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_param_id (V3_API* get_param_id)(void* self); + int32_t (V3_API* get_point_count)(void* self); + v3_result (V3_API* get_point)(void* self, int32_t idx, int32_t* sample_offset, double* value); + v3_result (V3_API* add_point)(void* self, int32_t sample_offset, double value, int32_t* idx); +}; + +static constexpr const v3_tuid v3_param_value_queue_iid = + V3_ID(0x01263A18, 0xED074F6F, 0x98C9D356, 0x4686F9BA); + +struct v3_param_changes { +#ifndef __cplusplus + struct v3_funknown; +#endif + int32_t (V3_API* get_param_count)(void* self); + struct v3_param_value_queue** (V3_API* get_param_data)(void* self, int32_t idx); + struct v3_param_value_queue** (V3_API* add_param_data)(void* self, v3_param_id* id, int32_t* index); +}; + +static constexpr const v3_tuid v3_param_changes_iid = + V3_ID(0xA4779663, 0x0BB64A56, 0xB44384A8, 0x466FEB9D); + +/** + * process context + */ + +struct v3_frame_rate { + uint32_t fps; + uint32_t flags; +}; + +struct v3_chord { + uint8_t key_note; + uint8_t root_note; + int16_t chord_mask; +}; + +enum { + V3_PROCESS_CTX_PLAYING = 1 << 1, + V3_PROCESS_CTX_CYCLE_ACTIVE = 1 << 2, + V3_PROCESS_CTX_RECORDING = 1 << 3, + V3_PROCESS_CTX_SYSTEM_TIME_VALID = 1 << 8, + V3_PROCESS_CTX_PROJECT_TIME_VALID = 1 << 9, + V3_PROCESS_CTX_TEMPO_VALID = 1 << 10, + V3_PROCESS_CTX_BAR_POSITION_VALID = 1 << 11, + V3_PROCESS_CTX_CYCLE_VALID = 1 << 12, + V3_PROCESS_CTX_TIME_SIG_VALID = 1 << 13, + V3_PROCESS_CTX_SMPTE_VALID = 1 << 14, + V3_PROCESS_CTX_NEXT_CLOCK_VALID = 1 << 15, + V3_PROCESS_CTX_CONT_TIME_VALID = 1 << 17, + V3_PROCESS_CTX_CHORD_VALID = 1 << 18 +}; + +struct v3_process_context { + uint32_t state; + double sample_rate; + int64_t project_time_in_samples; // with loop + int64_t system_time_ns; + int64_t continuous_time_in_samples; // without loop + double project_time_quarters; + double bar_position_quarters; + double cycle_start_quarters; + double cycle_end_quarters; + double bpm; + int32_t time_sig_numerator; + int32_t time_sig_denom; + struct v3_chord chord; + int32_t smpte_offset_subframes; + struct v3_frame_rate frame_rate; + int32_t samples_to_next_clock; +}; + +/** + * process context requirements + */ + +enum { + V3_PROCESS_CTX_NEED_SYSTEM_TIME = 1 << 0, + V3_PROCESS_CTX_NEED_CONTINUOUS_TIME = 1 << 1, + V3_PROCESS_CTX_NEED_PROJECT_TIME = 1 << 2, + V3_PROCESS_CTX_NEED_BAR_POSITION = 1 << 3, + V3_PROCESS_CTX_NEED_CYCLE = 1 << 4, + V3_PROCESS_CTX_NEED_NEXT_CLOCK = 1 << 5, + V3_PROCESS_CTX_NEED_TEMPO = 1 << 6, + V3_PROCESS_CTX_NEED_TIME_SIG = 1 << 7, + V3_PROCESS_CTX_NEED_CHORD = 1 << 8, + V3_PROCESS_CTX_NEED_FRAME_RATE = 1 << 9, + V3_PROCESS_CTX_NEED_TRANSPORT_STATE = 1 << 10 +}; + +struct v3_process_context_requirements { +#ifndef __cplusplus + struct v3_funknown; +#endif + uint32_t (V3_API* get_process_context_requirements)(void* self); +}; + +static constexpr const v3_tuid v3_process_context_requirements_iid = + V3_ID(0x2A654303, 0xEF764E3D, 0x95B5FE83, 0x730EF6D0); + +/** + * process data and context + */ + +struct v3_audio_bus_buffers { + int32_t num_channels; + uint64_t channel_silence_bitset; + union { + float** channel_buffers_32; + double** channel_buffers_64; + }; +}; + +struct v3_process_data { + int32_t process_mode; + int32_t symbolic_sample_size; + int32_t nframes; + int32_t num_input_buses; + int32_t num_output_buses; + struct v3_audio_bus_buffers* inputs; + struct v3_audio_bus_buffers* outputs; + struct v3_param_changes** input_params; + struct v3_param_changes** output_params; + struct v3_event_list** input_events; + struct v3_event_list** output_events; + struct v3_process_context* ctx; +}; + +/** + * audio processor + */ + +struct v3_audio_processor { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* set_bus_arrangements)(void* self, v3_speaker_arrangement* inputs, int32_t num_inputs, + v3_speaker_arrangement* outputs, int32_t num_outputs); + v3_result (V3_API* get_bus_arrangement)(void* self, int32_t bus_direction, int32_t idx, v3_speaker_arrangement*); + v3_result (V3_API* can_process_sample_size)(void* self, int32_t symbolic_sample_size); + uint32_t (V3_API* get_latency_samples)(void* self); + v3_result (V3_API* setup_processing)(void* self, struct v3_process_setup* setup); + v3_result (V3_API* set_processing)(void* self, v3_bool state); + v3_result (V3_API* process)(void* self, struct v3_process_data* data); + uint32_t (V3_API* get_tail_samples)(void* self); +}; + +static constexpr const v3_tuid v3_audio_processor_iid = + V3_ID(0x42043F99, 0xB7DA453C, 0xA569E79D, 0x9AAEC33D); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_param_value_queue_cpp : v3_funknown { + v3_param_value_queue queue; +}; + +struct v3_param_changes_cpp : v3_funknown { + v3_param_changes changes; +}; + +struct v3_process_context_requirements_cpp : v3_funknown { + v3_process_context_requirements req; +}; + +struct v3_audio_processor_cpp : v3_funknown { + v3_audio_processor proc; +}; + +#endif + +#include "align_pop.h" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/base.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/base.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,224 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include +#include +#include + +/** + * deal with C vs C++ differences + */ + +#if !defined(__cplusplus) && !defined(constexpr) +# define constexpr +#endif + +/** + * various types + */ + +typedef int32_t v3_result; + +typedef int16_t v3_str_128[128]; +typedef uint8_t v3_bool; + +typedef uint32_t v3_param_id; + +/** + * low-level ABI nonsense + */ + +typedef uint8_t v3_tuid[16]; + +static inline +bool v3_tuid_match(const v3_tuid a, const v3_tuid b) +{ + return memcmp(a, b, sizeof(v3_tuid)) == 0; +} + +#if defined(_WIN32) +# define V3_COM_COMPAT 1 +# define V3_API __stdcall +#else +# define V3_COM_COMPAT 0 +# define V3_API +#endif + +#if V3_COM_COMPAT +enum { + V3_NO_INTERFACE = 0x80004002L, + V3_OK = 0, + V3_TRUE = 0, + V3_FALSE = 1, + V3_INVALID_ARG = 0x80070057L, + V3_NOT_IMPLEMENTED = 0x80004001L, + V3_INTERNAL_ERR = 0x80004005L, + V3_NOT_INITIALIZED = 0x8000FFFFL, + V3_NOMEM = 0x8007000EL +}; + +# define V3_ID(a, b, c, d) { \ + ((a) & 0x000000FF), \ + ((a) & 0x0000FF00) >> 8, \ + ((a) & 0x00FF0000) >> 16, \ + ((a) & 0xFF000000) >> 24, \ + \ + ((b) & 0x00FF0000) >> 16, \ + ((b) & 0xFF000000) >> 24, \ + ((b) & 0x000000FF), \ + ((b) & 0x0000FF00) >> 8, \ + \ + ((c) & 0xFF000000) >> 24, \ + ((c) & 0x00FF0000) >> 16, \ + ((c) & 0x0000FF00) >> 8, \ + ((c) & 0x000000FF), \ + \ + ((d) & 0xFF000000) >> 24, \ + ((d) & 0x00FF0000) >> 16, \ + ((d) & 0x0000FF00) >> 8, \ + ((d) & 0x000000FF), \ +} + +#else // V3_COM_COMPAT +enum { + V3_NO_INTERFACE = -1, + V3_OK, + V3_TRUE = V3_OK, + V3_FALSE, + V3_INVALID_ARG, + V3_NOT_IMPLEMENTED, + V3_INTERNAL_ERR, + V3_NOT_INITIALIZED, + V3_NOMEM +}; + +# define V3_ID(a, b, c, d) { \ + ((a) & 0xFF000000) >> 24, \ + ((a) & 0x00FF0000) >> 16, \ + ((a) & 0x0000FF00) >> 8, \ + ((a) & 0x000000FF), \ + \ + ((b) & 0xFF000000) >> 24, \ + ((b) & 0x00FF0000) >> 16, \ + ((b) & 0x0000FF00) >> 8, \ + ((b) & 0x000000FF), \ + \ + ((c) & 0xFF000000) >> 24, \ + ((c) & 0x00FF0000) >> 16, \ + ((c) & 0x0000FF00) >> 8, \ + ((c) & 0x000000FF), \ + \ + ((d) & 0xFF000000) >> 24, \ + ((d) & 0x00FF0000) >> 16, \ + ((d) & 0x0000FF00) >> 8, \ + ((d) & 0x000000FF), \ +} +#endif // V3_COM_COMPAT + +#define V3_ID_COPY(iid) \ + { iid[0], iid[1], iid[ 2], iid[ 3], iid[ 4], iid[ 5], iid[ 6], iid[ 7], \ + iid[8], iid[9], iid[10], iid[11], iid[12], iid[13], iid[14], iid[15] } + +/** + * funknown + */ + +struct v3_funknown { + v3_result (V3_API* query_interface)(void* self, const v3_tuid iid, void** obj); + uint32_t (V3_API* ref)(void* self); + uint32_t (V3_API* unref)(void* self); +}; + +static constexpr const v3_tuid v3_funknown_iid = + V3_ID(0x00000000, 0x00000000, 0xC0000000, 0x00000046); + +/** + * plugin base + */ + +struct v3_plugin_base { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* initialize)(void* self, struct v3_funknown** context); + v3_result (V3_API* terminate)(void* self); +}; + +static constexpr const v3_tuid v3_plugin_base_iid = + V3_ID(0x22888DDB, 0x156E45AE, 0x8358B348, 0x08190625); + +#ifdef __cplusplus + +/** + * cast object into its proper C++ type. + * this is needed because `struct v3_funknown;` on a C++ class does not inherit `v3_funknown`'s fields. + * + * we can use this as a little helper for keeping both C and C++ compatiblity. + * specialized templated calls are defined where required + * (that is, object inherits from something other than `v3_funknown`) + * + * example usage: `v3_cpp_obj(obj)->method(obj, args...);` + */ + +template static inline +constexpr T* v3_cpp_obj(T** obj) +{ + /** + * this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default, + * but we need everything to be `static_cast` for it to be `constexpr` compatible. + */ + return static_cast(static_cast(static_cast(static_cast(*obj)) + sizeof(void*)*3)); +} + +/** + * helper C++ functions to manually call v3_funknown methods on an object. + */ + +template static inline +v3_result v3_cpp_obj_query_interface(T** obj, const v3_tuid iid, M*** obj2) +{ + return static_cast(static_cast(*obj))->query_interface(obj, iid, (void**)obj2); +} + +template static inline +uint32_t v3_cpp_obj_ref(T** obj) +{ + return static_cast(static_cast(*obj))->ref(obj); +} + +template static inline +uint32_t v3_cpp_obj_unref(T** obj) +{ + return static_cast(static_cast(*obj))->unref(obj); +} + +template static inline +v3_result v3_cpp_obj_initialize(T** obj, v3_funknown** context) +{ + return static_cast( + static_cast(static_cast(static_cast(*obj)) + sizeof(void*)*3))->initialize(obj, context); +} + +template static inline +v3_result v3_cpp_obj_terminate(T** obj) +{ + return static_cast( + static_cast(static_cast(static_cast(*obj)) + sizeof(void*)*3))->terminate(obj); +} + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/bstream.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/bstream.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,38 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" + +enum v3_seek_mode { + V3_SEEK_SET = 0, + V3_SEEK_CUR, + V3_SEEK_END +}; + +struct v3_bstream { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API *read)(void* self, void* buffer, int32_t num_bytes, int32_t* bytes_read); + v3_result (V3_API *write)(void* self, void* buffer, int32_t num_bytes, int32_t* bytes_written); + v3_result (V3_API *seek)(void* self, int64_t pos, int32_t seek_mode, int64_t* result); + v3_result (V3_API *tell)(void* self, int64_t* pos); +}; + +static constexpr const v3_tuid v3_bstream_iid = + V3_ID(0xC3BF6EA2, 0x30994752, 0x9B6BF990, 0x1EE33E9B); diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/component.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/component.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,145 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" +#include "bstream.h" + +#include "align_push.h" + +/** + * buses + */ + +enum v3_media_types { + V3_AUDIO = 0, + V3_EVENT +}; + +static inline +const char* v3_media_type_str(int32_t type) +{ + switch (type) + { + case V3_AUDIO: + return "V3_AUDIO"; + case V3_EVENT: + return "V3_EVENT"; + default: + return "[unknown]"; + } +} + +enum v3_bus_direction { + V3_INPUT = 0, + V3_OUTPUT +}; + +static inline +const char* v3_bus_direction_str(int32_t d) +{ + switch (d) + { + case V3_INPUT: + return "V3_INPUT"; + case V3_OUTPUT: + return "V3_OUTPUT"; + default: + return "[unknown]"; + } +} + +enum v3_bus_types { + V3_MAIN = 0, + V3_AUX +}; + +enum v3_bus_flags { + V3_DEFAULT_ACTIVE = 1 << 0, + V3_IS_CONTROL_VOLTAGE = 1 << 1 +}; + +enum v3_io_mode { + V3_SIMPLE = 0, + V3_ADVANCED, + V3_OFFLINE_PROCESSING +}; + +struct v3_bus_info { + int32_t media_type; + int32_t direction; + int32_t channel_count; + v3_str_128 bus_name; + int32_t bus_type; + uint32_t flags; +}; + +struct v3_routing_info { + int32_t media_type; + int32_t bus_idx; + int32_t channel; +}; + +/** + * component + */ + +struct v3_component { +#ifndef __cplusplus + struct v3_plugin_base; +#endif + v3_result (V3_API *get_controller_class_id)(void* self, v3_tuid class_id); + v3_result (V3_API *set_io_mode)(void* self, int32_t io_mode); + int32_t (V3_API *get_bus_count)(void* self, int32_t media_type, int32_t bus_direction); + v3_result (V3_API *get_bus_info)(void* self, int32_t media_type, int32_t bus_direction, + int32_t bus_idx, struct v3_bus_info* bus_info); + v3_result (V3_API *get_routing_info)(void* self, struct v3_routing_info* input, struct v3_routing_info* output); + v3_result (V3_API *activate_bus)(void* self, int32_t media_type, int32_t bus_direction, + int32_t bus_idx, v3_bool state); + v3_result (V3_API *set_active)(void* self, v3_bool state); + v3_result (V3_API *set_state)(void* self, struct v3_bstream **); + v3_result (V3_API *get_state)(void* self, struct v3_bstream **); +}; + +static constexpr const v3_tuid v3_component_iid = + V3_ID(0xE831FF31, 0xF2D54301, 0x928EBBEE, 0x25697802); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_component_cpp : v3_funknown { + v3_plugin_base base; + v3_component comp; +}; + +template<> inline +constexpr v3_component* v3_cpp_obj(v3_component** obj) +{ + /** + * this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default, + * but we need everything to be `static_cast` for it to be `constexpr` compatible. + */ + return static_cast( + static_cast(static_cast(static_cast(*obj)) + sizeof(void*)*5)); +} + +#endif + +#include "align_pop.h" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/edit_controller.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/edit_controller.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,157 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" +#include "bstream.h" +#include "view.h" + +#include "align_push.h" + +/** + * component handler + */ + +enum { + V3_RESTART_RELOAD_COMPONENT = 1 << 0, + V3_RESTART_IO_CHANGED = 1 << 1, + V3_RESTART_PARAM_VALUES_CHANGED = 1 << 2, + V3_RESTART_LATENCY_CHANGED = 1 << 3, + V3_RESTART_PARAM_TITLES_CHANGED = 1 << 4, + V3_RESTART_MIDI_CC_ASSIGNMENT_CHANGED = 1 << 5, + V3_RESTART_NOTE_EXPRESSION_CHANGED = 1 << 6, + V3_RESTART_IO_TITLES_CHANGED = 1 << 7, + V3_RESTART_PREFETCHABLE_SUPPORT_CHANGED = 1 << 8, + V3_RESTART_ROUTING_INFO_CHANGED = 1 << 9 +}; + +struct v3_component_handler { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* begin_edit)(void* self, v3_param_id); + v3_result (V3_API* perform_edit)(void* self, v3_param_id, double value_normalised); + v3_result (V3_API* end_edit)(void* self, v3_param_id); + v3_result (V3_API* restart_component)(void* self, int32_t flags); +}; + +static constexpr const v3_tuid v3_component_handler_iid = + V3_ID(0x93A0BEA3, 0x0BD045DB, 0x8E890B0C, 0xC1E46AC6); + +struct v3_component_handler2 { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* set_dirty)(void* self, v3_bool state); + v3_result (V3_API* request_open_editor)(void* self, const char* name); + v3_result (V3_API* start_group_edit)(void* self); + v3_result (V3_API* finish_group_edit)(void* self); +}; + +static constexpr const v3_tuid v3_component_handler2_iid = + V3_ID(0xF040B4B3, 0xA36045EC, 0xABCDC045, 0xB4D5A2CC); + +/** + * edit controller + */ + +enum { + V3_PARAM_CAN_AUTOMATE = 1 << 0, + V3_PARAM_READ_ONLY = 1 << 1, + V3_PARAM_WRAP_AROUND = 1 << 2, + V3_PARAM_IS_LIST = 1 << 3, + V3_PARAM_IS_HIDDEN = 1 << 4, + V3_PARAM_PROGRAM_CHANGE = 1 << 15, + V3_PARAM_IS_BYPASS = 1 << 16 +}; + +struct v3_param_info { + v3_param_id param_id; + v3_str_128 title; + v3_str_128 short_title; + v3_str_128 units; + int32_t step_count; + double default_normalised_value; + int32_t unit_id; + int32_t flags; +}; + +struct v3_edit_controller { +#ifndef __cplusplus + struct v3_plugin_base; +#endif + v3_result (V3_API* set_component_state)(void* self, struct v3_bstream**); + v3_result (V3_API* set_state)(void* self, struct v3_bstream**); + v3_result (V3_API* get_state)(void* self, struct v3_bstream**); + int32_t (V3_API* get_parameter_count)(void* self); + v3_result (V3_API* get_parameter_info)(void* self, int32_t param_idx, struct v3_param_info*); + v3_result (V3_API* get_parameter_string_for_value)(void* self, v3_param_id, double normalised, v3_str_128 output); + v3_result (V3_API* get_parameter_value_for_string)(void* self, v3_param_id, int16_t* input, double* output); + double (V3_API* normalised_parameter_to_plain)(void* self, v3_param_id, double normalised); + double (V3_API* plain_parameter_to_normalised)(void* self, v3_param_id, double plain); + double (V3_API* get_parameter_normalised)(void* self, v3_param_id); + v3_result (V3_API* set_parameter_normalised)(void* self, v3_param_id, double normalised); + v3_result (V3_API* set_component_handler)(void* self, struct v3_component_handler**); + struct v3_plugin_view** (V3_API* create_view)(void* self, const char* name); +}; + +static constexpr const v3_tuid v3_edit_controller_iid = + V3_ID(0xDCD7BBE3, 0x7742448D, 0xA874AACC, 0x979C759E); + +/** + * midi mapping + */ + +struct v3_midi_mapping { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* get_midi_controller_assignment)(void* self, int32_t bus, int16_t channel, int16_t cc, v3_param_id* id); +}; + +static constexpr const v3_tuid v3_midi_mapping_iid = + V3_ID(0xDF0FF9F7, 0x49B74669, 0xB63AB732, 0x7ADBF5E5); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_edit_controller_cpp : v3_funknown { + v3_plugin_base base; + v3_edit_controller ctrl; +}; + +struct v3_midi_mapping_cpp : v3_funknown { + v3_midi_mapping map; +}; + +template<> inline +constexpr v3_edit_controller* v3_cpp_obj(v3_edit_controller** obj) +{ + /** + * this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default, + * but we need everything to be `static_cast` for it to be `constexpr` compatible. + */ + return static_cast( + static_cast(static_cast(static_cast(*obj)) + sizeof(void*)*5)); +} + +#endif + +#include "align_pop.h" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/events.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/events.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,158 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" + +#include "align_push.h" + +/** + * note events + */ + +struct v3_event_note_on { + int16_t channel; + int16_t pitch; // MIDI note number + float tuning; + float velocity; + int32_t length; + int32_t note_id; +}; + +struct v3_event_note_off { + int16_t channel; + int16_t pitch; // MIDI note number + float velocity; + int32_t note_id; + float tuning; +}; + +struct v3_event_data { + uint32_t size; + uint32_t type; + const uint8_t* bytes; +}; + +struct v3_event_poly_pressure { + int16_t channel; + int16_t pitch; + float pressure; + int32_t note_id; +}; + +struct v3_event_chord { + int16_t root; + int16_t bass_note; + int16_t mask; + uint16_t text_len; + const int16_t* text; +}; + +struct v3_event_scale { + int16_t root; + int16_t mask; + uint16_t text_len; + const int16_t* text; +}; + +struct v3_event_legacy_midi_cc_out { + uint8_t cc_number; + int8_t channel; + int8_t value; + int8_t value2; +}; + +struct v3_event_note_expression_value { + uint32_t type_id; + int32_t note_id; + double value; +}; + +struct v3_event_note_expression_text { + int32_t note_id; + uint32_t text_len; + const int16_t* text; +}; + +/** + * event + */ + +enum v3_event_flags { + V3_EVENT_IS_LIVE = 1 << 0 +}; + +enum v3_event_type { + V3_EVENT_NOTE_ON = 0, + V3_EVENT_NOTE_OFF = 1, + V3_EVENT_DATA = 2, + V3_EVENT_POLY_PRESSURE = 3, + V3_EVENT_NOTE_EXP_VALUE = 4, + V3_EVENT_NOTE_EXP_TEXT = 5, + V3_EVENT_CHORD = 6, + V3_EVENT_SCALE = 7, + V3_EVENT_LEGACY_MIDI_CC_OUT = 65535 +}; + +struct v3_event { + int32_t bus_index; + int32_t sample_offset; + double ppq_position; + uint16_t flags; + uint16_t type; + union { + struct v3_event_note_on note_on; + struct v3_event_note_off note_off; + struct v3_event_data data; + struct v3_event_poly_pressure poly_pressure; + struct v3_event_chord chord; + struct v3_event_scale scale; + struct v3_event_legacy_midi_cc_out midi_cc_out; + struct v3_event_note_expression_value note_exp_value; + struct v3_event_note_expression_text note_exp_text; + }; +}; + +/** + * event list + */ + +struct v3_event_list { +#ifndef __cplusplus + struct v3_funknown; +#endif + uint32_t (V3_API* get_event_count)(void* self); + v3_result (V3_API* get_event)(void* self, int32_t idx, struct v3_event* event); + v3_result (V3_API* add_event)(void* self, struct v3_event* event); +}; + +static constexpr const v3_tuid v3_event_list_iid = + V3_ID(0x3A2C4214, 0x346349FE, 0xB2C4F397, 0xB9695A44); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_event_list_cpp : v3_funknown { + v3_event_list list; +}; + +#endif + +#include "align_pop.h" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/factory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/factory.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,147 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" + +/** + * plugin factory v1 + */ + +struct v3_factory_info { + char vendor[64]; + char url[256]; + char email[128]; + int32_t flags; // set to 0x10 (unicode) +}; + +struct v3_class_info { + v3_tuid class_id; + int32_t cardinality; // set to 0x7FFFFFFF (many instances) + char category[32]; + char name[64]; +}; + +struct v3_plugin_factory { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API *get_factory_info)(void* self, struct v3_factory_info*); + int32_t (V3_API *num_classes)(void* self); + v3_result (V3_API *get_class_info)(void* self, int32_t idx, struct v3_class_info*); + v3_result (V3_API *create_instance)(void* self, const v3_tuid class_id, const v3_tuid iid, void** instance); +}; + +static constexpr const v3_tuid v3_plugin_factory_iid = + V3_ID(0x7A4D811C, 0x52114A1F, 0xAED9D2EE, 0x0B43BF9F); + +/** + * plugin factory v2 + */ + +enum { + V3_DISTRIBUTABLE = 1 << 0, + V3_SIMPLE_MODE = 1 << 1 +}; + +struct v3_class_info_2 { + v3_tuid class_id; + int32_t cardinality; // set to 0x7FFFFFFF + char category[32]; + char name[64]; + uint32_t class_flags; + char sub_categories[128]; + char vendor[64]; + char version[64]; + char sdk_version[64]; +}; + +struct v3_plugin_factory_2 { +#ifndef __cplusplus + struct v3_plugin_factory; +#endif + v3_result (V3_API *get_class_info_2)(void* self, int32_t idx, struct v3_class_info_2*); +}; + +static constexpr const v3_tuid v3_plugin_factory_2_iid = + V3_ID(0x0007B650, 0xF24B4C0B, 0xA464EDB9, 0xF00B2ABB); + +/** + * plugin factory v3 + * (we got it right this time I swear) + * + * same as above, but "unicode" (really just utf-16, thanks microsoft!) + */ + +struct v3_class_info_3 { + v3_tuid class_id; + int32_t cardinality; // set to 0x7FFFFFFF + char category[32]; + int16_t name[64]; + uint32_t class_flags; + char sub_categories[128]; + int16_t vendor[64]; + int16_t version[64]; + int16_t sdk_version[64]; +}; + +struct v3_plugin_factory_3 { +#ifndef __cplusplus + struct v3_plugin_factory_2; +#endif + v3_result (V3_API *get_class_info_utf16)(void* self, int32_t idx, struct v3_class_info_3*); + v3_result (V3_API *set_host_context)(void* self, struct v3_funknown** host); +}; + +static constexpr const v3_tuid v3_plugin_factory_3_iid = + V3_ID(0x4555A2AB, 0xC1234E57, 0x9B122910, 0x36878931); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_plugin_factory_cpp : v3_funknown { + v3_plugin_factory v1; + v3_plugin_factory_2 v2; + v3_plugin_factory_3 v3; +}; + +template<> inline +constexpr v3_plugin_factory_2* v3_cpp_obj(v3_plugin_factory_2** obj) +{ + /** + * this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default, + * but we need everything to be `static_cast` for it to be `constexpr` compatible. + */ + return static_cast( + static_cast(static_cast(static_cast(*obj)) + sizeof(void*)*7)); +} + +template<> inline +constexpr v3_plugin_factory_3* v3_cpp_obj(v3_plugin_factory_3** obj) +{ + /** + * this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default, + * but we need everything to be `static_cast` for it to be `constexpr` compatible. + */ + return static_cast( + static_cast(static_cast(static_cast(*obj)) + sizeof(void*)*8)); +} + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/host.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/host.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,50 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "message.h" + +#include "align_push.h" + +/** + * host application + */ + +struct v3_host_application { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* get_name)(void* self, v3_str_128 name); // wtf? + v3_result (V3_API* create_instance)(void* self, v3_tuid cid, v3_tuid iid, void** obj); +}; + +static constexpr const v3_tuid v3_host_application_iid = + V3_ID(0x58E595CC, 0xDB2D4969, 0x8B6AAF8C, 0x36A664E5); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_host_application_cpp : v3_funknown { + v3_host_application app; +}; + +#endif + +#include "align_pop.h" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/message.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/message.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,96 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" + +#include "align_push.h" + +/** + * attribute list + */ + +struct v3_attribute_list { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* set_int)(void* self, const char* id, int64_t value); + v3_result (V3_API* get_int)(void* self, const char* id, int64_t* value); + v3_result (V3_API* set_float)(void* self, const char* id, double value); + v3_result (V3_API* get_float)(void* self, const char* id, double* value); + v3_result (V3_API* set_string)(void* self, const char* id, const int16_t* string); + v3_result (V3_API* get_string)(void* self, const char* id, int16_t* string, uint32_t size); + v3_result (V3_API* set_binary)(void* self, const char* id, const void* data, uint32_t size); + v3_result (V3_API* get_binary)(void* self, const char* id, const void** data, uint32_t* size); +}; + +static constexpr const v3_tuid v3_attribute_list_iid = + V3_ID(0x1E5F0AEB, 0xCC7F4533, 0xA2544011, 0x38AD5EE4); + +/** + * message + */ + +struct v3_message { +#ifndef __cplusplus + struct v3_funknown; +#endif + const char* (V3_API* get_message_id)(void* self); + void (V3_API* set_message_id)(void* self, const char* id); + v3_attribute_list** (V3_API* get_attributes)(void* self); +}; + +static constexpr const v3_tuid v3_message_iid = + V3_ID(0x936F033B, 0xC6C047DB, 0xBB0882F8, 0x13C1E613); + +/** + * connection point + */ + +struct v3_connection_point { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* connect)(void* self, struct v3_connection_point** other); + v3_result (V3_API* disconnect)(void* self, struct v3_connection_point** other); + v3_result (V3_API* notify)(void* self, struct v3_message** message); +}; + +static constexpr const v3_tuid v3_connection_point_iid = + V3_ID(0x70A4156F, 0x6E6E4026, 0x989148BF, 0xAA60D8D1); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_attribute_list_cpp : v3_funknown { + v3_attribute_list attrlist; +}; + +struct v3_message_cpp : v3_funknown { + v3_message msg; +}; + +struct v3_connection_point_cpp : v3_funknown { + v3_connection_point point; +}; + +#endif + +#include "align_pop.h" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/unit.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/unit.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,69 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" + +#include "align_push.h" + +struct v3_unit_info { + int32_t id; // 0 for root unit + int32_t parent_unit_id; // -1 for none + v3_str_128 name; + int32_t program_list_id; // -1 for none +}; + +struct v3_program_list_info { + int32_t id; + v3_str_128 name; + int32_t programCount; +}; + +struct v3_unit_information { +#ifndef __cplusplus + struct v3_funknown; +#endif + int32_t (V3_API* get_unit_count)(void* self); + v3_result (V3_API* get_unit_info)(void* self, int32_t unit_idx, v3_unit_info* info); + int32_t (V3_API* get_program_list_count)(void* self); + v3_result (V3_API* get_program_list_info)(void* self, int32_t list_idx, v3_program_list_info* info); + v3_result (V3_API* get_program_name)(void* self, int32_t list_id, int32_t program_idx, v3_str_128 name); + v3_result (V3_API* get_program_info)(void* self, int32_t list_id, int32_t program_idx, const char *attribute_id, v3_str_128 attribute_value); + v3_result (V3_API* has_program_pitch_names)(void* self, int32_t list_id, int32_t program_idx); + v3_result (V3_API* get_program_pitch_name)(void* self, int32_t list_id, int32_t program_idx, int16_t midi_pitch, v3_str_128 name); + int32_t (V3_API* get_selected_unit)(void* self); + v3_result (V3_API* select_unit)(void* self, int32_t unit_id); + v3_result (V3_API* get_unit_by_bus)(void* self, int32_t type, int32_t bus_direction, int32_t bus_idx, int32_t channel, int32_t* unit_id); + v3_result (V3_API* set_unit_program_data)(void* self, int32_t list_or_unit_id, int32_t program_idx, struct v3_bstream** data); +}; + +static constexpr const v3_tuid v3_unit_information_iid = + V3_ID(0x3D4BD6B5, 0x913A4FD2, 0xA886E768, 0xA5EB92C1); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_unit_information_cpp : v3_funknown { + v3_unit_information unit; +}; + +#endif + +#include "align_pop.h" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/travesty/view.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/travesty/view.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,193 @@ +/* + * travesty, pure C VST3-compatible interface + * Copyright (C) 2021-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include "base.h" + +/** + * base view stuff + */ + +struct v3_view_rect { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +}; + +#define V3_VIEW_PLATFORM_TYPE_HWND "HWND" +#define V3_VIEW_PLATFORM_TYPE_NSVIEW "NSView" +#define V3_VIEW_PLATFORM_TYPE_X11 "X11EmbedWindowID" + +#if defined(__APPLE__) +# define V3_VIEW_PLATFORM_TYPE_NATIVE V3_VIEW_PLATFORM_TYPE_NSVIEW +#elif defined(_WIN32) +# define V3_VIEW_PLATFORM_TYPE_NATIVE V3_VIEW_PLATFORM_TYPE_HWND +#else +# define V3_VIEW_PLATFORM_TYPE_NATIVE V3_VIEW_PLATFORM_TYPE_X11 +#endif + +/** + * plugin view + */ + +struct v3_plugin_frame; + +struct v3_plugin_view { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* is_platform_type_supported)(void* self, const char* platform_type); + v3_result (V3_API* attached)(void* self, void* parent, const char* platform_type); + v3_result (V3_API* removed)(void* self); + v3_result (V3_API* on_wheel)(void* self, float distance); + v3_result (V3_API* on_key_down)(void* self, int16_t key_char, int16_t key_code, int16_t modifiers); + v3_result (V3_API* on_key_up)(void* self, int16_t key_char, int16_t key_code, int16_t modifiers); + v3_result (V3_API* get_size)(void* self, struct v3_view_rect*); + v3_result (V3_API* on_size)(void* self, struct v3_view_rect*); + v3_result (V3_API* on_focus)(void* self, v3_bool state); + v3_result (V3_API* set_frame)(void* self, struct v3_plugin_frame**); + v3_result (V3_API* can_resize)(void* self); + v3_result (V3_API* check_size_constraint)(void* self, struct v3_view_rect*); +}; + +static constexpr const v3_tuid v3_plugin_view_iid = + V3_ID(0x5BC32507, 0xD06049EA, 0xA6151B52, 0x2B755B29); + +/** + * plugin frame + */ + +struct v3_plugin_frame { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* resize_view)(void* self, struct v3_plugin_view**, struct v3_view_rect*); +}; + +static constexpr const v3_tuid v3_plugin_frame_iid = + V3_ID(0x367FAF01, 0xAFA94693, 0x8D4DA2A0, 0xED0882A3); + +/** + * steinberg content scaling support + * (same IID/iface as presonus view scaling) + */ + +struct v3_plugin_view_content_scale { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* set_content_scale_factor)(void* self, float factor); +}; + +static constexpr const v3_tuid v3_plugin_view_content_scale_iid = + V3_ID(0x65ED9690, 0x8AC44525, 0x8AADEF7A, 0x72EA703F); + +/** + * support for querying the view to find what control is underneath the mouse + */ + +struct v3_plugin_view_parameter_finder { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* find_parameter)(void* self, int32_t x, int32_t y, v3_param_id *); +}; + +static constexpr const v3_tuid v3_plugin_view_parameter_finder_iid = + V3_ID(0x0F618302, 0x215D4587, 0xA512073C, 0x77B9D383); + +/** + * linux event handler + */ + +struct v3_event_handler { +#ifndef __cplusplus + struct v3_funknown; +#endif + void (V3_API* on_fd_is_set)(void* self, int fd); +}; + +static constexpr const v3_tuid v3_event_handler_iid = + V3_ID(0x561E65C9, 0x13A0496F, 0x813A2C35, 0x654D7983); + +/** + * linux timer handler + */ + +struct v3_timer_handler { +#ifndef __cplusplus + struct v3_funknown; +#endif + void (V3_API* on_timer)(void* self); +}; + +static constexpr const v3_tuid v3_timer_handler_iid = + V3_ID(0x10BDD94F, 0x41424774, 0x821FAD8F, 0xECA72CA9); + +/** + * linux host run loop + */ + +struct v3_run_loop { +#ifndef __cplusplus + struct v3_funknown; +#endif + v3_result (V3_API* register_event_handler)(void* self, v3_event_handler** handler, int fd); + v3_result (V3_API* unregister_event_handler)(void* self, v3_event_handler** handler); + v3_result (V3_API* register_timer)(void* self, v3_timer_handler** handler, uint64_t ms); + v3_result (V3_API* unregister_timer)(void* self, v3_timer_handler** handler); +}; + +static constexpr const v3_tuid v3_run_loop_iid = + V3_ID(0x18C35366, 0x97764F1A, 0x9C5B8385, 0x7A871389); + +#ifdef __cplusplus + +/** + * C++ variants + */ + +struct v3_plugin_view_cpp : v3_funknown { + v3_plugin_view view; +}; + +struct v3_plugin_frame_cpp : v3_funknown { + v3_plugin_frame frame; +}; + +struct v3_plugin_view_content_scale_cpp : v3_funknown { + v3_plugin_view_content_scale scale; +}; + +struct v3_plugin_view_parameter_finder_cpp : v3_funknown { + v3_plugin_view_parameter_finder finder; +}; + +struct v3_event_handler_cpp : v3_funknown { + v3_event_handler handler; +}; + +struct v3_timer_handler_cpp : v3_funknown { + v3_timer_handler timer; +}; + +struct v3_run_loop_cpp : v3_funknown { + v3_run_loop loop; +}; + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/xaymar-vst2/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/xaymar-vst2/LICENSE Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,11 @@ +Copyright 2020 Michael Fabian 'Xaymar' Dirks + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/xaymar-vst2/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/xaymar-vst2/README.md Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,21 @@ +# About the Project +This is a completely "clean room" untainted reverse engineered "SDK" for the VST 2.x interface. It was reverse engineered from binaries where no license restricting the reverse engineering was attached, or where the legal system explicitly allowed reverse engineering for the purpose of interoperability. + +# Frequently Asked Questions +## Is this legal? Can I use this in my own product? +**Disclaimer:** I am not a lawyer. The information presented below is purely from available copyright laws that I could find about this topic. You should always consult with a lawyer first before including this in your product. + +As this only enables interoperability with existing VST 2.x programs and addons, it is considered to be reverse engineering in the name of interoperability. In most of the developed world, this is considered completely legal and is fine to be used by anyone, as long as it is not the only function of the product. + +Note that this does not grant any patent licenses, nor does it grant you any right to use trademarks in the names. That could mean that you can't advertise your product as having support for VST, and can't use VST in the name or presentation of the product at all unless you have permission to do so. + +## Why recreate an SDK for something officially abandoned by the creators? +There is a ton of software that is only capable of loading VST2.x audio effects, and Steinberg has made no effort to create a VST3-to-VST2-adapter for that software. Notable software includes Audacity and OBS Studio, which both likely felt restricted by the license additions Steinberg added to the GPL license. + +## How did you reverse engineer this? +The reverse engineering was done with various tools (mostly disassemblers to x86 assembly code), hooking into system APIs, attempting to mimic functionality through observation and testing, and other methods. Primarily Visual Studio Code was used to write the header files, and Visual Studio 2019 Express was used to create fake VST plugins/hosts to figure out actual behavior. + +### Which binaries were disassembled? +* A fake VST2 host (using this header) was created to verify against existing plugins. +* A fake VST2 plugin (using this header) was created to verify against existing hosts. +* OBS Studio and Audacity were used to verify compatability between closed source and open source VST hosts. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/distrho/src/xaymar-vst2/vst.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/src/xaymar-vst2/vst.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1012 @@ +// This was created from released VST2.x plugins, and is technically under the 2-clause BSD license. +// Depending on which country you are in, Steinberg can do fuck all about this. Notable countries for +// this are most members of the United States of America, the entirety of Europe, Japan, and Russia. +// Consult a lawyer if you don't know if clean room reverse engineering is allowed in your country. + +// See README.md for all information. + +// Known additional information: +// - Function call standard seems to be stdcall. +// - Everything is aligned to 8 bytes. + +// VST Versioning: +// - Base-10, thus can't store many version numbers. +// - Always four components, with the major one being able to store the most numbers. +// - Format is A...ABCD, so 1.2.3.4 would turn into 1234. + +#pragma once +#ifndef VST2SDK_VST_H +#define VST2SDK_VST_H + +#define VST_FUNCTION_INTERFACE __cdecl +#define VST_ALIGNMENT 8 +#define VST_MAGICNUMBER 'VstP' + +// Common VST buffer lengths: +// 8: OpCodes(GetLabel, GetName, GetValue) +#define VST_BUFFER_8 8 +// 16: +#define VST_BUFFER_16 16 +// 24: OpCodes? +#define VST_BUFFER_24 24 +// 32: OpCodes(EffectName) +#define VST_BUFFER_32 32 +#define VST_EFFECT_BUFFER_SIZE 32 +// 64: OpCodes(ProductName, VendorName) +#define VST_BUFFER_64 64 +#define VST_VENDOR_BUFFER_SIZE VST_BUFFER_64 +#define VST_PRODUCT_BUFFER_SIZE VST_BUFFER_64 +#define VST_NAME_BUFFER_SIZE VST_BUFFER_64 +// 100: +#define VST_BUFFER_100 100 + +#define VST_MAX_CHANNELS 32 // Couldn't find any audio editing software which would attempt to add more channels. + +#pragma pack(push, VST_ALIGNMENT) + +#ifdef __cplusplus +#ifdef DISTRHO_PROPER_CPP11_SUPPORT +#include +#else +#include +#endif +extern "C" { +#else +#include +#endif + +/******************************************************************************* +|* Enumeration +|*/ +enum VST_VERSION { + VST_VERSION_1 = 0, // Anything before 2.0, used by official plug-ins. + VST_VERSION_1_0_0_0 = 1000, // 1.0, used by some third-party plug-ins. + VST_VERSION_1_1_0_0 = 1100, // 1.1, used by some third-party plug-ins. + VST_VERSION_2 = 2, // 2.0, used by official plug-ins. + VST_VERSION_2_0_0_0 = 2000, // 2.0, used by some third-party plug-ins. + VST_VERSION_2_1_0_0 = 2100, // 2.1 + VST_VERSION_2_2_0_0 = 2200, // 2.2 + VST_VERSION_2_3_0_0 = 2300, // 2.3 + VST_VERSION_2_4_0_0 = 2400, // 2.4 + + // Pad to force 32-bit number. + _VST_VERSION_PAD = 0xFFFFFFFFul, +}; + +enum VST_CATEGORY { + VST_CATEGORY_UNCATEGORIZED = 0x00, + VST_CATEGORY_01 = 0x01, + VST_CATEGORY_02 = 0x02, + VST_CATEGORY_03 = 0x03, + VST_CATEGORY_04 = 0x04, + VST_CATEGORY_05 = 0x05, + VST_CATEGORY_06 = 0x06, + VST_CATEGORY_07 = 0x07, + VST_CATEGORY_RESTORATION = 0x08, // Denoising and similar effects. + VST_CATEGORY_09 = 0x09, + VST_CATEGORY_CONTAINER = 0x0A, // Plugin contains more than one Plugin. + VST_CATEGORY_0B = 0x0B, + VST_CATEGORY_MAX, // Not part of specification, marks maximum category. + + // Pad to force 32-bit number. + _VST_CATEGORY_PAD = 0xFFFFFFFFul, +}; + +enum VST_EFFECT_OPCODE { + /* Create/Initialize the effect (if it has not been created already). + * + * @return Always 0. + */ + VST_EFFECT_OPCODE_00 = 0x00, + VST_EFFECT_OPCODE_CREATE = 0x00, + VST_EFFECT_OPCODE_INITIALIZE = 0x00, + + /* Destroy the effect (if there is any) and free its memory. + * + * This should destroy the actual object created by VST_ENTRYPOINT. + * + * @return Always 0. + */ + VST_EFFECT_OPCODE_01 = 0x01, + VST_EFFECT_OPCODE_DESTROY = 0x01, + + /* Set Program + * + * + */ + VST_EFFECT_OPCODE_02 = 0x02, + + /* Get Program + * + * + */ + VST_EFFECT_OPCODE_03 = 0x03, + + /* Set Program Name + * + * + */ + VST_EFFECT_OPCODE_04 = 0x04, + + /* Get Program Name + * + * "Returns 0. If ptr is valid, sets the first byte of ptr to 0 then returns 0." + */ + VST_EFFECT_OPCODE_05 = 0x05, + + /* Get the value? label for the parameter. + * + * @param p_int1 Parameter index. + * @param p_ptr 'char[8]' + * @return 0 on success, 1 on failure. + */ + VST_EFFECT_OPCODE_06 = 0x06, + VST_EFFECT_OPCODE_PARAM_GETLABEL = 0x06, + + /* Get the string value for the parameter. + * + * @param p_int1 Parameter index. + * @param p_ptr 'char[8]' + * @return 0 on success, 1 on failure. + */ + VST_EFFECT_OPCODE_07 = 0x07, + VST_EFFECT_OPCODE_PARAM_GETVALUE = 0x07, + + /* Get the name for the parameter. + * + * @param p_int1 Parameter index. + * @param p_ptr 'char[8]' + * @return 0 on success, 1 on failure. + */ + VST_EFFECT_OPCODE_08 = 0x08, + VST_EFFECT_OPCODE_PARAM_GETNAME = 0x08, + + /* + * + * + */ + VST_EFFECT_OPCODE_09 = 0x09, + + /* Set the new sample rate for the plugin to use. + * + * @param p_float New sample rate as a float (double on 64-bit because register upgrades). + */ + VST_EFFECT_OPCODE_0A = 0x0A, + VST_EFFECT_OPCODE_SETSAMPLERATE = 0x0A, + VST_EFFECT_OPCODE_SET_SAMPLE_RATE = 0x0A, + + /* Sets the block size, which is the maximum number of samples passed into the effect via process calls. + * + * @param p_int2 The maximum number of samples to be passed in. + */ + VST_EFFECT_OPCODE_0B = 0x0B, + VST_EFFECT_OPCODE_SETBLOCKSIZE = 0x0B, + VST_EFFECT_OPCODE_SET_BLOCK_SIZE = 0x0B, + + /* Effect processing should be suspended/paused. + * + * Unclear if this is should result in a flush of buffers. + * + * @param p_int2 0 if the effect should suspend processing, 1 if it should resume. + */ + VST_EFFECT_OPCODE_0C = 0x0C, + VST_EFFECT_OPCODE_SUSPEND = 0x0C, + + /* Retrieve the client rect size of the plugins window. + * If no window has been created, returns the default rect. + * + * @param p_ptr Pointer of type 'struct vst_rect*'. + * @return On success, returns 1 and updates p_ptr to the rect. On failure, returns 0. + */ + VST_EFFECT_OPCODE_0D = 0x0D, + VST_EFFECT_OPCODE_WINDOW_GETRECT = 0x0D, + + /* Create the window for the plugin. + * + * @param p_ptr HWND of the parent window. + * @return 0 on failure, or HWND on success. + */ + VST_EFFECT_OPCODE_0E = 0x0E, + VST_EFFECT_OPCODE_WINDOW_CREATE = 0x0E, + + /* Destroy the plugins window. + * + * @return Always 0. + */ + VST_EFFECT_OPCODE_0F = 0x0F, + VST_EFFECT_OPCODE_WINDOW_DESTROY = 0x0F, + + /* + * + * + */ + VST_EFFECT_OPCODE_10 = 0x10, + + /* + * + * + */ + VST_EFFECT_OPCODE_11 = 0x11, + + /* + * + * + */ + VST_EFFECT_OPCODE_12 = 0x12, + + /* + * + * + */ + VST_EFFECT_OPCODE_13 = 0x13, + + /* + * + * + */ + VST_EFFECT_OPCODE_14 = 0x14, + + /* + * + * + */ + VST_EFFECT_OPCODE_15 = 0x15, + + /* Always returns the FourCC 'NvEF' (0x4E764566). + */ + VST_EFFECT_OPCODE_16 = 0x16, + + /* Get Chunk + * + * + */ + VST_EFFECT_OPCODE_17 = 0x17, + + /* Set Chunk + * + * + */ + VST_EFFECT_OPCODE_18 = 0x18, + + // VST2.x starts here. + + /* + * + * + */ + VST_EFFECT_OPCODE_19 = 0x19, + + /* Can the parameter be automated? + * + * @param p_int1 Index of the parameter. + * @return 1 if the parameter can be automated, otherwise 0. + */ + VST_EFFECT_OPCODE_1A = 0x1A, + VST_EFFECT_OPCODE_PARAM_ISAUTOMATABLE = 0x1A, + + /* + * + * + */ + VST_EFFECT_OPCODE_1B = 0x1B, + + /* + * + * + */ + VST_EFFECT_OPCODE_1C = 0x1C, + + /* + * + * + */ + VST_EFFECT_OPCODE_1D = 0x1D, // See VST_EFFECT_OPCODE_05 + + /* + * + * + */ + VST_EFFECT_OPCODE_1E = 0x1E, + + /* Input connected. + * + * + */ + VST_EFFECT_OPCODE_1F = 0x1F, + + /* Input disconnected. + * + * + */ + VST_EFFECT_OPCODE_20 = 0x20, + + /* Retrieve the name of the input channel at the given index. + * + * @param p_int1 Index of the input to get the name for. + * @param p_ptr Pointer to a char* buffer able to hold at minimum 20 characters. Might need to be 32 even. + * @return 0 on failure, 1 on success. + */ + VST_EFFECT_OPCODE_21 = 0x21, + VST_EFFECT_OPCODE_INPUT_GETCHANNELNAME = 0x21, + VST_EFFECT_OPCODE_INPUT_CHANNEL_NAME = 0x21, + + /* Retrieve the name of the output channel at the given index. + * + * @param p_int1 Index of the output to get the name for. + * @param p_ptr Pointer to a char* buffer able to hold at minimum 20 characters. Might need to be 32 even. + * @return 0 on failure, 1 on success. + */ + VST_EFFECT_OPCODE_22 = 0x22, + VST_EFFECT_OPCODE_OUTPUT_GETCHANNELNAME = 0x22, + VST_EFFECT_OPCODE_OUTPUT_CHANNEL_NAME = 0x22, + + /* Retrieve category of this effect. + * + * @return The category that this effect is in, see VST_CATEGORY. + */ + VST_EFFECT_OPCODE_23 = 0x23, + VST_EFFECT_OPCODE_EFFECT_CATEGORY = 0x23, + + /* + * + * + */ + VST_EFFECT_OPCODE_24 = 0x24, + + /* + * + * + */ + VST_EFFECT_OPCODE_25 = 0x25, + + /* + * + * + */ + VST_EFFECT_OPCODE_26 = 0x26, + + /* + * + * + */ + VST_EFFECT_OPCODE_27 = 0x27, + + /* + * + * + */ + VST_EFFECT_OPCODE_28 = 0x28, + + /* + * + * + */ + VST_EFFECT_OPCODE_29 = 0x29, + + /* Set the speaker arrangement + * + * @param p_int2 (vst_speaker_arrangement*) Pointer to a pointer to the speaker arrangement for the input. + * @param p_ptr (vst_speaker_arrangement*) Pointer to a pointer to the speaker arrangement for the output. + */ + VST_EFFECT_OPCODE_2A = 0x2A, + VST_EFFECT_OPCODE_SET_SPEAKER_ARRANGEMENT = 0x2A, + + /* + * + * + */ + VST_EFFECT_OPCODE_2B = 0x2B, + + /* Enable/Disable bypassing the effect. + * + * @param p_int2 Zero if bypassing the effect is disabled, otherwise 1. + */ + VST_EFFECT_OPCODE_2C = 0x2C, + VST_EFFECT_OPCODE_BYPASS = 0x2C, + + /* Retrieve the effect name into the ptr buffer. + * + * @param p_ptr char[64] Buffer containing a zero-terminated effect information string. May be shorter than 64 bytes on older hosts. + * @return Always 0, even on failure. + */ + VST_EFFECT_OPCODE_2D = 0x2D, + VST_EFFECT_OPCODE_GETNAME = 0x2D, + VST_EFFECT_OPCODE_EFFECT_NAME = 0x2D, + + /* Translate an error code to a string. + * + * @param p_ptr char[256] Buffer that should contain a zero-terminated error string. + */ + VST_EFFECT_OPCODE_2E = 0x2E, + VST_EFFECT_OPCODE_TRANSLATE_ERROR = 0x2E, + + /* Retrieve the vendor name into the ptr buffer. + * + * @param p_ptr char[64] Buffer containing a zero-terminated vendor information string. May be shorter than 64 bytes on older hosts. + * @return Always 0, even on failure. + */ + VST_EFFECT_OPCODE_2F = 0x2F, + VST_EFFECT_OPCODE_GETVENDOR = 0x2F, + VST_EFFECT_OPCODE_VENDOR_NAME = 0x2F, + + /* See VST_EFFECT_OPCODE_GETNAME + * + * Rarely used, if at all even supported. Not sure what the purpose of this is even. + */ + VST_EFFECT_OPCODE_30 = 0x30, + VST_EFFECT_OPCODE_GETNAME2 = 0x30, + VST_EFFECT_OPCODE_PRODUCT_NAME = 0x30, + + /* Retrieve the vendor version in return value. + * + * @return Version. + */ + VST_EFFECT_OPCODE_31 = 0x31, + VST_EFFECT_OPCODE_GETVENDORVERSION = 0x31, + VST_EFFECT_OPCODE_VENDOR_VERSION = 0x31, + + /* User defined OP Code, for custom interaction. + * + */ + VST_EFFECT_OPCODE_32 = 0x32, + VST_EFFECT_OPCODE_CUSTOM = 0x32, + + /* Test for support of a specific named feature. + * + * @param p_ptr Pointer to a zero-terminated buffer containing the feature name. + * @return Non-zero if the feature is supported, otherwise 0. + */ + VST_EFFECT_OPCODE_33 = 0x33, + VST_EFFECT_OPCODE_SUPPORTS = 0x33, + + /* Number of samples that are at the tail at the end of playback. + * + * @return 0 or 1 for no tail, > 1 for number of samples to tail. + */ + VST_EFFECT_OPCODE_34 = 0x34, + VST_EFFECT_OPCODE_GETTAILSAMPLES = 0x34, + VST_EFFECT_OPCODE_TAIL_SAMPLES = 0x34, + + /* + * + * + */ + VST_EFFECT_OPCODE_35 = 0x35, + + /* + * + * + */ + VST_EFFECT_OPCODE_36 = 0x36, + + /* + * + * + */ + VST_EFFECT_OPCODE_37 = 0x37, + + /* + * + * + */ + VST_EFFECT_OPCODE_38 = 0x38, + + /* Parameter Properties + * + * @param p_ptr vst_parameter_properties* + * @return 1 if supported, otherwise 0. + */ + VST_EFFECT_OPCODE_39 = 0x39, + VST_EFFECT_OPCODE_GET_PARAMETER_PROPERTIES = VST_EFFECT_OPCODE_39, + + /* Retrieve the VST Version supported. + * + * @return Return 0 for <2.0, 2 for 2.0, 2100 for 2.1, 2200 for 2.2, 2300 for 2.3, etc. + */ + VST_EFFECT_OPCODE_3A = 0x3A, + VST_EFFECT_OPCODE_VST_VERSION = 0x3A, + + // VST 2.1 or later + + /* + * + * + */ + VST_EFFECT_OPCODE_3B = 0x3B, + + /* + * + * + */ + VST_EFFECT_OPCODE_3C = 0x3C, + + /* + * + * + */ + VST_EFFECT_OPCODE_3D = 0x3D, + + /* + * + * + */ + VST_EFFECT_OPCODE_3E = 0x3E, + + /* + * + * + */ + VST_EFFECT_OPCODE_3F = 0x3F, + + /* + * + * + */ + VST_EFFECT_OPCODE_40 = 0x40, + + /* + * + * + */ + VST_EFFECT_OPCODE_41 = 0x41, + + /* + * + * + */ + VST_EFFECT_OPCODE_42 = 0x42, + + /* + * + * + */ + VST_EFFECT_OPCODE_43 = 0x43, + + /* + * + * + */ + VST_EFFECT_OPCODE_44 = 0x44, + + // VST 2.3 or later + + /* Retrieve the speaker arrangement. + * + * @param p_int2 (vst_speaker_arrangement**) Pointer to a pointer to the speaker arrangement for the input. + * @param p_ptr (vst_speaker_arrangement**) Pointer to a pointer to the speaker arrangement for the output. + */ + VST_EFFECT_OPCODE_45 = 0x45, + VST_EFFECT_OPCODE_GET_SPEAKER_ARRANGEMENT = 0x45, + + /* + * + * + */ + VST_EFFECT_OPCODE_46 = 0x46, + + /* Begin processing of audio. + * + * + * + */ + VST_EFFECT_OPCODE_PROCESS_BEGIN = 0x47, + + /* End processing of audio. + * + * + * + */ + VST_EFFECT_OPCODE_PROCESS_END = 0x48, + + /* + * + * + */ + VST_EFFECT_OPCODE_49 = 0x49, + + /* + * + * + */ + VST_EFFECT_OPCODE_4A = 0x4A, + + /* + * + * + */ + VST_EFFECT_OPCODE_4B = 0x4B, + + /* + * + * + */ + VST_EFFECT_OPCODE_4C = 0x4C, + + // VST 2.4 or later + + /* + * + * + */ + VST_EFFECT_OPCODE_4D = 0x4D, + + /* + * + * + */ + VST_EFFECT_OPCODE_4E = 0x4E, + + /* + * + * + */ + VST_EFFECT_OPCODE_4F = 0x4F, + + // Highest number of known OPCODE. + VST_EFFECT_OPCODE_MAX, + + // Pad to force 32-bit number. + _VST_EFFECT_OPCODE_PAD = 0xFFFFFFFFul, +}; + +enum VST_HOST_OPCODE { + /* + * @param int1 -1 or Parameter Index + * @return Expected to return... something. + */ + VST_HOST_OPCODE_00 = 0x00, // cb(vst, 0x00, ?, 0, 0); + VST_HOST_OPCODE_01 = 0x01, + VST_HOST_OPCODE_02 = 0x02, // bool cb(0, 0x02, 0, 0, 0); + VST_HOST_OPCODE_03 = 0x03, + VST_HOST_OPCODE_04 = 0x04, + VST_HOST_OPCODE_05 = 0x05, + VST_HOST_OPCODE_06 = 0x06, + VST_HOST_OPCODE_07 = 0x07, + VST_HOST_OPCODE_08 = 0x08, + VST_HOST_OPCODE_09 = 0x09, + VST_HOST_OPCODE_0A = 0x0A, + VST_HOST_OPCODE_0B = 0x0B, + VST_HOST_OPCODE_0C = 0x0C, + VST_HOST_OPCODE_0D = 0x0D, + VST_HOST_OPCODE_0E = 0x0E, + VST_HOST_OPCODE_0F = 0x0F, + VST_HOST_OPCODE_10 = 0x10, + VST_HOST_OPCODE_11 = 0x11, + VST_HOST_OPCODE_12 = 0x12, + VST_HOST_OPCODE_13 = 0x13, + VST_HOST_OPCODE_14 = 0x14, + VST_HOST_OPCODE_15 = 0x15, + VST_HOST_OPCODE_16 = 0x16, + VST_HOST_OPCODE_17 = 0x17, + VST_HOST_OPCODE_18 = 0x18, + VST_HOST_OPCODE_19 = 0x19, + VST_HOST_OPCODE_1A = 0x1A, + VST_HOST_OPCODE_1B = 0x1B, + VST_HOST_OPCODE_1C = 0x1C, + VST_HOST_OPCODE_1D = 0x1D, + VST_HOST_OPCODE_1E = 0x1E, + VST_HOST_OPCODE_1F = 0x1F, + VST_HOST_OPCODE_20 = 0x20, + VST_HOST_OPCODE_21 = 0x21, + VST_HOST_OPCODE_22 = 0x22, + VST_HOST_OPCODE_23 = 0x23, + VST_HOST_OPCODE_24 = 0x24, + VST_HOST_OPCODE_25 = 0x25, + VST_HOST_OPCODE_26 = 0x26, + VST_HOST_OPCODE_27 = 0x27, + VST_HOST_OPCODE_28 = 0x28, + VST_HOST_OPCODE_29 = 0x29, + VST_HOST_OPCODE_2A = 0x2A, + + /* Parameter gained focus. + * + * @param int1 Parameter index. + */ + VST_HOST_OPCODE_2B = 0x2B, + + /* Parameter lost focus. + * + * @param int1 Parameter index. + */ + VST_HOST_OPCODE_2C = 0x2C, + + VST_HOST_OPCODE_2D = 0x2D, + VST_HOST_OPCODE_2E = 0x2E, + VST_HOST_OPCODE_2F = 0x2F, + + // Highest number of known OPCODE. + VST_HOST_OPCODE_MAX, + + // Pad to force 32-bit number. + _VST_HOST_OPCODE_PAD = 0xFFFFFFFFul, +}; + +enum VST_ARRANGEMENT_TYPE { + /* Custom speaker arrangement. + * + * Accidentally discovered through random testing. + */ + VST_ARRANGEMENT_TYPE_CUSTOM = -2, + + /* Unknown/Empty speaker layout. + * + */ + VST_ARRANGEMENT_TYPE_UNKNOWN = -1, + + /* Mono + */ + VST_ARRANGEMENT_TYPE_MONO = 0, + + /* Stereo + */ + VST_ARRANGEMENT_TYPE_STEREO = 1, + + /* 5.1 + */ + VST_ARRANGEMENT_TYPE_5_1 = 0x0F, + + // Pad to force 32-bit number. + _VST_ARRANGEMENT_TYPE_PAD = 0xFFFFFFFFul, +}; + +enum VST_SPEAKER_TYPE { + VST_SPEAKER_TYPE_MONO = 0, + VST_SPEAKER_TYPE_LEFT = 1, + VST_SPEAKER_TYPE_RIGHT = 2, + VST_SPEAKER_TYPE_CENTER = 3, + VST_SPEAKER_TYPE_LFE = 4, + VST_SPEAKER_TYPE_LEFT_SIDE = 5, + VST_SPEAKER_TYPE_RIGHT_SIDE = 6, + + // Pad to force 32-bit number. + _VST_SPEAKER_TYPE_PAD = 0xFFFFFFFFul, +}; + +enum VST_PARAMETER_FLAGS { + /** + * Parameter is an on/off switch. + */ + VST_PARAMETER_FLAGS_SWITCH = 1, + /** + * Limits defined by integers. + */ + VST_PARAMETER_FLAGS_INTEGER_LIMITS = 1 << 1, + /** + * Uses float steps. + */ + VST_PARAMETER_FLAGS_STEP_FLOAT = 1 << 2, + /** + * Uses integer steps. + */ + VST_PARAMETER_FLAGS_STEP_INT = 1 << 3, + /** + * Respect index variable for display ordering. + */ + VST_PARAMETER_FLAGS_INDEX = 1 << 4, + /** + * Respect category value and names. + */ + VST_PARAMETER_FLAGS_CATEGORY = 1 << 5, + VST_PARAMETER_FLAGS_UNKNOWN6 = 1 << 6, + _VST_PARAMETER_FLAGS_PAD = 0xFFFFFFFFul, +}; + +/******************************************************************************* +|* Structures +|*/ + +struct vst_rect { + int16_t top; + int16_t left; + int16_t bottom; + int16_t right; +}; + +struct vst_effect { + int32_t magic_number; // Should always be VST_MAGICNUMBER + + // 64-bit adds 4-byte padding here to align pointers. + + /* Control the VST through an opcode and up to four parameters. + * + * @param this Pointer to the effect itself. + * @param opcode The opcode to run, see VST_EFFECT_OPCODES. + * @param p_int1 Parameter, see VST_EFFECT_OPCODES. + * @param p_int2 Parameter, see VST_EFFECT_OPCODES. + * @param p_ptr Parameter, see VST_EFFECT_OPCODES. + * @param p_float Parameter, see VST_EFFECT_OPCODES. + */ + intptr_t(VST_FUNCTION_INTERFACE* control)(vst_effect* pthis, VST_EFFECT_OPCODE opcode, int32_t p_int1, + intptr_t p_int2, void* p_ptr, float p_float); + + /* Process the given number of samples in inputs and outputs. + * + * Different to process_float how? Never seen any difference. + * + * @param pthis Pointer to the effect itself. + * @param inputs Pointer to an array of 'const float[samples]' with size numInputs. + * @param outputs Pointer to an array of 'float[samples]' with size numOutputs. + * @param samples Number of samples per channel in inputs. + */ + void(VST_FUNCTION_INTERFACE* process)(vst_effect* pthis, const float* const* inputs, float** outputs, + int32_t samples); + + /* Updates the value for the parameter at the given index, or does nothing if out of bounds. + * + * @param pthis Pointer to the effect itself. + * @param index Parameter index. + * @param value New value for the parameter. + */ + void(VST_FUNCTION_INTERFACE* set_parameter)(vst_effect* pthis, uint32_t index, float value); + + /* Returns the value stored for the parameter at index, or 0 if out of bounds. + * + * @param pthis Pointer to the effect itself. + * @param index Parameter index. + * @return float Value of the parameter. + */ + float(VST_FUNCTION_INTERFACE* get_parameter)(vst_effect* pthis, uint32_t index); + + int32_t num_programs; // Number of possible programs. + int32_t num_params; // Number of possible parameters. + int32_t num_inputs; // Number of inputs. + int32_t num_outputs; // Number of outputs. + + /* Bitflags + * + * Bit Description + * 1 Effect has "Editor" + * 2 Unknown (Found in: ReaDelay) + * 3 Unknown (Found in: ReaDelay) + * 4 Unknown (Found in: ReaDelay) + * 5 Has process_float (Found in: ReaDelay, ReaComp, ReaControlMIDI, ReaStream, ReaFir) + * 6 Unknown (Found in: ReaControlMIDI, ReaStream, ReaFir) + * 10 Unknown (Found in: ReaFir) + * 13 Has process_double (Found in: ReaControlMIDI) + */ + int32_t flags; + + // 64-bit adds 4-byte padding here to align pointers. + + void* _unknown_ptr_00[2]; + + /* Initial delay before processing of samples can actually begin in Samples. + * + * Should be updated before or during handling the 0x47 control call. + */ + int32_t delay; + + int32_t _unknown_int32_00[2]; // Unknown int32_t values. + float _unknown_float_00; // Seems to always be 1.0 + + void* effect_internal; // Pointer to Plugin internal data + void* host_internal; // Pointer to Host internal data. + + /* Id of the plugin. + * + * Due to this not being enough for uniqueness, it should not be used alone + * for indexing. Ideally you want to index like this: + * [unique_id][module_name][version][flags] + * If any of the checks after unique_id fail, you default to the first + * possible choice. + */ + int32_t unique_id; + + /* Plugin version + * + * Unrelated to the minimum VST Version, but often the same. + */ + int32_t version; + + // There is no padding here if everything went right. + + /* Process the given number of single samples in inputs and outputs. + * + * @param pthis Pointer to the effect itself. + * @param inputs Pointer to an array of 'const float[samples]' with size numInputs. + * @param outputs Pointer to an array of 'float[samples]' with size numOutputs. + * @param samples Number of samples per channel in inputs. + */ + void(VST_FUNCTION_INTERFACE* process_float)(vst_effect* pthis, const float* const* inputs, float** outputs, + int32_t samples); + + /* Process the given number of double samples in inputs and outputs. + * + * Used only by 2.4 hosts and plugins, possibly restricted to said version. + * + * @param pthis Pointer to the effect itself. + * @param inputs Pointer to an array of 'const double[samples]' with size numInputs. + * @param outputs Pointer to an array of 'double[samples]' with size numOutputs. + * @param samples Number of samples per channel in inputs. + */ + void(VST_FUNCTION_INTERFACE* process_double)(vst_effect* pthis, const double* const* inputs, double** outputs, + int32_t samples); + + // Everything after this is unknown and was present in reacomp-standalone.dll. + uint8_t _unknown[56]; // 56-bytes of something. Could also just be 52-bytes. +}; + +struct vst_parameter_properties { + float step_f32; + float step_small_f32; + float step_large_f32; + + char name[VST_BUFFER_64]; + + uint32_t flags; + int32_t min_value_i32; + int32_t max_value_i32; + int32_t step_i32; + + char label[VST_BUFFER_8]; + + uint16_t index; + + uint16_t category; + uint16_t num_parameters_in_category; + uint16_t _unknown_00; + + char category_label[VST_BUFFER_24]; + + char _unknown_01[VST_BUFFER_16]; +}; + +struct vst_speaker_properties { + float _unknown_00; // 10.0 if LFE, otherwise random? Never exceeds -PI to PI range. + float _unknown_04; // 10.0 if LFE, otherwise random? Never exceeds -PI to PI range. + float _unknown_08; // 0.0 if LFE, otherwise 1.0. + float _unknown_0C; + char name[VST_BUFFER_64]; + VST_SPEAKER_TYPE type; + + uint8_t _unknown[28]; // Padding detected from testing. +}; + +struct vst_speaker_arrangement { + VST_ARRANGEMENT_TYPE type; // See VST_SPEAKER_ARRANGEMENT_TYPE + int32_t channels; // Number of channels in speakers. + vst_speaker_properties speakers[VST_MAX_CHANNELS]; // Array of speaker properties, actual size defined by channels. +}; + +/* Callback used by the plugin to interface with the host. + * + * @param opcode See VST_HOST_OPCODE + * @param p_str Zero terminated string or null on call. + * @return ? + */ +typedef intptr_t (*vst_host_callback)(vst_effect* plugin, VST_HOST_OPCODE opcode, int32_t p_int1, int64_t p_int2, + void* p_str, int32_t p_int3); + +/* Entry point for VST2.x plugins. + * + * @return A new instance of the VST2.x effect. + */ +#define VST_ENTRYPOINT vst_effect* VSTPluginMain(vst_host_callback callback) +#define VST_ENTRYPOINT_WINDOWS \ + vst_effect* MAIN(vst_host_callback callback) \ + { \ + return VSTPluginMain(callback); \ + } +#define VST_ENTRYPOINT_MACOS \ + vst_effect* main_macho(vst_host_callback callback) \ + { \ + return VSTPluginMain(callback); \ + } + +#ifdef __cplusplus +} +#endif + +// Variable size variant of vst_speaker_arrangement. +#ifdef __cplusplus +template +struct vst_speaker_arrangement_t { + VST_ARRANGEMENT_TYPE type; // See VST_SPEAKER_ARRANGEMENT_TYPE + int32_t channels; // Number of channels in speakers. + vst_speaker_properties speakers[T]; // Array of speaker properties, actual size defined by channels. +}; +#endif + +#pragma pack(pop) + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dpf.doxygen --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dpf.doxygen Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,309 @@ +# Doxyfile 1.7.6.1 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "DISTRHO Plugin Framework" +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = docs +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = YES +SYMBOL_CACHE_SIZE = 0 +LOOKUP_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = YES +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = distrho distrho/extra dgl +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = . +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = NO +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +USE_INLINE_TREES = NO +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_RELPATH = http://www.mathjax.org/mathjax +MATHJAX_EXTENSIONS = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = DOXYGEN \ + DEBUG \ + HAVE_CAIRO=1 \ + HAVE_OPENGL=1 \ + DISTRHO_PLUGIN_NAME="Plugin Name" \ + DISTRHO_PLUGIN_NUM_INPUTS=2 \ + DISTRHO_PLUGIN_NUM_OUTPUTS=2 \ + DISTRHO_PLUGIN_URI="urn:distrho:name" \ + DISTRHO_PLUGIN_HAS_UI=1 \ + DISTRHO_PLUGIN_HAS_EMBED_UI=1 \ + DISTRHO_PLUGIN_HAS_EXTERNAL_UI=1 \ + DISTRHO_PLUGIN_IS_RT_SAFE=1 \ + DISTRHO_PLUGIN_IS_SYNTH=1 \ + DISTRHO_PLUGIN_WANT_DIRECT_ACCESS=1 \ + DISTRHO_PLUGIN_WANT_LATENCY=1 \ + DISTRHO_PLUGIN_WANT_MIDI_INPUT=1 \ + DISTRHO_PLUGIN_WANT_MIDI_OUTPUT=1 \ + DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST=1 \ + DISTRHO_PLUGIN_WANT_PROGRAMS=1 \ + DISTRHO_PLUGIN_WANT_STATE=1 \ + DISTRHO_PLUGIN_WANT_TIMEPOS=1 \ + DISTRHO_PLUGIN_WANT_FULL_STATE=1 \ + DISTRHO_UI_USE_NANOVG=1 +EXPAND_AS_DEFINED = YES +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = YES +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/dpf.kdev4 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/dpf.kdev4 Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,9 @@ +[Project] +Manager=KDevGenericManager +Name=DPF + +[Filters] +Excludes=*/.*,*/*~,*/*.a + +[Project] +VersionControlSupport=kdevgit diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/lac/2014-small-talk.odp Binary file DPF-Prymula-audioplugins/dpf/lac/2014-small-talk.odp has changed diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/generate-ttl.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/generate-ttl.sh Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,41 @@ +#!/bin/bash + +# function not available on some systems +if ! which realpath &>/dev/null; then + function realpath() { + [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" + } +fi + +set -e + +if [ ! -d bin ]; then + echo "Please run this script from the source root folder" + exit +fi + +PWD="$(dirname "${0}")" + +if [ -f "${PWD}/lv2_ttl_generator.exe" ]; then + GEN="${PWD}/lv2_ttl_generator.exe" + EXT=dll +else + GEN="$(realpath ${PWD}/lv2_ttl_generator)" + if [ -d /Library/Audio ]; then + EXT=dylib + else + EXT=so + fi +fi + +cd bin +FOLDERS=`find . -type d -name \*.lv2` + +for i in ${FOLDERS}; do + cd ${i} + FILE="$(ls *.${EXT} 2>/dev/null | sort | head -n 1)" + if [ -n "${FILE}" ]; then + ${EXE_WRAPPER} "${GEN}" "./${FILE}" + fi + cd .. +done diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/generate-vst-bundles.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/generate-vst-bundles.sh Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,29 @@ +#!/bin/bash + +echo "WARNING: generate-vst-bundles.sh script is no longer used" +exit 0 + +set -e + +if [ -d bin ]; then + cd bin +else + echo "Please run this script from the root folder" + exit +fi + +DPF_DIR=$(dirname $0)/.. +PLUGINS=$(ls | grep vst.dylib) + +rm -rf *.vst/ + +for i in $PLUGINS; do + BUNDLE=$(echo ${i} | awk 'sub("-vst.dylib","")') + cp -r ${DPF_DIR}/utils/plugin.vst/ ${BUNDLE}.vst + mv ${i} ${BUNDLE}.vst/Contents/MacOS/${BUNDLE} + rm -f ${BUNDLE}.vst/Contents/MacOS/deleteme + sed -i -e "s/@INFO_PLIST_PROJECT_NAME@/${BUNDLE}/" ${BUNDLE}.vst/Contents/Info.plist + rm -f ${BUNDLE}.vst/Contents/Info.plist-e +done + +cd .. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/lv2-ttl-generator/GNUmakefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/lv2-ttl-generator/GNUmakefile Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,29 @@ +#!/usr/bin/makefile -f + +include ../../Makefile.base.mk + +all: build + +ifeq ($(WINDOWS),true) + +build: ../lv2_ttl_generator.exe + +../lv2_ttl_generator.exe: lv2_ttl_generator.c + $(CC) $< $(BUILD_C_FLAGS) -o $@ $(LINK_FLAGS) -static + touch ../lv2_ttl_generator + +else # WINDOWS + +ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) +LINK_FLAGS += -ldl +endif + +build: ../lv2_ttl_generator + +../lv2_ttl_generator: lv2_ttl_generator.c + $(CC) $< $(BUILD_C_FLAGS) -o $@ $(LINK_FLAGS) + +endif # WINDOWS + +clean: + rm -f ../lv2_ttl_generator ../lv2_ttl_generator.exe diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/lv2-ttl-generator/lv2_ttl_generator.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/lv2-ttl-generator/lv2_ttl_generator.c Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,145 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2016 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#ifdef _WIN32 + #include + #define TTL_GENERATOR_WINDOWS +#else + #include +#endif + +#ifndef nullptr + #define nullptr (0) +#endif + +typedef void (*TTL_Generator_Function)(const char* basename); + +static int isPathSeparator(char c); +static char* makeNormalPath(const char* path); + +// TODO support Unicode paths on the Windows platform + +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + printf("usage: %s /path/to/plugin-DLL\n", argv[0]); + return 1; + } + + const char* path = argv[1]; + +#ifdef TTL_GENERATOR_WINDOWS + const HMODULE handle = LoadLibraryA(path); +#else + void* const handle = dlopen(path, RTLD_LAZY); +#endif + + if (! handle) + { +#ifdef TTL_GENERATOR_WINDOWS + printf("Failed to open plugin DLL\n"); +#else + printf("Failed to open plugin DLL, error was:\n%s\n", dlerror()); +#endif + return 2; + } + +#ifdef TTL_GENERATOR_WINDOWS +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-function-type" +# endif + const TTL_Generator_Function ttlFn = (TTL_Generator_Function)GetProcAddress(handle, "lv2_generate_ttl"); +# if defined(__GNUC__) && (__GNUC__ >= 9) +# pragma GCC diagnostic pop +# endif +#else + const TTL_Generator_Function ttlFn = (TTL_Generator_Function)dlsym(handle, "lv2_generate_ttl"); +#endif + + if (ttlFn != NULL) + { + // convert the paths to a normalized form, such that path separators are + // replaced with '/', and duplicate separators are removed + char* normalPath = makeNormalPath(path); + + // get rid of any "./" prefixes + path = normalPath; + while (path[0] == '.' && path[1] == '/') + path += 2; + + // extract the file name part + char* basename = strrchr(path, '/'); + if (basename != NULL) + basename += 1; + else + basename = (char*)path; + + // remove the file extension + char* dotPos = strrchr(basename, '.'); + if (dotPos) + *dotPos = '\0'; + + printf("Generate ttl data for '%s', basename: '%s'\n", path, basename); + + ttlFn(basename); + + free(normalPath); + } + else + printf("Failed to find 'lv2_generate_ttl' function\n"); + +#ifdef TTL_GENERATOR_WINDOWS + FreeLibrary(handle); +#else + dlclose(handle); +#endif + + return 0; +} + +static int isPathSeparator(char c) +{ +#ifdef TTL_GENERATOR_WINDOWS + return c == '/' || c == '\\'; +#else + return c == '/'; +#endif +} + +static char* makeNormalPath(const char* path) +{ + size_t i, j; + size_t len = strlen(path); + char* result = (char*)malloc(len + 1); + int isSep, wasSep = 0; + for (i = 0, j = 0; i < len; ++i) + { + isSep = isPathSeparator(path[i]); + if (!isSep) + result[j++] = path[i]; + else if (!wasSep) + result[j++] = '/'; + wasSep = isSep; + } + result[j] = '\0'; + return result; +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/lv2_ttl_generator.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/lv2_ttl_generator.d Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,95 @@ +../lv2_ttl_generator: lv2_ttl_generator.c /usr/include/stdc-predef.h \ + /usr/include/stdio.h /usr/include/bits/libc-header-start.h \ + /usr/include/features.h /usr/include/features-time64.h \ + /usr/include/bits/wordsize.h /usr/include/bits/timesize.h \ + /usr/include/sys/cdefs.h /usr/include/bits/long-double.h \ + /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-redhat-linux/13/include/stddef.h \ + /usr/lib/gcc/x86_64-redhat-linux/13/include/stdarg.h \ + /usr/include/bits/types.h /usr/include/bits/typesizes.h \ + /usr/include/bits/time64.h /usr/include/bits/types/__fpos_t.h \ + /usr/include/bits/types/__mbstate_t.h \ + /usr/include/bits/types/__fpos64_t.h /usr/include/bits/types/__FILE.h \ + /usr/include/bits/types/FILE.h /usr/include/bits/types/struct_FILE.h \ + /usr/include/bits/stdio_lim.h /usr/include/bits/floatn.h \ + /usr/include/bits/floatn-common.h /usr/include/bits/stdio.h \ + /usr/include/stdlib.h /usr/include/bits/waitflags.h \ + /usr/include/bits/waitstatus.h /usr/include/sys/types.h \ + /usr/include/bits/types/clock_t.h /usr/include/bits/types/clockid_t.h \ + /usr/include/bits/types/time_t.h /usr/include/bits/types/timer_t.h \ + /usr/include/bits/stdint-intn.h /usr/include/endian.h \ + /usr/include/bits/endian.h /usr/include/bits/endianness.h \ + /usr/include/bits/byteswap.h /usr/include/bits/uintn-identity.h \ + /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/types/sigset_t.h /usr/include/bits/types/__sigset_t.h \ + /usr/include/bits/types/struct_timeval.h \ + /usr/include/bits/types/struct_timespec.h \ + /usr/include/bits/pthreadtypes.h /usr/include/bits/thread-shared-types.h \ + /usr/include/bits/pthreadtypes-arch.h \ + /usr/include/bits/atomic_wide_counter.h /usr/include/bits/struct_mutex.h \ + /usr/include/bits/struct_rwlock.h /usr/include/alloca.h \ + /usr/include/bits/stdlib-bsearch.h /usr/include/bits/stdlib-float.h \ + /usr/include/string.h /usr/include/bits/types/locale_t.h \ + /usr/include/bits/types/__locale_t.h /usr/include/strings.h \ + /usr/include/dlfcn.h /usr/include/bits/dlfcn.h +/usr/include/stdc-predef.h: +/usr/include/stdio.h: +/usr/include/bits/libc-header-start.h: +/usr/include/features.h: +/usr/include/features-time64.h: +/usr/include/bits/wordsize.h: +/usr/include/bits/timesize.h: +/usr/include/sys/cdefs.h: +/usr/include/bits/long-double.h: +/usr/include/gnu/stubs.h: +/usr/include/gnu/stubs-64.h: +/usr/lib/gcc/x86_64-redhat-linux/13/include/stddef.h: +/usr/lib/gcc/x86_64-redhat-linux/13/include/stdarg.h: +/usr/include/bits/types.h: +/usr/include/bits/typesizes.h: +/usr/include/bits/time64.h: +/usr/include/bits/types/__fpos_t.h: +/usr/include/bits/types/__mbstate_t.h: +/usr/include/bits/types/__fpos64_t.h: +/usr/include/bits/types/__FILE.h: +/usr/include/bits/types/FILE.h: +/usr/include/bits/types/struct_FILE.h: +/usr/include/bits/stdio_lim.h: +/usr/include/bits/floatn.h: +/usr/include/bits/floatn-common.h: +/usr/include/bits/stdio.h: +/usr/include/stdlib.h: +/usr/include/bits/waitflags.h: +/usr/include/bits/waitstatus.h: +/usr/include/sys/types.h: +/usr/include/bits/types/clock_t.h: +/usr/include/bits/types/clockid_t.h: +/usr/include/bits/types/time_t.h: +/usr/include/bits/types/timer_t.h: +/usr/include/bits/stdint-intn.h: +/usr/include/endian.h: +/usr/include/bits/endian.h: +/usr/include/bits/endianness.h: +/usr/include/bits/byteswap.h: +/usr/include/bits/uintn-identity.h: +/usr/include/sys/select.h: +/usr/include/bits/select.h: +/usr/include/bits/types/sigset_t.h: +/usr/include/bits/types/__sigset_t.h: +/usr/include/bits/types/struct_timeval.h: +/usr/include/bits/types/struct_timespec.h: +/usr/include/bits/pthreadtypes.h: +/usr/include/bits/thread-shared-types.h: +/usr/include/bits/pthreadtypes-arch.h: +/usr/include/bits/atomic_wide_counter.h: +/usr/include/bits/struct_mutex.h: +/usr/include/bits/struct_rwlock.h: +/usr/include/alloca.h: +/usr/include/bits/stdlib-bsearch.h: +/usr/include/bits/stdlib-float.h: +/usr/include/string.h: +/usr/include/bits/types/locale_t.h: +/usr/include/bits/types/__locale_t.h: +/usr/include/strings.h: +/usr/include/dlfcn.h: +/usr/include/bits/dlfcn.h: diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/package-osx-bundles.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/package-osx-bundles.sh Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,74 @@ +#!/bin/bash + +set -e + +if [ -d bin ]; then + cd bin +else + echo "Please run this script from the root folder" + exit +fi + +NAME="$(basename $(git rev-parse --show-toplevel))" +SNAME="$(echo ${NAME} | tr -d ' ' | tr '/' '-')" + +rm -rf lv2 +rm -rf vst2 +rm -rf vst3 +rm -rf clap + +mkdir lv2 vst2 vst3 clap +cp -RL *.lv2 lv2/ +cp -RL *.vst vst2/ +cp -RL *.vst3 vst3/ +cp -RL *.clap clap/ +rm -rf *.lv2 *.vst *.vst3 *.clap + +pkgbuild \ + --identifier "studio.kx.distrho.plugins.${SNAME}.lv2bundles" \ + --install-location "/Library/Audio/Plug-Ins/LV2/" \ + --root "${PWD}/lv2/" \ + ../dpf-${SNAME}-lv2bundles.pkg + +pkgbuild \ + --identifier "studio.kx.distrho.plugins.${SNAME}.vst2bundles" \ + --install-location "/Library/Audio/Plug-Ins/VST/" \ + --root "${PWD}/vst2/" \ + ../dpf-${SNAME}-vst2bundles.pkg + +pkgbuild \ + --identifier "studio.kx.distrho.plugins.${SNAME}.vst3bundles" \ + --install-location "/Library/Audio/Plug-Ins/VST3/" \ + --root "${PWD}/vst3/" \ + ../dpf-${SNAME}-vst3bundles.pkg + +pkgbuild \ + --identifier "studio.kx.distrho.plugins.${SNAME}.clapbundles" \ + --install-location "/Library/Audio/Plug-Ins/CLAP/" \ + --root "${PWD}/clap/" \ + ../dpf-${SNAME}-clapbundles.pkg + +cd .. + +DPF_UTILS_DIR=$(dirname ${0}) + +# can be overridden by environment variables +WELCOME_TXT=${WELCOME_TXT:=${DPF_UTILS_DIR}/plugin.pkg/welcome.txt.in} + +mkdir -p build +sed -e "s|@name@|${NAME}|" "${WELCOME_TXT}" > build/welcome.txt +sed -e "s|@builddir@|${PWD}/build|" \ + -e "s|@lv2bundleref@|dpf-${SNAME}-lv2bundles.pkg|" \ + -e "s|@vst2bundleref@|dpf-${SNAME}-vst2bundles.pkg|" \ + -e "s|@vst3bundleref@|dpf-${SNAME}-vst3bundles.pkg|" \ + -e "s|@clapbundleref@|dpf-${SNAME}-clapbundles.pkg|" \ + -e "s|@name@|${NAME}|g" \ + -e "s|@sname@|${SNAME}|g" \ + ${DPF_UTILS_DIR}/plugin.pkg/package.xml.in > build/package.xml + +productbuild \ + --distribution build/package.xml \ + --identifier "studio.kx.distrho.${SNAME}" \ + --package-path "${PWD}" \ + --version 0 \ + ${SNAME}-macOS.pkg diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/plugin.app/Contents/Info.plist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/plugin.app/Contents/Info.plist Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + @INFO_PLIST_PROJECT_NAME@ + CFBundleIconFile + + CFBundleIdentifier + studio.kx.distrho.@INFO_PLIST_PROJECT_NAME@ + NSHighResolutionCapable + + NSRequiresAquaSystemAppearance + + NSMicrophoneUsageDescription + @INFO_PLIST_PROJECT_NAME@ requires microphone permissions for audio input. + + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/plugin.bundle/Contents/Info.plist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/plugin.bundle/Contents/Info.plist Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + @INFO_PLIST_PROJECT_NAME@ + CFBundleIconFile + + CFBundleIdentifier + studio.kx.distrho.@INFO_PLIST_PROJECT_NAME@ + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CSResourcesFileMapped + + + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/plugin.bundle/Contents/PkgInfo --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/plugin.bundle/Contents/PkgInfo Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1 @@ +BNDL???? diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/plugin.bundle/Contents/Resources/empty.lproj diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/plugin.pkg/package.xml.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/plugin.pkg/package.xml.in Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,26 @@ + + + @name@ + + + + + + @lv2bundleref@ + + + @vst2bundleref@ + + + @vst3bundleref@ + + + @clapbundleref@ + + + + + + + + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/plugin.pkg/welcome.txt.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/plugin.pkg/welcome.txt.in Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3 @@ +@name@ + +This is an audio plugin installer based on DPF. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/png2rgba.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/png2rgba.py Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# DISTRHO Plugin Framework (DPF) +# Copyright (C) 2012-2019 Filipe Coelho +# +# Permission to use, copy, modify, and/or distribute this software for any purpose with +# or without fee is hereby granted, provided that the above copyright notice and this +# permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN +# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import os, numpy, sys +try: + import Image +except: + from PIL import Image + +# ----------------------------------------------------- + +formats = { + 2: "GL_LUMINANCE", + 3: "GL_BGR", + 4: "GL_BGRA" +} + +def png2rgba(namespace, filenames): + + fdH = open("%s.hpp" % namespace, "w") + fdH.write("/* (Auto-generated binary data file). */\n") + fdH.write("\n") + fdH.write("#ifndef BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("#define BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("\n") + fdH.write("namespace %s\n" % namespace) + fdH.write("{\n") + + fdC = open("%s.cpp" % namespace, "w") + fdC.write("/* (Auto-generated binary data file). */\n") + fdC.write("\n") + fdC.write("#include \"%s.hpp\"\n" % namespace) + fdC.write("\n") + + tempIndex = 1 + + for filename in filenames: + shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] + shortFilename = shortFilename.replace("-", "_") + + png = Image.open(filename) + if png.getpalette(): + png = png.convert() + + pngNumpy = numpy.array(png) + pngData = pngNumpy.tolist() + #pngData.reverse() + + height = len(pngData) + for dataBlock in pngData: + width = len(dataBlock) + if isinstance(dataBlock[0], int): + channels = 2 + else: + channels = len(dataBlock[0]) + break + else: + print("Invalid image found, cannot continue!") + quit() + + if channels not in formats.keys(): + print("Invalid image channel count, cannot continue!") + quit() + + print("Generating data for \"%s\" using '%s' type" % (filename, formats[channels])) + #print(" Width: %i" % width) + #print(" Height: %i" % height) + #print(" DataSize: %i" % (width * height * channels)) + + fdH.write(" extern const char* %sData;\n" % shortFilename) + fdH.write(" const unsigned int %sDataSize = %i;\n" % (shortFilename, width * height * channels)) + fdH.write(" const unsigned int %sWidth = %i;\n" % (shortFilename, width)) + fdH.write(" const unsigned int %sHeight = %i;\n" % (shortFilename, height)) + + if tempIndex != len(filenames): + fdH.write("\n") + + fdC.write("static const unsigned char temp_%s_%i[] = {\n" % (shortFilename, tempIndex)) + + curColumn = 1 + fdC.write(" ") + + for dataBlock in pngData: + if curColumn == 0: + fdC.write(" ") + + for data in dataBlock: + if channels == 2: + fdC.write(" %3u," % data) + + elif channels == 3: + r, g, b = data + fdC.write(" %3u, %3u, %3u," % (b, g, r)) + + else: + r, g, b, a = data + + if filename in ("artwork/claw1.png", + "artwork/claw2.png", + "artwork/run1.png", + "artwork/run2.png", + "artwork/run3.png", + "artwork/run4.png", + "artwork/scratch1.png", + "artwork/scratch2.png", + "artwork/sit.png", + "artwork/tail.png"): + if r == 255: + a -= 38 + if a < 0: a = 0 + #a = 0 + #else: + #r = g = b = 255 + + fdC.write(" %3u, %3u, %3u, %3u," % (b, g, r, a)) + + if curColumn > 20: + fdC.write("\n ") + curColumn = 1 + else: + curColumn += 1 + + fdC.write("};\n") + fdC.write("const char* %s::%sData = (const char*)temp_%s_%i;\n" % (namespace, shortFilename, shortFilename, tempIndex)) + + if tempIndex != len(filenames): + fdC.write("\n") + + tempIndex += 1 + + fdH.write("}\n") + fdH.write("\n") + fdH.write("#endif // BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("\n") + fdH.close() + + fdC.write("\n") + fdC.close() + +# ----------------------------------------------------- + +if __name__ == '__main__': + if len(sys.argv) != 3: + print("Usage: %s " % sys.argv[0]) + quit() + + namespace = sys.argv[1].replace("-","_") + artFolder = sys.argv[2] + + if not os.path.exists(artFolder): + print("Folder '%s' does not exist" % artFolder) + quit() + + # find png files + pngFiles = [] + + for root, dirs, files in os.walk(artFolder): + for name in [name for name in files if name.lower().endswith(".png")]: + pngFiles.append(os.path.join(root, name)) + + pngFiles.sort() + + # create code now + png2rgba(namespace, pngFiles) diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/res2c.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/res2c.py Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# DISTRHO Plugin Framework (DPF) +# Copyright (C) 2012-2019 Filipe Coelho +# +# Permission to use, copy, modify, and/or distribute this software for any purpose with +# or without fee is hereby granted, provided that the above copyright notice and this +# permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN +# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import os, sys + +# ----------------------------------------------------- + +def res2c(namespace, filenames): + + fdH = open("%s.hpp" % namespace, "w") + fdH.write("/* (Auto-generated binary data file). */\n") + fdH.write("\n") + fdH.write("#ifndef BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("#define BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("\n") + fdH.write("namespace %s\n" % namespace) + fdH.write("{\n") + + fdC = open("%s.cpp" % namespace, "w") + fdC.write("/* (Auto-generated binary data file). */\n") + fdC.write("\n") + fdC.write("#include \"%s.hpp\"\n" % namespace) + fdC.write("\n") + + tempIndex = 1 + + for filename in filenames: + shortFilename = filename.rsplit(os.sep, 1)[-1].split(".", 1)[0] + shortFilename = shortFilename.replace("-", "_").replace("@","_") + + resData = open(filename, 'rb').read() + + print("Generating data for \"%s\"" % (filename)) + + fdH.write(" extern const unsigned char* %sData;\n" % shortFilename) + fdH.write(" const unsigned int %sDataSize = %i;\n" % (shortFilename, len(resData))) + + if tempIndex != len(filenames): + fdH.write("\n") + + fdC.write("static const unsigned char temp_%s_%i[] = {\n" % (shortFilename, tempIndex)) + + curColumn = 1 + fdC.write(" ") + + for data in resData: + if curColumn == 0: + fdC.write(" ") + + fdC.write(" %3u," % data) + + if curColumn > 20: + fdC.write("\n ") + curColumn = 1 + else: + curColumn += 1 + + fdC.write("};\n") + fdC.write("const unsigned char* %s::%sData = (const unsigned char*)temp_%s_%i;\n" % (namespace, shortFilename, shortFilename, tempIndex)) + + if tempIndex != len(filenames): + fdC.write("\n") + + tempIndex += 1 + + fdH.write("}\n") + fdH.write("\n") + fdH.write("#endif // BINARY_%s_HPP\n" % namespace.upper()) + fdH.write("\n") + fdH.close() + + fdC.write("\n") + fdC.close() + +# ----------------------------------------------------- + +if __name__ == '__main__': + if len(sys.argv) not in (3, 4): + print("Usage: %s [output-folder=$CWD]" % sys.argv[0]) + quit() + + namespace = sys.argv[1].replace("-","_") + resFolder = sys.argv[2] + outFolder = sys.argv[3] if len(sys.argv) == 4 else None + + if not os.path.exists(resFolder): + print("Folder '%s' does not exist" % resFolder) + quit() + + if outFolder is not None and not os.path.exists(outFolder): + print("Output folder '%s' does not exist" % outFolder) + quit() + + # find resource files + resFiles = [] + + for root, dirs, files in os.walk(resFolder): + for name in files: + resFiles.append(os.path.abspath(os.path.join(root, name))) + + resFiles.sort() + + if outFolder is not None: + os.chdir(outFolder) + + # create code now + res2c(namespace, resFiles) diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/clap.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/clap.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2 @@ +EXPORTS +clap_entry diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/clap.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/clap.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1 @@ +_clap_entry diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/clap.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/clap.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: clap_entry; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/dssi.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/dssi.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3 @@ +EXPORTS +ladspa_descriptor +dssi_descriptor diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/dssi.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/dssi.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2 @@ +_ladspa_descriptor +_dssi_descriptor diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/dssi.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/dssi.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: ladspa_descriptor; dssi_descriptor; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/ladspa.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/ladspa.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2 @@ +EXPORTS +ladspa_descriptor diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/ladspa.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/ladspa.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1 @@ +_ladspa_descriptor diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/ladspa.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/ladspa.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: ladspa_descriptor; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-dsp.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-dsp.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3 @@ +EXPORTS +lv2_descriptor +lv2_generate_ttl diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-dsp.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-dsp.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2 @@ +_lv2_descriptor +_lv2_generate_ttl diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-dsp.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-dsp.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: lv2_descriptor; lv2_generate_ttl; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-ui.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-ui.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2 @@ +EXPORTS +lv2ui_descriptor diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-ui.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-ui.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1 @@ +_lv2ui_descriptor diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-ui.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2-ui.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: lv2ui_descriptor; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +EXPORTS +lv2_descriptor +lv2ui_descriptor +lv2_generate_ttl diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3 @@ +_lv2_descriptor +_lv2ui_descriptor +_lv2_generate_ttl diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/lv2.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/lv2.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: lv2_descriptor; lv2ui_descriptor; lv2_generate_ttl; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/shared.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/shared.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,2 @@ +EXPORTS +createSharedPlugin diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/shared.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/shared.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1 @@ +_createSharedPlugin diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/shared.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/shared.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: createSharedPlugin; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/vst2.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/vst2.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3 @@ +EXPORTS +VSTPluginMain +main=VSTPluginMain diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/vst2.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/vst2.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1 @@ +_VSTPluginMain diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/vst2.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/vst2.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: VSTPluginMain; main; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/vst3.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/vst3.def Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +EXPORTS +GetPluginFactory +InitDll +ExitDll diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/vst3.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/vst3.exp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,3 @@ +_GetPluginFactory +_bundleEntry +_bundleExit diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/symbols/vst3.version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/symbols/vst3.version Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4 @@ +{ + global: GetPluginFactory; ModuleEntry; ModuleExit; + local: *; +}; diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/dpf/utils/valgrind-dpf.supp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/utils/valgrind-dpf.supp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,95 @@ +{ + libdl is full of leaks + Memcheck:Leak + ... + fun:_dl_open + ... +} +{ + libdl is full of leaks + Memcheck:Leak + ... + fun:_dl_close + ... +} +{ + libdl is full of leaks + Memcheck:Leak + ... + fun:_dl_init +} +{ + libdl is full of leaks + Memcheck:Leak + ... + fun:_dl_allocate_tls + ... +} +{ + libdl is full of leaks + Memcheck:Leak + ... + fun:call_init.part.0 +} +{ + libdl is really something else + Memcheck:Addr8 + ... + fun:dl_open_worker +} +{ + ignore XInitThreads + Memcheck:Leak + ... + fun:XInitThreads + ... +} +{ + ignore XrmGetStringDatabase + Memcheck:Leak + ... + fun:XrmGetStringDatabase + ... +} +{ + ignore XPutImage + Memcheck:Param + writev(vector[...]) + ... + fun:XPutImage + ... +} +{ + ignore mesa stuff + Memcheck:Value8 + ... + obj:/usr/lib/x86_64-linux-gnu/dri/swrast_dri.so + fun:start_thread + fun:clone +} +{ + leak in fftw plan + Memcheck:Leak + fun:malloc + fun:fftwf_malloc_plain + fun:fftwf_mkplanner + fun:fftwf_the_planner + fun:fftwf_mkapiplan + fun:fftwf_plan_many_dft_r2c + fun:fftwf_plan_dft_r2c + fun:fftwf_plan_dft_r2c_1d + ... +} +{ + leak in fftw plan + Memcheck:Leak + fun:memalign + fun:fftwf_malloc_plain + fun:fftwf_mkplanner + fun:fftwf_the_planner + fun:fftwf_mkapiplan + fun:fftwf_plan_many_dft_r2c + fun:fftwf_plan_dft_r2c + fun:fftwf_plan_dft_r2c_1d + ... +} diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/Changelog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/Changelog Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,6 @@ +0.231015-2 - Sprzątanie kodu +0.231015-1 - Uzupełniłem opis funkcji dla wtyczki ladspa +0.231015-0 - Oprócz klonowania, dostępne jest przenoszenie pojedyńczej ścieżki, pomiędzy kanałami +0.231014-1 - Poprawiłem grafikę +0.231014-0 - Kopiuje z kanału na kanał +0.231013-0 - Inicjacja projektu diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoArtworkCloneChannel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoArtworkCloneChannel.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,4714 @@ +/* (Auto-generated binary data file). */ + +#include "DistrhoArtworkCloneChannel.hpp" + +static const unsigned char temp_background_1[] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 246, 246, 246, 215, 215, 215, 209, 209, 209, 199, 199, 199, 189, 189, 189, 175, 175, 175, 159, 159, 159, 151, 151, 151, 146, 146, 146, 132, 132, 132, 123, 123, 123, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 103, 103, 103, 101, 101, 101, 101, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 92, 92, 92, + 101, 101, 100, 101, 101, 100, 101, 101, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 111, 111, 111, 114, 114, 114, 114, 114, 114, 114, 114, 114, 116, 116, 116, 132, 132, 132, 132, 132, 132, 136, 136, 136, 151, 151, 151, 170, 170, 170, 170, 170, 170, 183, 183, 183, 189, 189, 189, 207, 207, 207, + 223, 223, 223, 249, 249, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 247, + 209, 209, 209, 172, 172, 172, 142, 142, 142, 113, 113, 113, 91, 91, 91, 57, 57, 57, 40, 40, 40, 14, 14, 14, 7, 7, 7, 9, 9, 9, 11, 11, 12, 12, 12, 14, 11, 11, 14, 12, 12, 15, 11, 11, 16, 8, 8, 17, 7, 7, 18, 7, 7, 18, 7, 7, 20, 7, 7, 21, 7, 7, 23, + 7, 7, 23, 7, 7, 24, 7, 7, 24, 8, 8, 26, 9, 9, 28, 10, 10, 29, 10, 10, 29, 10, 10, 30, 10, 10, 30, 10, 10, 30, 11, 11, 30, 10, 10, 29, 12, 12, 32, 12, 12, 33, 12, 12, 32, 12, 12, 32, 12, 12, 32, 12, 12, 34, 13, 13, 52, 13, 13, 55, 13, 13, 52, + 13, 13, 50, 13, 13, 49, 13, 13, 48, 13, 13, 47, 13, 13, 46, 13, 13, 46, 13, 13, 45, 13, 13, 44, 13, 13, 43, 13, 13, 43, 13, 13, 42, 13, 13, 42, 13, 13, 42, 13, 13, 42, 13, 13, 42, 13, 13, 42, 13, 13, 42, 13, 13, 43, 13, 13, 43, 13, 13, 44, 13, 13, 44, + 13, 13, 44, 13, 13, 44, 13, 13, 44, 13, 13, 44, 13, 13, 44, 13, 13, 44, 13, 13, 44, 13, 13, 44, 13, 13, 43, 13, 13, 43, 13, 13, 43, 13, 13, 43, 13, 13, 43, 13, 13, 42, 13, 13, 42, 13, 13, 42, 13, 13, 41, 13, 13, 40, 13, 13, 40, 13, 13, 39, 13, 13, 39, + 13, 13, 38, 13, 13, 38, 13, 13, 38, 13, 13, 38, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 38, 13, 13, 38, 13, 13, 38, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, + 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 37, 13, 13, 36, 13, 13, 36, 13, 13, 36, 13, 13, 36, 13, 13, 36, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, + 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 35, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, + 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 34, 13, 13, 33, 13, 13, 34, 13, 13, 42, 13, 13, 53, 13, 13, 54, 13, 13, 52, 13, 13, 51, 13, 13, 50, 13, 13, 49, 13, 13, 48, 13, 13, 47, 13, 13, 47, 13, 13, 46, 13, 13, 46, 13, 13, 45, 13, 13, 45, + 13, 13, 45, 13, 13, 45, 13, 13, 45, 13, 13, 45, 13, 13, 45, 13, 13, 46, 13, 13, 46, 13, 13, 45, 13, 13, 45, 13, 13, 45, 13, 13, 44, 13, 13, 44, 13, 13, 44, 13, 13, 43, 13, 13, 42, 13, 13, 42, 13, 13, 41, 13, 13, 41, 12, 12, 41, 12, 12, 40, 12, 12, 40, + 12, 12, 40, 12, 12, 40, 12, 12, 39, 11, 11, 37, 10, 10, 36, 10, 10, 36, 10, 10, 36, 10, 10, 35, 10, 10, 35, 10, 10, 34, 9, 9, 34, 7, 7, 30, 7, 7, 29, 7, 7, 28, 7, 7, 27, 7, 7, 26, 7, 7, 24, 7, 7, 23, 7, 7, 21, 7, 7, 20, 8, 8, 18, + 10, 10, 18, 10, 10, 16, 12, 12, 16, 12, 12, 14, 11, 11, 12, 7, 7, 8, 7, 7, 7, 14, 14, 14, 34, 34, 34, 64, 64, 64, 82, 82, 82, 116, 116, 116, 148, 148, 148, 165, 165, 165, 203, 203, 203, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 250, + 218, 218, 218, 187, 187, 187, 135, 135, 135, 76, 76, 76, 42, 42, 42, 28, 28, 29, 15, 15, 18, 7, 7, 15, 9, 9, 22, 12, 12, 27, 12, 12, 31, 9, 9, 34, 7, 7, 37, 7, 7, 43, 7, 7, 48, 8, 8, 50, 9, 9, 52, 8, 8, 52, 9, 9, 53, 8, 8, 54, 7, 7, 55, + 7, 7, 56, 7, 7, 57, 7, 7, 58, 7, 7, 58, 7, 7, 59, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 61, 7, 7, 61, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 64, 7, 7, 64, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 61, 7, 7, 60, + 7, 7, 60, 7, 7, 69, 7, 7, 115, 7, 7, 113, 7, 7, 106, 7, 7, 101, 7, 7, 98, 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 91, 7, 7, 89, 7, 7, 86, 7, 7, 85, 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 83, 7, 7, 83, + 7, 7, 84, 7, 7, 85, 7, 7, 87, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 85, 7, 7, 85, 7, 7, 85, 7, 7, 84, 7, 7, 83, 7, 7, 81, + 7, 7, 80, 7, 7, 79, 7, 7, 78, 7, 7, 77, 7, 7, 76, 7, 7, 74, 7, 7, 74, 7, 7, 73, 7, 7, 72, 7, 7, 72, 7, 7, 71, 7, 7, 71, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 71, 7, 7, 71, 7, 7, 71, 7, 7, 72, 7, 7, 72, 7, 7, 73, + 7, 7, 72, 7, 7, 72, 7, 7, 71, 7, 7, 71, 7, 7, 71, 7, 7, 71, 7, 7, 71, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 68, 7, 7, 68, 7, 7, 68, 7, 7, 68, 7, 7, 67, 7, 7, 67, 7, 7, 66, 7, 7, 66, + 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 64, 7, 7, 64, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, + 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 61, 7, 7, 65, 7, 7, 84, 7, 7, 108, 7, 7, 112, 7, 7, 108, 7, 7, 105, 7, 7, 102, 7, 7, 98, 7, 7, 96, + 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 92, 7, 7, 91, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 90, 7, 7, 91, 7, 7, 91, 7, 7, 92, 7, 7, 91, 7, 7, 90, 7, 7, 89, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 85, 7, 7, 83, + 7, 7, 82, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 78, 7, 7, 78, 7, 7, 77, 7, 7, 77, 7, 7, 76, 7, 7, 75, 7, 7, 73, 7, 7, 72, 7, 7, 70, + 7, 7, 68, 7, 7, 67, 7, 7, 66, 7, 7, 64, 7, 7, 61, 8, 8, 61, 8, 8, 59, 9, 9, 58, 9, 9, 57, 8, 8, 55, 7, 7, 52, 7, 7, 47, 7, 7, 41, 11, 11, 37, 13, 13, 33, 12, 12, 28, 7, 7, 20, 7, 7, 17, 11, 11, 16, 26, 26, 26, 39, 39, 39, + 78, 78, 78, 144, 144, 144, 200, 200, 200, 222, 222, 222, 246, 246, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 229, 229, 229, 153, 153, 153, 73, 73, 73, 30, 30, 31, 10, 10, 12, 8, 8, 13, 12, 12, 23, 8, 8, 32, 9, 9, 45, 9, 9, 51, 7, 7, 56, 7, 7, 60, 7, 7, 61, 7, 7, 61, 7, 7, 62, 7, 7, 62, 7, 7, 64, 7, 7, 64, 7, 7, 65, + 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 66, 7, 7, 67, 7, 7, 68, 7, 7, 68, 7, 7, 69, 7, 7, 69, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 71, 7, 7, 71, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, + 7, 7, 72, 7, 7, 71, 7, 7, 71, 7, 7, 70, 7, 7, 69, 7, 7, 69, 7, 7, 86, 7, 7, 129, 7, 7, 121, 7, 7, 115, 7, 7, 110, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 101, 7, 7, 98, 7, 7, 96, 7, 7, 93, 7, 7, 92, + 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 92, 7, 7, 93, 7, 7, 95, 7, 7, 96, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, + 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 92, 7, 7, 91, 7, 7, 90, 7, 7, 89, 7, 7, 88, 7, 7, 87, 7, 7, 85, 7, 7, 84, 7, 7, 83, 7, 7, 82, 7, 7, 81, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, + 7, 7, 80, 7, 7, 80, 7, 7, 81, 7, 7, 82, 7, 7, 82, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 79, 7, 7, 79, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 77, 7, 7, 76, 7, 7, 76, 7, 7, 76, + 7, 7, 76, 7, 7, 76, 7, 7, 75, 7, 7, 75, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 73, 7, 7, 73, 7, 7, 73, 7, 7, 73, 7, 7, 73, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 73, 7, 7, 73, 7, 7, 72, + 7, 7, 72, 7, 7, 72, 7, 7, 71, 7, 7, 71, 7, 7, 71, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 71, 7, 7, 71, 7, 7, 70, 7, 7, 71, 7, 7, 92, 7, 7, 125, + 7, 7, 122, 7, 7, 117, 7, 7, 113, 7, 7, 109, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 100, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 99, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 97, 7, 7, 96, + 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 92, 7, 7, 90, 7, 7, 89, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 86, 7, 7, 85, + 7, 7, 84, 7, 7, 83, 7, 7, 83, 7, 7, 81, 7, 7, 80, 7, 7, 79, 7, 7, 77, 7, 7, 76, 7, 7, 75, 7, 7, 74, 7, 7, 73, 7, 7, 73, 7, 7, 72, 7, 7, 72, 7, 7, 71, 7, 7, 70, 7, 7, 69, 7, 7, 68, 7, 7, 67, 7, 7, 66, 7, 7, 65, + 7, 7, 64, 7, 7, 60, 8, 8, 54, 8, 8, 45, 8, 8, 32, 11, 11, 21, 7, 7, 11, 10, 10, 12, 35, 35, 35, 68, 68, 68, 153, 153, 153, 238, 238, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 225, 225, 225, 115, 115, 115, 45, 45, 45, 9, 9, 9, 8, 8, 20, 8, 8, 38, 7, 7, 50, 7, 7, 59, 7, 7, 64, 7, 7, 65, 7, 7, 67, 7, 7, 68, 7, 7, 69, 7, 7, 70, 7, 7, 71, 7, 7, 72, + 7, 7, 72, 7, 7, 73, 7, 7, 73, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 73, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 75, 7, 7, 76, 7, 7, 76, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 78, 7, 7, 78, 7, 7, 79, + 7, 7, 79, 7, 7, 79, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 79, 7, 7, 78, 7, 7, 78, 7, 7, 80, 7, 7, 117, 7, 7, 138, 7, 7, 130, 7, 7, 124, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 113, + 7, 7, 111, 7, 7, 108, 7, 7, 105, 7, 7, 102, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 100, 7, 7, 100, 7, 7, 101, 7, 7, 102, 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, + 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 102, 7, 7, 102, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 96, 7, 7, 95, 7, 7, 93, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, 7, 7, 90, + 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 91, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, + 7, 7, 86, 7, 7, 85, 7, 7, 85, 7, 7, 85, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, + 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 81, 7, 7, 81, 7, 7, 81, 7, 7, 81, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 79, + 7, 7, 79, 7, 7, 78, 7, 7, 78, 7, 7, 81, 7, 7, 111, 7, 7, 137, 7, 7, 131, 7, 7, 124, 7, 7, 120, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 109, + 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, + 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 92, 7, 7, 91, 7, 7, 90, 7, 7, 89, 7, 7, 88, 7, 7, 86, 7, 7, 85, 7, 7, 84, 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 81, 7, 7, 81, + 7, 7, 80, 7, 7, 78, 7, 7, 77, 7, 7, 77, 7, 7, 75, 7, 7, 74, 7, 7, 73, 7, 7, 71, 7, 7, 69, 7, 7, 68, 7, 7, 66, 7, 7, 59, 8, 8, 49, 9, 9, 37, 9, 9, 19, 7, 7, 7, 31, 31, 31, 118, 118, 118, 216, 216, 216, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 193, 193, 193, 87, 87, 87, 21, 21, 21, 9, 9, 12, 9, 9, 27, 8, 8, 43, 7, 7, 61, 7, 7, 67, 7, 7, 70, 7, 7, 71, 7, 7, 73, 7, 7, 74, 7, 7, 75, + 7, 7, 77, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 79, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 81, 7, 7, 81, 7, 7, 82, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, + 7, 7, 83, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 85, 7, 7, 86, 7, 7, 86, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 85, 7, 7, 84, 7, 7, 83, 7, 7, 100, 7, 7, 141, 7, 7, 140, 7, 7, 134, 7, 7, 130, 7, 7, 126, + 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 108, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 112, + 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 106, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 100, + 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, + 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, + 7, 7, 89, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, + 7, 7, 88, 7, 7, 89, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 85, 7, 7, 85, 7, 7, 85, 7, 7, 84, 7, 7, 90, 7, 7, 134, 7, 7, 140, 7, 7, 133, 7, 7, 128, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 114, + 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, + 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 97, 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 92, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 90, + 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 87, 7, 7, 86, 7, 7, 85, 7, 7, 85, 7, 7, 84, 7, 7, 83, 7, 7, 82, 7, 7, 81, 7, 7, 80, 7, 7, 78, 7, 7, 76, 7, 7, 73, 7, 7, 70, 7, 7, 66, 7, 7, 59, 7, 7, 45, + 7, 7, 24, 8, 8, 11, 20, 20, 20, 93, 93, 93, 197, 197, 197, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 252, 118, 118, 118, 24, 24, 24, 7, 7, 12, 8, 8, 30, 7, 7, 51, 7, 7, 64, 7, 7, 70, 7, 7, 74, 7, 7, 77, + 7, 7, 78, 7, 7, 79, 7, 7, 80, 7, 7, 81, 7, 7, 82, 7, 7, 83, 7, 7, 84, 7, 7, 85, 7, 7, 85, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 87, 7, 7, 87, + 7, 7, 88, 7, 7, 88, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 91, 7, 7, 91, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 93, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 90, 7, 7, 89, 7, 7, 122, + 7, 7, 150, 7, 7, 143, 7, 7, 139, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 118, 7, 7, 116, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, + 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, + 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, + 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, + 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, + 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 96, 7, 7, 96, 7, 7, 100, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 97, 7, 7, 93, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 116, 7, 7, 147, 7, 7, 142, 7, 7, 136, 7, 7, 133, 7, 7, 131, + 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, + 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 99, + 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 90, 7, 7, 89, 7, 7, 88, 7, 7, 87, 7, 7, 86, 7, 7, 84, 7, 7, 83, + 7, 7, 81, 7, 7, 79, 7, 7, 76, 7, 7, 73, 7, 7, 68, 7, 7, 61, 7, 7, 48, 7, 7, 26, 7, 7, 11, 24, 24, 24, 131, 131, 130, 252, 252, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 237, 237, 237, 105, 105, 105, 7, 7, 7, 7, 7, 22, 7, 7, 54, 7, 7, 69, + 7, 7, 72, 7, 7, 75, 7, 7, 78, 7, 7, 81, 7, 7, 83, 7, 7, 85, 7, 7, 86, 7, 7, 87, 7, 7, 88, 7, 7, 89, 7, 7, 90, 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, + 7, 7, 91, 7, 7, 90, 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 92, 7, 7, 92, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, + 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 95, 7, 7, 138, 7, 7, 152, 7, 7, 145, 7, 7, 141, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 130, 7, 7, 126, 7, 7, 124, 7, 7, 120, 7, 7, 118, 7, 7, 117, + 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, + 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, + 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, + 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, + 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 100, 7, 7, 103, 7, 7, 105, 7, 7, 107, 7, 7, 110, 7, 7, 110, 7, 7, 108, 7, 7, 108, 7, 7, 104, 7, 7, 97, 7, 7, 96, 7, 7, 93, 7, 7, 103, + 7, 7, 147, 7, 7, 148, 7, 7, 142, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, + 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 95, + 7, 7, 94, 7, 7, 93, 7, 7, 92, 7, 7, 91, 7, 7, 90, 7, 7, 88, 7, 7, 85, 7, 7, 82, 7, 7, 79, 7, 7, 75, 7, 7, 72, 7, 7, 68, 7, 7, 62, 7, 7, 48, 7, 7, 18, 7, 7, 7, 97, 97, 97, 245, 245, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 218, 75, 75, 75, + 8, 8, 9, 7, 7, 30, 7, 7, 66, 7, 7, 75, 7, 7, 77, 7, 7, 79, 7, 7, 82, 7, 7, 86, 7, 7, 89, 7, 7, 91, 7, 7, 91, 7, 7, 92, 7, 7, 92, 7, 7, 93, 7, 7, 94, 7, 7, 95, 7, 7, 95, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, + 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 95, 7, 7, 95, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 98, 7, 7, 98, 7, 7, 98, + 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 100, 7, 7, 144, 7, 7, 154, 7, 7, 147, 7, 7, 143, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 135, + 7, 7, 132, 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, + 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, + 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, + 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, + 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 103, 7, 7, 106, 7, 7, 108, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 116, + 7, 7, 113, 7, 7, 106, 7, 7, 100, 7, 7, 97, 7, 7, 102, 7, 7, 146, 7, 7, 155, 7, 7, 148, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, + 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, + 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 103, + 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 92, 7, 7, 90, 7, 7, 87, 7, 7, 84, 7, 7, 80, 7, 7, 76, 7, 7, 72, 7, 7, 68, 7, 7, 59, 7, 7, 28, + 7, 7, 7, 72, 72, 72, 237, 237, 237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 205, 205, 205, 52, 52, 52, 9, 9, 12, 8, 8, 35, 7, 7, 70, 7, 7, 77, 7, 7, 81, 7, 7, 85, 7, 7, 87, 7, 7, 89, 7, 7, 91, 7, 7, 94, 7, 7, 96, 7, 7, 96, 7, 7, 97, 7, 7, 97, 7, 7, 98, 7, 7, 98, 7, 7, 99, + 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 99, 7, 7, 99, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 101, 7, 7, 101, + 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 99, 7, 7, 100, 7, 7, 139, 7, 7, 157, 7, 7, 150, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 133, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 119, + 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, + 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, + 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 106, 7, 7, 110, 7, 7, 111, 7, 7, 112, + 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 116, 7, 7, 119, 7, 7, 119, 7, 7, 115, 7, 7, 108, 7, 7, 102, 7, 7, 101, 7, 7, 141, 7, 7, 160, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 140, 7, 7, 137, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 121, + 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, + 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 96, 7, 7, 94, 7, 7, 92, 7, 7, 89, 7, 7, 87, + 7, 7, 83, 7, 7, 80, 7, 7, 75, 7, 7, 69, 7, 7, 61, 7, 7, 29, 9, 9, 11, 46, 46, 46, 206, 206, 205, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 228, 228, 228, 38, 38, 38, 7, 7, 11, 8, 8, 42, 7, 7, 71, 7, 7, 79, 7, 7, 85, 7, 7, 89, 7, 7, 91, 7, 7, 92, 7, 7, 94, 7, 7, 96, 7, 7, 99, 7, 7, 100, 7, 7, 101, + 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 102, 7, 7, 102, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, + 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 128, 7, 7, 160, + 7, 7, 153, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, + 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, + 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, + 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, + 7, 7, 109, 7, 7, 109, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 111, 7, 7, 117, 7, 7, 121, 7, 7, 118, 7, 7, 113, 7, 7, 106, 7, 7, 102, 7, 7, 130, 7, 7, 164, 7, 7, 161, 7, 7, 157, 7, 7, 154, 7, 7, 152, + 7, 7, 149, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, + 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 100, + 7, 7, 100, 7, 7, 98, 7, 7, 96, 7, 7, 94, 7, 7, 92, 7, 7, 89, 7, 7, 86, 7, 7, 82, 7, 7, 78, 7, 7, 71, 7, 7, 61, 7, 7, 37, 7, 7, 10, 38, 38, 38, 239, 239, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 108, 108, 108, 8, 8, 9, 7, 7, 48, 7, 7, 74, 7, 7, 82, 7, 7, 89, 7, 7, 93, 7, 7, 95, 7, 7, 97, 7, 7, 98, + 7, 7, 100, 7, 7, 101, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, + 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, + 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 118, 7, 7, 160, 7, 7, 156, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 125, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, + 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, + 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 111, 7, 7, 108, 7, 7, 107, 7, 7, 105, 7, 7, 106, 7, 7, 107, 7, 7, 112, 7, 7, 118, 7, 7, 121, 7, 7, 118, 7, 7, 110, 7, 7, 104, 7, 7, 109, + 7, 7, 141, 7, 7, 166, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 155, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, + 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, + 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 99, 7, 7, 97, 7, 7, 95, 7, 7, 93, 7, 7, 91, 7, 7, 88, 7, 7, 85, 7, 7, 81, 7, 7, 74, 7, 7, 66, 7, 7, 42, 7, 7, 7, 108, 108, 107, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 194, 194, 194, 24, 24, 24, 7, 7, 30, 7, 7, 73, 7, 7, 83, 7, 7, 91, + 7, 7, 96, 7, 7, 99, 7, 7, 101, 7, 7, 102, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, + 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, + 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 122, 7, 7, 162, 7, 7, 157, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, + 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, + 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 109, 7, 7, 114, + 7, 7, 118, 7, 7, 118, 7, 7, 112, 7, 7, 106, 7, 7, 105, 7, 7, 107, 7, 7, 132, 7, 7, 168, 7, 7, 170, 7, 7, 166, 7, 7, 161, 7, 7, 155, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 140, + 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 123, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, + 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 100, 7, 7, 99, 7, 7, 97, 7, 7, 95, 7, 7, 93, 7, 7, 90, 7, 7, 87, 7, 7, 82, + 7, 7, 75, 7, 7, 64, 7, 7, 25, 24, 24, 24, 200, 200, 200, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 247, 75, 75, 75, + 7, 7, 12, 7, 7, 60, 7, 7, 82, 7, 7, 91, 7, 7, 97, 7, 7, 100, 7, 7, 103, 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 107, 7, 7, 143, 7, 7, 165, 7, 7, 158, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, + 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, + 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 107, + 7, 7, 106, 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 111, 7, 7, 116, 7, 7, 117, 7, 7, 112, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 109, 7, 7, 156, 7, 7, 175, 7, 7, 170, 7, 7, 165, 7, 7, 160, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, + 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 102, 7, 7, 100, 7, 7, 99, + 7, 7, 98, 7, 7, 96, 7, 7, 95, 7, 7, 92, 7, 7, 88, 7, 7, 82, 7, 7, 73, 7, 7, 51, 7, 7, 11, 72, 72, 72, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 166, 166, 166, 16, 16, 16, 8, 8, 37, 7, 7, 79, 7, 7, 89, 7, 7, 96, 7, 7, 102, 7, 7, 104, 7, 7, 106, 7, 7, 107, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 111, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 111, + 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 131, 7, 7, 164, 7, 7, 164, 7, 7, 158, + 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, + 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, + 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 114, + 7, 7, 114, 7, 7, 115, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 106, 7, 7, 108, 7, 7, 112, 7, 7, 113, 7, 7, 110, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 156, 7, 7, 177, 7, 7, 172, 7, 7, 169, + 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 153, 7, 7, 148, 7, 7, 144, 7, 7, 142, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 107, + 7, 7, 106, 7, 7, 106, 7, 7, 104, 7, 7, 103, 7, 7, 101, 7, 7, 100, 7, 7, 99, 7, 7, 97, 7, 7, 95, 7, 7, 93, 7, 7, 87, 7, 7, 80, 7, 7, 68, 7, 7, 31, 15, 15, 15, 167, 167, 167, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 247, 28, 28, 28, 7, 7, 19, 7, 7, 69, 7, 7, 85, 7, 7, 95, 7, 7, 100, 7, 7, 104, 7, 7, 107, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 111, 7, 7, 111, + 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, + 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 111, + 7, 7, 135, 7, 7, 165, 7, 7, 165, 7, 7, 161, 7, 7, 157, 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 121, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 112, + 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 115, 7, 7, 116, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, + 7, 7, 109, 7, 7, 145, 7, 7, 176, 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 161, 7, 7, 155, 7, 7, 150, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 126, + 7, 7, 127, 7, 7, 129, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 119, 7, 7, 118, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 122, + 7, 7, 119, 7, 7, 118, 7, 7, 115, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 100, 7, 7, 98, 7, 7, 96, 7, 7, 92, 7, 7, 86, 7, 7, 75, 7, 7, 57, 7, 7, 16, 38, 38, 38, + 247, 247, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 149, 149, 149, 7, 7, 8, 7, 7, 49, 7, 7, 81, 7, 7, 90, 7, 7, 99, 7, 7, 104, 7, 7, 107, 7, 7, 109, + 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, + 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 113, 7, 7, 115, 7, 7, 138, 7, 7, 166, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 153, + 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 127, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 128, + 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, + 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 107, 7, 7, 107, + 7, 7, 107, 7, 7, 107, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 117, 7, 7, 150, 7, 7, 175, 7, 7, 176, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 168, 7, 7, 164, 7, 7, 157, 7, 7, 151, 7, 7, 147, 7, 7, 144, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 130, 7, 7, 127, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 122, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 125, + 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 101, 7, 7, 98, 7, 7, 95, + 7, 7, 90, 7, 7, 81, 7, 7, 69, 7, 7, 39, 7, 7, 7, 152, 152, 152, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 250, 78, 78, 78, 7, 7, 21, 7, 7, 71, 7, 7, 84, + 7, 7, 95, 7, 7, 101, 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, + 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 120, + 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 112, 7, 7, 114, 7, 7, 117, 7, 7, 120, 7, 7, 129, 7, 7, 162, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, + 7, 7, 149, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 133, + 7, 7, 134, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 126, 7, 7, 124, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 116, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 111, + 7, 7, 109, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 108, 7, 7, 109, 7, 7, 107, 7, 7, 107, 7, 7, 113, 7, 7, 142, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 170, + 7, 7, 165, 7, 7, 158, 7, 7, 152, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 144, + 7, 7, 140, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 124, + 7, 7, 125, 7, 7, 125, 7, 7, 129, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 8, 129, 7, 7, 130, 7, 7, 131, 7, 7, 128, 7, 8, 125, 7, 7, 125, 7, 7, 127, 7, 7, 121, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, + 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 100, 7, 7, 97, 7, 7, 92, 7, 7, 85, 7, 7, 73, 7, 7, 59, 7, 7, 17, 84, 84, 84, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 215, 215, 215, 19, 19, 19, 9, 9, 41, 7, 7, 79, 7, 7, 87, 7, 7, 97, 7, 7, 103, 7, 7, 108, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, + 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 122, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 127, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 115, 7, 7, 120, 7, 7, 125, 7, 7, 129, 7, 7, 138, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 154, 7, 7, 150, 7, 7, 147, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 145, + 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 136, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 121, 7, 7, 122, 7, 7, 121, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, + 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 106, 7, 7, 104, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 118, 7, 7, 165, 7, 7, 167, + 7, 7, 166, 7, 7, 167, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 164, 7, 7, 159, 7, 7, 154, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 153, + 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 148, 7, 7, 144, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 143, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, + 7, 7, 137, 7, 7, 133, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 135, 7, 7, 138, 7, 7, 140, 7, 7, 138, 7, 7, 139, 7, 16, 140, 7, 27, 142, 7, 26, 140, 7, 9, 135, 7, 8, 130, 7, 7, 134, 7, 7, 127, 7, 7, 120, 7, 7, 116, + 7, 7, 113, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 105, 7, 7, 102, 7, 7, 99, 7, 7, 95, 7, 7, 88, 7, 7, 78, 7, 7, 68, 9, 9, 33, 32, 32, 32, 230, 230, 230, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 187, 187, 187, 8, 8, 9, 7, 7, 60, 7, 7, 81, 7, 7, 89, 7, 7, 98, 7, 7, 105, 7, 7, 109, 7, 7, 111, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, + 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, + 7, 7, 123, 7, 7, 126, 7, 7, 127, 7, 7, 127, 7, 7, 128, 7, 7, 127, 7, 7, 127, 7, 7, 128, 7, 7, 127, 7, 7, 124, 7, 7, 122, 7, 7, 118, 7, 7, 115, 7, 7, 116, 7, 7, 119, 7, 7, 127, 7, 7, 133, 7, 7, 138, 7, 7, 141, 7, 7, 152, 7, 7, 156, + 7, 7, 152, 7, 7, 143, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 140, 7, 7, 143, 7, 7, 144, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 147, 7, 7, 147, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 139, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 138, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 8, 131, 7, 7, 131, + 7, 7, 133, 7, 7, 129, 7, 7, 128, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 125, 7, 7, 127, 7, 7, 126, 7, 7, 123, 7, 7, 121, 7, 7, 119, 7, 8, 118, 7, 9, 117, 7, 8, 116, 7, 9, 113, 7, 10, 113, + 7, 7, 113, 7, 7, 115, 7, 7, 117, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 102, 7, 8, 99, 7, 8, 95, + 7, 8, 93, 7, 8, 91, 7, 9, 99, 7, 7, 129, 7, 7, 148, 7, 7, 153, 7, 7, 160, 7, 7, 163, 7, 7, 165, 7, 7, 166, 7, 7, 164, 7, 7, 159, 7, 7, 155, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, + 7, 7, 147, 7, 7, 149, 7, 7, 153, 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 149, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 141, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 136, 7, 7, 137, 7, 7, 139, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 9, 143, 7, 20, 144, 7, 22, 144, 7, 25, 144, 7, 7, 140, + 7, 7, 138, 7, 7, 137, 7, 7, 131, 7, 7, 124, 7, 7, 117, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 106, 7, 7, 103, 7, 7, 100, 7, 7, 96, 7, 7, 90, 7, 7, 81, 7, 7, 71, 7, 7, 48, 7, 7, 7, + 182, 182, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 111, 111, 111, 10, 10, 14, 7, 7, 72, 7, 7, 83, 7, 7, 91, 7, 7, 99, 7, 7, 105, 7, 7, 110, 7, 7, 111, 7, 7, 113, 7, 7, 114, + 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, + 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 121, 7, 8, 125, 7, 10, 128, 7, 12, 130, 7, 13, 131, 7, 15, 132, 7, 17, 132, 7, 16, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 119, 7, 7, 117, 7, 7, 121, 7, 7, 126, 7, 7, 135, + 7, 7, 141, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 136, 7, 8, 136, 7, 10, 139, 7, 11, 140, 7, 8, 139, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 141, 7, 7, 143, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 8, 139, 7, 7, 142, 7, 7, 146, 7, 7, 147, 7, 7, 144, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 141, 7, 7, 135, 7, 7, 126, 7, 7, 124, + 7, 7, 123, 7, 8, 126, 7, 7, 140, 7, 7, 141, 7, 7, 131, 7, 9, 131, 7, 8, 134, 7, 7, 138, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 144, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 140, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 8, 141, 7, 9, 141, + 7, 11, 140, 7, 11, 140, 7, 11, 138, 7, 8, 137, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 133, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 127, 7, 7, 128, 7, 8, 128, 7, 9, 130, 7, 15, 131, + 7, 23, 132, 7, 43, 136, 7, 47, 136, 7, 47, 135, 7, 34, 131, 7, 17, 126, 7, 11, 125, 7, 7, 122, 7, 8, 120, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 109, 7, 7, 107, 7, 7, 106, + 7, 7, 104, 7, 7, 102, 7, 7, 99, 7, 8, 98, 7, 11, 97, 7, 14, 96, 7, 12, 95, 7, 11, 91, 7, 7, 89, 7, 9, 87, 7, 7, 107, 7, 7, 140, 7, 7, 154, 7, 7, 161, 7, 7, 164, 7, 7, 163, 7, 7, 160, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 154, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 150, 7, 7, 154, 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 163, 7, 7, 163, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 8, 154, 7, 10, 154, 7, 9, 154, 7, 9, 154, 7, 8, 154, 7, 8, 152, 7, 7, 148, 7, 7, 144, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 143, 7, 7, 144, 7, 7, 144, + 7, 8, 145, 7, 8, 145, 7, 8, 145, 7, 8, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 133, 7, 7, 126, 7, 7, 120, 7, 7, 116, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 106, 7, 7, 103, 7, 7, 101, 7, 7, 97, + 7, 7, 92, 7, 7, 84, 7, 7, 74, 7, 7, 62, 8, 8, 11, 107, 107, 107, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 241, 241, 51, 51, 51, 7, 7, 27, 7, 7, 76, 7, 7, 85, 7, 7, 94, 7, 7, 100, + 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, + 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 116, 7, 7, 118, 7, 8, 123, 7, 18, 129, 7, 38, 135, 7, 36, 135, 7, 26, 133, 7, 13, 131, 7, 12, 132, 7, 11, 132, 7, 19, 132, 7, 8, 129, 7, 7, 129, 7, 7, 128, 7, 7, 127, 7, 7, 124, + 7, 7, 120, 7, 7, 120, 7, 7, 126, 7, 7, 133, 7, 7, 141, 7, 7, 146, 7, 7, 145, 7, 7, 141, 7, 7, 138, 7, 7, 136, 7, 10, 135, 7, 39, 142, 7, 52, 146, 7, 31, 143, 7, 11, 136, 7, 7, 133, 7, 7, 135, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 140, + 7, 7, 138, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 9, 142, 7, 7, 141, 7, 7, 140, 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 141, 7, 7, 142, 7, 7, 132, 7, 8, 136, 7, 22, 140, 7, 23, 138, 7, 7, 135, 7, 7, 140, 7, 7, 137, 7, 7, 136, 7, 10, 139, 7, 8, 140, 7, 7, 141, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 7, 142, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 140, + 7, 7, 136, 7, 7, 136, 7, 8, 137, 7, 13, 141, 7, 20, 143, 7, 21, 143, 7, 21, 144, 7, 21, 144, 7, 19, 142, 7, 8, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 134, 7, 7, 129, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 130, + 7, 7, 132, 7, 8, 133, 7, 11, 134, 7, 19, 134, 7, 21, 135, 7, 20, 136, 7, 22, 136, 7, 26, 136, 7, 31, 137, 7, 34, 137, 7, 37, 138, 7, 33, 137, 7, 17, 132, 7, 7, 129, 7, 7, 125, 7, 7, 120, 7, 7, 124, 7, 7, 118, 7, 7, 115, 7, 7, 114, 7, 7, 114, + 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 104, 7, 10, 104, 7, 19, 105, 7, 25, 105, 7, 28, 106, 7, 30, 105, 7, 32, 105, 7, 26, 102, 7, 9, 97, 7, 7, 92, 7, 7, 89, 7, 7, 133, 7, 7, 151, 7, 7, 158, 7, 7, 163, + 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 153, 7, 7, 158, 7, 7, 161, 7, 7, 162, 7, 8, 164, 7, 8, 165, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 160, 7, 7, 155, + 7, 7, 153, 7, 7, 151, 7, 7, 154, 7, 7, 158, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 9, 159, 7, 11, 157, 7, 13, 158, 7, 10, 158, 7, 12, 159, 7, 12, 159, 7, 10, 158, 7, 9, 155, 7, 7, 151, 7, 7, 149, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, + 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 8, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 133, 7, 7, 127, 7, 7, 121, 7, 7, 117, 7, 7, 114, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, + 7, 7, 110, 7, 7, 107, 7, 7, 104, 7, 7, 101, 7, 7, 98, 7, 7, 93, 7, 7, 86, 7, 7, 77, 7, 7, 67, 7, 7, 24, 51, 51, 51, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 180, 180, 180, 16, 16, 18, + 9, 9, 48, 7, 7, 80, 7, 7, 87, 7, 7, 96, 7, 7, 101, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 124, 7, 7, 126, 7, 7, 122, 7, 7, 120, 7, 7, 123, 7, 19, 128, 7, 48, 136, 7, 48, 137, 7, 30, 134, 7, 24, 133, 7, 25, 133, 7, 17, 132, 7, 15, 132, 7, 15, 132, 7, 20, 132, + 7, 11, 130, 7, 7, 128, 7, 7, 127, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 124, 7, 7, 130, 7, 7, 137, 7, 7, 145, 7, 7, 147, 7, 7, 145, 7, 7, 141, 7, 7, 136, 7, 9, 133, 7, 33, 137, 7, 47, 143, 7, 33, 142, 7, 15, 140, 7, 8, 135, 7, 7, 131, + 7, 7, 133, 7, 7, 136, 7, 7, 141, 7, 7, 142, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 21, 143, 7, 37, 145, 7, 31, 145, 7, 7, 140, 7, 8, 140, 7, 7, 140, 7, 11, 140, 7, 22, 139, 7, 8, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 139, 7, 8, 141, 7, 8, 142, 7, 11, 140, 7, 11, 136, 7, 9, 135, 7, 10, 138, 7, 11, 142, 7, 10, 143, 7, 9, 142, 7, 8, 142, 7, 8, 142, 7, 9, 143, 7, 10, 141, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 132, 7, 7, 130, + 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 134, 7, 8, 135, 7, 10, 135, 7, 9, 135, 7, 8, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 8, 135, 7, 10, 135, 7, 12, 135, 7, 12, 135, 7, 14, 135, 7, 19, 135, 7, 10, 132, 7, 7, 127, + 7, 7, 120, 7, 7, 122, 7, 7, 118, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 111, 7, 8, 110, 7, 12, 108, 7, 14, 108, 7, 11, 106, 7, 9, 106, 7, 8, 105, 7, 8, 104, 7, 10, 104, 7, 14, 103, 7, 24, 104, 7, 20, 102, + 7, 7, 96, 7, 7, 89, 7, 7, 127, 7, 7, 151, 7, 7, 157, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 156, 7, 7, 161, 7, 7, 164, 7, 7, 166, 7, 7, 168, 7, 7, 169, + 7, 7, 170, 7, 7, 170, 7, 7, 166, 7, 7, 161, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 8, 159, 7, 8, 162, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 8, 161, 7, 9, 160, 7, 8, 161, 7, 9, 162, 7, 8, 163, 7, 9, 161, 7, 13, 160, 7, 7, 157, + 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 137, 7, 7, 133, 7, 7, 126, 7, 7, 121, 7, 7, 117, + 7, 7, 115, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 105, 7, 7, 102, 7, 7, 99, 7, 7, 94, 7, 7, 88, 7, 7, 80, 7, 7, 71, 9, 9, 42, 21, 21, 22, 195, 195, 195, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 115, 115, 115, 7, 7, 15, 7, 7, 62, 7, 7, 83, 7, 7, 90, 7, 7, 98, 7, 7, 103, 7, 7, 108, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 124, 7, 7, 126, 7, 7, 123, 7, 7, 123, 7, 8, 127, 7, 20, 130, 7, 33, 133, 7, 36, 135, 7, 33, 134, 7, 23, 133, 7, 15, 131, + 7, 13, 131, 7, 11, 131, 7, 13, 132, 7, 21, 133, 7, 23, 132, 7, 14, 130, 7, 8, 128, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 127, 7, 7, 132, 7, 7, 141, 7, 7, 145, 7, 7, 147, 7, 7, 145, 7, 7, 140, 7, 7, 135, 7, 8, 131, 7, 12, 133, + 7, 14, 136, 7, 18, 141, 7, 15, 141, 7, 9, 138, 7, 7, 135, 7, 7, 136, 7, 7, 138, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 136, 7, 7, 135, 7, 7, 137, + 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 141, 7, 7, 143, 7, 7, 143, 10, 43, 138, 16, 85, 122, 21, 108, 105, 22, 116, 98, 24, 123, 90, 25, 128, 84, 24, 123, 89, 24, 118, 96, 21, 106, 106, 16, 85, 121, 10, 51, 133, 7, 7, 139, 7, 9, 137, 7, 8, 134, + 7, 7, 135, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 136, 7, 7, 133, 7, 7, 135, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 8, 139, 7, 13, 141, 7, 10, 142, 7, 11, 143, 7, 10, 140, 7, 11, 140, 7, 11, 141, 7, 9, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 138, 7, 7, 135, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 135, 7, 8, 135, 7, 8, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 8, 135, 7, 7, 135, 7, 9, 134, 7, 18, 135, 7, 12, 132, 7, 7, 125, 7, 7, 118, 7, 7, 120, 7, 7, 117, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 9, 117, 7, 10, 115, 7, 8, 114, 7, 8, 112, 7, 7, 109, 7, 7, 107, 7, 7, 107, + 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 11, 103, 7, 14, 103, 7, 8, 99, 7, 7, 94, 7, 7, 137, 7, 7, 154, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 154, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 8, 153, 7, 7, 153, 7, 7, 159, + 7, 7, 163, 7, 7, 168, 7, 7, 169, 7, 7, 171, 7, 7, 173, 7, 7, 174, 7, 7, 173, 7, 7, 168, 7, 7, 162, 7, 7, 158, 7, 7, 156, 7, 7, 158, 7, 9, 162, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 8, 163, 7, 8, 164, + 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 153, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 141, 7, 7, 139, + 7, 7, 136, 7, 7, 131, 7, 7, 125, 7, 7, 120, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 103, 7, 7, 100, 7, 7, 95, 7, 7, 89, 7, 7, 82, 7, 7, 74, 7, 7, 52, 7, 7, 12, + 135, 135, 135, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 66, 66, 66, 10, 10, 28, 7, 7, 73, 7, 7, 84, 7, 7, 92, 7, 7, 100, 7, 7, 104, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, + 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 122, 7, 7, 124, 7, 7, 126, 7, 7, 123, 7, 7, 123, 7, 8, 128, 7, 18, 130, 7, 15, 131, + 7, 10, 131, 7, 11, 131, 7, 11, 132, 7, 15, 131, 7, 20, 130, 7, 23, 130, 7, 19, 131, 7, 8, 130, 7, 16, 131, 7, 22, 132, 7, 9, 130, 7, 7, 128, 7, 8, 126, 7, 7, 127, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 135, 7, 7, 141, 7, 7, 146, 7, 7, 147, + 7, 7, 145, 7, 7, 141, 7, 7, 137, 7, 7, 134, 7, 8, 135, 7, 14, 138, 7, 14, 142, 7, 9, 142, 7, 7, 141, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, + 7, 7, 142, 7, 7, 139, 7, 7, 136, 7, 7, 134, 7, 7, 136, 7, 7, 141, 7, 7, 142, 7, 7, 139, 7, 7, 139, 7, 7, 139, 12, 63, 132, 22, 114, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 21, 112, 101, 14, 71, 123, 7, 7, 131, 7, 7, 133, 7, 7, 136, 7, 7, 141, 7, 7, 142, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 142, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 9, 141, 7, 15, 142, 7, 9, 144, 7, 9, 144, 7, 9, 143, 7, 9, 144, 7, 8, 144, 7, 8, 143, 7, 7, 143, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 135, 7, 10, 137, 7, 8, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 10, 135, 7, 22, 136, 7, 10, 130, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 12, 125, 7, 11, 123, 7, 8, 121, + 7, 7, 119, 7, 7, 115, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 10, 104, 7, 14, 103, 7, 8, 103, 7, 9, 119, 7, 7, 148, 7, 7, 157, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, + 7, 9, 155, 7, 8, 155, 7, 7, 154, 7, 7, 155, 7, 7, 160, 7, 7, 166, 7, 7, 170, 7, 7, 171, 7, 7, 172, 7, 7, 174, 7, 7, 174, 7, 7, 171, 7, 7, 167, 7, 7, 160, 7, 7, 156, 7, 7, 156, 7, 7, 160, 7, 8, 165, 7, 7, 169, 7, 7, 170, 7, 7, 168, + 7, 7, 166, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 169, 7, 7, 170, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 8, 151, + 7, 8, 148, 7, 7, 146, 7, 7, 142, 7, 7, 139, 7, 7, 136, 7, 7, 132, 7, 7, 128, 7, 7, 122, 7, 7, 120, 7, 7, 118, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 109, 7, 7, 106, 7, 7, 104, 7, 7, 101, 7, 7, 96, + 7, 7, 90, 7, 7, 83, 7, 7, 76, 7, 7, 64, 8, 8, 21, 73, 73, 73, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 32, 32, 32, 7, 7, 40, 7, 7, 76, 7, 7, 86, 7, 7, 94, 7, 7, 101, 7, 7, 106, 7, 7, 110, + 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 123, 7, 7, 123, 7, 7, 125, 7, 7, 124, + 7, 7, 122, 7, 7, 128, 7, 22, 132, 7, 13, 131, 7, 8, 131, 7, 7, 130, 7, 8, 130, 7, 12, 130, 7, 16, 129, 7, 12, 127, 7, 11, 125, 7, 9, 126, 7, 7, 128, 7, 8, 129, 7, 10, 130, 7, 10, 130, 7, 10, 128, 7, 9, 126, 7, 7, 127, 7, 7, 126, 7, 7, 127, + 7, 7, 130, 7, 7, 135, 7, 7, 140, 7, 7, 144, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 140, 7, 7, 137, 7, 7, 139, 7, 7, 141, 7, 8, 141, 7, 8, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 137, 7, 7, 136, 7, 7, 138, 7, 7, 141, 7, 7, 140, 7, 7, 138, 9, 41, 133, 19, 106, 106, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 112, 100, 10, 47, 131, 7, 7, 138, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 23, 119, 94, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 10, 142, 7, 17, 145, 7, 9, 144, 7, 8, 144, 7, 8, 143, + 7, 8, 143, 7, 8, 142, 7, 8, 144, 7, 8, 143, 7, 7, 139, 7, 7, 136, 7, 7, 137, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 11, 136, 7, 11, 137, 7, 8, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 8, 135, 7, 16, 135, 7, 24, 134, 7, 8, 126, 7, 7, 122, 7, 7, 127, 7, 7, 128, 7, 7, 128, + 7, 7, 129, 7, 13, 129, 7, 13, 129, 7, 8, 127, 7, 8, 125, 7, 7, 123, 7, 7, 120, 7, 7, 115, 7, 7, 112, 7, 7, 108, 7, 7, 107, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 12, 106, 7, 10, 109, 7, 7, 116, 7, 7, 147, 7, 7, 157, + 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 8, 159, 7, 8, 158, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 161, 7, 7, 166, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 162, 7, 7, 156, 7, 7, 153, 7, 7, 154, + 7, 7, 159, 7, 7, 166, 7, 7, 172, 7, 7, 174, 7, 7, 171, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 168, 7, 7, 171, 7, 7, 173, 7, 7, 174, 7, 7, 172, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 8, 154, 7, 9, 152, 7, 8, 150, 7, 7, 146, 7, 7, 141, 7, 7, 139, 7, 7, 133, 7, 7, 130, 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, + 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 102, 7, 7, 97, 7, 7, 91, 7, 7, 85, 7, 7, 77, 7, 7, 67, 7, 7, 32, 33, 33, 33, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 237, 237, 237, 22, 22, 22, 7, 7, 50, 7, 7, 77, + 7, 7, 87, 7, 7, 95, 7, 7, 102, 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, + 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 127, 7, 7, 121, 7, 8, 127, 7, 25, 132, 7, 20, 133, 7, 8, 131, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 8, 129, 7, 8, 128, 7, 7, 125, 7, 8, 125, 7, 8, 125, 7, 7, 127, 7, 7, 127, 7, 9, 129, 7, 12, 130, + 7, 9, 128, 7, 8, 127, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 130, 7, 7, 134, 7, 7, 137, 7, 7, 141, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 144, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 139, 11, 57, 129, 24, 122, 90, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 125, 87, 15, 74, 126, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 140, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 12, 144, 7, 18, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 8, 142, 7, 8, 142, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 8, 137, 7, 9, 137, 7, 8, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 10, 135, 7, 25, 134, + 7, 11, 129, 7, 7, 127, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 8, 131, 7, 8, 131, 7, 8, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 124, 7, 7, 120, 7, 7, 116, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, + 7, 8, 107, 7, 10, 112, 7, 7, 122, 7, 7, 148, 7, 7, 157, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 160, 7, 7, 164, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, + 7, 7, 161, 7, 7, 156, 7, 7, 152, 7, 7, 150, 7, 7, 152, 7, 7, 156, 7, 7, 164, 7, 7, 170, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 168, 7, 7, 171, 7, 7, 175, 7, 7, 175, 7, 7, 172, 7, 7, 167, 7, 7, 162, 7, 7, 160, + 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 8, 157, 7, 10, 155, 7, 7, 153, 7, 7, 147, 7, 7, 142, 7, 7, 137, 7, 7, 131, 7, 7, 126, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 117, 7, 7, 116, + 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 102, 7, 7, 97, 7, 7, 92, 7, 7, 85, 7, 7, 78, 7, 7, 69, 7, 7, 42, 21, 21, 21, 239, 239, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 210, 210, 210, 20, 20, 21, 8, 8, 57, 7, 7, 79, 7, 7, 88, 7, 7, 97, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 124, 7, 7, 125, 7, 7, 128, 7, 7, 126, 7, 7, 127, 7, 17, 131, 7, 31, 135, 7, 13, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 8, 126, 7, 7, 125, + 7, 7, 126, 7, 7, 127, 7, 7, 128, 7, 8, 128, 7, 8, 129, 7, 7, 129, 7, 7, 129, 7, 7, 127, 7, 7, 126, 7, 7, 127, 7, 7, 130, 7, 7, 132, 7, 7, 134, 7, 7, 137, 7, 7, 140, 7, 7, 141, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 137, + 7, 7, 138, 7, 7, 141, 7, 7, 144, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 142, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 13, 68, 127, 24, 126, 86, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 128, 83, 15, 81, 124, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 142, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, + 7, 7, 139, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 11, 144, 7, 17, 144, 7, 8, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 9, 135, 7, 15, 134, 7, 15, 131, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 123, 7, 7, 119, 7, 7, 115, 7, 7, 113, + 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 109, 7, 9, 116, 7, 7, 127, 7, 7, 148, 7, 7, 160, 7, 7, 162, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 156, 7, 7, 158, + 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 151, 7, 7, 157, 7, 7, 163, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 168, 7, 7, 171, + 7, 7, 172, 7, 7, 169, 7, 7, 164, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 8, 161, 7, 8, 159, 7, 7, 155, 7, 7, 149, 7, 7, 144, 7, 7, 137, 7, 7, 129, 7, 7, 123, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 102, 7, 7, 98, 7, 7, 92, 7, 7, 86, 7, 7, 79, 7, 7, 70, 8, 8, 49, 19, 19, 20, + 212, 212, 212, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 171, 171, 171, 15, 15, 20, 9, 9, 61, 7, 7, 81, 7, 7, 89, 7, 7, 98, 7, 7, 104, 7, 7, 107, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, + 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 125, 7, 7, 128, 7, 7, 128, 7, 7, 127, 7, 8, 130, 7, 25, 133, 7, 21, 133, 7, 12, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 8, 127, 7, 7, 127, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 127, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 130, 7, 7, 132, 7, 7, 131, 7, 8, 134, 7, 7, 136, 7, 7, 138, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 135, 7, 7, 138, 7, 7, 143, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 147, 7, 7, 143, 7, 7, 141, 7, 7, 137, 7, 7, 134, 7, 7, 135, 7, 7, 138, 7, 7, 142, + 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 10, 49, 136, 24, 125, 88, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 116, 99, 18, 93, 117, 16, 83, 122, 15, 73, 126, 16, 82, 122, 17, 92, 117, 21, 112, 102, 25, 128, 83, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, 14, 69, 130, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 141, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 141, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 9, 144, 7, 14, 143, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 8, 140, 7, 7, 142, 7, 8, 141, 7, 8, 143, + 7, 10, 143, 7, 13, 144, 7, 12, 144, 7, 10, 142, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 8, 136, 7, 9, 133, 7, 12, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 128, 7, 7, 127, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 109, 7, 7, 111, 7, 8, 119, 7, 7, 132, 7, 7, 153, 7, 7, 161, 7, 7, 165, 7, 7, 169, 7, 8, 170, 7, 7, 168, 7, 7, 164, 7, 7, 160, + 7, 7, 158, 7, 7, 155, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 8, 148, 7, 7, 145, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 147, 7, 7, 150, 7, 7, 154, 7, 7, 157, 7, 7, 158, 7, 7, 156, + 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 160, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 157, 7, 7, 159, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 161, 7, 7, 158, + 7, 7, 152, 7, 7, 144, 7, 7, 136, 7, 7, 127, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 104, 7, 7, 103, 7, 7, 98, 7, 7, 92, + 7, 7, 87, 7, 7, 80, 7, 7, 72, 8, 8, 53, 16, 16, 19, 178, 178, 178, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 135, 135, 135, 8, 8, 21, 7, 7, 67, 7, 7, 83, 7, 7, 91, 7, 7, 100, 7, 7, 104, 7, 7, 108, 7, 7, 112, 7, 7, 113, + 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 126, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 12, 132, 7, 17, 132, + 7, 15, 133, 7, 15, 132, 7, 12, 131, 7, 9, 130, 7, 8, 130, 7, 9, 130, 7, 13, 130, 7, 22, 131, 7, 26, 132, 7, 26, 132, 7, 17, 130, 7, 9, 129, 7, 7, 129, 7, 8, 129, 7, 8, 129, 7, 8, 128, 7, 7, 126, 7, 7, 123, 7, 8, 118, 7, 7, 125, 7, 7, 130, + 7, 7, 130, 7, 7, 131, 7, 11, 132, 7, 8, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 133, 7, 7, 138, 7, 7, 145, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 151, 7, 7, 147, 7, 7, 144, 7, 7, 141, + 7, 7, 137, 7, 7, 132, 7, 7, 134, 7, 7, 138, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 8, 26, 140, 22, 118, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 111, 104, 11, 54, 139, 7, 7, 145, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 9, 42, 136, 20, 105, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 123, 90, 8, 31, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 18, 91, 118, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 8, 143, 7, 10, 140, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 8, 141, + 7, 16, 142, 7, 31, 144, 7, 43, 147, 7, 40, 148, 7, 33, 146, 7, 27, 145, 7, 26, 145, 7, 27, 145, 7, 26, 144, 7, 19, 143, 7, 8, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 8, 135, 7, 9, 133, 7, 11, 133, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 114, 7, 7, 111, 7, 7, 113, 7, 7, 122, 7, 8, 137, 7, 7, 157, 7, 7, 162, 7, 7, 169, + 7, 10, 172, 7, 7, 173, 7, 7, 170, 7, 7, 165, 7, 7, 161, 7, 7, 157, 7, 7, 152, 7, 7, 149, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 8, 142, 7, 7, 139, 7, 7, 138, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 144, + 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 9, 152, 7, 19, 151, 7, 21, 151, 7, 21, 153, 7, 17, 154, 7, 11, 155, 7, 8, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 160, 7, 7, 164, 7, 7, 166, 7, 7, 165, 7, 7, 165, + 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 159, 7, 7, 153, 7, 7, 146, 7, 7, 136, 7, 7, 128, 7, 7, 124, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 109, + 7, 7, 107, 7, 7, 104, 7, 7, 103, 7, 7, 98, 7, 7, 93, 7, 7, 88, 7, 7, 81, 7, 7, 74, 7, 7, 56, 8, 8, 17, 142, 142, 142, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 108, 108, 108, 8, 8, 27, 7, 7, 72, 7, 7, 85, 7, 7, 93, + 7, 7, 101, 7, 7, 105, 7, 7, 109, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 126, + 7, 7, 129, 7, 7, 131, 7, 7, 130, 7, 8, 132, 7, 14, 133, 7, 18, 132, 7, 22, 132, 7, 18, 132, 7, 12, 131, 7, 8, 130, 7, 8, 130, 7, 9, 130, 7, 13, 131, 7, 19, 131, 7, 19, 132, 7, 13, 131, 7, 8, 129, 7, 7, 129, 7, 8, 129, 7, 10, 129, 7, 17, 129, + 7, 32, 131, 7, 34, 129, 7, 9, 121, 7, 7, 122, 7, 7, 130, 7, 7, 129, 7, 11, 131, 7, 14, 132, 7, 9, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 130, 7, 7, 136, 7, 7, 141, 7, 7, 148, 7, 7, 152, + 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 7, 136, 7, 7, 136, 7, 7, 139, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 138, 18, 94, 115, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 86, 123, + 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 7, 139, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 139, 15, 80, 122, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 97, 115, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 143, 7, 8, 143, + 7, 8, 140, 7, 8, 136, 7, 7, 135, 7, 8, 138, 7, 14, 143, 7, 26, 145, 7, 30, 146, 7, 26, 146, 7, 18, 144, 7, 12, 144, 7, 10, 144, 7, 9, 142, 7, 10, 142, 7, 9, 141, 7, 8, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 8, 135, 7, 10, 134, 7, 11, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 129, 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 122, 7, 7, 118, 7, 7, 114, 7, 7, 116, + 7, 7, 125, 7, 7, 144, 7, 7, 158, 7, 7, 164, 7, 9, 170, 7, 9, 173, 7, 7, 173, 7, 7, 171, 7, 7, 166, 7, 7, 160, 7, 7, 155, 7, 7, 149, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 134, 7, 7, 130, 7, 7, 135, + 7, 7, 143, 7, 7, 144, 7, 8, 143, 7, 8, 143, 7, 9, 142, 7, 13, 143, 7, 12, 144, 7, 18, 144, 7, 29, 150, 7, 47, 155, 7, 49, 155, 7, 33, 150, 7, 17, 148, 7, 9, 148, 7, 8, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 156, + 7, 7, 160, 7, 7, 165, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 10, 170, 7, 7, 169, 7, 7, 166, 7, 7, 160, 7, 7, 153, 7, 7, 144, 7, 7, 135, 7, 7, 128, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 116, + 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 104, 7, 7, 102, 7, 7, 98, 7, 7, 94, 7, 7, 89, 7, 7, 82, 7, 7, 75, 7, 7, 61, 7, 7, 22, 111, 111, 111, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 82, 82, 82, 11, 11, 35, 7, 7, 76, 7, 7, 87, 7, 7, 94, 7, 7, 102, 7, 7, 106, 7, 7, 110, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 126, 7, 7, 129, 7, 7, 130, 7, 7, 129, 7, 7, 130, 7, 11, 131, 7, 18, 131, 7, 21, 131, 7, 18, 131, 7, 12, 131, 7, 8, 130, 7, 7, 130, 7, 7, 131, 7, 9, 131, 7, 9, 132, 7, 9, 131, 7, 8, 131, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 8, 129, 7, 11, 130, 7, 21, 130, 7, 44, 134, 7, 17, 126, 7, 8, 123, 7, 7, 129, 7, 7, 130, 7, 13, 132, 7, 13, 132, 7, 9, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 131, 7, 7, 132, 7, 7, 138, 7, 7, 144, 7, 7, 151, 7, 7, 155, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 138, 7, 7, 134, 9, 38, 132, 24, 126, 85, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 86, 122, 7, 7, 143, 7, 7, 144, 7, 7, 146, 7, 7, 145, 7, 7, 140, 7, 7, 135, 7, 7, 136, 7, 8, 138, 7, 8, 141, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 16, 86, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 24, 126, 86, 9, 38, 139, 7, 7, 142, 7, 7, 141, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, + 7, 7, 141, 10, 47, 134, 17, 87, 119, 21, 111, 103, 23, 120, 94, 25, 127, 85, 25, 125, 87, 23, 119, 94, 20, 109, 105, 16, 85, 124, 9, 46, 140, 7, 11, 145, 7, 8, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 8, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 136, 7, 7, 136, 7, 8, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 11, 52, 131, 19, 98, 110, 24, 118, 95, 24, 125, 87, 25, 127, 84, 23, 122, 89, 22, 113, 96, 16, 90, 110, 10, 47, 121, 7, 7, 126, 7, 7, 131, 7, 7, 134, 7, 7, 135, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 11, 135, 7, 14, 135, 7, 11, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 10, 49, 126, 17, 88, 112, 21, 113, 98, 22, 120, 91, 25, 127, 85, 24, 125, 86, 23, 119, 92, 21, 108, 101, 15, 82, 116, 9, 38, 129, 7, 7, 132, 7, 7, 131, + 7, 7, 129, 7, 7, 126, 7, 7, 122, 7, 8, 119, 7, 7, 121, 7, 8, 131, 7, 7, 150, 7, 7, 159, 7, 7, 165, 7, 10, 170, 7, 8, 173, 7, 7, 173, 7, 7, 170, 7, 7, 164, 7, 7, 158, 7, 7, 153, 7, 7, 147, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 142, + 7, 7, 143, 7, 7, 143, 7, 7, 138, 7, 7, 136, 7, 7, 141, 7, 7, 144, 7, 7, 145, 7, 7, 140, 7, 8, 143, 7, 19, 145, 7, 20, 143, 7, 21, 143, 7, 32, 146, 7, 48, 155, 7, 57, 161, 7, 38, 158, 7, 14, 152, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, + 7, 7, 145, 7, 7, 147, 7, 7, 150, 7, 7, 152, 7, 7, 157, 7, 7, 159, 7, 7, 163, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 8, 171, 7, 12, 172, 7, 7, 171, 7, 7, 166, 7, 7, 159, 7, 7, 151, 7, 7, 142, 7, 7, 134, 7, 7, 127, 7, 7, 123, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 104, 7, 7, 103, 7, 7, 99, 7, 7, 94, 7, 7, 90, 7, 7, 83, 7, 7, 76, 7, 7, 65, 9, 9, 28, 83, 83, 83, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 247, 45, 45, 45, 13, 13, 43, 7, 7, 78, 7, 7, 88, 7, 7, 96, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 126, 7, 7, 127, 7, 7, 130, 7, 7, 130, 7, 7, 126, 7, 8, 128, 7, 12, 128, 7, 15, 129, 7, 12, 130, 7, 8, 131, 7, 7, 131, 7, 7, 130, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 8, 130, 7, 10, 130, 7, 26, 132, 7, 15, 129, 7, 9, 127, 7, 7, 129, 7, 7, 130, 7, 12, 131, 7, 10, 130, 7, 9, 131, 7, 8, 131, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 131, 7, 7, 135, 7, 7, 145, 7, 7, 152, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 139, + 7, 7, 133, 18, 96, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 106, 108, 7, 7, 144, 7, 7, 143, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 140, 7, 7, 134, 7, 7, 133, 7, 9, 136, 7, 9, 141, 7, 7, 142, 7, 7, 140, 7, 7, 138, + 7, 7, 136, 7, 8, 136, 13, 64, 128, 14, 69, 130, 14, 69, 128, 14, 69, 128, 14, 69, 130, 14, 69, 131, 9, 39, 140, 7, 7, 144, 7, 7, 143, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 119, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 9, 41, 136, 19, 102, 111, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 84, 18, 99, 114, 9, 39, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, + 7, 7, 141, 7, 7, 142, 7, 7, 139, 7, 7, 137, 7, 7, 138, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 9, 40, 132, 18, 95, 111, 26, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, + 18, 92, 108, 7, 12, 129, 7, 7, 131, 7, 7, 133, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 12, 136, 7, 16, 136, 7, 11, 135, 7, 7, 133, 7, 7, 132, 10, 44, 127, 21, 104, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 24, 126, 85, 17, 93, 112, 8, 28, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 122, 7, 7, 123, 7, 7, 135, 7, 7, 155, 7, 7, 160, 7, 8, 167, 7, 9, 171, 7, 7, 173, 7, 7, 173, 7, 7, 169, 7, 7, 164, 7, 7, 159, 7, 7, 152, + 7, 7, 147, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 145, 7, 7, 147, 7, 9, 137, 7, 13, 142, 7, 39, 148, 7, 20, 144, 7, 23, 145, 7, 28, 150, 7, 25, 156, 7, 14, 160, 7, 9, 162, + 7, 7, 158, 7, 7, 155, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 147, 7, 7, 149, 7, 7, 152, 7, 7, 154, 7, 7, 156, 7, 7, 158, 7, 7, 160, 7, 7, 162, 7, 7, 163, 7, 8, 166, 7, 12, 169, 7, 15, 170, 7, 8, 166, 7, 7, 162, 7, 7, 154, 7, 7, 148, + 7, 7, 141, 7, 7, 133, 7, 7, 127, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 100, 7, 7, 96, 7, 7, 91, + 7, 7, 85, 7, 7, 77, 7, 7, 66, 11, 11, 36, 53, 53, 53, 249, 249, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 243, 243, 243, 22, 22, 22, 8, 8, 51, 7, 7, 80, 7, 7, 90, 7, 7, 97, 7, 7, 104, 7, 7, 109, 7, 7, 112, 7, 7, 115, 7, 7, 116, 7, 7, 118, + 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 125, 7, 7, 127, 7, 7, 128, 7, 7, 129, 7, 7, 126, 7, 8, 125, 7, 8, 126, + 7, 9, 128, 7, 8, 129, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 9, 131, 7, 15, 131, 7, 9, 130, 7, 10, 129, 7, 7, 130, 7, 7, 130, + 7, 9, 130, 7, 9, 131, 7, 11, 131, 7, 9, 130, 7, 8, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 131, 7, 7, 136, 7, 7, 146, 7, 7, 153, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 142, 7, 7, 138, 23, 121, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 9, 42, 139, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 136, + 7, 9, 138, 7, 8, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 8, 136, 7, 9, 137, 7, 8, 140, 7, 7, 140, 7, 7, 139, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 18, 91, 118, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 139, 14, 69, 127, 24, 125, 87, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 24, 125, 88, 13, 67, 125, 7, 7, 136, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 114, 99, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 101, 104, 7, 7, 130, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 11, 136, 7, 13, 135, 7, 10, 134, 7, 7, 133, 13, 72, 120, 24, 126, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 119, 93, 10, 47, 126, 7, 7, 129, 7, 7, 127, 7, 7, 124, 7, 8, 125, 7, 7, 141, 7, 7, 158, 7, 7, 161, 7, 8, 167, 7, 7, 170, 7, 7, 173, + 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 158, 7, 7, 153, 7, 7, 147, 7, 7, 144, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 12, 137, 7, 12, 142, 7, 26, 146, 7, 30, 147, + 7, 20, 146, 7, 10, 150, 7, 13, 160, 7, 10, 169, 7, 7, 172, 7, 7, 167, 7, 7, 160, 7, 7, 154, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 8, 155, 7, 8, 159, 7, 18, 163, + 7, 14, 163, 7, 7, 160, 7, 7, 155, 7, 7, 149, 7, 7, 143, 7, 7, 137, 7, 7, 132, 7, 7, 127, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 108, + 7, 7, 105, 7, 7, 103, 7, 7, 100, 7, 7, 97, 7, 7, 92, 7, 7, 86, 7, 7, 78, 7, 7, 68, 7, 7, 39, 31, 31, 31, 244, 244, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 237, 237, 237, 10, 10, 10, 7, 7, 58, 7, 7, 81, 7, 7, 91, 7, 7, 99, 7, 7, 105, + 7, 7, 110, 7, 7, 112, 7, 7, 115, 7, 7, 116, 7, 7, 118, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 124, 7, 7, 126, + 7, 7, 128, 7, 7, 127, 7, 8, 125, 7, 7, 126, 7, 7, 128, 7, 8, 129, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 8, 131, + 7, 9, 131, 7, 9, 131, 7, 9, 130, 7, 7, 131, 7, 7, 130, 7, 8, 130, 7, 14, 131, 7, 20, 130, 7, 15, 130, 7, 8, 128, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 132, 7, 7, 139, 7, 7, 148, 7, 7, 154, 7, 7, 156, + 7, 7, 150, 7, 7, 147, 7, 7, 147, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 11, 55, 136, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 102, 110, 7, 7, 142, 7, 7, 144, 7, 7, 143, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 8, 139, 7, 7, 139, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 11, 139, 7, 8, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, + 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 15, 81, 122, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 83, 14, 78, 121, 7, 7, 138, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 83, 114, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 8, 135, 7, 10, 136, 7, 13, 135, 7, 8, 134, 15, 82, 117, + 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 123, 89, 10, 49, 125, 7, 7, 127, 7, 7, 124, 7, 7, 128, 7, 7, 148, + 7, 7, 158, 7, 7, 163, 7, 7, 167, 7, 7, 169, 7, 7, 171, 7, 7, 170, 7, 7, 167, 7, 7, 162, 7, 7, 159, 7, 7, 156, 7, 7, 151, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 141, 7, 7, 135, + 7, 7, 138, 7, 11, 140, 7, 13, 143, 7, 10, 143, 7, 32, 146, 7, 24, 148, 7, 8, 153, 7, 8, 164, 7, 7, 169, 7, 7, 169, 7, 7, 171, 7, 7, 165, 7, 7, 160, 7, 7, 156, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 154, + 7, 7, 150, 7, 7, 152, 7, 11, 147, 7, 8, 153, 7, 8, 155, 7, 7, 154, 7, 7, 152, 7, 7, 148, 7, 7, 145, 7, 7, 141, 7, 7, 135, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 115, + 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 104, 7, 7, 101, 7, 7, 97, 7, 7, 93, 7, 7, 87, 7, 7, 79, 7, 7, 70, 7, 7, 46, 10, 10, 10, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 221, 221, 221, 7, 7, 7, + 7, 7, 64, 7, 7, 82, 7, 7, 91, 7, 7, 100, 7, 7, 106, 7, 7, 110, 7, 7, 113, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 127, 7, 7, 126, 7, 7, 120, 7, 8, 125, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 8, 131, 7, 8, 131, 7, 13, 130, 7, 9, 128, 7, 7, 131, 7, 7, 129, 7, 9, 129, 7, 30, 132, 7, 36, 133, 7, 28, 131, 7, 8, 128, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 131, + 7, 7, 133, 7, 7, 141, 7, 7, 150, 7, 7, 156, 7, 7, 155, 7, 7, 151, 7, 7, 147, 7, 7, 146, 7, 7, 148, 7, 7, 151, 7, 7, 152, 7, 8, 154, 7, 7, 155, 7, 7, 154, 7, 7, 152, 17, 89, 124, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 12, 68, 129, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 8, 138, 7, 9, 139, 7, 8, 140, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 14, 139, 7, 10, 138, 7, 8, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 138, 7, 7, 139, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 116, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 13, 64, 130, 25, 128, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 86, 24, 126, 86, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 12, 60, 132, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 140, 23, 119, 93, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 24, 126, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 123, 89, 7, 23, 132, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 11, 135, 7, 12, 135, 12, 63, 124, 25, 128, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 85, 25, 127, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 22, 116, 94, 9, 20, 127, 7, 7, 125, 7, 7, 133, 7, 7, 149, 7, 7, 159, 7, 7, 164, 7, 7, 169, 7, 7, 171, 7, 7, 171, 7, 7, 169, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 153, 7, 7, 150, 7, 7, 151, 7, 7, 148, + 7, 7, 149, 7, 7, 148, 7, 7, 135, 7, 7, 125, 7, 7, 129, 7, 7, 135, 7, 8, 140, 7, 8, 143, 7, 7, 143, 7, 23, 143, 7, 24, 148, 7, 7, 154, 7, 7, 164, 7, 7, 149, 7, 7, 146, 7, 7, 163, 7, 7, 167, 7, 7, 163, 7, 7, 159, 7, 7, 158, 7, 7, 158, + 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 12, 142, 7, 13, 147, 7, 8, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 138, 7, 7, 134, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 102, 7, 7, 98, 7, 7, 93, 7, 7, 88, 7, 7, 81, 7, 7, 71, 7, 7, 52, 7, 7, 7, 229, 229, 229, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 214, 213, 10, 10, 11, 7, 7, 68, 7, 7, 83, 7, 7, 92, 7, 7, 101, 7, 7, 107, 7, 7, 111, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 119, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, + 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 127, 7, 7, 128, 7, 7, 126, 7, 12, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 8, 131, 7, 10, 130, 7, 11, 129, 7, 8, 128, 7, 7, 130, 7, 7, 128, 7, 7, 127, 7, 36, 132, 7, 46, 135, 7, 42, 134, 7, 9, 129, 7, 7, 129, + 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 142, 7, 7, 151, 7, 7, 156, 7, 7, 154, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 147, 7, 7, 147, 7, 8, 151, 7, 8, 154, 7, 8, 155, 7, 7, 156, 7, 7, 154, 20, 100, 116, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 84, 8, 28, 139, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 9, 140, 7, 10, 141, 7, 8, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 139, 7, 14, 140, 7, 14, 139, 7, 8, 137, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 139, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 108, 7, 7, 116, 7, 7, 132, 7, 7, 141, 7, 7, 141, 8, 26, 139, + 24, 123, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 17, 92, 118, 10, 46, 136, 7, 11, 143, 7, 8, 143, 10, 47, 138, 18, 95, 117, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 120, 94, 7, 23, 142, + 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 140, 23, 119, 93, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 117, 96, 13, 65, 124, 7, 18, 135, 7, 7, 134, 10, 49, 128, 19, 97, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 14, 69, 123, 7, 7, 134, 7, 7, 135, 7, 8, 135, 7, 10, 135, 8, 24, 133, 23, 122, 90, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 122, 89, 16, 82, 115, 10, 45, 126, 7, 19, 130, 7, 15, 131, 10, 49, 127, 16, 85, 116, + 25, 123, 89, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 93, 107, 7, 7, 127, 7, 7, 138, 7, 7, 148, 7, 7, 157, 7, 8, 163, 7, 7, 170, 7, 7, 173, 7, 7, 174, 7, 7, 171, 7, 7, 166, 7, 7, 163, 7, 7, 159, 7, 7, 156, 7, 7, 154, + 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 153, 7, 7, 150, 7, 7, 141, 7, 7, 136, 7, 7, 138, 7, 15, 141, 7, 39, 146, 7, 13, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 22, 145, 7, 24, 144, 7, 7, 146, 7, 7, 148, 7, 7, 144, 7, 7, 146, 7, 7, 153, + 7, 7, 165, 7, 7, 163, 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 149, 7, 7, 142, 7, 7, 143, 7, 7, 146, 7, 7, 147, 7, 8, 145, 7, 9, 145, 7, 8, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 134, + 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 102, 7, 7, 99, 7, 7, 94, 7, 7, 89, + 7, 7, 81, 7, 7, 72, 7, 7, 56, 8, 8, 8, 221, 221, 221, 255, 255, 255, 255, 255, 255, 255, 255, 255, 198, 198, 198, 11, 11, 12, 7, 7, 70, 7, 7, 84, 7, 7, 93, 7, 7, 102, 7, 7, 108, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 121, + 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 125, 7, 7, 126, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 14, 131, 7, 8, 130, 7, 7, 131, 7, 7, 130, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 8, 132, 7, 7, 131, 7, 8, 131, 7, 15, 129, 7, 9, 125, 7, 8, 128, 7, 7, 129, 7, 7, 129, 7, 7, 125, + 7, 14, 128, 7, 39, 134, 7, 28, 132, 7, 13, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 133, 7, 7, 140, 7, 7, 150, 7, 7, 155, 7, 7, 152, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 8, 145, + 7, 8, 151, 7, 9, 153, 7, 8, 155, 7, 7, 153, 21, 109, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 119, 95, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 143, 7, 9, 143, 7, 8, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 10, 139, 7, 14, 138, 7, 8, 138, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 92, 113, + 7, 9, 121, 7, 9, 121, 7, 7, 139, 7, 7, 140, 18, 92, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 120, 93, 12, 60, 135, 7, 7, 141, 7, 8, 139, 7, 11, 141, 7, 8, 140, 7, 7, 144, 7, 7, 144, 13, 65, 131, 24, 122, 91, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 86, 122, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, 23, 119, 93, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 115, 97, 10, 33, 133, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 18, 91, 112, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 94, 111, 7, 7, 134, 7, 8, 135, 7, 8, 135, 7, 9, 135, 17, 88, 115, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 112, 99, 8, 23, 132, 7, 7, 131, + 7, 7, 130, 7, 7, 129, 7, 8, 130, 7, 8, 131, 7, 8, 132, 8, 30, 132, 22, 114, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 125, 86, 8, 32, 129, 7, 7, 137, 7, 7, 146, 7, 7, 154, 7, 7, 159, 7, 7, 168, 7, 7, 173, 7, 7, 174, 7, 7, 171, + 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 146, 7, 7, 146, 7, 11, 149, 7, 31, 152, 7, 45, 157, 7, 22, 150, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 17, 149, 7, 19, 148, + 7, 7, 145, 7, 7, 146, 7, 7, 150, 7, 7, 154, 7, 7, 157, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 158, 7, 7, 154, 7, 7, 149, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 8, 145, 7, 9, 144, 7, 7, 143, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 109, + 7, 7, 107, 7, 7, 104, 7, 7, 100, 7, 7, 95, 7, 7, 90, 7, 7, 82, 7, 7, 73, 7, 7, 57, 9, 9, 10, 201, 201, 201, 255, 255, 255, 255, 255, 255, 255, 255, 255, 181, 181, 181, 13, 13, 15, 7, 7, 72, 7, 7, 85, 7, 7, 94, 7, 7, 103, 7, 7, 108, 7, 7, 112, + 7, 7, 115, 7, 7, 117, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 126, 7, 7, 128, 7, 7, 131, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 11, 132, 7, 12, 132, 7, 9, 131, 7, 16, 130, 7, 12, 125, + 7, 9, 123, 7, 7, 127, 7, 7, 128, 7, 7, 130, 7, 7, 124, 7, 8, 128, 7, 17, 132, 7, 13, 131, 7, 10, 130, 7, 8, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 134, 7, 7, 140, 7, 7, 148, 7, 7, 151, 7, 7, 150, 7, 7, 144, + 7, 7, 139, 7, 7, 136, 7, 7, 137, 7, 9, 138, 7, 8, 143, 7, 13, 147, 7, 9, 150, 7, 7, 154, 7, 7, 152, 22, 115, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 113, 100, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 137, 7, 7, 141, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 8, 139, 7, 11, 139, 7, 7, 138, 7, 8, 139, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 23, 119, 95, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 95, 120, 7, 15, 132, 7, 8, 125, 7, 7, 140, 7, 17, 140, 24, 125, 88, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 10, 49, 137, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 12, 140, 7, 9, 141, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 12, 58, 133, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 122, 92, 7, 7, 138, 7, 7, 137, 7, 7, 134, 7, 7, 134, 23, 119, 93, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 84, 10, 47, 132, + 7, 8, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 8, 25, 132, 24, 126, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 105, 105, 7, 7, 136, 7, 10, 135, 7, 7, 135, 7, 18, 135, 23, 123, 89, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 23, 120, 92, 10, 33, 129, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 8, 131, 7, 7, 133, 7, 7, 133, 9, 39, 130, 24, 123, 89, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 88, 114, 7, 7, 136, 7, 7, 142, 7, 7, 149, + 7, 8, 154, 7, 8, 164, 7, 8, 170, 7, 7, 171, 7, 7, 171, 7, 7, 167, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 8, 154, 7, 9, 154, 7, 16, 156, 7, 30, 157, 7, 25, 157, 7, 11, 154, 7, 7, 153, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 11, 153, 7, 14, 152, 7, 8, 151, 7, 7, 151, 7, 7, 155, 7, 7, 159, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 8, 154, 7, 8, 150, 7, 7, 149, + 7, 8, 146, 7, 8, 145, 7, 19, 146, 7, 30, 147, 7, 10, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, + 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 105, 7, 7, 101, 7, 7, 96, 7, 7, 91, 7, 7, 83, 7, 7, 74, 7, 7, 59, 11, 11, 12, 181, 181, 181, 255, 255, 255, 255, 255, 255, 255, 255, 255, 154, 154, 154, 13, 13, 18, 7, 7, 74, + 7, 7, 87, 7, 7, 95, 7, 7, 104, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, + 7, 7, 124, 7, 7, 126, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 10, 132, 7, 22, 133, + 7, 18, 131, 7, 15, 130, 7, 26, 129, 7, 14, 124, 7, 10, 120, 7, 7, 124, 7, 7, 126, 7, 7, 127, 7, 7, 129, 7, 7, 127, 7, 7, 129, 7, 7, 131, 7, 9, 131, 7, 9, 130, 7, 9, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 133, + 7, 7, 141, 7, 7, 146, 7, 7, 149, 7, 7, 147, 7, 7, 142, 7, 7, 136, 7, 7, 133, 7, 8, 133, 7, 8, 136, 7, 13, 142, 7, 10, 145, 7, 9, 146, 7, 7, 151, 7, 7, 150, 22, 113, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 114, 100, 7, 7, 138, + 7, 7, 137, 7, 7, 138, 7, 7, 136, 7, 7, 137, 7, 7, 142, 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 138, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 9, 138, 7, 10, 138, 7, 13, 138, 7, 13, 140, + 7, 11, 139, 7, 8, 137, 7, 7, 138, 7, 7, 140, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 117, 7, 9, 137, 7, 7, 130, 7, 7, 140, 13, 68, 128, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 91, 118, 7, 7, 144, + 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 10, 142, 7, 8, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 141, 19, 98, 111, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 11, 57, 126, 7, 7, 134, 7, 7, 135, 7, 7, 135, 23, 119, 93, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 114, 98, 7, 8, 137, 7, 8, 137, 7, 8, 136, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 21, 112, 98, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 114, 98, 7, 12, 136, 7, 11, 136, 7, 7, 136, + 12, 62, 127, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 83, 116, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 132, 18, 92, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 21, 112, 99, 7, 7, 134, 7, 7, 137, 7, 7, 142, 7, 8, 147, 7, 8, 159, 7, 8, 166, 7, 7, 169, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 8, 159, 7, 11, 157, 7, 15, 159, 7, 14, 158, + 7, 8, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 11, 156, 7, 10, 155, 7, 7, 155, 7, 7, 156, 7, 7, 159, 7, 7, 163, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 165, 7, 7, 165, + 7, 7, 164, 7, 8, 161, 7, 7, 156, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 18, 146, 7, 19, 145, 7, 8, 142, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, + 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 102, 7, 7, 97, 7, 7, 92, 7, 7, 84, 7, 7, 75, 7, 7, 61, 11, 11, 15, 164, 164, 164, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 138, 138, 138, 11, 11, 21, 7, 7, 76, 7, 7, 88, 7, 7, 96, 7, 7, 105, 7, 7, 110, 7, 7, 114, 7, 7, 117, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 127, 7, 7, 129, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 8, 130, 7, 8, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 8, 131, 7, 10, 131, + 7, 15, 130, 7, 22, 131, 7, 25, 131, 7, 23, 132, 7, 18, 130, 7, 28, 129, 7, 35, 126, 7, 16, 119, 7, 11, 115, 7, 7, 120, 7, 7, 125, 7, 7, 124, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 131, 7, 8, 130, 7, 8, 131, 7, 10, 131, + 7, 8, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 134, 7, 7, 139, 7, 7, 146, 7, 7, 149, 7, 7, 147, 7, 7, 142, 7, 7, 137, 7, 7, 134, 7, 7, 135, 7, 10, 137, 7, 9, 140, 7, 9, 140, 7, 7, 142, 7, 7, 146, 7, 7, 147, 21, 106, 110, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 121, 93, 7, 8, 138, 7, 8, 138, 7, 8, 139, 7, 7, 138, 7, 7, 139, 7, 7, 142, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 138, 7, 7, 134, 7, 7, 135, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 140, + 7, 7, 138, 7, 7, 137, 7, 12, 138, 7, 18, 139, 7, 16, 140, 7, 11, 136, 7, 8, 133, 7, 7, 135, 7, 7, 137, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 118, 7, 8, 139, 7, 7, 136, 7, 7, 140, 18, 96, 114, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 24, 126, 86, 9, 20, 141, 7, 7, 143, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 8, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 140, 9, 37, 136, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 90, 114, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 23, 119, 93, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 102, 108, 7, 9, 137, 7, 8, 136, 7, 8, 136, 7, 8, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 19, 102, 106, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 23, 115, 97, 7, 8, 136, 7, 7, 136, 7, 7, 135, 17, 93, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 85, 8, 30, 128, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 10, 46, 128, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 85, 9, 20, 131, 7, 7, 133, 7, 7, 138, 7, 7, 142, 7, 10, 153, 7, 8, 162, 7, 8, 168, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 161, + 7, 7, 162, 7, 8, 161, 7, 8, 160, 7, 8, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 9, 158, 7, 9, 158, 7, 7, 158, 7, 8, 159, 7, 8, 162, 7, 8, 166, 7, 9, 168, 7, 9, 166, + 7, 8, 165, 7, 7, 165, 7, 7, 165, 7, 7, 167, 7, 7, 168, 7, 7, 166, 7, 7, 162, 7, 7, 156, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 11, 146, 7, 10, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, + 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 103, 7, 7, 99, 7, 7, 93, 7, 7, 85, + 7, 7, 76, 7, 7, 62, 7, 7, 17, 139, 139, 140, 255, 255, 255, 255, 255, 255, 255, 255, 255, 122, 122, 122, 9, 9, 25, 7, 7, 77, 7, 7, 90, 7, 7, 97, 7, 7, 106, 7, 7, 111, 7, 7, 115, 7, 7, 118, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, + 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 127, 7, 7, 130, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 12, 130, 7, 11, 130, + 7, 8, 130, 7, 8, 131, 7, 9, 131, 7, 15, 132, 7, 20, 132, 7, 22, 131, 7, 26, 131, 7, 19, 129, 7, 20, 128, 7, 34, 128, 7, 32, 122, 7, 17, 113, 7, 9, 110, 7, 7, 116, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 127, 7, 7, 129, 7, 7, 128, + 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 8, 131, 7, 15, 132, 7, 17, 133, 7, 14, 132, 7, 9, 131, 7, 8, 132, 7, 9, 133, 7, 9, 139, 7, 10, 144, 7, 10, 147, 7, 8, 147, 7, 7, 143, 7, 7, 140, 7, 7, 137, 7, 8, 138, 7, 8, 140, 7, 8, 139, 7, 7, 137, + 7, 7, 138, 7, 7, 137, 7, 7, 140, 19, 99, 115, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 84, 8, 35, 140, 7, 9, 140, 7, 8, 141, 7, 8, 141, 7, 7, 141, 7, 8, 140, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 139, 7, 7, 137, 7, 7, 132, + 7, 7, 133, 7, 7, 136, 7, 7, 141, 7, 7, 142, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 9, 138, 7, 11, 139, 7, 9, 139, 7, 7, 135, 7, 7, 131, 7, 7, 133, 7, 7, 136, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 117, 7, 7, 139, + 7, 7, 139, 7, 7, 141, 20, 108, 107, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 110, 105, 7, 7, 142, 7, 7, 143, 7, 7, 146, 7, 7, 143, 7, 7, 140, 7, 8, 140, 7, 7, 141, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 23, 115, 97, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 101, 108, 7, 7, 135, 7, 7, 136, 7, 7, 136, 23, 119, 93, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 94, 112, 7, 8, 136, 7, 8, 137, 7, 8, 137, 7, 7, 136, 7, 8, 136, 7, 7, 136, 7, 8, 136, + 7, 13, 135, 18, 96, 111, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 117, 95, 7, 7, 136, 7, 7, 136, 7, 7, 136, 20, 105, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 10, 49, 126, 7, 7, 133, 7, 7, 136, 7, 7, 141, 7, 9, 146, 7, 13, 160, 7, 8, 169, 7, 9, 173, 7, 8, 174, + 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 8, 160, 7, 7, 160, + 7, 7, 161, 7, 8, 164, 7, 10, 167, 7, 11, 169, 7, 11, 167, 7, 9, 165, 7, 8, 165, 7, 8, 166, 7, 7, 170, 7, 7, 170, 7, 7, 167, 7, 7, 161, 7, 7, 157, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 143, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 112, + 7, 7, 108, 7, 7, 105, 7, 7, 100, 7, 7, 95, 7, 7, 86, 7, 7, 77, 7, 7, 64, 7, 7, 19, 124, 124, 124, 255, 255, 255, 255, 255, 255, 255, 255, 255, 106, 106, 106, 7, 7, 28, 7, 7, 79, 7, 7, 91, 7, 7, 99, 7, 7, 107, 7, 7, 112, 7, 7, 116, 7, 7, 118, + 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 127, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 132, 7, 7, 131, + 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 10, 130, 7, 14, 130, 7, 14, 132, 7, 12, 131, 7, 12, 132, 7, 12, 132, 7, 9, 131, 7, 8, 130, 7, 13, 129, 7, 27, 128, 7, 28, 125, 7, 19, 119, 7, 11, 111, 7, 9, 108, 7, 7, 112, 7, 7, 124, 7, 7, 126, 7, 7, 125, + 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 127, 7, 7, 129, 7, 8, 129, 7, 8, 130, 7, 10, 131, 7, 18, 132, 7, 27, 133, 7, 29, 134, 7, 27, 133, 7, 27, 137, 7, 26, 139, 7, 19, 142, 7, 10, 145, 7, 7, 146, 7, 7, 145, 7, 7, 143, + 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 133, 16, 86, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 14, 77, 130, 7, 16, 144, 7, 14, 144, 7, 11, 142, 7, 9, 141, 7, 7, 139, 7, 7, 140, + 7, 7, 136, 7, 7, 134, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 136, 7, 7, 138, 23, 119, 94, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 117, 7, 7, 138, 7, 7, 141, 7, 7, 142, 22, 114, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 100, 111, 7, 7, 142, 7, 7, 143, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 8, 138, 7, 7, 140, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 19, 105, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 108, 103, 7, 7, 136, 7, 7, 136, 7, 7, 136, 23, 119, 93, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 92, 112, 7, 9, 136, 7, 8, 136, + 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 9, 136, 7, 20, 137, 17, 96, 115, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 94, 7, 7, 135, 7, 7, 136, 7, 7, 135, 21, 113, 99, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 133, 7, 7, 137, 7, 7, 143, + 7, 9, 141, 7, 12, 153, 7, 19, 167, 7, 10, 174, 7, 8, 175, 7, 9, 174, 7, 9, 170, 7, 8, 166, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, + 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 163, 7, 8, 162, 7, 8, 163, 7, 8, 163, 7, 10, 164, 7, 10, 164, 7, 9, 164, 7, 8, 163, 7, 7, 163, 7, 7, 165, 7, 7, 167, 7, 7, 166, 7, 7, 163, 7, 7, 159, 7, 7, 155, 7, 7, 153, 7, 7, 150, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, + 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 112, 7, 7, 110, 7, 7, 106, 7, 7, 101, 7, 7, 96, 7, 7, 87, 7, 7, 78, 7, 7, 66, 7, 7, 22, 114, 114, 114, 255, 255, 255, 255, 255, 255, 255, 255, 255, 99, 99, 99, 7, 7, 32, 7, 7, 80, 7, 7, 93, + 7, 7, 100, 7, 7, 108, 7, 7, 113, 7, 7, 117, 7, 7, 119, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, + 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 127, 7, 7, 128, 7, 8, 128, 7, 8, 129, 7, 9, 130, 7, 10, 130, 7, 12, 131, 7, 13, 131, 7, 12, 130, 7, 12, 129, 7, 11, 129, 7, 10, 126, 7, 9, 123, 7, 8, 118, 7, 7, 113, + 7, 7, 117, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 129, 7, 7, 129, 7, 7, 126, 7, 7, 124, 7, 7, 126, 7, 8, 126, 7, 9, 125, 7, 13, 127, 7, 11, 126, 7, 12, 127, 7, 12, 128, 7, 11, 131, 7, 12, 133, + 7, 10, 138, 7, 8, 142, 7, 8, 144, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 138, 7, 7, 134, 7, 7, 129, 7, 7, 126, 7, 7, 127, 10, 47, 125, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 110, 104, 7, 12, 137, + 7, 9, 138, 7, 9, 138, 7, 7, 138, 7, 7, 137, 7, 7, 139, 7, 7, 135, 7, 7, 132, 7, 7, 135, 7, 7, 138, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 8, 139, 7, 7, 140, 7, 7, 141, + 7, 7, 139, 7, 7, 140, 7, 7, 141, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 116, 7, 7, 139, 7, 7, 143, 7, 7, 143, 22, 114, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 105, 108, 7, 7, 141, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 139, 19, 106, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 110, 102, 7, 7, 136, 7, 7, 137, 7, 7, 137, 23, 119, 93, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 18, 92, 112, 7, 8, 133, 7, 7, 136, 7, 8, 137, 7, 7, 137, 7, 7, 136, 7, 7, 137, 7, 8, 136, 7, 8, 136, 17, 92, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 94, 7, 7, 136, 7, 7, 135, 7, 7, 135, 22, 116, 96, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 13, 72, 121, 7, 7, 135, 7, 7, 141, 7, 7, 149, 7, 7, 149, 7, 9, 144, 7, 13, 155, 7, 22, 168, 7, 20, 172, 7, 14, 172, 7, 9, 171, 7, 8, 169, 7, 8, 170, 7, 7, 171, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 166, + 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 161, 7, 8, 159, 7, 7, 158, 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 159, 7, 7, 157, + 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 125, + 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 107, 7, 7, 103, 7, 7, 97, 7, 7, 88, 7, 7, 79, 7, 7, 67, 7, 7, 25, 106, 106, 106, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 89, 89, 89, 7, 7, 34, 7, 7, 81, 7, 7, 94, 7, 7, 101, 7, 7, 109, 7, 7, 114, 7, 7, 117, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, + 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 124, 7, 7, 121, 7, 8, 120, 7, 10, 121, 7, 10, 124, 7, 11, 125, 7, 10, 127, 7, 9, 128, 7, 8, 128, 7, 8, 129, + 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 122, 7, 7, 123, 7, 7, 127, 7, 7, 126, 7, 7, 127, 7, 7, 127, 7, 7, 127, 7, 7, 127, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 127, 7, 7, 122, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 11, 114, + 7, 12, 115, 7, 14, 116, 7, 17, 119, 7, 20, 122, 7, 14, 129, 7, 9, 133, 7, 7, 138, 7, 7, 139, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 135, 7, 7, 131, 7, 7, 127, 7, 7, 124, 7, 7, 124, 7, 7, 126, 23, 119, 94, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 59, 119, 7, 7, 127, 7, 7, 127, 7, 7, 130, 7, 7, 136, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 137, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 142, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 141, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 117, 7, 7, 142, 7, 7, 144, 7, 7, 145, 20, 108, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 24, 118, 96, 7, 7, 140, 7, 7, 143, 7, 7, 145, 7, 7, 145, 7, 8, 141, 7, 8, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 21, 115, 98, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 103, 107, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 23, 119, 93, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 110, 7, 7, 130, 7, 7, 134, 7, 8, 135, 7, 8, 136, 7, 7, 137, 7, 8, 136, 7, 9, 135, 7, 11, 134, 17, 92, 112, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 23, 118, 94, 7, 7, 136, 7, 7, 135, 7, 7, 134, 22, 110, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 64, 125, 7, 7, 138, 7, 7, 147, 7, 7, 159, 7, 7, 163, 7, 7, 147, 7, 9, 140, 7, 12, 149, 7, 13, 158, 7, 11, 162, 7, 9, 166, 7, 8, 168, 7, 9, 171, 7, 7, 172, 7, 8, 170, + 7, 7, 168, 7, 7, 167, 7, 7, 170, 7, 7, 169, 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 166, 7, 7, 168, 7, 7, 169, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 8, 157, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 112, 7, 7, 108, 7, 7, 104, 7, 7, 98, 7, 7, 89, 7, 7, 80, + 7, 7, 68, 7, 7, 28, 92, 92, 92, 255, 255, 255, 255, 255, 255, 255, 255, 255, 88, 88, 88, 7, 7, 37, 7, 7, 82, 7, 7, 95, 7, 7, 102, 7, 7, 110, 7, 7, 114, 7, 7, 118, 7, 7, 120, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 129, + 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 126, 7, 7, 115, 7, 7, 110, 7, 7, 112, 7, 10, 115, + 7, 9, 118, 7, 9, 122, 7, 8, 125, 7, 7, 127, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 127, 7, 7, 127, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 128, 7, 7, 127, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 126, + 7, 7, 125, 7, 7, 118, 7, 7, 110, 7, 7, 105, 7, 7, 105, 7, 8, 106, 7, 12, 107, 7, 11, 109, 7, 9, 113, 7, 9, 122, 7, 8, 130, 7, 8, 134, 7, 7, 136, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 128, 7, 7, 126, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 17, 92, 106, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 116, 91, 9, 20, 129, 7, 7, 143, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 144, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 141, + 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 139, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 120, 7, 7, 145, 7, 7, 148, + 7, 7, 148, 19, 97, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 84, 8, 28, 139, 7, 7, 141, 7, 7, 144, 7, 7, 146, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 10, 33, 139, 25, 128, 83, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 94, 114, 7, 7, 137, 7, 7, 138, 7, 7, 138, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 114, 7, 7, 131, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 8, 134, 7, 8, 133, 7, 8, 131, 7, 8, 128, + 17, 92, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 93, 7, 7, 134, 7, 7, 135, 7, 7, 134, 19, 101, 106, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 109, 99, 21, 109, 100, 21, 109, 101, 21, 109, 101, 21, 109, 101, 21, 109, 101, + 21, 109, 101, 21, 109, 100, 21, 109, 100, 21, 109, 100, 21, 109, 100, 21, 109, 99, 21, 109, 98, 21, 109, 98, 21, 109, 98, 21, 109, 100, 21, 109, 100, 9, 44, 127, 7, 7, 131, 7, 7, 135, 7, 7, 160, 7, 7, 177, 7, 7, 173, 7, 7, 142, 7, 7, 132, 7, 7, 138, 7, 8, 147, + 7, 7, 154, 7, 7, 159, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 169, 7, 7, 170, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 172, 7, 7, 173, 7, 7, 172, 7, 7, 167, 7, 7, 165, 7, 7, 162, + 7, 7, 158, 7, 7, 152, 7, 7, 148, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 117, 7, 7, 113, + 7, 7, 109, 7, 7, 104, 7, 7, 99, 7, 7, 90, 7, 7, 81, 7, 7, 69, 7, 7, 31, 89, 89, 89, 255, 255, 255, 255, 255, 255, 255, 255, 255, 79, 79, 79, 7, 7, 39, 7, 7, 83, 7, 7, 96, 7, 7, 103, 7, 7, 111, 7, 7, 115, 7, 7, 119, 7, 7, 122, 7, 7, 124, + 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, + 7, 7, 131, 7, 7, 126, 7, 7, 111, 7, 7, 104, 7, 7, 105, 7, 7, 109, 7, 7, 116, 7, 7, 121, 7, 7, 127, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 123, 7, 7, 112, 7, 7, 103, 7, 7, 96, 7, 7, 97, 7, 7, 98, 7, 7, 105, 7, 7, 117, 7, 7, 125, 7, 7, 131, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, + 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 127, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 123, 8, 29, 121, 24, 124, 86, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 102, 121, 7, 18, 161, 7, 7, 159, 7, 7, 155, 7, 7, 153, 7, 7, 149, + 7, 7, 146, 7, 7, 143, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 141, 7, 7, 143, 19, 98, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, 11, 52, 136, 7, 7, 141, 7, 7, 142, 23, 119, 95, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 18, 91, 122, 7, 7, 149, 7, 7, 151, 7, 7, 151, 14, 69, 136, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 94, 118, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 141, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 19, 97, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 128, 7, 7, 138, 7, 7, 139, 7, 7, 140, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 116, 7, 7, 137, 7, 7, 133, 7, 7, 129, + 7, 7, 127, 7, 7, 127, 7, 7, 125, 7, 7, 123, 7, 7, 119, 17, 92, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 94, 7, 7, 135, 7, 7, 134, 7, 7, 133, 16, 80, 117, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 72, 119, + 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 126, 7, 7, 127, 7, 7, 127, 7, 7, 127, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 137, 7, 7, 167, + 7, 7, 183, 7, 7, 182, 7, 7, 157, 7, 7, 138, 7, 7, 134, 7, 7, 138, 7, 7, 141, 7, 7, 149, 7, 7, 154, 7, 7, 163, 7, 7, 167, 7, 7, 171, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 173, 7, 7, 176, + 7, 7, 176, 7, 7, 174, 7, 7, 170, 7, 7, 166, 7, 7, 161, 7, 7, 154, 7, 7, 148, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 144, 7, 7, 146, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, + 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 118, 7, 7, 114, 7, 7, 110, 7, 7, 105, 7, 7, 100, 7, 7, 90, 7, 7, 82, 7, 7, 69, 7, 7, 32, 89, 89, 89, 255, 255, 255, 255, 255, 255, 255, 255, 255, 79, 79, 79, 8, 8, 43, 7, 7, 85, 7, 7, 97, 7, 7, 104, + 7, 7, 113, 7, 7, 117, 7, 7, 120, 7, 7, 123, 7, 7, 126, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 126, 7, 7, 125, 7, 7, 126, 7, 7, 127, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 122, 7, 7, 128, + 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 128, 7, 7, 127, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 17, 89, 107, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 20, 105, 119, 9, 20, 161, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 151, 7, 7, 148, 7, 7, 143, 7, 7, 140, 7, 7, 139, 7, 7, 141, 7, 17, 143, 20, 101, 114, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 105, 112, 7, 7, 146, + 7, 7, 144, 7, 7, 145, 23, 119, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 126, 7, 7, 153, 7, 7, 154, 7, 7, 152, 7, 23, 150, 24, 125, 90, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 10, 49, 137, 7, 7, 143, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 11, 56, 132, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 123, 90, 7, 18, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 18, 91, 116, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 131, 7, 7, 128, 7, 7, 126, 7, 7, 124, 17, 92, 106, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 94, 7, 7, 135, 7, 7, 134, 7, 7, 132, 10, 33, 128, 26, 128, 83, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 113, 97, 7, 20, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 12, 126, 10, 45, 122, 10, 45, 122, 10, 45, 122, 10, 45, 122, 10, 45, 122, 9, 37, 124, + 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 125, 7, 7, 136, 7, 7, 166, 7, 7, 185, 7, 7, 179, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 166, 7, 7, 168, 7, 7, 169, 7, 7, 166, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 168, 7, 7, 165, + 7, 7, 166, 7, 7, 168, 7, 7, 171, 7, 7, 173, 7, 7, 176, 7, 7, 176, 7, 7, 174, 7, 7, 170, 7, 7, 165, 7, 7, 159, 7, 7, 154, 7, 7, 149, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, + 7, 7, 144, 7, 7, 145, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 114, 7, 7, 111, 7, 7, 105, 7, 7, 100, 7, 7, 91, 7, 7, 82, 7, 7, 70, 7, 7, 33, 79, 79, 79, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 80, 80, 79, 9, 9, 45, 7, 7, 86, 7, 7, 99, 7, 7, 106, 7, 7, 114, 7, 7, 118, 7, 7, 122, 7, 7, 124, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, + 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 127, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 127, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 23, 122, 22, 114, 101, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 120, 100, 13, 72, 145, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 153, 7, 7, 150, 7, 7, 147, 7, 7, 147, 12, 58, 138, 22, 117, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 24, 125, 91, 10, 45, 151, 7, 7, 155, 7, 7, 152, 7, 7, 152, 23, 119, 98, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 128, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 17, 93, 124, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 23, 120, 94, 12, 58, 136, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, 12, 63, 130, 23, 122, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 88, 118, 7, 7, 139, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 116, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 17, 92, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 93, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 19, 102, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 104, 104, 7, 12, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 20, 128, 20, 105, 100, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 92, 107, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 128, 7, 7, 163, 7, 7, 185, 7, 7, 180, 7, 7, 176, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 166, + 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 166, 7, 7, 169, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 170, 7, 7, 166, 7, 7, 161, 7, 7, 158, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 115, 7, 7, 111, 7, 7, 106, 7, 7, 101, 7, 7, 92, 7, 7, 83, 7, 7, 71, + 8, 8, 36, 79, 79, 79, 255, 255, 255, 255, 255, 255, 251, 251, 251, 74, 74, 74, 10, 10, 46, 7, 7, 87, 7, 7, 100, 7, 7, 108, 7, 7, 116, 7, 7, 120, 7, 7, 124, 7, 7, 126, 7, 7, 129, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 9, 41, 132, 24, 123, 98, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 121, 98, 19, 97, 128, 16, 83, 138, 13, 72, 143, 16, 79, 138, 17, 91, 128, 23, 115, 103, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 14, 76, 147, 7, 7, 166, 7, 7, 162, 7, 7, 161, 7, 7, 161, 23, 119, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 129, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 154, 8, 29, 151, 24, 123, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 18, 91, 121, 9, 39, 141, 7, 7, 144, 7, 7, 144, 10, 43, 139, 17, 94, 118, 26, 128, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 24, 121, 92, 9, 20, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 23, 119, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 117, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 17, 92, 113, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 93, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 9, 41, 128, 24, 126, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 119, 92, 15, 81, 118, 9, 42, 129, 7, 7, 132, 7, 7, 132, + 9, 20, 130, 13, 72, 119, 22, 116, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 125, 86, 9, 38, 121, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 128, 7, 7, 158, 7, 7, 179, 7, 7, 182, + 7, 7, 182, 7, 7, 180, 7, 7, 176, 7, 7, 172, 7, 7, 167, 7, 7, 163, 7, 7, 160, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 161, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 160, 7, 7, 157, + 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 115, 7, 7, 111, + 7, 7, 106, 7, 7, 102, 7, 7, 93, 7, 7, 84, 7, 7, 72, 9, 9, 38, 73, 73, 73, 251, 251, 251, 255, 255, 255, 248, 248, 248, 69, 69, 70, 11, 11, 49, 7, 7, 89, 7, 7, 102, 7, 7, 110, 7, 7, 118, 7, 7, 122, 7, 7, 125, 7, 7, 129, 7, 7, 131, 7, 7, 133, + 7, 7, 135, 7, 7, 136, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, + 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 129, 12, 59, 155, 24, 124, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 89, 145, 7, 7, 176, 7, 7, 172, 7, 7, 169, 7, 7, 166, 7, 7, 165, 23, 119, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 18, 91, 129, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 13, 66, 140, 26, 128, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 125, 88, 24, 125, 88, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 12, 60, 131, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 117, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 17, 92, 114, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 93, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 15, 79, 117, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 85, 24, 124, 88, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 15, 78, 113, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 130, 7, 7, 139, 7, 7, 149, 7, 7, 163, 7, 7, 178, 7, 7, 178, 7, 7, 171, 7, 7, 165, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 159, 7, 7, 162, 7, 7, 160, + 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, + 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 115, 7, 7, 111, 7, 7, 107, 7, 7, 102, 7, 7, 93, 7, 7, 85, 7, 7, 73, 10, 10, 39, 69, 69, 69, 248, 248, 248, 255, 255, 255, 241, 241, 241, 60, 60, 61, 12, 12, 52, 7, 7, 90, 7, 7, 104, 7, 7, 111, 7, 7, 119, + 7, 7, 124, 7, 7, 128, 7, 7, 130, 7, 7, 133, 7, 7, 135, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 127, 7, 7, 127, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 142, 10, 47, 170, 23, 118, 107, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 85, 17, 87, 147, 7, 7, 180, 7, 7, 180, 7, 7, 176, 7, 7, 172, 7, 7, 168, + 7, 7, 167, 23, 119, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 129, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 16, 82, 131, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 15, 74, 127, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 18, 91, 117, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 17, 92, 114, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 94, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 18, 91, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 92, 107, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 125, 7, 7, 143, 7, 7, 177, 7, 7, 174, 7, 7, 167, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 158, + 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 115, 7, 7, 111, 7, 7, 107, 7, 7, 102, 7, 7, 94, 7, 7, 86, 7, 7, 73, 11, 11, 42, 67, 67, 67, 245, 245, 245, 255, 255, 255, 239, 239, 239, 58, 58, 59, + 12, 12, 54, 7, 7, 91, 7, 7, 105, 7, 7, 112, 7, 7, 120, 7, 7, 124, 7, 7, 129, 7, 7, 132, 7, 7, 135, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 127, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 124, + 7, 7, 146, 8, 31, 170, 20, 100, 135, 25, 128, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 120, 102, 13, 65, 160, 7, 7, 179, + 7, 7, 181, 7, 7, 180, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 166, 23, 119, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 128, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 14, 71, 137, 25, 125, 88, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 123, 90, 13, 64, 132, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 116, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 17, 92, 114, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 94, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 14, 78, 119, 24, 126, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, + 17, 87, 110, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 129, 7, 7, 173, 7, 7, 176, 7, 7, 169, + 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, + 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 114, 7, 7, 111, 7, 7, 107, 7, 7, 102, 7, 7, 94, 7, 7, 86, 7, 7, 74, 11, 11, 43, + 58, 58, 58, 239, 239, 239, 255, 255, 255, 239, 239, 239, 59, 59, 59, 13, 13, 56, 7, 7, 92, 7, 7, 106, 7, 7, 112, 7, 7, 120, 7, 7, 125, 7, 7, 129, 7, 7, 133, 7, 7, 136, 7, 7, 138, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, + 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 127, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 133, 7, 7, 159, 11, 52, 173, 21, 107, 131, 25, 128, 86, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 23, 121, 100, 17, 88, 144, 7, 23, 176, 7, 7, 179, 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 175, 7, 7, 171, 7, 7, 167, 7, 7, 164, 23, 119, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 127, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 10, 45, 146, 19, 102, 114, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 19, 97, 115, 9, 38, 140, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 116, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 17, 92, 115, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 94, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 10, 47, 129, 19, 103, 106, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 113, 95, 11, 56, 120, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 122, 7, 7, 129, 7, 7, 173, 7, 7, 176, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 157, + 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 114, 7, 7, 111, 7, 7, 107, + 7, 7, 102, 7, 7, 94, 7, 7, 87, 7, 7, 75, 11, 11, 46, 58, 58, 59, 239, 239, 239, 255, 255, 255, 239, 239, 239, 59, 59, 59, 13, 13, 57, 7, 7, 92, 7, 7, 106, 7, 7, 112, 7, 7, 120, 7, 7, 125, 7, 7, 130, 7, 7, 133, 7, 7, 137, 7, 7, 139, 7, 7, 141, + 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 126, 7, 7, 143, 7, 7, 177, 8, 31, 184, 15, 79, 160, 20, 105, 132, 23, 115, 116, 23, 122, 102, 25, 127, 87, + 24, 126, 89, 23, 122, 99, 22, 113, 115, 18, 96, 136, 13, 67, 157, 7, 18, 175, 7, 7, 177, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 179, 7, 7, 176, 7, 7, 173, 7, 7, 169, 7, 7, 165, 7, 7, 159, 7, 7, 155, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 149, + 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 10, 46, 143, 17, 88, 125, 21, 111, 106, 22, 120, 95, 24, 126, 86, 24, 126, 87, 23, 120, 95, 20, 109, 107, 16, 85, 126, 9, 42, 141, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 10, 47, 129, 16, 86, 116, + 22, 110, 102, 23, 120, 91, 24, 125, 86, 25, 127, 84, 23, 122, 90, 21, 115, 96, 18, 95, 108, 12, 59, 122, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 141, 7, 7, 180, 7, 7, 176, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 162, 7, 7, 161, + 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 123, + 7, 7, 121, 7, 7, 118, 7, 7, 115, 7, 7, 111, 7, 7, 107, 7, 7, 102, 7, 7, 94, 7, 7, 87, 7, 7, 76, 11, 11, 46, 58, 58, 59, 239, 239, 239, 255, 255, 255, 239, 239, 239, 59, 59, 60, 13, 13, 58, 7, 7, 93, 7, 7, 106, 7, 7, 113, 7, 7, 121, 7, 7, 125, + 7, 7, 130, 7, 7, 133, 7, 7, 137, 7, 7, 139, 7, 7, 141, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 133, 7, 7, 142, + 7, 7, 141, 7, 7, 143, 7, 7, 165, 7, 7, 186, 7, 7, 182, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 177, 7, 7, 180, 7, 7, 182, 7, 7, 183, 7, 7, 182, 7, 7, 178, 7, 7, 174, 7, 7, 170, 7, 7, 165, 7, 7, 161, 7, 7, 155, + 7, 7, 149, 7, 7, 145, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 147, 7, 7, 150, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 158, 7, 7, 181, 7, 7, 175, 7, 7, 172, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, + 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 142, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 124, 7, 7, 121, 7, 7, 119, 7, 7, 115, 7, 7, 111, 7, 7, 107, 7, 7, 102, 7, 7, 95, 7, 7, 88, 7, 7, 76, 11, 11, 47, 58, 58, 59, 239, 239, 239, 255, 255, 255, 234, 234, 234, 53, 53, 54, 13, 13, 59, + 7, 7, 93, 7, 7, 106, 7, 7, 113, 7, 7, 121, 7, 7, 126, 7, 7, 130, 7, 7, 134, 7, 7, 136, 7, 7, 138, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, + 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 131, 7, 7, 164, 7, 7, 187, 7, 7, 181, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 180, 7, 7, 183, 7, 7, 185, 7, 7, 185, 7, 7, 182, 7, 7, 178, + 7, 7, 173, 7, 7, 167, 7, 7, 163, 7, 7, 158, 7, 7, 151, 7, 7, 144, 7, 7, 140, 7, 7, 137, 7, 7, 137, 7, 7, 139, 7, 7, 143, 7, 7, 148, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 131, 7, 7, 178, 7, 7, 180, 7, 7, 175, 7, 7, 172, 7, 7, 171, + 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, + 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 119, 7, 7, 116, 7, 7, 111, 7, 7, 107, 7, 7, 103, 7, 7, 95, 7, 7, 88, 7, 7, 77, 12, 12, 47, 58, 58, 59, + 239, 239, 239, 255, 255, 255, 230, 230, 230, 48, 48, 49, 11, 11, 59, 7, 7, 94, 7, 7, 107, 7, 7, 113, 7, 7, 122, 7, 7, 126, 7, 7, 131, 7, 7, 134, 7, 7, 136, 7, 7, 138, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 133, 7, 7, 171, 7, 7, 186, 7, 7, 183, 7, 7, 181, 7, 7, 181, 7, 7, 183, 7, 7, 186, + 7, 7, 189, 7, 7, 192, 7, 7, 189, 7, 7, 184, 7, 7, 177, 7, 7, 172, 7, 7, 167, 7, 7, 161, 7, 7, 155, 7, 7, 149, 7, 7, 142, 7, 7, 136, 7, 7, 133, 7, 7, 134, 7, 7, 136, 7, 7, 142, 7, 7, 147, 7, 7, 150, 7, 7, 154, 7, 7, 155, 7, 7, 156, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 139, 7, 7, 139, 7, 7, 140, + 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 149, + 7, 7, 187, 7, 7, 180, 7, 7, 175, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 108, 7, 7, 103, + 7, 7, 95, 7, 7, 89, 7, 7, 77, 12, 12, 48, 54, 54, 55, 235, 235, 235, 255, 255, 255, 230, 230, 230, 48, 48, 50, 12, 12, 60, 7, 7, 94, 7, 7, 107, 7, 7, 113, 7, 7, 122, 7, 7, 126, 7, 7, 131, 7, 7, 134, 7, 7, 137, 7, 7, 139, 7, 7, 141, 7, 7, 143, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 136, 7, 7, 171, + 7, 7, 186, 7, 7, 186, 7, 7, 186, 7, 7, 183, 7, 7, 168, 7, 7, 159, 7, 7, 172, 7, 7, 190, 7, 7, 185, 7, 7, 178, 7, 7, 173, 7, 7, 167, 7, 7, 161, 7, 7, 154, 7, 7, 148, 7, 7, 141, 7, 7, 135, 7, 7, 131, 7, 7, 132, 7, 7, 135, 7, 7, 141, + 7, 7, 147, 7, 7, 150, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, + 7, 7, 146, 7, 7, 141, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, + 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 151, 7, 7, 188, 7, 7, 182, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 177, 7, 7, 174, 7, 7, 169, 7, 7, 165, + 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 129, 7, 7, 125, 7, 7, 122, + 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 108, 7, 7, 103, 7, 7, 95, 7, 7, 89, 7, 7, 77, 10, 10, 48, 47, 47, 49, 230, 230, 230, 255, 255, 255, 230, 230, 230, 48, 48, 50, 13, 13, 61, 7, 7, 93, 7, 7, 106, 7, 7, 113, 7, 7, 122, 7, 7, 128, 7, 7, 132, + 7, 7, 136, 7, 7, 139, 7, 7, 141, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 136, 7, 7, 161, 7, 7, 176, 7, 7, 169, 7, 7, 145, 7, 7, 130, 7, 7, 126, 7, 7, 135, 7, 7, 179, 7, 7, 187, 7, 7, 179, 7, 7, 174, 7, 7, 168, 7, 7, 162, 7, 7, 155, 7, 7, 149, 7, 7, 142, + 7, 7, 137, 7, 7, 134, 7, 7, 135, 7, 7, 137, 7, 7, 143, 7, 7, 147, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 141, 7, 7, 136, 7, 7, 135, 7, 7, 137, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 136, 7, 7, 179, 7, 7, 186, 7, 7, 184, 7, 7, 183, 7, 7, 182, 7, 7, 183, 7, 7, 184, 7, 7, 185, 7, 7, 185, 7, 7, 183, 7, 7, 182, + 7, 7, 181, 7, 7, 179, 7, 7, 175, 7, 7, 170, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, + 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 108, 7, 7, 103, 7, 7, 95, 7, 7, 88, 7, 7, 77, 9, 9, 49, 47, 47, 49, 230, 230, 230, 255, 255, 255, 230, 230, 230, 48, 48, 50, 13, 13, 62, 7, 7, 94, + 7, 7, 107, 7, 7, 114, 7, 7, 122, 7, 7, 128, 7, 7, 133, 7, 7, 138, 7, 7, 141, 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 130, 7, 7, 171, 7, 7, 187, 7, 7, 179, 7, 7, 174, + 7, 7, 170, 7, 7, 163, 7, 7, 157, 7, 7, 151, 7, 7, 145, 7, 7, 141, 7, 7, 138, 7, 7, 139, 7, 7, 142, 7, 7, 145, 7, 7, 150, 7, 7, 153, 7, 7, 155, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 133, 7, 7, 150, 7, 7, 166, 7, 7, 183, 7, 7, 189, 7, 7, 188, + 7, 7, 190, 7, 7, 193, 7, 7, 193, 7, 7, 188, 7, 7, 184, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 172, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 108, 7, 7, 103, 7, 7, 95, 7, 7, 88, 7, 7, 76, 10, 10, 49, 47, 47, 49, 230, 230, 230, + 255, 255, 255, 230, 230, 230, 48, 48, 50, 13, 13, 64, 7, 7, 94, 7, 7, 107, 7, 7, 114, 7, 7, 124, 7, 7, 130, 7, 7, 135, 7, 7, 140, 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 132, 7, 7, 175, 7, 7, 185, 7, 7, 178, 7, 7, 174, 7, 7, 169, 7, 7, 164, 7, 7, 159, 7, 7, 154, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, + 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 125, 7, 7, 140, 7, 7, 175, 7, 7, 193, 7, 7, 196, 7, 7, 195, 7, 7, 192, 7, 7, 193, 7, 7, 186, 7, 7, 182, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 170, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, + 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 108, 7, 7, 103, 7, 7, 95, + 7, 7, 87, 7, 7, 76, 10, 10, 49, 47, 47, 49, 230, 230, 230, 255, 255, 255, 229, 229, 229, 47, 47, 48, 13, 13, 64, 7, 7, 95, 7, 7, 109, 7, 7, 117, 7, 7, 126, 7, 7, 133, 7, 7, 138, 7, 7, 142, 7, 7, 145, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 135, 7, 7, 178, 7, 7, 183, 7, 7, 177, 7, 7, 173, 7, 7, 169, 7, 7, 165, 7, 7, 161, 7, 7, 157, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 155, + 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 151, + 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 134, 7, 7, 162, 7, 7, 178, 7, 7, 153, 7, 7, 145, 7, 7, 179, 7, 7, 189, 7, 7, 183, 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 173, 7, 7, 169, + 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 122, 7, 7, 120, + 7, 7, 117, 7, 7, 113, 7, 7, 108, 7, 7, 103, 7, 7, 95, 7, 7, 87, 7, 7, 76, 10, 10, 50, 47, 47, 49, 230, 230, 230, 255, 255, 255, 222, 222, 222, 38, 38, 40, 11, 11, 65, 7, 7, 97, 7, 7, 111, 7, 7, 119, 7, 7, 130, 7, 7, 136, 7, 7, 141, 7, 7, 145, + 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 145, 7, 7, 183, 7, 7, 180, 7, 7, 175, 7, 7, 172, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, + 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 124, 7, 7, 128, 7, 7, 123, 7, 7, 123, 7, 7, 147, 7, 7, 189, 7, 7, 185, + 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 177, 7, 7, 172, 7, 7, 168, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 133, + 7, 7, 131, 7, 7, 129, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 109, 7, 7, 104, 7, 7, 95, 7, 7, 88, 7, 7, 76, 10, 10, 50, 47, 47, 49, 230, 230, 230, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 99, 7, 7, 114, + 7, 7, 122, 7, 7, 134, 7, 7, 140, 7, 7, 145, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 164, 7, 7, 185, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 168, + 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, + 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, + 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 129, 7, 7, 178, 7, 7, 188, 7, 7, 184, 7, 7, 185, 7, 7, 186, 7, 7, 184, 7, 7, 178, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 114, 7, 7, 109, 7, 7, 104, 7, 7, 95, 7, 7, 88, 7, 7, 76, 10, 10, 50, 47, 47, 49, 230, 230, 230, 255, 255, 255, + 222, 222, 222, 37, 37, 40, 10, 10, 69, 7, 7, 101, 7, 7, 116, 7, 7, 126, 7, 7, 138, 7, 7, 144, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 129, 7, 7, 174, + 7, 7, 182, 7, 7, 176, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, + 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 161, 7, 7, 189, 7, 7, 186, 7, 7, 188, 7, 7, 182, 7, 7, 177, 7, 7, 184, 7, 7, 178, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 164, + 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 124, 7, 7, 121, 7, 7, 118, 7, 7, 114, 7, 7, 109, 7, 7, 104, 7, 7, 96, 7, 7, 88, + 7, 7, 77, 10, 10, 51, 47, 47, 49, 230, 230, 230, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 70, 7, 7, 103, 7, 7, 119, 7, 7, 130, 7, 7, 141, 7, 7, 147, 7, 7, 151, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, + 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 133, 7, 7, 179, 7, 7, 180, 7, 7, 174, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 162, + 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 136, 7, 7, 179, 7, 7, 190, 7, 7, 188, 7, 7, 147, 7, 7, 136, 7, 7, 169, 7, 7, 185, + 7, 7, 179, 7, 7, 175, 7, 7, 172, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 157, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 124, 7, 7, 121, 7, 7, 118, + 7, 7, 114, 7, 7, 110, 7, 7, 104, 7, 7, 96, 7, 7, 88, 7, 7, 77, 8, 8, 51, 40, 40, 42, 225, 225, 225, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 72, 7, 7, 105, 7, 7, 121, 7, 7, 133, 7, 7, 144, 7, 7, 150, 7, 7, 153, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 23, 133, 14, 70, 122, 20, 100, 109, 21, 113, 100, 23, 119, 94, 24, 126, 85, 25, 127, 85, 23, 121, 91, 22, 116, 95, 19, 102, 104, 15, 80, 117, 10, 43, 132, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 134, 7, 7, 180, 7, 7, 180, 7, 7, 174, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, + 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, + 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 137, 7, 7, 157, + 7, 7, 149, 7, 7, 124, 7, 7, 122, 7, 7, 137, 7, 7, 184, 7, 7, 184, 7, 7, 178, 7, 7, 173, 7, 7, 169, 7, 7, 164, 7, 7, 158, 7, 7, 125, 7, 7, 108, 7, 7, 122, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 134, + 7, 7, 131, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 118, 7, 7, 114, 7, 7, 110, 7, 7, 104, 7, 7, 96, 7, 7, 88, 7, 7, 77, 7, 7, 50, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 74, 7, 7, 108, 7, 7, 124, 7, 7, 136, + 7, 7, 147, 7, 7, 152, 7, 7, 155, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 10, 45, 130, 19, 102, 107, 24, 125, 87, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 111, 101, 14, 69, 124, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 21, 103, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 132, 7, 7, 178, 7, 7, 181, 7, 7, 174, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, + 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, + 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, + 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 124, 21, 103, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 166, 7, 7, 175, 7, 7, 169, 7, 7, 160, 7, 7, 128, 7, 7, 110, 7, 7, 115, 7, 7, 114, 7, 7, 121, 7, 7, 148, + 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 132, 7, 7, 129, 7, 7, 125, 7, 7, 122, 7, 7, 118, 7, 7, 115, 7, 7, 110, 7, 7, 104, 7, 7, 96, 7, 7, 88, 7, 7, 77, 7, 7, 51, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 40, 10, 10, 76, 7, 7, 111, 7, 7, 129, 7, 7, 140, 7, 7, 151, 7, 7, 154, 7, 7, 157, 7, 7, 160, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 8, 30, 132, 19, 94, 111, 25, 127, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 115, 96, 11, 55, 127, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, + 7, 7, 131, 21, 103, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 174, 7, 7, 182, + 7, 7, 175, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, + 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 21, 103, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 169, 7, 7, 175, 7, 7, 166, 7, 7, 128, 7, 7, 111, + 7, 7, 121, 7, 7, 126, 7, 7, 126, 7, 7, 120, 7, 7, 123, 7, 7, 147, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 130, 7, 7, 126, 7, 7, 123, 7, 7, 119, 7, 7, 115, 7, 7, 110, 7, 7, 105, 7, 7, 96, 7, 7, 88, 7, 7, 77, + 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 41, 10, 10, 80, 7, 7, 117, 7, 7, 136, 7, 7, 147, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 162, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 156, + 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 10, 49, 129, 23, 119, 92, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 16, 90, 114, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 21, 103, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 171, 7, 7, 183, 7, 7, 175, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 167, + 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, + 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 21, 103, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 12, 63, 171, 7, 7, 178, 7, 7, 142, 7, 7, 108, 7, 7, 120, 7, 7, 127, 7, 7, 132, 7, 7, 132, 7, 7, 127, 7, 7, 116, 7, 7, 119, 7, 7, 151, 7, 7, 154, 7, 7, 156, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 131, 7, 7, 128, 7, 7, 124, 7, 7, 120, 7, 7, 115, + 7, 7, 110, 7, 7, 105, 7, 7, 96, 7, 7, 89, 7, 7, 77, 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 41, 10, 10, 86, 7, 7, 116, 7, 7, 116, 7, 7, 108, 7, 7, 131, 7, 7, 159, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 162, + 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 144, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 13, 64, 126, 24, 124, 88, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 103, 106, 7, 20, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 21, 103, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 167, 7, 7, 184, 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 167, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 162, + 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 21, 103, 100, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 168, 7, 7, 147, 7, 7, 107, 7, 7, 119, 7, 7, 127, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 129, 7, 7, 121, 7, 7, 108, 7, 7, 111, 7, 7, 156, 7, 7, 159, 7, 7, 160, 7, 7, 159, + 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 136, + 7, 7, 133, 7, 7, 129, 7, 7, 125, 7, 7, 121, 7, 7, 116, 7, 7, 111, 7, 7, 105, 7, 7, 96, 7, 7, 89, 7, 7, 78, 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 41, 10, 10, 66, 7, 7, 74, 7, 7, 77, 7, 7, 82, 7, 7, 94, + 7, 7, 145, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 12, 57, 129, 25, 127, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 84, 23, 122, 92, 23, 120, 94, 24, 126, 86, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 103, 105, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 21, 103, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 161, 7, 7, 184, 7, 7, 176, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 168, + 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, + 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 21, 103, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 127, 7, 7, 110, 7, 7, 120, 7, 7, 128, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 126, 7, 7, 118, + 7, 7, 103, 7, 7, 109, 7, 7, 159, 7, 7, 162, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 137, 7, 7, 134, 7, 7, 130, 7, 7, 126, 7, 7, 122, 7, 7, 118, 7, 7, 112, 7, 7, 106, 7, 7, 97, 7, 7, 89, 7, 7, 78, 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 45, 7, 7, 64, 7, 7, 74, 7, 7, 82, 7, 7, 89, 7, 7, 136, 7, 7, 163, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 9, 35, 135, 23, 121, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 120, 94, 17, 93, 115, + 11, 53, 132, 7, 18, 141, 7, 7, 142, 7, 7, 143, 7, 7, 142, 8, 30, 140, 15, 74, 126, 21, 107, 107, 26, 128, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 88, 115, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, + 21, 103, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 155, 7, 7, 185, 7, 7, 178, + 7, 7, 173, 7, 7, 171, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, + 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 21, 103, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 107, 7, 7, 123, 7, 7, 130, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 126, 7, 7, 115, 7, 7, 100, 7, 7, 114, 7, 7, 157, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 131, 7, 7, 128, 7, 7, 123, 7, 7, 118, 7, 7, 113, 7, 7, 107, 7, 7, 97, 7, 7, 90, 7, 7, 78, 7, 7, 53, + 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 74, 7, 7, 81, 7, 7, 106, 7, 7, 152, 7, 7, 160, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 21, 112, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 127, 85, 18, 92, 118, 7, 23, 138, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 12, 59, 132, 23, 119, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 24, 126, 85, 10, 46, 129, 7, 7, 134, 7, 7, 132, 7, 7, 131, 21, 103, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 150, 7, 7, 186, 7, 7, 181, 7, 7, 177, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 167, + 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 127, 21, 103, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 116, + 7, 7, 130, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 130, 7, 7, 125, 7, 7, 116, 7, 7, 106, 7, 7, 117, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 132, 7, 7, 129, 7, 7, 124, 7, 7, 119, 7, 7, 114, + 7, 7, 107, 7, 7, 98, 7, 7, 90, 7, 7, 79, 7, 7, 53, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 75, 7, 7, 103, 7, 7, 148, 7, 7, 158, 7, 7, 156, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, + 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 13, 72, 127, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 86, 12, 63, 132, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 8, 28, 139, 22, 113, 101, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 105, 105, 7, 7, 134, 7, 7, 133, 7, 7, 132, 21, 103, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 136, 7, 7, 177, 7, 7, 186, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 180, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 172, + 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, + 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 129, 7, 7, 128, 21, 103, 102, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 123, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 127, 7, 7, 123, 7, 7, 118, 7, 7, 121, 7, 7, 148, + 7, 7, 150, 7, 7, 155, 7, 7, 154, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, + 7, 7, 132, 7, 7, 129, 7, 7, 125, 7, 7, 120, 7, 7, 115, 7, 7, 108, 7, 7, 99, 7, 7, 91, 7, 7, 79, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 81, 7, 7, 132, 7, 7, 153, 7, 7, 153, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 143, 7, 18, 142, 22, 117, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 12, 63, 132, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 8, 35, 138, 24, 118, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, 10, 49, 130, 7, 7, 135, 7, 7, 134, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 12, 63, 122, 7, 7, 129, 12, 58, 122, 19, 99, 105, 23, 117, 93, 24, 125, 87, 25, 128, 83, 24, 122, 89, 23, 115, 95, 18, 96, 108, 12, 60, 123, 7, 7, 130, 7, 7, 130, 7, 7, 150, 7, 7, 182, 7, 7, 188, 7, 7, 188, 7, 7, 187, 7, 7, 187, 7, 7, 187, 7, 7, 184, + 7, 7, 180, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 176, 7, 23, 173, 12, 68, 155, 19, 99, 130, 23, 115, 109, 23, 122, 97, 25, 127, 86, 24, 125, 92, 23, 119, 102, 20, 106, 119, 13, 73, 145, 7, 23, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 167, + 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 10, 44, 142, 17, 93, 120, 21, 115, 101, 24, 123, 91, 25, 128, 84, 24, 124, 89, + 22, 118, 97, 19, 103, 110, 13, 73, 127, 7, 23, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 10, 44, 140, + 17, 93, 119, 21, 115, 100, 24, 123, 90, 25, 128, 84, 24, 124, 89, 22, 118, 96, 19, 103, 108, 13, 73, 125, 7, 23, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 10, 45, 130, 16, 85, 116, 22, 110, 101, 23, 119, 93, 24, 125, 87, 25, 127, 84, 23, 121, 91, 22, 114, 97, 18, 95, 109, 12, 62, 123, 7, 18, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 130, 7, 7, 130, 21, 103, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 123, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 132, 7, 7, 132, 7, 7, 129, 7, 7, 126, 7, 7, 127, 7, 7, 141, 7, 7, 147, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, + 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 132, 7, 7, 130, 7, 7, 125, 7, 7, 121, 7, 7, 115, 7, 7, 109, 7, 7, 100, 7, 7, 92, 7, 7, 80, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, + 7, 7, 64, 7, 7, 92, 7, 7, 141, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 15, 74, 127, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 91, 119, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 8, 31, 140, 11, 54, 135, 11, 54, 134, 11, 54, 134, 11, 54, 133, 11, 54, 132, 11, 54, 131, 8, 35, 136, 7, 7, 137, 7, 7, 136, 21, 103, 106, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 14, 70, 120, 20, 105, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 112, 99, 10, 47, 125, 7, 7, 130, 7, 7, 144, 7, 7, 159, + 7, 7, 155, 7, 7, 149, 7, 7, 148, 7, 7, 160, 7, 7, 179, 7, 7, 188, 7, 7, 185, 7, 7, 183, 7, 18, 182, 16, 80, 154, 23, 121, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 118, 103, + 11, 56, 154, 7, 7, 164, 15, 75, 146, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 163, 7, 7, 165, 7, 7, 164, 7, 7, 162, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 115, 102, 7, 12, 149, 17, 94, 121, 25, 127, 85, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 119, 96, 13, 65, 131, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 21, 103, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 23, 115, 100, 7, 12, 144, 17, 94, 119, 25, 127, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 119, 94, 13, 65, 126, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 10, 46, 129, 20, 104, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 117, 93, 14, 69, 120, 7, 7, 130, + 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 140, 7, 7, 144, 7, 7, 147, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 153, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 132, 7, 7, 130, 7, 7, 125, 7, 7, 121, 7, 7, 116, 7, 7, 110, 7, 7, 100, 7, 7, 93, 7, 7, 81, 7, 7, 56, 36, 36, 39, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 102, 7, 7, 140, 7, 7, 145, 7, 7, 148, 7, 7, 150, 7, 7, 152, 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 144, 20, 105, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 120, 94, 7, 20, 141, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 138, 7, 7, 138, 7, 7, 140, 7, 7, 139, 21, 103, 107, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 85, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 125, 86, 12, 59, 122, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 135, 7, 7, 155, 7, 7, 181, 9, 37, 187, 22, 113, 122, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 87, 14, 69, 150, 15, 75, 147, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 164, 7, 7, 166, 7, 7, 164, 7, 7, 162, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 24, 118, 99, 20, 110, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 83, 14, 76, 127, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 21, 103, 111, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 118, 98, 20, 110, 107, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 83, 14, 76, 121, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 16, 86, 117, 25, 127, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 105, 103, 9, 20, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 133, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 137, 7, 7, 140, 7, 7, 143, 7, 7, 145, + 7, 7, 150, 7, 7, 153, 7, 7, 154, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 132, 7, 7, 130, 7, 7, 125, 7, 7, 121, 7, 7, 116, 7, 7, 110, + 7, 7, 101, 7, 7, 94, 7, 7, 82, 7, 7, 57, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 110, 7, 7, 140, 7, 7, 145, 7, 7, 148, 7, 7, 151, 7, 7, 155, 7, 7, 158, 7, 7, 161, 7, 7, 163, 7, 7, 162, + 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 152, + 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 20, 143, 24, 125, 89, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 16, 86, 122, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 141, 21, 103, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 123, 88, 10, 47, 125, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 10, 46, 134, 23, 120, 99, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 125, 91, 17, 89, 138, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 164, 7, 7, 166, 7, 7, 164, + 7, 7, 162, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 84, + 13, 64, 133, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 21, 103, 112, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 84, 13, 64, 126, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 18, 134, 19, 98, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 113, 97, 8, 35, 129, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 21, 103, 105, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 131, 7, 7, 135, 7, 7, 137, 7, 7, 140, 7, 7, 145, 7, 7, 150, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 133, + 7, 7, 130, 7, 7, 125, 7, 7, 122, 7, 7, 117, 7, 7, 111, 7, 7, 102, 7, 7, 95, 7, 7, 84, 7, 7, 58, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 67, 7, 7, 117, 7, 7, 140, 7, 7, 146, 7, 7, 150, 7, 7, 154, + 7, 7, 158, 7, 7, 162, 7, 7, 165, 7, 7, 167, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 13, 66, 132, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, 8, 31, 138, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 108, 101, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 8, 25, 130, + 22, 116, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 86, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 8, 35, 164, 7, 7, 166, 7, 7, 164, 7, 7, 163, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 116, 99, 7, 18, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 21, 103, 112, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 116, 96, 7, 18, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 17, 92, 113, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 109, 101, 7, 7, 131, 7, 7, 130, 7, 7, 132, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 123, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 136, 7, 7, 141, 7, 7, 146, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, + 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 126, 7, 7, 122, 7, 7, 117, 7, 7, 112, 7, 7, 104, 7, 7, 96, 7, 7, 85, 7, 7, 58, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 70, + 7, 7, 124, 7, 7, 142, 7, 7, 148, 7, 7, 153, 7, 7, 158, 7, 7, 163, 7, 7, 168, 7, 7, 170, 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 16, 85, 123, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 115, 98, 7, 7, 137, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 21, 103, 109, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 114, 96, 18, 95, 108, 18, 91, 111, 21, 103, 103, 23, 120, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 11, 53, 125, 7, 7, 131, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 20, 100, 106, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 125, 93, 20, 105, 127, 16, 90, 142, 16, 85, 144, 17, 94, 136, 21, 112, 114, 25, 128, 84, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 163, 7, 7, 166, 7, 7, 164, 7, 7, 163, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 114, 102, + 17, 93, 121, 16, 85, 126, 19, 99, 117, 23, 117, 98, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 65, 136, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 21, 103, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 114, 101, 17, 93, 119, 16, 85, 123, 19, 99, 114, 23, 117, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 65, 127, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 14, 70, 123, 25, 129, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 122, 90, 20, 104, 105, 17, 93, 112, 17, 87, 115, 19, 98, 108, 21, 111, 100, 25, 129, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 17, 89, 113, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 133, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 139, 7, 7, 145, 7, 7, 151, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 133, 7, 7, 130, 7, 7, 126, 7, 7, 122, 7, 7, 118, 7, 7, 113, 7, 7, 104, 7, 7, 97, 7, 7, 86, 7, 7, 59, 36, 36, 39, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 68, 7, 7, 118, 7, 7, 146, 7, 7, 152, 7, 7, 157, 7, 7, 162, 7, 7, 167, 7, 7, 171, 7, 7, 173, 7, 7, 173, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 158, + 7, 7, 155, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 18, 93, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 99, 105, 7, 7, 135, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 125, 87, 14, 70, 120, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 23, 131, 20, 103, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 91, 112, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 10, 49, 127, 25, 128, 83, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 106, 126, 8, 31, 175, 7, 7, 177, 7, 7, 176, 7, 7, 174, + 7, 7, 172, 7, 7, 171, 12, 57, 160, 23, 118, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 163, 7, 7, 165, 7, 7, 164, 7, 7, 163, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 24, 126, 87, 15, 74, 133, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 12, 148, 18, 95, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 96, 119, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, + 21, 103, 114, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 87, 15, 74, 133, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 12, 143, 18, 95, 115, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 18, 96, 112, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 20, 134, 23, 120, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 86, 16, 89, 115, 8, 25, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 11, 56, 127, + 21, 110, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 85, 10, 33, 130, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 122, 8, 8, 130, 8, 8, 129, + 8, 8, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 139, + 7, 7, 144, 7, 7, 149, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 126, 7, 7, 123, 7, 7, 119, 7, 7, 114, 7, 7, 106, + 7, 7, 99, 7, 7, 86, 7, 7, 59, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 99, 7, 7, 146, 7, 7, 157, 7, 7, 161, 7, 7, 165, 7, 7, 169, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 169, 7, 7, 166, + 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 19, 102, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 18, 91, 114, 8, 8, 135, 8, 8, 139, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 21, 103, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 14, 69, 123, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, + 7, 7, 132, 7, 7, 132, 22, 114, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 109, 101, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 19, 102, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 83, 149, + 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 173, 7, 7, 173, 8, 23, 171, 20, 104, 125, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 162, 7, 7, 164, 7, 7, 163, 7, 7, 162, + 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 15, 74, 133, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 21, 108, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 21, 111, 107, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 21, 103, 114, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 15, 74, 133, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 21, 108, 106, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 111, 102, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 135, 16, 82, 117, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, 13, 72, 123, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 129, 7, 7, 130, 7, 7, 133, 7, 20, 133, 21, 110, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 93, 112, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 12, 63, 123, 8, 8, 131, 8, 8, 129, 8, 8, 130, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 130, 8, 8, 131, 7, 7, 132, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 137, 7, 7, 140, 7, 7, 145, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 131, + 7, 7, 128, 7, 7, 124, 7, 7, 120, 7, 7, 115, 7, 7, 107, 7, 7, 100, 7, 7, 87, 7, 7, 60, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 81, 7, 7, 135, 7, 7, 161, 7, 7, 164, 7, 7, 167, 7, 7, 171, + 7, 7, 173, 7, 7, 174, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 162, 7, 7, 158, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 144, 21, 106, 107, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 85, 121, 8, 8, 139, 8, 8, 139, 8, 8, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 21, 103, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 117, 96, 7, 7, 136, + 7, 7, 134, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 16, 80, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 119, 93, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 20, 133, 25, 125, 86, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 105, 126, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 177, 8, 29, 174, 24, 123, 98, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 8, 35, 162, 7, 7, 164, 7, 7, 163, 7, 7, 162, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 115, 102, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 13, 73, 134, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 120, 96, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 21, 103, 115, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 115, 102, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 13, 73, 128, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 120, 93, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 135, 22, 117, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 17, 91, 114, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 129, 7, 7, 126, 7, 7, 127, 7, 7, 131, 7, 7, 133, 7, 7, 134, 8, 31, 132, 24, 122, 90, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 123, 89, 7, 7, 133, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 21, 103, 106, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 8, 8, 127, 8, 8, 129, 7, 7, 131, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 139, 7, 7, 143, 7, 7, 147, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 124, 7, 7, 120, 7, 7, 116, 7, 7, 108, 7, 7, 101, 7, 7, 88, 7, 7, 61, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 76, + 7, 7, 110, 7, 7, 163, 7, 7, 165, 7, 7, 167, 7, 7, 172, 7, 7, 176, 7, 7, 177, 7, 7, 175, 7, 7, 172, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 168, 7, 7, 164, 7, 7, 160, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 145, 7, 7, 146, 7, 7, 148, 20, 100, 116, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 93, 119, 8, 8, 141, 8, 8, 140, 8, 8, 139, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 8, 8, 139, 7, 7, 139, 8, 8, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 21, 103, 108, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 92, 116, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 10, 44, 129, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 123, 89, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 13, 64, 124, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 90, 10, 44, 171, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 181, 14, 78, 157, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 161, 7, 7, 163, 7, 7, 162, 7, 7, 161, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 93, 123, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 9, 35, 149, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 125, 88, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 21, 103, 116, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 17, 93, 124, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 9, 35, 141, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 125, 87, 7, 7, 139, 7, 7, 138, 7, 7, 136, 9, 41, 131, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, 8, 35, 134, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 134, 18, 95, 111, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 11, 53, 128, 7, 7, 134, 7, 7, 134, 7, 7, 134, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 132, + 7, 7, 130, 7, 7, 127, 8, 8, 125, 8, 8, 128, 8, 8, 130, 7, 7, 132, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 135, 7, 7, 136, 7, 7, 139, 7, 7, 142, 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 145, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 125, 7, 7, 122, 7, 7, 117, 7, 7, 109, 7, 7, 102, 7, 7, 90, 7, 7, 62, 36, 36, 39, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 75, 7, 7, 103, 7, 7, 162, 7, 7, 164, 7, 7, 168, 7, 7, 169, 7, 7, 152, 7, 7, 154, 7, 7, 171, 7, 7, 176, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 165, 7, 7, 160, + 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 150, 7, 7, 151, 17, 93, 124, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 101, 113, 7, 7, 143, 8, 8, 141, 8, 8, 140, 8, 8, 141, 7, 7, 142, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 139, 8, 8, 138, 8, 8, 138, 8, 8, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 15, 74, 125, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 18, 134, 25, 127, 84, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 125, 86, 7, 7, 133, 7, 7, 133, 7, 7, 133, 16, 90, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 102, 133, 7, 7, 180, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 180, 7, 7, 182, 7, 7, 185, 7, 7, 187, + 7, 7, 188, 7, 7, 188, 7, 7, 188, 7, 7, 188, 7, 7, 186, 23, 123, 99, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 161, 7, 7, 163, 7, 7, 162, 7, 7, 161, 21, 103, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 15, 79, 133, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 24, 126, 88, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 86, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 21, 103, 116, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 15, 79, 134, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 24, 126, 87, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 85, + 7, 7, 139, 7, 7, 138, 7, 7, 137, 15, 81, 120, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 109, 104, 10, 51, 130, 10, 51, 127, 10, 51, 125, 10, 51, 127, 10, 51, 128, 10, 51, 127, 10, 51, 126, 10, 51, 126, 10, 51, 127, 10, 51, 127, 10, 51, 127, + 10, 51, 128, 13, 72, 122, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 87, 116, 7, 7, 134, 7, 7, 134, 7, 7, 134, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 125, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 129, 8, 8, 125, 8, 8, 123, 8, 8, 125, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 135, 7, 7, 137, 7, 7, 139, 7, 7, 142, 7, 7, 147, 7, 7, 149, 7, 7, 149, + 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 118, 7, 7, 110, 7, 7, 103, + 7, 7, 91, 7, 7, 64, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 75, 7, 7, 92, 7, 7, 151, 7, 7, 164, 7, 7, 163, 7, 7, 133, 7, 7, 108, 7, 7, 110, 7, 7, 131, 7, 7, 170, 7, 7, 177, 7, 7, 174, + 7, 7, 172, 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 152, 16, 84, 130, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 117, 99, + 7, 7, 144, 7, 7, 142, 8, 8, 142, 8, 8, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 139, 8, 8, 139, 8, 8, 139, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 21, 103, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 67, 128, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 24, 124, 88, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 133, 7, 7, 133, 7, 7, 133, 19, 97, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 15, 81, 158, 7, 7, 183, 7, 7, 180, 7, 7, 179, + 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 186, 7, 7, 190, 7, 7, 194, 7, 7, 195, 7, 7, 195, 7, 7, 195, 7, 7, 192, 19, 105, 131, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 161, 7, 7, 163, 7, 7, 162, 7, 7, 160, 21, 103, 118, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 14, 69, 139, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 23, 122, 95, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 7, 18, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 21, 103, 116, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 14, 69, 141, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 23, 122, 93, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 18, 140, 7, 7, 139, 7, 7, 137, 19, 94, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 98, 109, 7, 7, 134, 7, 7, 134, 7, 7, 134, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 12, 63, 125, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 131, 8, 8, 129, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 126, 7, 7, 129, 7, 7, 136, 7, 7, 138, 7, 7, 140, + 7, 7, 143, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 130, + 7, 7, 128, 7, 7, 123, 7, 7, 119, 7, 7, 112, 7, 7, 105, 7, 7, 93, 7, 7, 66, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 75, 7, 7, 82, 7, 7, 104, 7, 7, 121, 7, 7, 116, 7, 7, 103, 7, 7, 105, + 7, 7, 106, 7, 7, 108, 7, 7, 136, 7, 7, 177, 7, 7, 176, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 163, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 152, 12, 61, 141, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 10, 45, 138, 7, 7, 142, 7, 7, 142, 8, 8, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 64, 130, 7, 7, 138, 7, 7, 137, + 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 23, 122, 90, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 133, 7, 7, 133, 7, 7, 132, 20, 104, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 12, 68, 173, 7, 7, 188, 7, 7, 185, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 183, 7, 7, 187, 7, 7, 193, 7, 7, 196, 7, 7, 197, 7, 7, 198, 7, 7, 198, 7, 7, 195, 19, 97, 143, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 8, 35, 161, 7, 7, 163, 7, 7, 162, 7, 7, 161, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 65, 141, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 23, 120, 98, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 21, 103, 117, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 65, 142, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 23, 120, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, 7, 7, 139, 7, 7, 138, 19, 101, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 105, 104, 7, 7, 133, 7, 7, 133, 7, 7, 134, + 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 125, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 128, 7, 7, 127, 7, 7, 126, + 7, 7, 127, 7, 7, 139, 7, 7, 141, 7, 7, 143, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 129, 7, 7, 125, 7, 7, 121, 7, 7, 113, 7, 7, 107, 7, 7, 95, 7, 7, 67, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 83, + 7, 7, 91, 7, 7, 95, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 108, 7, 7, 124, 7, 7, 174, 7, 7, 176, 7, 7, 172, 7, 7, 169, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 147, 7, 7, 147, + 7, 7, 148, 7, 7, 149, 7, 7, 152, 7, 18, 152, 25, 123, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 93, 118, 7, 7, 144, 7, 7, 143, 8, 8, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 142, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 12, 63, 130, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 19, 105, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 13, 64, 180, 7, 7, 196, 7, 7, 192, 7, 7, 186, 7, 7, 184, 7, 7, 183, 7, 7, 184, 7, 7, 187, 7, 7, 192, 7, 7, 194, 7, 7, 195, 7, 7, 196, 7, 7, 197, 7, 7, 195, 19, 97, 143, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 162, 7, 7, 164, 7, 7, 163, 7, 7, 161, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 144, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, + 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 158, 23, 119, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 21, 103, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 143, + 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 23, 119, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, 7, 7, 140, 7, 7, 139, 21, 106, 105, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 21, 112, 98, 7, 7, 132, 7, 7, 132, 7, 7, 132, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 125, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 138, 7, 7, 142, 7, 7, 146, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 131, 7, 7, 126, 7, 7, 122, 7, 7, 115, 7, 7, 109, 7, 7, 97, 7, 7, 69, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 39, 10, 10, 46, 7, 7, 66, 7, 7, 76, 7, 7, 83, 7, 7, 91, 7, 7, 95, 7, 7, 99, 7, 7, 103, 7, 7, 105, 7, 7, 107, 7, 7, 109, 7, 7, 139, 7, 7, 177, 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 162, 7, 7, 160, 7, 7, 157, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 149, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 150, 7, 7, 151, 19, 102, 115, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 125, 87, 10, 33, 142, 7, 7, 145, 8, 8, 144, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 8, 8, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 131, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 127, 84, 7, 7, 133, 7, 7, 133, 7, 7, 132, 19, 99, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 15, 75, 143, 7, 7, 173, 7, 7, 190, 7, 7, 192, 7, 7, 187, 7, 7, 185, 7, 7, 185, 7, 7, 186, 7, 7, 189, 7, 7, 192, + 7, 7, 193, 7, 7, 194, 7, 7, 195, 7, 7, 193, 21, 110, 124, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 163, 7, 7, 165, 7, 7, 164, 7, 7, 162, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 145, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 159, 23, 118, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 159, 7, 7, 160, 7, 7, 159, 7, 7, 158, 21, 103, 118, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 143, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 23, 118, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, + 7, 7, 140, 7, 7, 139, 20, 100, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 108, 101, 8, 8, 129, 8, 8, 129, 8, 8, 130, 21, 103, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 126, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 139, 7, 7, 142, 7, 7, 148, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 135, 7, 7, 133, 7, 7, 129, 7, 7, 124, 7, 7, 117, 7, 7, 111, 7, 7, 100, + 7, 7, 70, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 66, 7, 7, 77, 7, 7, 84, 7, 7, 92, 7, 7, 96, 7, 7, 100, 7, 7, 104, 7, 7, 106, 7, 7, 107, 7, 7, 120, 7, 7, 167, 7, 7, 176, 7, 7, 173, 7, 7, 170, + 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 147, + 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 149, 7, 7, 150, 14, 69, 136, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 20, 105, 110, 8, 8, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 8, 8, 144, 8, 8, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 131, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 133, 7, 7, 133, 7, 7, 132, 17, 92, 112, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 95, 109, 7, 7, 134, 7, 7, 159, 7, 7, 192, 7, 7, 192, + 7, 7, 188, 7, 7, 186, 7, 7, 187, 7, 7, 189, 7, 7, 190, 7, 7, 192, 7, 7, 193, 7, 7, 194, 7, 7, 192, 24, 122, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 164, 7, 7, 166, 7, 7, 165, 7, 7, 164, 21, 103, 120, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 146, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 159, 23, 118, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 159, + 7, 7, 160, 7, 7, 159, 7, 7, 159, 21, 103, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 143, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 146, 7, 7, 145, 23, 118, 96, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, 7, 7, 140, 7, 7, 139, 17, 92, 116, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 99, 106, 8, 8, 129, 9, 9, 127, 8, 8, 127, 21, 103, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 12, 63, 124, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 137, 7, 7, 144, 7, 7, 149, 7, 7, 154, 7, 7, 155, + 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, + 7, 7, 131, 7, 7, 128, 7, 7, 119, 7, 7, 113, 7, 7, 102, 7, 7, 71, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 66, 7, 7, 77, 7, 7, 85, 7, 7, 92, 7, 7, 97, 7, 7, 100, 7, 7, 104, 7, 7, 106, 7, 7, 112, + 7, 7, 155, 7, 7, 174, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 22, 113, 103, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 16, 86, 124, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 8, 8, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 10, 51, 136, 22, 116, 98, 22, 120, 93, 22, 120, 93, 22, 120, 93, 22, 120, 93, 22, 120, 93, 22, 120, 93, 12, 58, 131, 7, 7, 141, 7, 7, 141, 21, 103, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 131, 7, 7, 140, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 134, 7, 7, 133, 7, 7, 133, 14, 70, 121, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 23, 121, 91, 8, 23, 131, 7, 7, 133, 7, 7, 156, 7, 7, 193, 7, 7, 195, 7, 7, 190, 7, 7, 189, 7, 7, 190, 7, 7, 192, 7, 7, 192, 7, 7, 194, 7, 7, 195, 13, 67, 174, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 165, + 7, 7, 169, 7, 7, 168, 7, 7, 166, 21, 103, 121, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 147, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 160, 23, 118, 101, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 158, 7, 7, 160, 7, 7, 159, 7, 7, 158, 21, 103, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 143, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 23, 118, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, 7, 7, 140, 7, 7, 139, 14, 71, 128, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 121, 95, 7, 12, 149, 7, 7, 147, + 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 132, 8, 8, 131, 8, 8, 132, 7, 7, 133, 7, 7, 132, 8, 8, 128, 8, 8, 125, 8, 8, 125, 21, 103, 101, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 123, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, + 7, 7, 135, 7, 7, 144, 7, 7, 150, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 130, 7, 7, 122, 7, 7, 116, 7, 7, 104, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 67, 7, 7, 78, 7, 7, 86, 7, 7, 93, + 7, 7, 97, 7, 7, 101, 7, 7, 104, 7, 7, 105, 7, 7, 129, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 147, + 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 13, 65, 135, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 89, 123, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 11, 55, 134, 23, 123, 90, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 113, 100, 7, 7, 141, 7, 7, 141, 7, 7, 140, 21, 103, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 12, 63, 131, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 134, 7, 7, 133, 7, 7, 133, 8, 23, 131, + 25, 127, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 18, 95, 109, 7, 7, 132, 7, 7, 133, 7, 7, 151, 7, 7, 173, 7, 7, 186, 7, 7, 192, 7, 7, 194, 7, 7, 195, 7, 7, 195, 7, 7, 196, 7, 7, 196, 23, 115, 120, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 169, 7, 7, 172, 7, 7, 170, 7, 7, 168, 21, 103, 122, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 148, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, + 7, 7, 159, 7, 7, 160, 7, 7, 160, 23, 118, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 21, 103, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 143, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 23, 118, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, 7, 7, 140, 7, 7, 139, 7, 23, 140, 24, 125, 88, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 14, 75, 132, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 133, 8, 8, 132, 8, 8, 132, 8, 8, 131, + 8, 8, 130, 8, 8, 128, 9, 9, 127, 8, 8, 127, 21, 103, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 123, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 143, 7, 7, 150, 7, 7, 156, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 145, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 132, 7, 7, 123, 7, 7, 118, 7, 7, 105, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 46, 7, 7, 67, 7, 7, 78, 7, 7, 86, 7, 7, 93, 7, 7, 98, 7, 7, 101, 7, 7, 104, 7, 7, 106, 7, 7, 143, 7, 7, 170, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 155, + 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 148, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 147, 20, 105, 111, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 20, 105, 110, 9, 44, 140, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 16, 83, 123, 25, 125, 87, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, 12, 63, 130, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 21, 103, 107, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 130, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 127, 84, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 21, 108, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 83, 13, 67, 123, 7, 7, 132, 7, 7, 132, 7, 7, 135, 7, 7, 143, 7, 7, 152, 7, 7, 157, 7, 7, 159, 7, 7, 159, + 7, 7, 157, 16, 86, 130, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 173, 7, 7, 175, 7, 7, 173, 7, 7, 171, 21, 103, 124, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 148, 7, 7, 159, + 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 23, 118, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 158, 7, 7, 159, 7, 7, 158, 7, 7, 158, 21, 103, 118, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 142, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 23, 118, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 142, 19, 102, 113, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 124, 90, 11, 54, 140, 7, 7, 146, 7, 7, 142, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 17, 88, 115, 22, 110, 102, + 22, 110, 101, 22, 110, 101, 22, 110, 101, 22, 110, 101, 21, 106, 101, 8, 17, 128, 8, 8, 129, 8, 8, 130, 8, 8, 130, 21, 103, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 123, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 131, 7, 7, 131, 7, 7, 143, 7, 7, 151, 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 137, 7, 7, 134, 7, 7, 125, 7, 7, 119, 7, 7, 105, 7, 7, 72, + 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 67, 7, 7, 79, 7, 7, 86, 7, 7, 94, 7, 7, 98, 7, 7, 101, 7, 7, 104, 7, 7, 106, 7, 7, 143, 7, 7, 169, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 164, + 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 8, 26, 146, 22, 118, 98, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 126, 87, 18, 100, 114, 13, 65, 133, 7, 12, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 8, 32, 139, 15, 82, 123, 22, 114, 100, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 19, 94, 115, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 138, 21, 103, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 130, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 12, 60, 125, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 83, 19, 98, 109, 8, 28, 132, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 30, 132, 18, 96, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 178, 7, 7, 179, 7, 7, 177, 7, 7, 173, 21, 103, 125, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 148, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 23, 118, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 158, 7, 7, 159, + 7, 7, 158, 7, 7, 158, 21, 103, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 142, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 23, 118, 96, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 140, 7, 7, 140, 7, 7, 140, 7, 7, 143, 9, 41, 141, 24, 126, 86, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 124, 90, 15, 80, 128, 7, 17, 139, 7, 7, 134, 7, 7, 132, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 8, 32, 132, 18, 100, 108, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 99, 106, 8, 8, 130, 8, 8, 131, 8, 8, 132, 7, 7, 133, 21, 103, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 129, 7, 7, 142, 7, 7, 153, 7, 7, 159, 7, 7, 162, 7, 7, 163, + 7, 7, 161, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 139, + 7, 7, 135, 7, 7, 126, 7, 7, 119, 7, 7, 104, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 67, 7, 7, 79, 7, 7, 86, 7, 7, 94, 7, 7, 98, 7, 7, 102, 7, 7, 104, 7, 7, 105, 7, 7, 132, 7, 7, 169, + 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 147, + 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 148, 7, 7, 148, + 10, 49, 143, 24, 125, 89, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 128, 83, 23, 122, 92, 23, 118, 96, 24, 124, 89, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 21, 111, 103, 7, 17, 140, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 21, 103, 109, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 131, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 21, 106, 102, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 123, 89, 19, 102, 106, 17, 89, 114, 16, 82, 117, 16, 90, 113, 20, 105, 104, 24, 125, 87, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 183, 7, 7, 183, + 7, 7, 180, 7, 7, 176, 21, 103, 126, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 148, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 23, 118, 103, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 21, 103, 118, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 142, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 23, 118, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 141, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 147, 16, 89, 120, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 23, 122, 92, 19, 102, 105, 18, 92, 110, 16, 82, 114, 17, 88, 114, 21, 103, 105, 24, 124, 88, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 123, 88, 10, 41, 129, 8, 8, 131, 8, 8, 132, 7, 7, 133, 7, 7, 133, 21, 103, 105, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 125, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 127, + 7, 7, 142, 7, 7, 154, 7, 7, 162, 7, 7, 165, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 156, 7, 7, 157, 7, 7, 156, 7, 7, 153, + 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 135, 7, 7, 126, 7, 7, 118, 7, 7, 104, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 79, 7, 7, 87, 7, 7, 94, 7, 7, 98, + 7, 7, 102, 7, 7, 105, 7, 7, 106, 7, 7, 118, 7, 7, 165, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 11, 54, 140, 23, 121, 94, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 22, 113, 101, 8, 28, 139, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 21, 103, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 12, 63, 131, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 23, 121, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 8, 35, 132, 22, 120, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 189, 7, 7, 187, 7, 7, 183, 7, 7, 178, 21, 103, 127, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 150, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, + 7, 7, 164, 7, 7, 165, 23, 118, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 143, 7, 7, 154, 7, 7, 153, + 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 23, 118, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 148, 7, 7, 145, 21, 103, 113, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 83, 14, 70, 122, 8, 8, 132, 8, 8, 132, + 8, 8, 133, 7, 7, 133, 7, 7, 134, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 125, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 133, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 128, 7, 7, 124, 7, 7, 140, 7, 7, 158, 7, 7, 164, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, + 7, 7, 156, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 156, 7, 7, 152, 7, 7, 148, 7, 7, 145, 7, 7, 141, 7, 7, 138, 7, 7, 134, 7, 7, 125, 7, 7, 118, 7, 7, 104, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, + 7, 7, 68, 7, 7, 79, 7, 7, 87, 7, 7, 94, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 106, 7, 7, 111, 7, 7, 152, 7, 7, 171, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 152, + 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 147, 7, 7, 147, + 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 148, 9, 37, 143, 22, 114, 101, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 19, 102, 109, 8, 28, 139, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 21, 103, 110, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 131, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 23, 121, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 11, 54, 128, 23, 123, 89, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 21, 112, 99, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 193, 7, 7, 190, 7, 7, 185, 7, 7, 180, 21, 103, 129, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 152, 7, 7, 164, 7, 7, 164, + 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 167, 23, 118, 103, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 21, 103, 119, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 12, 63, 144, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 146, 23, 118, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 146, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 23, 149, 19, 105, 112, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 127, 84, 13, 73, 121, 7, 7, 134, 8, 8, 133, 7, 7, 132, 8, 8, 132, 7, 7, 132, 7, 7, 133, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 127, 7, 7, 120, 7, 7, 135, 7, 7, 159, 7, 7, 166, 7, 7, 169, 7, 7, 169, 7, 7, 167, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, + 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 156, 7, 7, 159, 7, 7, 161, 7, 7, 163, 7, 7, 161, 7, 7, 157, 7, 7, 153, 7, 7, 149, 7, 7, 145, 7, 7, 141, 7, 7, 138, 7, 7, 134, 7, 7, 124, 7, 7, 117, 7, 7, 103, 7, 7, 72, 36, 36, 40, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 79, 7, 7, 87, 7, 7, 95, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 108, 7, 7, 129, 7, 7, 172, 7, 7, 169, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 149, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 23, 145, 17, 87, 123, 24, 124, 89, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 123, 90, 16, 80, 124, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 21, 103, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 131, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 23, 121, 92, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 10, 44, 130, 22, 117, 96, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 17, 87, 116, 15, 75, 121, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 194, 7, 7, 194, 7, 7, 188, 7, 7, 183, 21, 103, 130, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 12, 63, 155, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 23, 118, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 160, 7, 7, 161, 7, 7, 162, + 7, 7, 161, 21, 103, 120, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 145, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 23, 118, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 7, 20, 148, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 150, 17, 88, 125, 26, 128, 84, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 123, 90, 13, 68, 126, 7, 7, 136, 7, 7, 135, 8, 8, 133, 8, 8, 133, 8, 8, 132, 7, 7, 133, 7, 7, 133, 21, 103, 105, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 133, + 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 127, 7, 7, 121, 7, 7, 127, 7, 7, 160, 7, 7, 168, 7, 7, 171, 7, 7, 170, 7, 7, 168, + 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 162, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 159, 7, 7, 155, 7, 7, 150, 7, 7, 146, 7, 7, 141, 7, 7, 137, 7, 7, 133, + 7, 7, 123, 7, 7, 116, 7, 7, 103, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 68, 7, 7, 80, 7, 7, 87, 7, 7, 95, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 108, 7, 7, 113, 7, 7, 162, + 7, 7, 171, 7, 7, 166, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 147, 7, 7, 140, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 144, 8, 31, 141, 18, 94, 116, 24, 122, 91, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 24, 121, 93, 18, 91, 118, 8, 28, 139, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 142, 21, 103, 110, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 131, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 23, 121, 92, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 127, 84, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 23, 135, 17, 87, 117, 24, 124, 88, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 23, 119, 93, 13, 67, 124, 7, 7, 135, 15, 75, 121, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 8, 35, 192, 7, 7, 196, 7, 7, 190, + 7, 7, 187, 21, 103, 132, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 157, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 23, 118, 104, 25, 129, 82, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 7, 20, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 21, 103, 120, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 145, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, + 7, 7, 147, 23, 118, 97, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 7, 20, 150, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 10, 49, 144, 19, 102, 113, 25, 128, 84, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 25, 129, 82, 26, 128, 84, 19, 97, 113, 8, 32, 138, 7, 7, 139, 7, 7, 137, 7, 7, 135, 8, 8, 134, 8, 8, 133, 8, 8, 132, 8, 8, 132, 8, 8, 133, 21, 103, 105, 25, 129, 82, 25, 129, 82, + 25, 129, 82, 25, 129, 82, 25, 129, 82, 12, 63, 124, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 129, 7, 7, 120, 7, 7, 121, + 7, 7, 160, 7, 7, 170, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 166, 7, 7, 168, 7, 7, 168, 7, 7, 165, 7, 7, 160, 7, 7, 156, + 7, 7, 151, 7, 7, 147, 7, 7, 142, 7, 7, 137, 7, 7, 132, 7, 7, 122, 7, 7, 115, 7, 7, 102, 7, 7, 71, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 87, 7, 7, 95, 7, 7, 99, 7, 7, 102, + 7, 7, 105, 7, 7, 107, 7, 7, 108, 7, 7, 110, 7, 7, 142, 7, 7, 173, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 147, 7, 7, 139, 7, 7, 142, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 150, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 12, 61, 134, 18, 94, 119, 21, 111, 107, 22, 117, 99, 24, 124, 91, 25, 128, 84, 24, 125, 89, 22, 120, 95, 22, 110, 106, + 17, 93, 119, 13, 64, 132, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 8, 28, 136, 15, 74, 124, 19, 102, 108, 22, 117, 96, 23, 123, 90, 26, 128, 83, 24, 125, 87, 23, 119, 93, 20, 104, 105, 15, 74, 122, 9, 20, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 149, 7, 7, 197, 7, 7, 198, 7, 7, 195, 7, 7, 192, 7, 7, 189, 7, 7, 185, 7, 7, 182, 7, 7, 179, 7, 7, 177, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 169, + 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 9, 39, 144, 15, 81, 129, 19, 106, 111, 23, 117, 99, 24, 124, 91, 26, 128, 84, 24, 124, 90, 22, 117, 99, 20, 108, 108, 16, 81, 127, 10, 33, 142, 7, 7, 145, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 136, 8, 8, 133, 8, 8, 132, + 8, 8, 132, 8, 8, 132, 8, 8, 133, 8, 8, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 122, 7, 7, 118, 7, 7, 157, 7, 7, 173, 7, 7, 176, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 169, + 7, 7, 171, 7, 7, 170, 7, 7, 167, 7, 7, 162, 7, 7, 157, 7, 7, 153, 7, 7, 147, 7, 7, 143, 7, 7, 138, 7, 7, 132, 7, 7, 122, 7, 7, 114, 7, 7, 101, 7, 7, 70, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, + 7, 7, 80, 7, 7, 87, 7, 7, 95, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 108, 7, 7, 110, 7, 7, 121, 7, 7, 167, 7, 7, 173, 7, 7, 167, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 154, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 149, 7, 7, 143, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 143, 7, 7, 190, 7, 7, 202, 7, 7, 199, 7, 7, 198, 7, 7, 198, 7, 7, 192, 7, 7, 187, 7, 7, 183, 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 175, 7, 7, 174, 7, 7, 173, + 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 137, 7, 7, 134, 7, 7, 132, 8, 8, 132, 8, 8, 132, 8, 8, 132, 8, 8, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 130, 7, 7, 125, 7, 7, 118, 7, 7, 157, 7, 7, 178, 7, 7, 182, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 177, 7, 7, 173, 7, 7, 169, 7, 7, 168, + 7, 7, 169, 7, 7, 171, 7, 7, 172, 7, 7, 171, 7, 7, 171, 7, 7, 172, 7, 7, 172, 7, 7, 169, 7, 7, 164, 7, 7, 159, 7, 7, 154, 7, 7, 150, 7, 7, 144, 7, 7, 139, 7, 7, 133, 7, 7, 122, 7, 7, 114, 7, 7, 100, 7, 7, 70, 36, 36, 40, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 87, 7, 7, 94, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 108, 7, 7, 110, 7, 7, 112, 7, 7, 141, 7, 7, 174, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 167, + 7, 7, 166, 7, 7, 164, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 148, 7, 7, 158, 7, 7, 153, 7, 7, 155, 7, 7, 177, 7, 7, 198, 7, 7, 190, 7, 7, 186, 7, 7, 183, + 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, + 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, + 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 8, 8, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 131, + 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 125, 7, 7, 118, 7, 7, 136, 7, 7, 139, 7, 7, 141, 7, 7, 148, 7, 7, 157, 7, 7, 161, + 7, 7, 167, 7, 7, 177, 7, 7, 179, 7, 7, 173, 7, 7, 172, 7, 7, 173, 7, 7, 175, 7, 7, 176, 7, 7, 174, 7, 7, 173, 7, 7, 174, 7, 7, 174, 7, 7, 173, 7, 7, 167, 7, 7, 162, 7, 7, 157, 7, 7, 152, 7, 7, 147, 7, 7, 141, 7, 7, 133, 7, 7, 122, + 7, 7, 113, 7, 7, 100, 7, 7, 69, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 87, 7, 7, 94, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 119, + 7, 7, 154, 7, 7, 175, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 167, 7, 7, 163, 7, 7, 160, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 156, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 149, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 148, 7, 7, 197, 7, 7, 193, 7, 7, 187, 7, 7, 184, 7, 7, 181, 7, 7, 179, 7, 7, 177, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 162, + 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 8, 8, 143, 8, 8, 141, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 134, + 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 124, 7, 7, 118, 7, 7, 123, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 140, 7, 7, 168, 7, 7, 179, 7, 7, 177, 7, 7, 178, 7, 7, 180, 7, 7, 179, 7, 7, 176, 7, 7, 175, 7, 7, 176, 7, 7, 179, 7, 7, 177, 7, 7, 172, 7, 7, 165, 7, 7, 160, + 7, 7, 155, 7, 7, 149, 7, 7, 142, 7, 7, 134, 7, 7, 121, 7, 7, 113, 7, 7, 99, 7, 7, 69, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 68, 7, 7, 79, 7, 7, 87, 7, 7, 94, 7, 7, 98, 7, 7, 102, 7, 7, 105, + 7, 7, 107, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 120, 7, 7, 157, 7, 7, 179, 7, 7, 178, 7, 7, 177, 7, 7, 175, 7, 7, 171, 7, 7, 166, 7, 7, 163, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 158, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 141, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 145, 7, 7, 197, 7, 7, 193, 7, 7, 187, 7, 7, 184, 7, 7, 181, 7, 7, 179, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 168, + 7, 7, 166, 7, 7, 165, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, + 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 8, 8, 144, 8, 8, 142, 8, 8, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 130, 7, 7, 124, 7, 7, 126, 7, 7, 126, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 129, 7, 7, 167, 7, 7, 183, 7, 7, 184, 7, 7, 184, 7, 7, 182, 7, 7, 179, 7, 7, 177, 7, 7, 180, + 7, 7, 165, 7, 7, 146, 7, 7, 166, 7, 7, 170, 7, 7, 163, 7, 7, 158, 7, 7, 151, 7, 7, 143, 7, 7, 135, 7, 7, 121, 7, 7, 112, 7, 7, 99, 7, 7, 69, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 68, 7, 7, 79, + 7, 7, 86, 7, 7, 94, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 108, 7, 7, 109, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 119, 7, 7, 138, 7, 7, 156, 7, 7, 169, 7, 7, 176, 7, 7, 178, 7, 7, 172, 7, 7, 167, 7, 7, 163, 7, 7, 160, + 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 151, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 135, 7, 7, 136, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 143, 7, 7, 196, 7, 7, 193, 7, 7, 188, 7, 7, 185, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 173, 7, 7, 172, + 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, + 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 144, 7, 7, 145, 7, 7, 147, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 8, 8, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 128, 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 124, 7, 7, 142, 7, 7, 162, + 7, 7, 180, 7, 7, 186, 7, 7, 182, 7, 7, 181, 7, 7, 170, 7, 7, 125, 7, 7, 111, 7, 7, 134, 7, 7, 171, 7, 7, 167, 7, 7, 160, 7, 7, 154, 7, 7, 145, 7, 7, 135, 7, 7, 121, 7, 7, 112, 7, 7, 99, 7, 7, 69, 36, 36, 40, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 68, 7, 7, 78, 7, 7, 86, 7, 7, 93, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 108, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 119, 7, 7, 123, 7, 7, 133, + 7, 7, 154, 7, 7, 175, 7, 7, 172, 7, 7, 167, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 159, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 160, 7, 7, 162, + 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 152, 7, 7, 149, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, + 7, 7, 151, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 171, 7, 7, 174, 7, 7, 140, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 139, 7, 7, 192, 7, 7, 195, 7, 7, 189, 7, 7, 185, 7, 7, 182, + 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, + 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 148, + 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 145, + 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 139, 7, 7, 136, 7, 7, 134, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 121, 7, 7, 132, 7, 7, 158, 7, 7, 176, 7, 7, 174, 7, 7, 137, 7, 7, 114, 7, 7, 112, 7, 7, 118, 7, 7, 163, 7, 7, 169, 7, 7, 162, 7, 7, 155, 7, 7, 146, 7, 7, 135, 7, 7, 121, 7, 7, 112, + 7, 7, 100, 7, 7, 70, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 78, 7, 7, 85, 7, 7, 93, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 116, + 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 123, 7, 7, 151, 7, 7, 177, 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, + 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 147, + 7, 7, 150, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 140, 7, 7, 198, 7, 7, 203, 7, 7, 162, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 176, 7, 7, 197, 7, 7, 192, 7, 7, 186, 7, 7, 182, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, + 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 148, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 147, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 146, 7, 7, 141, 7, 7, 135, 7, 7, 130, 7, 7, 129, 7, 7, 131, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 117, 7, 7, 120, 7, 7, 128, 7, 7, 129, 7, 7, 115, 7, 7, 113, 7, 7, 112, 7, 7, 113, 7, 7, 157, 7, 7, 170, 7, 7, 162, + 7, 7, 155, 7, 7, 146, 7, 7, 136, 7, 7, 122, 7, 7, 114, 7, 7, 101, 7, 7, 71, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 67, 7, 7, 78, 7, 7, 85, 7, 7, 93, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 109, + 7, 7, 111, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 119, 7, 7, 125, 7, 7, 169, 7, 7, 177, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, + 7, 7, 158, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, + 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 153, 7, 7, 155, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, + 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 181, 7, 7, 205, + 7, 7, 189, 7, 7, 139, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 155, 7, 7, 196, 7, 7, 194, 7, 7, 187, 7, 7, 183, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, + 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 153, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 149, + 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, + 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 149, 7, 7, 145, 7, 7, 137, 7, 7, 133, 7, 7, 131, 7, 7, 128, + 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, + 7, 7, 112, 7, 7, 111, 7, 7, 151, 7, 7, 170, 7, 7, 161, 7, 7, 153, 7, 7, 145, 7, 7, 137, 7, 7, 123, 7, 7, 115, 7, 7, 102, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 67, 7, 7, 78, 7, 7, 85, + 7, 7, 93, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 113, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 156, 7, 7, 180, 7, 7, 175, 7, 7, 172, + 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 160, + 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 155, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 147, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 149, 7, 7, 194, 7, 7, 203, 7, 7, 150, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 145, 7, 7, 193, 7, 7, 194, 7, 7, 187, 7, 7, 182, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 171, + 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, + 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 150, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, + 7, 7, 148, 7, 7, 144, 7, 7, 137, 7, 7, 131, 7, 7, 127, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, + 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 139, 7, 7, 168, 7, 7, 159, 7, 7, 151, 7, 7, 144, 7, 7, 136, 7, 7, 124, 7, 7, 116, 7, 7, 103, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 39, 10, 10, 47, 7, 7, 67, 7, 7, 78, 7, 7, 85, 7, 7, 93, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 111, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, + 7, 7, 120, 7, 7, 150, 7, 7, 181, 7, 7, 177, 7, 7, 175, 7, 7, 174, 7, 7, 171, 7, 7, 169, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 151, 7, 7, 155, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 158, + 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 158, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, + 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 147, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, + 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 159, 7, 7, 180, 7, 7, 142, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 149, 7, 7, 194, 7, 7, 193, 7, 7, 186, 7, 7, 181, 7, 7, 178, + 7, 7, 175, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, + 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 146, 7, 7, 138, 7, 7, 131, 7, 7, 126, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 110, 7, 7, 132, 7, 7, 166, 7, 7, 158, 7, 7, 150, 7, 7, 142, 7, 7, 135, 7, 7, 124, 7, 7, 117, 7, 7, 104, + 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 78, 7, 7, 86, 7, 7, 93, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 119, + 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 152, 7, 7, 182, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 174, 7, 7, 171, 7, 7, 166, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 147, 7, 7, 154, 7, 7, 157, + 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 157, 7, 7, 160, 7, 7, 162, 7, 7, 162, + 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 152, 7, 7, 147, 7, 7, 145, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 67, 20, 136, 242, 74, 92, 209, 62, 107, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 137, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 161, + 7, 7, 196, 7, 7, 189, 7, 7, 183, 7, 7, 179, 7, 7, 176, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, + 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 67, 20, 153, 242, 74, 92, 209, 62, 113, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, + 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 146, 7, 7, 138, 7, 7, 136, 7, 7, 146, 7, 7, 138, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 121, 7, 7, 142, 7, 7, 148, 7, 7, 134, 7, 7, 129, 7, 7, 140, 7, 7, 155, 7, 7, 137, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 110, 7, 7, 128, 7, 7, 165, 7, 7, 157, 7, 7, 148, + 7, 7, 141, 7, 7, 135, 7, 7, 124, 7, 7, 117, 7, 7, 104, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 79, 7, 7, 86, 7, 7, 94, 7, 7, 99, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, + 7, 7, 114, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 154, 7, 7, 182, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 178, 7, 7, 173, 7, 7, 167, 7, 7, 161, 7, 7, 158, + 7, 7, 155, 7, 7, 149, 7, 7, 147, 7, 7, 153, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, + 7, 7, 155, 7, 7, 158, 7, 7, 161, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 156, 7, 7, 157, 7, 7, 159, 7, 7, 161, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, + 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 67, 20, 136, 242, 74, 92, 209, 62, 107, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 173, 233, 70, 103, 242, 74, 92, 242, 74, 92, 231, 70, 103, 199, 59, 129, 77, 21, 167, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 171, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 170, + 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, + 7, 7, 159, 7, 7, 157, 67, 20, 153, 242, 74, 92, 209, 62, 113, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 144, 7, 7, 147, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 44, 14, 147, 176, 52, 124, + 226, 69, 101, 238, 73, 94, 222, 68, 103, 134, 37, 137, 7, 7, 150, 7, 7, 151, 135, 39, 139, 223, 68, 105, 238, 72, 93, 217, 66, 109, 105, 30, 144, 7, 7, 152, 44, 14, 150, 176, 52, 126, 226, 69, 102, 238, 73, 94, 222, 68, 103, 134, 37, 135, 7, 7, 147, 99, 26, 144, 200, 59, 117, + 229, 69, 101, 237, 72, 95, 218, 67, 106, 137, 39, 138, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 144, 7, 7, 145, 7, 7, 176, 7, 7, 196, 7, 7, 189, + 7, 7, 137, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 132, 7, 7, 186, 7, 7, 193, 7, 7, 188, 7, 7, 185, 7, 7, 186, 7, 7, 186, 7, 7, 175, 7, 7, 122, 7, 7, 114, 7, 7, 113, + 7, 7, 111, 7, 7, 124, 7, 7, 164, 7, 7, 156, 7, 7, 147, 7, 7, 141, 7, 7, 134, 7, 7, 124, 7, 7, 117, 7, 7, 105, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 79, 7, 7, 86, 7, 7, 94, + 7, 7, 99, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 156, 7, 7, 182, 7, 7, 180, 7, 7, 182, 7, 7, 183, + 7, 7, 179, 7, 7, 171, 7, 7, 164, 7, 7, 159, 7, 7, 155, 7, 7, 153, 7, 7, 147, 7, 7, 149, 7, 7, 152, 7, 7, 156, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, + 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 161, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 159, 7, 7, 161, + 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 67, 20, 136, 242, 74, 92, 208, 63, 108, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 180, 233, 70, 103, 236, 71, 99, 178, 52, 144, 210, 63, 122, 242, 74, 92, 201, 60, 125, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 171, + 7, 7, 173, 7, 7, 174, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 167, + 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 67, 20, 154, 242, 74, 92, 209, 62, 113, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 142, 7, 7, 145, 7, 7, 149, 7, 7, 151, + 7, 7, 151, 7, 7, 149, 7, 7, 148, 135, 38, 135, 241, 74, 92, 215, 65, 108, 187, 55, 120, 235, 71, 95, 236, 71, 95, 65, 17, 146, 69, 19, 148, 236, 71, 95, 232, 70, 98, 190, 56, 121, 238, 72, 93, 220, 66, 106, 7, 7, 151, 135, 38, 139, 241, 74, 92, 215, 65, 109, 187, 55, 121, + 235, 71, 95, 236, 71, 95, 65, 17, 143, 99, 26, 142, 229, 70, 99, 197, 59, 118, 187, 55, 123, 236, 72, 95, 237, 72, 95, 51, 12, 150, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 171, 7, 7, 190, 7, 7, 194, 7, 7, 194, 7, 7, 140, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 126, 7, 7, 169, 7, 7, 188, 7, 7, 189, 7, 7, 185, 7, 7, 183, + 7, 7, 182, 7, 7, 177, 7, 7, 126, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 124, 7, 7, 163, 7, 7, 156, 7, 7, 147, 7, 7, 140, 7, 7, 135, 7, 7, 125, 7, 7, 118, 7, 7, 106, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 47, 7, 7, 68, 7, 7, 79, 7, 7, 87, 7, 7, 94, 7, 7, 99, 7, 7, 104, 7, 7, 108, 7, 7, 111, 7, 7, 113, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 142, 7, 7, 179, 7, 7, 184, 7, 7, 186, 7, 7, 184, 7, 7, 177, 7, 7, 168, 7, 7, 160, 7, 7, 156, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, + 7, 7, 156, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 157, 7, 7, 160, 7, 7, 163, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, + 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 67, 20, 137, 242, 74, 92, 208, 63, 108, 204, 61, 110, 238, 72, 93, 211, 64, 106, + 87, 25, 134, 219, 66, 102, 242, 74, 92, 90, 24, 133, 7, 7, 136, 131, 38, 127, 242, 74, 92, 200, 59, 109, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 183, 233, 70, 103, 229, 69, 106, 7, 7, 178, 31, 10, 173, 232, 70, 100, 235, 71, 98, + 7, 7, 169, 67, 20, 165, 242, 74, 92, 170, 50, 141, 201, 60, 126, 238, 72, 95, 238, 73, 95, 242, 74, 92, 90, 24, 168, 7, 7, 173, 131, 38, 156, 242, 74, 92, 200, 59, 126, 67, 20, 166, 242, 74, 92, 178, 52, 136, 210, 63, 118, 236, 71, 97, 218, 66, 113, 127, 37, 152, 205, 61, 121, + 236, 71, 97, 222, 67, 109, 115, 34, 155, 7, 7, 167, 83, 23, 163, 242, 74, 92, 205, 61, 122, 7, 7, 166, 7, 7, 164, 224, 68, 107, 236, 72, 95, 7, 7, 158, 67, 20, 154, 242, 74, 92, 209, 62, 114, 7, 7, 153, 7, 7, 153, 165, 49, 130, 223, 68, 104, 237, 72, 95, 229, 69, 101, + 164, 48, 127, 7, 7, 146, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 148, 123, 36, 137, 7, 7, 146, 7, 7, 146, 197, 58, 117, 242, 74, 92, 117, 33, 140, 152, 43, 134, 242, 74, 92, 169, 49, 128, 7, 7, 151, 193, 58, 120, 242, 74, 92, + 110, 31, 142, 7, 7, 150, 123, 36, 140, 7, 7, 149, 7, 7, 148, 197, 58, 116, 242, 74, 92, 117, 33, 137, 7, 7, 146, 31, 10, 148, 7, 7, 151, 7, 7, 151, 207, 62, 112, 240, 73, 93, 57, 14, 146, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 153, 7, 7, 186, 7, 7, 191, 7, 7, 194, 7, 7, 175, 7, 7, 129, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 128, 7, 7, 159, 7, 7, 186, 7, 7, 184, 7, 7, 182, 7, 7, 182, 7, 7, 167, 7, 7, 119, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 132, 7, 7, 163, 7, 7, 154, 7, 7, 146, 7, 7, 141, 7, 7, 135, 7, 7, 126, 7, 7, 120, 7, 7, 107, 7, 7, 75, + 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 79, 7, 7, 87, 7, 7, 95, 7, 7, 100, 7, 7, 104, 7, 7, 108, 7, 7, 111, 7, 7, 113, 7, 7, 115, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 144, 7, 7, 164, 7, 7, 168, 7, 7, 174, 7, 7, 176, 7, 7, 166, 7, 7, 157, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 153, 7, 7, 154, + 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 161, 7, 7, 162, 7, 7, 161, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 67, 20, 137, + 242, 74, 92, 242, 74, 92, 199, 59, 111, 206, 61, 109, 242, 74, 92, 201, 60, 110, 167, 50, 120, 242, 74, 92, 164, 48, 121, 7, 7, 136, 187, 55, 113, 242, 74, 92, 140, 40, 124, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 181, 233, 70, 103, + 229, 69, 106, 7, 7, 178, 44, 14, 173, 235, 71, 99, 234, 71, 100, 7, 7, 169, 67, 20, 165, 242, 74, 92, 240, 73, 92, 220, 66, 112, 184, 54, 137, 176, 51, 143, 242, 74, 92, 164, 48, 148, 7, 7, 175, 187, 55, 135, 242, 74, 92, 140, 40, 153, 67, 20, 167, 242, 74, 92, 242, 74, 92, + 205, 61, 123, 207, 62, 121, 242, 74, 92, 242, 74, 92, 209, 62, 119, 201, 60, 123, 242, 74, 92, 210, 63, 118, 7, 7, 168, 83, 23, 164, 242, 74, 92, 205, 61, 122, 7, 7, 167, 7, 7, 165, 224, 68, 107, 236, 72, 95, 7, 7, 159, 67, 20, 155, 242, 74, 92, 209, 62, 114, 7, 7, 155, + 7, 7, 153, 165, 48, 130, 200, 59, 116, 184, 54, 122, 226, 69, 102, 241, 74, 92, 106, 30, 144, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 31, 10, 147, 223, 67, 103, 238, 72, 94, 69, 19, 145, 178, 52, 125, + 242, 74, 92, 136, 40, 138, 7, 7, 150, 165, 49, 129, 242, 74, 92, 146, 42, 134, 7, 7, 150, 7, 7, 149, 7, 7, 148, 31, 10, 147, 223, 67, 103, 238, 72, 94, 69, 19, 144, 7, 7, 148, 90, 24, 143, 178, 52, 125, 197, 59, 117, 236, 72, 94, 167, 49, 126, 7, 7, 144, 7, 7, 142, + 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 148, 7, 7, 184, 7, 7, 184, 7, 7, 159, 7, 7, 132, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 125, 7, 7, 166, 7, 7, 187, 7, 7, 186, 7, 7, 179, 7, 7, 142, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 116, 7, 7, 154, 7, 7, 163, 7, 7, 153, 7, 7, 146, 7, 7, 141, + 7, 7, 136, 7, 7, 128, 7, 7, 120, 7, 7, 108, 7, 7, 76, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 68, 7, 7, 79, 7, 7, 87, 7, 7, 95, 7, 7, 100, 7, 7, 105, 7, 7, 108, 7, 7, 111, 7, 7, 114, 7, 7, 116, + 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 125, 7, 7, 130, 7, 7, 141, 7, 7, 161, 7, 7, 164, 7, 7, 157, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 8, 8, 151, 7, 7, 153, 7, 7, 156, 7, 7, 159, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 154, + 7, 7, 153, 7, 7, 155, 7, 7, 157, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 67, 20, 137, 242, 74, 92, 223, 67, 101, 7, 7, 140, 25, 12, 139, 231, 70, 97, 236, 71, 94, 77, 21, 135, 239, 73, 92, 211, 64, 106, 7, 7, 136, 226, 69, 99, 233, 70, 96, 41, 9, 151, 7, 7, 144, 7, 7, 136, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 174, 233, 70, 103, 236, 71, 99, 180, 53, 143, 215, 64, 117, 242, 74, 92, 194, 57, 130, 7, 7, 171, 67, 20, 167, 242, 74, 92, 227, 69, 105, 48, 12, 172, 7, 7, 174, 77, 21, 171, 239, 73, 94, 211, 64, 122, 7, 7, 176, 226, 69, 108, + 233, 70, 100, 41, 9, 174, 67, 20, 171, 242, 74, 92, 229, 69, 105, 7, 7, 173, 57, 14, 169, 242, 74, 92, 233, 71, 100, 36, 9, 168, 31, 10, 167, 236, 72, 96, 227, 69, 105, 7, 7, 169, 83, 23, 165, 242, 74, 92, 205, 61, 123, 7, 7, 168, 7, 7, 166, 224, 68, 107, 236, 72, 95, + 7, 7, 160, 67, 20, 156, 242, 74, 92, 209, 62, 114, 7, 7, 156, 7, 7, 153, 83, 23, 147, 160, 46, 131, 176, 52, 125, 209, 62, 111, 242, 74, 92, 147, 42, 135, 7, 7, 152, 8, 8, 151, 9, 9, 152, 8, 8, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 179, 53, 124, 242, 74, 92, 177, 52, 125, 7, 7, 149, 184, 54, 122, 242, 74, 92, 129, 36, 139, 7, 7, 151, 158, 47, 131, 242, 74, 92, 161, 48, 129, 7, 7, 149, 7, 7, 149, 7, 7, 148, 179, 53, 123, 242, 74, 92, 177, 52, 124, 7, 7, 147, 7, 7, 147, 122, 34, 138, 242, 74, 92, + 242, 74, 92, 223, 67, 102, 157, 45, 126, 7, 7, 137, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 138, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 132, 7, 7, 142, 7, 7, 137, 7, 7, 126, 7, 7, 124, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 128, 7, 7, 153, 7, 7, 153, 7, 7, 134, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 143, + 7, 7, 166, 7, 7, 159, 7, 7, 151, 7, 7, 145, 7, 7, 141, 7, 7, 137, 7, 7, 128, 7, 7, 121, 7, 7, 109, 7, 7, 78, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 68, 7, 7, 80, 7, 7, 88, 7, 7, 96, 7, 7, 101, + 7, 7, 105, 7, 7, 109, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 124, 7, 7, 131, 7, 7, 138, 7, 7, 149, + 7, 7, 158, 7, 7, 157, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 8, 8, 151, 8, 8, 151, 11, 11, 152, 8, 8, 155, 7, 7, 158, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 154, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 152, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 159, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 157, + 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 67, 20, 138, 242, 74, 92, 210, 63, 107, 7, 7, 140, 7, 7, 140, 218, 66, 104, 242, 74, 92, 51, 12, 137, 204, 62, 108, 239, 73, 93, 125, 35, 127, 242, 74, 92, + 191, 57, 128, 7, 7, 197, 7, 7, 188, 7, 7, 171, 7, 7, 160, 7, 7, 152, 7, 7, 139, 7, 7, 134, 7, 7, 170, 233, 70, 104, 242, 74, 92, 241, 74, 93, 232, 70, 102, 193, 58, 133, 59, 18, 171, 7, 7, 173, 67, 20, 168, 242, 74, 92, 210, 63, 121, 7, 7, 173, 7, 7, 174, + 7, 7, 176, 204, 62, 126, 239, 73, 94, 125, 35, 162, 242, 74, 92, 191, 57, 135, 7, 7, 177, 67, 20, 174, 242, 74, 92, 211, 64, 121, 7, 7, 175, 7, 7, 173, 240, 73, 93, 220, 66, 112, 7, 7, 170, 7, 7, 169, 231, 70, 102, 229, 69, 103, 7, 7, 170, 83, 23, 166, 242, 74, 92, + 205, 61, 123, 7, 7, 169, 7, 7, 167, 226, 69, 105, 236, 72, 96, 7, 7, 161, 67, 20, 158, 242, 74, 92, 209, 62, 115, 7, 7, 156, 103, 28, 146, 236, 72, 96, 242, 74, 92, 242, 74, 92, 242, 74, 92, 242, 74, 92, 151, 44, 135, 7, 7, 151, 10, 10, 151, 12, 12, 152, 12, 12, 152, + 9, 9, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 160, 46, 129, 242, 74, 92, 205, 61, 113, 36, 9, 149, 7, 7, 150, 173, 51, 127, 242, 74, 92, 136, 40, 138, 7, 7, 151, 164, 49, 128, 242, 74, 92, 152, 45, 132, 7, 7, 149, 7, 7, 149, 160, 46, 129, 242, 74, 92, 205, 61, 113, + 36, 9, 147, 7, 7, 148, 7, 7, 146, 7, 7, 148, 25, 12, 148, 90, 26, 140, 217, 65, 105, 242, 74, 92, 120, 35, 124, 7, 7, 127, 7, 7, 129, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 127, + 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 120, 7, 7, 119, 7, 7, 117, + 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 122, 7, 7, 167, 7, 7, 164, 7, 7, 155, 7, 7, 149, 7, 7, 144, 7, 7, 140, 7, 7, 136, 7, 7, 128, 7, 7, 121, 7, 7, 109, 7, 7, 79, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, + 7, 7, 69, 7, 7, 80, 7, 7, 88, 7, 7, 96, 7, 7, 101, 7, 7, 106, 7, 7, 109, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 125, 7, 7, 132, 7, 7, 141, 7, 7, 149, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 9, 9, 149, 16, 16, 151, 11, 11, 154, 7, 7, 157, 7, 7, 160, 7, 7, 163, 7, 7, 162, + 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 152, 7, 7, 153, 7, 7, 157, 7, 7, 161, 7, 7, 163, + 7, 7, 162, 7, 7, 161, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 67, 20, 138, 242, 74, 92, 225, 68, 101, 7, 7, 140, 31, 10, 140, 232, 71, 96, 235, 71, 94, + 7, 7, 138, 143, 42, 125, 242, 74, 92, 213, 65, 104, 242, 74, 92, 127, 37, 172, 7, 7, 196, 7, 7, 196, 7, 7, 198, 7, 7, 199, 7, 7, 196, 7, 7, 177, 7, 7, 144, 7, 7, 168, 233, 70, 104, 229, 69, 107, 7, 7, 183, 7, 7, 179, 7, 7, 177, 7, 7, 176, 7, 7, 175, + 67, 20, 170, 242, 74, 92, 209, 62, 121, 7, 7, 174, 7, 7, 175, 7, 7, 176, 143, 42, 157, 242, 74, 92, 213, 65, 120, 242, 74, 92, 127, 37, 163, 7, 7, 180, 67, 20, 177, 242, 74, 92, 209, 62, 124, 7, 7, 176, 7, 7, 174, 240, 73, 93, 219, 66, 114, 7, 7, 171, 7, 7, 170, + 231, 70, 102, 229, 69, 103, 7, 7, 172, 73, 22, 169, 242, 74, 92, 210, 63, 120, 7, 7, 171, 48, 12, 167, 237, 72, 96, 236, 72, 96, 7, 7, 163, 67, 20, 159, 242, 74, 92, 209, 62, 116, 7, 7, 157, 169, 49, 131, 242, 74, 92, 187, 55, 122, 54, 16, 149, 171, 50, 128, 242, 74, 92, + 151, 45, 134, 10, 10, 151, 16, 16, 152, 14, 14, 152, 13, 13, 153, 12, 12, 152, 8, 8, 151, 7, 7, 150, 147, 42, 135, 240, 73, 92, 208, 62, 112, 48, 12, 150, 7, 7, 151, 7, 7, 152, 145, 43, 136, 242, 74, 92, 169, 49, 129, 7, 7, 151, 192, 57, 119, 242, 74, 92, 118, 33, 139, + 7, 7, 149, 147, 42, 134, 240, 73, 92, 208, 62, 111, 48, 12, 147, 7, 7, 148, 7, 7, 148, 25, 12, 146, 7, 7, 146, 7, 7, 146, 7, 7, 142, 192, 57, 111, 242, 74, 92, 150, 44, 113, 7, 7, 130, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, + 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 138, 7, 7, 170, 7, 7, 161, 7, 7, 153, 7, 7, 147, 7, 7, 142, 7, 7, 139, 7, 7, 135, 7, 7, 126, 7, 7, 120, 7, 7, 109, 7, 7, 79, 36, 36, 40, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 89, 7, 7, 97, 7, 7, 102, 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 123, 7, 7, 123, + 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 129, 7, 7, 140, 7, 7, 149, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 8, 8, 150, 9, 9, 150, + 8, 8, 151, 7, 7, 154, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 146, 7, 7, 148, 7, 7, 147, + 7, 7, 149, 7, 7, 152, 7, 7, 157, 7, 7, 162, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 67, 20, 139, 242, 74, 92, + 242, 74, 92, 202, 61, 111, 206, 61, 109, 242, 74, 92, 200, 59, 111, 7, 7, 137, 36, 9, 136, 232, 71, 96, 240, 73, 91, 229, 69, 103, 18, 7, 195, 7, 7, 190, 7, 7, 190, 7, 7, 190, 7, 7, 193, 7, 7, 195, 7, 7, 201, 7, 7, 190, 7, 7, 187, 233, 70, 105, 229, 69, 108, + 7, 7, 185, 7, 7, 181, 7, 7, 179, 7, 7, 178, 7, 7, 178, 67, 20, 173, 242, 74, 92, 209, 62, 122, 7, 7, 175, 7, 7, 175, 7, 7, 176, 36, 9, 176, 232, 71, 102, 240, 73, 92, 229, 69, 107, 18, 7, 181, 7, 7, 183, 67, 20, 180, 242, 74, 92, 209, 62, 124, 7, 7, 177, + 7, 7, 175, 240, 73, 93, 219, 66, 114, 7, 7, 172, 7, 7, 172, 231, 70, 103, 229, 69, 104, 7, 7, 174, 7, 7, 175, 232, 70, 101, 238, 72, 95, 171, 50, 142, 201, 60, 125, 242, 74, 92, 236, 72, 96, 7, 7, 164, 67, 20, 161, 242, 74, 92, 209, 62, 116, 7, 7, 158, 155, 46, 136, + 242, 74, 92, 219, 65, 106, 187, 55, 122, 232, 70, 97, 242, 74, 92, 152, 46, 134, 20, 20, 151, 18, 18, 152, 12, 12, 152, 13, 13, 152, 11, 11, 151, 7, 7, 150, 129, 36, 139, 238, 72, 94, 238, 73, 94, 182, 54, 124, 178, 52, 125, 178, 52, 125, 127, 35, 141, 48, 12, 151, 233, 70, 97, + 232, 70, 98, 190, 56, 120, 238, 72, 93, 226, 69, 102, 25, 12, 150, 129, 36, 139, 238, 72, 94, 238, 73, 93, 182, 54, 122, 178, 52, 124, 178, 52, 124, 127, 35, 138, 182, 54, 122, 207, 62, 110, 183, 55, 117, 194, 58, 111, 238, 72, 93, 236, 72, 93, 85, 22, 131, 7, 7, 139, 7, 7, 138, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 116, 7, 7, 150, 7, 7, 169, 7, 7, 159, 7, 7, 152, 7, 7, 146, 7, 7, 141, 7, 7, 137, 7, 7, 133, + 7, 7, 124, 7, 7, 118, 7, 7, 107, 7, 7, 78, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 81, 7, 7, 89, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 118, + 7, 7, 119, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 128, 7, 7, 136, 7, 7, 149, 7, 7, 156, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 8, 8, 150, 8, 8, 149, 7, 7, 151, 7, 7, 153, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 141, + 7, 7, 141, 7, 7, 144, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 152, 7, 7, 157, 7, 7, 162, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 67, 20, 139, 242, 74, 92, 177, 52, 120, 207, 62, 108, 238, 72, 93, 210, 63, 107, 83, 23, 135, 7, 7, 137, 7, 7, 136, 187, 55, 113, 242, 74, 92, 183, 55, 144, 7, 7, 192, 7, 7, 187, 7, 7, 187, 7, 7, 188, 7, 7, 190, 7, 7, 193, + 7, 7, 199, 7, 7, 206, 7, 7, 207, 233, 70, 105, 229, 69, 108, 7, 7, 186, 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 180, 67, 20, 175, 242, 74, 92, 209, 62, 123, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 178, 187, 55, 138, 242, 74, 92, 183, 55, 142, 7, 7, 183, + 7, 7, 184, 67, 20, 181, 242, 74, 92, 209, 62, 124, 7, 7, 177, 7, 7, 175, 240, 73, 94, 219, 66, 115, 7, 7, 174, 7, 7, 174, 231, 70, 103, 229, 69, 104, 7, 7, 176, 7, 7, 176, 142, 42, 156, 228, 68, 107, 235, 71, 98, 201, 60, 125, 196, 58, 127, 236, 72, 96, 7, 7, 166, + 67, 20, 162, 242, 74, 92, 209, 62, 116, 7, 7, 157, 51, 12, 145, 206, 62, 112, 238, 73, 94, 222, 68, 104, 135, 38, 136, 240, 73, 93, 152, 48, 134, 24, 24, 151, 18, 18, 152, 12, 12, 151, 10, 10, 151, 7, 7, 151, 7, 7, 151, 180, 53, 124, 242, 74, 92, 242, 74, 92, 242, 74, 92, + 242, 74, 92, 242, 74, 92, 173, 51, 128, 7, 7, 152, 132, 38, 139, 224, 67, 104, 238, 72, 93, 217, 65, 107, 112, 31, 143, 7, 7, 151, 180, 53, 124, 242, 74, 92, 242, 74, 92, 242, 74, 92, 242, 74, 92, 242, 74, 92, 173, 51, 125, 150, 43, 131, 223, 68, 103, 237, 72, 94, 236, 72, 93, + 214, 64, 100, 127, 35, 127, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 149, 7, 7, 169, 7, 7, 159, + 7, 7, 152, 7, 7, 146, 7, 7, 141, 7, 7, 136, 7, 7, 131, 7, 7, 122, 7, 7, 116, 7, 7, 105, 7, 7, 76, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, 7, 7, 81, 7, 7, 90, 7, 7, 98, 7, 7, 103, 7, 7, 108, + 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 130, 7, 7, 143, 7, 7, 153, + 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 146, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 155, 7, 7, 160, 7, 7, 164, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, + 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 199, 59, 110, 242, 74, 92, 112, 31, 180, 7, 7, 187, + 7, 7, 186, 7, 7, 187, 7, 7, 189, 7, 7, 192, 7, 7, 194, 7, 7, 198, 7, 7, 205, 7, 7, 205, 7, 7, 199, 7, 7, 192, 7, 7, 185, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 180, 7, 7, 178, 7, 7, 178, 7, 7, 178, + 7, 7, 178, 199, 59, 132, 242, 74, 92, 112, 31, 170, 7, 7, 184, 7, 7, 185, 7, 7, 186, 7, 7, 184, 7, 7, 180, 7, 7, 177, 7, 7, 176, 7, 7, 175, 7, 7, 175, 7, 7, 176, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 176, 7, 7, 175, + 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 160, 7, 7, 147, 7, 7, 143, 7, 7, 148, 7, 7, 150, 7, 7, 149, 10, 10, 150, 21, 21, 150, 22, 22, 151, 21, 21, 152, 17, 17, 151, 11, 11, 151, 8, 8, 150, 7, 7, 149, + 7, 7, 150, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 149, + 7, 7, 148, 7, 7, 145, 7, 7, 140, 7, 7, 130, 7, 7, 129, 7, 7, 140, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 117, + 7, 7, 116, 7, 7, 115, 7, 7, 142, 7, 7, 171, 7, 7, 162, 7, 7, 154, 7, 7, 147, 7, 7, 141, 7, 7, 135, 7, 7, 130, 7, 7, 121, 7, 7, 115, 7, 7, 104, 7, 7, 75, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, + 7, 7, 82, 7, 7, 91, 7, 7, 99, 7, 7, 104, 7, 7, 108, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 118, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 132, 7, 7, 150, 7, 7, 156, 7, 7, 154, 7, 7, 157, 7, 7, 155, 8, 8, 153, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 153, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 151, 7, 7, 154, 7, 7, 158, 7, 7, 162, 7, 7, 164, + 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 143, 42, 125, + 193, 58, 112, 241, 74, 92, 210, 63, 127, 7, 7, 189, 7, 7, 185, 7, 7, 185, 7, 7, 187, 7, 7, 192, 7, 7, 194, 7, 7, 197, 7, 7, 203, 7, 7, 206, 7, 7, 205, 7, 7, 197, 7, 7, 190, 7, 7, 185, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 182, + 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 179, 143, 42, 159, 193, 58, 135, 241, 74, 93, 210, 63, 125, 7, 7, 182, 7, 7, 183, 7, 7, 184, 7, 7, 184, 7, 7, 182, 7, 7, 180, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 180, 7, 7, 180, 7, 7, 180, + 7, 7, 179, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 175, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 157, 7, 7, 135, 7, 7, 144, 7, 7, 149, 7, 7, 150, 9, 9, 149, 15, 15, 151, 18, 18, 150, 19, 19, 151, + 14, 14, 151, 9, 9, 150, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 144, 7, 7, 135, 7, 7, 135, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 133, 7, 7, 173, 7, 7, 164, 7, 7, 156, 7, 7, 149, 7, 7, 141, 7, 7, 135, 7, 7, 129, 7, 7, 119, 7, 7, 113, 7, 7, 102, 7, 7, 73, 36, 36, 40, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 71, 7, 7, 83, 7, 7, 92, 7, 7, 100, 7, 7, 105, 7, 7, 109, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, + 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 139, 7, 7, 153, 7, 7, 150, 7, 7, 156, 8, 8, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 146, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 151, 7, 7, 154, 7, 7, 159, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 152, + 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 189, 56, 114, 237, 72, 94, 206, 62, 113, 77, 21, 186, 7, 7, 188, 7, 7, 185, 7, 7, 186, 7, 7, 189, 7, 7, 195, 7, 7, 199, 7, 7, 201, 7, 7, 184, 7, 7, 165, 7, 7, 185, 7, 7, 198, 7, 7, 193, 7, 7, 185, + 7, 7, 182, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 181, 7, 7, 180, 189, 56, 139, 237, 72, 97, 206, 62, 127, 77, 21, 175, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 180, 7, 7, 178, 7, 7, 178, 7, 7, 178, + 7, 7, 179, 7, 7, 182, 7, 7, 184, 7, 7, 185, 7, 7, 184, 7, 7, 182, 7, 7, 180, 7, 7, 179, 7, 7, 177, 7, 7, 176, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 151, 7, 7, 140, 7, 7, 145, 7, 7, 149, + 10, 10, 150, 13, 13, 151, 13, 13, 151, 12, 12, 151, 12, 12, 150, 8, 8, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 146, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 145, 7, 7, 139, 7, 7, 139, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 133, 7, 7, 175, 7, 7, 166, 7, 7, 158, 7, 7, 150, 7, 7, 142, 7, 7, 135, 7, 7, 129, 7, 7, 119, + 7, 7, 112, 7, 7, 100, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 72, 7, 7, 84, 7, 7, 92, 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 121, + 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 134, 7, 7, 147, 7, 7, 151, 7, 7, 155, 9, 9, 157, 8, 8, 155, 7, 7, 154, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 151, 7, 7, 154, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 159, + 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 144, 7, 7, 188, 7, 7, 190, 7, 7, 187, 7, 7, 188, 7, 7, 193, 7, 7, 198, 7, 7, 203, 7, 7, 180, 7, 7, 145, + 7, 7, 136, 7, 7, 146, 7, 7, 181, 7, 7, 196, 7, 7, 188, 7, 7, 183, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 180, + 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 182, 7, 7, 185, 7, 7, 188, 7, 7, 190, 7, 7, 188, 7, 7, 185, 7, 7, 183, 7, 7, 181, 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 173, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, + 7, 7, 160, 7, 7, 155, 7, 7, 145, 7, 7, 148, 13, 13, 149, 15, 15, 151, 13, 13, 151, 10, 10, 151, 8, 8, 150, 8, 8, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 146, 7, 7, 142, 7, 7, 142, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 144, 7, 7, 175, 7, 7, 166, 7, 7, 159, + 7, 7, 151, 7, 7, 142, 7, 7, 135, 7, 7, 128, 7, 7, 118, 7, 7, 111, 7, 7, 100, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 50, 7, 7, 72, 7, 7, 85, 7, 7, 93, 7, 7, 102, 7, 7, 106, 7, 7, 110, 7, 7, 114, + 7, 7, 116, 7, 7, 117, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 132, 7, 7, 140, + 7, 7, 153, 8, 8, 158, 9, 9, 159, 9, 9, 157, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 147, 7, 7, 152, 7, 7, 157, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 137, 7, 7, 174, 7, 7, 195, 7, 7, 192, 7, 7, 192, + 7, 7, 196, 7, 7, 202, 7, 7, 186, 7, 7, 146, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 146, 7, 7, 180, 7, 7, 193, 7, 7, 185, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 183, 7, 7, 182, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, + 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 180, 7, 7, 184, 7, 7, 187, 7, 7, 194, 7, 7, 197, 7, 7, 195, 7, 7, 190, 7, 7, 186, 7, 7, 184, 7, 7, 183, 7, 7, 181, 7, 7, 179, + 7, 7, 174, 7, 7, 170, 7, 7, 167, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 152, 9, 9, 151, 14, 14, 152, 17, 17, 152, 14, 14, 152, 9, 9, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 150, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 143, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, + 7, 7, 119, 7, 7, 162, 7, 7, 172, 7, 7, 165, 7, 7, 158, 7, 7, 151, 7, 7, 143, 7, 7, 135, 7, 7, 128, 7, 7, 118, 7, 7, 111, 7, 7, 100, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 50, 7, 7, 73, 7, 7, 86, + 7, 7, 94, 7, 7, 102, 7, 7, 107, 7, 7, 111, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 137, 7, 7, 149, 7, 7, 159, 8, 8, 161, 8, 8, 159, 7, 7, 157, 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 146, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 153, 7, 7, 157, 7, 7, 160, + 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 146, 7, 7, 186, 7, 7, 198, 7, 7, 199, 7, 7, 199, 7, 7, 178, 7, 7, 141, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 144, 7, 7, 184, 7, 7, 190, 7, 7, 185, 7, 7, 183, 7, 7, 183, 7, 7, 183, 7, 7, 184, + 7, 7, 182, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 182, 7, 7, 186, 7, 7, 194, 7, 7, 199, 7, 7, 188, 7, 7, 196, 7, 7, 198, + 7, 7, 193, 7, 7, 190, 7, 7, 188, 7, 7, 186, 7, 7, 182, 7, 7, 176, 7, 7, 171, 7, 7, 165, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 8, 8, 152, 10, 10, 151, 17, 17, 152, 13, 13, 152, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 122, 7, 7, 169, 7, 7, 170, 7, 7, 163, 7, 7, 157, 7, 7, 150, 7, 7, 143, 7, 7, 135, 7, 7, 128, 7, 7, 118, 7, 7, 111, 7, 7, 100, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 39, 10, 10, 51, 7, 7, 74, 7, 7, 86, 7, 7, 94, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, + 7, 7, 128, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 133, 7, 7, 144, 7, 7, 157, 7, 7, 162, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 148, 7, 7, 151, 7, 7, 150, 7, 7, 151, + 7, 7, 151, 7, 7, 153, 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 147, 7, 7, 163, 7, 7, 170, 7, 7, 161, 7, 7, 142, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 153, 7, 7, 185, + 7, 7, 190, 7, 7, 186, 7, 7, 186, 7, 7, 186, 7, 7, 185, 7, 7, 184, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 181, 7, 7, 184, 7, 7, 190, + 7, 7, 195, 7, 7, 167, 7, 7, 141, 7, 7, 158, 7, 7, 197, 7, 7, 201, 7, 7, 198, 7, 7, 196, 7, 7, 192, 7, 7, 184, 7, 7, 177, 7, 7, 170, 7, 7, 164, 7, 7, 159, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 9, 9, 152, 12, 12, 151, + 10, 10, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, + 7, 7, 147, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, + 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 123, 7, 7, 168, 7, 7, 170, 7, 7, 162, 7, 7, 156, 7, 7, 150, 7, 7, 143, 7, 7, 136, 7, 7, 129, 7, 7, 118, 7, 7, 111, + 7, 7, 100, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 52, 7, 7, 75, 7, 7, 87, 7, 7, 95, 7, 7, 103, 7, 7, 108, 7, 7, 112, 7, 7, 115, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 122, 7, 7, 122, 7, 7, 123, + 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 132, 7, 7, 137, 7, 7, 155, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 158, + 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 146, 7, 7, 148, 7, 7, 152, 7, 7, 154, 7, 7, 156, 7, 7, 156, 7, 7, 158, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 166, + 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 155, 7, 7, 185, 7, 7, 193, 7, 7, 192, 7, 7, 190, 7, 7, 188, 7, 7, 186, 7, 7, 184, 7, 7, 181, 7, 7, 180, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 178, + 7, 7, 179, 7, 7, 181, 7, 7, 183, 7, 7, 187, 7, 7, 195, 7, 7, 180, 7, 7, 140, 7, 7, 134, 7, 7, 137, 7, 7, 160, 7, 7, 182, 7, 7, 192, 7, 7, 201, 7, 7, 197, 7, 7, 186, 7, 7, 177, 7, 7, 169, 7, 7, 162, 7, 7, 156, 7, 7, 154, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 8, 8, 153, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, + 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 117, 7, 7, 154, 7, 7, 171, 7, 7, 162, 7, 7, 156, 7, 7, 149, + 7, 7, 143, 7, 7, 136, 7, 7, 129, 7, 7, 119, 7, 7, 112, 7, 7, 100, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 52, 7, 7, 76, 7, 7, 87, 7, 7, 95, 7, 7, 104, 7, 7, 108, 7, 7, 112, 7, 7, 116, 7, 7, 118, + 7, 7, 119, 7, 7, 120, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 133, 7, 7, 136, + 7, 7, 148, 7, 7, 160, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 150, 7, 7, 154, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, + 7, 7, 162, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 146, 7, 7, 180, 7, 7, 199, 7, 7, 196, 7, 7, 194, 7, 7, 190, 7, 7, 187, 7, 7, 185, 7, 7, 183, 7, 7, 182, 7, 7, 181, + 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 184, 7, 7, 186, 7, 7, 190, 7, 7, 196, 7, 7, 156, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 136, 7, 7, 141, 7, 7, 172, 7, 7, 198, 7, 7, 185, 7, 7, 175, + 7, 7, 167, 7, 7, 161, 7, 7, 156, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 155, 7, 7, 155, 7, 7, 152, 7, 7, 144, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 143, 7, 7, 146, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 141, 7, 7, 144, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, + 7, 7, 135, 7, 7, 172, 7, 7, 162, 7, 7, 155, 7, 7, 148, 7, 7, 142, 7, 7, 136, 7, 7, 130, 7, 7, 119, 7, 7, 112, 7, 7, 100, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 53, 7, 7, 76, 7, 7, 88, 7, 7, 96, + 7, 7, 104, 7, 7, 109, 7, 7, 112, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, + 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 133, 7, 7, 135, 7, 7, 142, 7, 7, 156, 7, 7, 162, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, + 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 151, 7, 7, 156, 7, 7, 158, 7, 7, 159, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, + 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 162, 7, 7, 163, 7, 7, 165, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 143, 7, 7, 170, 7, 7, 195, 7, 7, 200, 7, 7, 195, + 7, 7, 192, 7, 7, 188, 7, 7, 187, 7, 7, 186, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 183, 7, 7, 185, 7, 7, 186, 7, 7, 186, 7, 7, 188, 7, 7, 193, 7, 7, 195, 7, 7, 150, 7, 7, 135, 7, 7, 134, 7, 7, 138, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 165, 7, 7, 196, 7, 7, 183, 7, 7, 174, 7, 7, 166, 7, 7, 160, 7, 7, 155, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 153, 7, 7, 147, 7, 7, 140, 7, 7, 133, + 7, 7, 130, 7, 7, 132, 7, 7, 136, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 137, 7, 7, 139, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 142, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 123, 7, 7, 169, 7, 7, 163, 7, 7, 155, 7, 7, 147, 7, 7, 141, 7, 7, 135, 7, 7, 129, 7, 7, 119, 7, 7, 112, 7, 7, 101, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 39, 10, 10, 53, 7, 7, 77, 7, 7, 88, 7, 7, 96, 7, 7, 104, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, + 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 134, 7, 7, 138, 7, 7, 145, 7, 7, 157, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 159, 7, 7, 159, 7, 7, 162, 7, 7, 162, 7, 7, 161, + 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 155, 7, 7, 158, 7, 7, 160, 7, 7, 161, 7, 7, 161, + 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 166, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 161, + 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 138, 7, 7, 158, 7, 7, 187, 7, 7, 200, 7, 7, 196, 7, 7, 193, 7, 7, 190, 7, 7, 189, 7, 7, 186, 7, 7, 184, 7, 7, 183, 7, 7, 184, 7, 7, 186, 7, 7, 189, 7, 7, 189, 7, 7, 189, 7, 7, 190, 7, 7, 194, 7, 7, 197, 7, 7, 155, + 7, 7, 134, 7, 7, 147, 7, 7, 178, 7, 7, 155, 7, 7, 134, 7, 7, 139, 7, 7, 179, 7, 7, 193, 7, 7, 181, 7, 7, 173, 7, 7, 167, 7, 7, 161, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 150, 7, 7, 143, 7, 7, 137, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 127, 7, 7, 127, 7, 7, 128, 7, 7, 131, 7, 7, 132, 7, 7, 135, 7, 7, 140, 7, 7, 146, + 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 126, + 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 120, 7, 7, 167, 7, 7, 163, 7, 7, 154, 7, 7, 147, 7, 7, 140, 7, 7, 135, 7, 7, 129, 7, 7, 119, 7, 7, 113, 7, 7, 101, + 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 53, 7, 7, 77, 7, 7, 89, 7, 7, 97, 7, 7, 105, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, + 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 134, 7, 7, 135, 7, 7, 137, 7, 7, 147, 7, 7, 156, 7, 7, 161, 7, 7, 162, + 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 163, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 155, + 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 167, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 169, + 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 149, 7, 7, 190, 7, 7, 201, 7, 7, 197, 7, 7, 194, 7, 7, 192, 7, 7, 188, 7, 7, 186, 7, 7, 186, 7, 7, 188, 7, 7, 190, 7, 7, 194, 7, 7, 194, + 7, 7, 193, 7, 7, 192, 7, 7, 194, 7, 7, 201, 7, 7, 173, 7, 7, 139, 7, 7, 183, 7, 7, 209, 7, 7, 182, 7, 7, 135, 7, 7, 150, 7, 7, 194, 7, 7, 189, 7, 7, 180, 7, 7, 173, 7, 7, 168, 7, 7, 163, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 156, + 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 139, 7, 7, 135, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 134, + 7, 7, 140, 7, 7, 145, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 121, 7, 7, 168, 7, 7, 162, 7, 7, 154, 7, 7, 146, 7, 7, 140, + 7, 7, 134, 7, 7, 129, 7, 7, 119, 7, 7, 113, 7, 7, 102, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 78, 7, 7, 89, 7, 7, 97, 7, 7, 105, 7, 7, 110, 7, 7, 113, 7, 7, 116, 7, 7, 118, 7, 7, 119, + 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, + 7, 7, 135, 7, 7, 137, 7, 7, 146, 7, 7, 155, 7, 7, 158, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 153, 7, 7, 163, 7, 7, 168, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, + 7, 7, 167, 7, 7, 169, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 147, 7, 7, 179, 7, 7, 200, 7, 7, 198, 7, 7, 195, 7, 7, 192, 7, 7, 190, + 7, 7, 190, 7, 7, 194, 7, 7, 198, 7, 7, 200, 7, 7, 200, 7, 7, 198, 7, 7, 195, 7, 7, 196, 7, 7, 203, 7, 7, 194, 7, 7, 165, 7, 7, 209, 7, 7, 210, 7, 7, 192, 7, 7, 138, 7, 7, 163, 7, 7, 197, 7, 7, 188, 7, 7, 179, 7, 7, 174, 7, 7, 169, + 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 122, + 7, 7, 168, 7, 7, 163, 7, 7, 154, 7, 7, 146, 7, 7, 140, 7, 7, 135, 7, 7, 129, 7, 7, 120, 7, 7, 114, 7, 7, 103, 7, 7, 75, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 78, 7, 7, 90, 7, 7, 98, 7, 7, 105, + 7, 7, 110, 7, 7, 113, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 137, 7, 7, 143, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 149, 7, 7, 146, 7, 7, 148, 7, 7, 150, 7, 7, 162, 7, 7, 172, 7, 7, 164, 7, 7, 162, 7, 7, 161, + 7, 7, 160, 7, 7, 160, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, + 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 143, + 7, 7, 176, 7, 7, 199, 7, 7, 198, 7, 7, 195, 7, 7, 194, 7, 7, 197, 7, 7, 196, 7, 7, 179, 7, 7, 161, 7, 7, 168, 7, 7, 190, 7, 7, 199, 7, 7, 200, 7, 7, 196, 7, 7, 166, 7, 7, 146, 7, 7, 183, 7, 7, 186, 7, 7, 157, 7, 7, 135, 7, 7, 157, + 7, 7, 195, 7, 7, 188, 7, 7, 180, 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 119, 7, 7, 166, 7, 7, 165, 7, 7, 156, 7, 7, 148, 7, 7, 141, 7, 7, 136, 7, 7, 131, 7, 7, 121, 7, 7, 116, 7, 7, 106, 7, 7, 76, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 55, 7, 7, 78, 7, 7, 90, 7, 7, 98, 7, 7, 105, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, + 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 138, 7, 7, 139, 7, 7, 144, + 7, 7, 162, 7, 7, 172, 7, 7, 165, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 162, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, + 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 163, + 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 142, 7, 7, 166, 7, 7, 200, 7, 7, 199, 7, 7, 200, 7, 7, 194, 7, 7, 163, 7, 7, 141, 7, 7, 135, 7, 7, 136, 7, 7, 149, 7, 7, 168, 7, 7, 169, 7, 7, 151, 7, 7, 137, 7, 7, 135, + 7, 7, 139, 7, 7, 139, 7, 7, 135, 7, 7, 135, 7, 7, 147, 7, 7, 189, 7, 7, 189, 7, 7, 181, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 156, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, + 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 113, 7, 7, 152, 7, 7, 169, 7, 7, 159, 7, 7, 151, 7, 7, 143, 7, 7, 138, 7, 7, 133, 7, 7, 124, 7, 7, 120, 7, 7, 109, 7, 7, 79, + 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 79, 7, 7, 90, 7, 7, 98, 7, 7, 105, 7, 7, 109, 7, 7, 112, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 134, 7, 7, 139, 7, 7, 160, 7, 7, 177, 7, 7, 168, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, + 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 165, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 167, + 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 138, 7, 7, 179, 7, 7, 203, 7, 7, 201, 7, 7, 158, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 139, 7, 7, 179, 7, 7, 192, 7, 7, 183, 7, 7, 178, 7, 7, 175, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, + 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 113, 7, 7, 126, 7, 7, 166, 7, 7, 165, 7, 7, 155, 7, 7, 147, 7, 7, 141, + 7, 7, 137, 7, 7, 129, 7, 7, 125, 7, 7, 116, 7, 7, 81, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 79, 7, 7, 90, 7, 7, 97, 7, 7, 104, 7, 7, 109, 7, 7, 112, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 131, 7, 7, 147, 7, 7, 177, 7, 7, 175, 7, 7, 168, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 168, 7, 7, 168, + 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, + 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 142, 7, 7, 185, 7, 7, 190, 7, 7, 138, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 170, 7, 7, 194, 7, 7, 184, 7, 7, 179, 7, 7, 175, 7, 7, 173, + 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, + 7, 7, 141, 7, 7, 168, 7, 7, 161, 7, 7, 153, 7, 7, 147, 7, 7, 142, 7, 7, 136, 7, 7, 133, 7, 7, 108, 7, 7, 57, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 79, 7, 7, 90, 7, 7, 97, 7, 7, 104, 7, 7, 109, + 7, 7, 112, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 133, 7, 7, 160, 7, 7, 179, 7, 7, 177, 7, 7, 171, 7, 7, 170, + 7, 7, 169, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, + 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 135, 7, 7, 170, 7, 7, 194, 7, 7, 146, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 166, + 7, 7, 195, 7, 7, 184, 7, 7, 179, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 116, 7, 7, 148, 7, 7, 166, 7, 7, 160, 7, 7, 155, 7, 7, 150, 7, 7, 143, 7, 7, 120, 7, 7, 76, 7, 7, 44, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, + 7, 7, 79, 7, 7, 90, 7, 7, 97, 7, 7, 104, 7, 7, 109, 7, 7, 112, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, + 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 136, 7, 7, 154, 7, 7, 177, 7, 7, 182, 7, 7, 179, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 171, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 162, 7, 7, 164, 7, 7, 166, + 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, + 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 177, 7, 7, 209, 7, 7, 187, 7, 7, 144, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 163, 7, 7, 194, 7, 7, 184, 7, 7, 179, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, + 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 126, + 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 113, 7, 7, 136, 7, 7, 150, 7, 7, 150, 7, 7, 146, 7, 7, 121, 7, 7, 86, 7, 7, 65, 7, 7, 44, 36, 36, 38, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 79, 7, 7, 90, 7, 7, 97, 7, 7, 104, 7, 7, 108, 7, 7, 112, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, + 7, 7, 124, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 135, 7, 7, 141, 7, 7, 158, 7, 7, 170, 7, 7, 180, 7, 7, 185, 7, 7, 180, 7, 7, 175, 7, 7, 171, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 157, + 7, 7, 157, 7, 7, 158, 7, 7, 161, 7, 7, 163, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 168, + 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 180, 7, 7, 206, 7, 7, 207, 7, 7, 196, 7, 7, 177, 7, 7, 168, 7, 7, 150, 7, 7, 138, 7, 7, 135, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 135, 7, 7, 161, 7, 7, 194, 7, 7, 184, 7, 7, 178, 7, 7, 174, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 168, + 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 105, 7, 7, 102, 7, 7, 99, 7, 7, 94, + 7, 7, 84, 7, 7, 76, 7, 7, 65, 7, 7, 44, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 78, 7, 7, 89, 7, 7, 96, 7, 7, 104, 7, 7, 108, 7, 7, 112, 7, 7, 116, 7, 7, 118, 7, 7, 118, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 135, 7, 7, 136, 7, 7, 143, 7, 7, 169, 7, 7, 181, 7, 7, 175, 7, 7, 170, 7, 7, 166, + 7, 7, 162, 7, 7, 159, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 155, 7, 7, 158, 7, 7, 161, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, + 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, + 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 176, 7, 7, 206, 7, 7, 206, 7, 7, 209, + 7, 7, 209, 7, 7, 208, 7, 7, 200, 7, 7, 165, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 139, 7, 7, 140, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 157, 7, 7, 192, 7, 7, 182, 7, 7, 176, 7, 7, 174, 7, 7, 171, 7, 7, 169, + 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 127, 7, 7, 127, 7, 7, 127, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 110, + 7, 7, 108, 7, 7, 105, 7, 7, 102, 7, 7, 97, 7, 7, 92, 7, 7, 85, 7, 7, 77, 7, 7, 66, 7, 7, 44, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 78, 7, 7, 88, 7, 7, 96, 7, 7, 103, 7, 7, 108, 7, 7, 112, + 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 143, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 165, 7, 7, 161, 7, 7, 157, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 154, 7, 7, 158, 7, 7, 162, 7, 7, 164, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, + 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 151, 7, 7, 182, 7, 7, 182, 7, 7, 176, 7, 7, 187, 7, 7, 204, 7, 7, 207, 7, 7, 181, 7, 7, 139, 7, 7, 136, 7, 7, 139, 7, 7, 144, 7, 7, 147, 7, 7, 150, 7, 7, 152, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 152, 7, 7, 183, + 7, 7, 178, 7, 7, 173, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 157, 7, 7, 153, 7, 7, 154, + 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, + 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 128, 7, 7, 127, 7, 7, 124, 7, 7, 121, + 7, 7, 120, 7, 7, 117, 7, 7, 116, 7, 7, 113, 7, 7, 111, 7, 7, 108, 7, 7, 106, 7, 7, 102, 7, 7, 97, 7, 7, 93, 7, 7, 85, 7, 7, 77, 7, 7, 66, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 77, + 7, 7, 88, 7, 7, 95, 7, 7, 103, 7, 7, 108, 7, 7, 112, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 136, 7, 7, 155, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 155, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 149, 7, 7, 153, 7, 7, 157, 7, 7, 162, + 7, 7, 164, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 163, 7, 7, 161, + 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 139, 7, 7, 159, 7, 7, 182, 7, 7, 159, 7, 7, 136, 7, 7, 139, 7, 7, 145, 7, 7, 151, 7, 7, 156, 7, 7, 160, 7, 7, 161, + 7, 7, 160, 7, 7, 159, 7, 7, 154, 7, 7, 152, 7, 7, 172, 7, 7, 169, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 163, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, + 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 155, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 152, 7, 7, 151, 7, 7, 147, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 127, 7, 7, 124, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 102, 7, 7, 98, 7, 7, 93, 7, 7, 85, 7, 7, 77, 7, 7, 66, 7, 7, 45, 36, 36, 38, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 77, 7, 7, 87, 7, 7, 95, 7, 7, 103, 7, 7, 108, 7, 7, 112, 7, 7, 116, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, + 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 9, 9, 134, 10, 10, 135, 12, 12, 135, 13, 13, 135, 8, 8, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 8, 8, 135, 12, 12, 143, 8, 8, 150, 7, 7, 155, 7, 7, 157, 7, 7, 154, 7, 7, 148, 7, 7, 142, 9, 9, 139, 12, 12, 138, 8, 8, 138, + 7, 7, 138, 7, 7, 144, 7, 7, 149, 7, 7, 155, 7, 7, 160, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 8, 8, 161, 11, 11, 161, 13, 13, 161, 11, 11, 161, 8, 8, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 8, 8, 162, 12, 12, 162, + 13, 13, 162, 15, 15, 161, 15, 15, 162, 9, 9, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 139, 7, 7, 138, 7, 7, 142, 7, 7, 147, + 9, 9, 154, 12, 12, 161, 11, 11, 167, 10, 10, 169, 9, 9, 169, 7, 7, 169, 7, 7, 166, 7, 7, 162, 7, 7, 158, 7, 7, 160, 8, 8, 160, 11, 11, 158, 13, 13, 157, 18, 18, 158, 18, 18, 159, 13, 13, 159, 7, 7, 159, 7, 7, 163, 7, 7, 163, 7, 7, 165, 7, 7, 165, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 8, 8, 163, 8, 8, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 8, 8, 160, 12, 12, 161, 15, 15, 160, 12, 12, 160, 8, 8, 158, 7, 7, 157, 7, 7, 155, + 7, 7, 154, 7, 7, 150, 7, 7, 146, 7, 7, 143, 7, 7, 140, 7, 7, 140, 8, 8, 140, 9, 9, 139, 9, 9, 140, 8, 8, 140, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 8, 8, 140, 8, 8, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 140, 8, 8, 140, 8, 8, 139, 8, 8, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 130, 7, 7, 126, 7, 7, 122, 7, 7, 119, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 102, 7, 7, 98, 7, 7, 93, 7, 7, 85, + 7, 7, 78, 7, 7, 67, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 76, 7, 7, 87, 7, 7, 95, 7, 7, 102, 7, 7, 107, 7, 7, 112, 7, 7, 115, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, + 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 8, 8, 134, 11, 11, 134, 11, 11, 135, + 10, 10, 135, 12, 12, 134, 15, 15, 135, 19, 19, 135, 9, 9, 134, 7, 7, 134, 7, 7, 133, 8, 8, 133, 17, 17, 135, 15, 15, 135, 8, 8, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 18, 18, 135, 39, 39, 139, 26, 26, 142, 7, 7, 146, 7, 7, 149, 7, 7, 146, + 7, 7, 144, 7, 7, 138, 23, 23, 137, 27, 27, 136, 16, 16, 135, 7, 7, 136, 7, 7, 138, 7, 7, 145, 7, 7, 151, 7, 7, 157, 7, 7, 160, 7, 7, 161, 7, 7, 160, 15, 15, 161, 22, 22, 162, 30, 30, 162, 29, 29, 162, 26, 26, 162, 16, 16, 161, 7, 7, 160, 7, 7, 161, + 7, 7, 162, 8, 8, 162, 15, 15, 163, 22, 22, 163, 28, 28, 164, 29, 29, 163, 34, 34, 163, 42, 42, 164, 30, 30, 163, 9, 9, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 138, 7, 7, 138, 8, 8, 140, 19, 19, 149, 33, 33, 158, 39, 39, 165, 34, 34, 171, 23, 23, 172, 15, 15, 174, 11, 11, 175, 8, 8, 174, 7, 7, 171, 7, 7, 168, 8, 8, 163, 14, 14, 161, 22, 22, 159, 30, 30, 155, 35, 35, 156, 39, 39, 157, 52, 52, 159, 53, 53, 160, + 18, 18, 157, 7, 7, 157, 7, 7, 160, 8, 8, 160, 7, 7, 161, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 11, 11, 163, 17, 17, 163, 8, 8, 162, 7, 7, 162, 7, 7, 164, 7, 7, 163, 7, 7, 164, 9, 9, 164, 21, 21, 166, 37, 37, 168, 46, 46, 169, + 51, 51, 169, 46, 46, 168, 32, 32, 164, 14, 14, 161, 7, 7, 158, 7, 7, 156, 7, 7, 152, 7, 7, 145, 7, 7, 142, 8, 8, 140, 9, 9, 140, 10, 10, 140, 16, 16, 139, 24, 24, 141, 25, 25, 141, 16, 16, 141, 8, 8, 140, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 8, 8, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 139, 8, 8, 139, 9, 9, 140, 11, 11, 140, 14, 14, 140, 16, 16, 140, 12, 12, 140, + 7, 7, 140, 7, 7, 140, 8, 8, 140, 13, 13, 140, 8, 8, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 8, 8, 139, 12, 12, 139, 17, 17, 139, 9, 9, 137, 7, 7, 133, 7, 7, 128, 7, 7, 124, 7, 7, 120, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 109, + 7, 7, 106, 7, 7, 102, 7, 7, 98, 7, 7, 93, 7, 7, 86, 7, 7, 78, 7, 7, 67, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 76, 7, 7, 87, 7, 7, 94, 7, 7, 102, 7, 7, 107, 7, 7, 111, 7, 7, 115, + 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 134, 8, 8, 134, 12, 12, 135, 13, 13, 135, 8, 8, 134, 7, 7, 134, 8, 8, 134, 8, 8, 134, 9, 9, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 13, 13, 134, 32, 32, 136, 22, 22, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 11, 11, 134, + 26, 26, 136, 19, 19, 137, 7, 7, 141, 7, 7, 144, 7, 7, 141, 7, 7, 138, 8, 8, 135, 19, 19, 135, 13, 13, 134, 11, 11, 134, 7, 7, 134, 7, 7, 136, 7, 7, 140, 7, 7, 148, 7, 7, 155, 7, 7, 159, 7, 7, 160, 13, 13, 161, 14, 14, 160, 11, 11, 161, 10, 10, 162, + 10, 10, 161, 10, 10, 161, 10, 10, 161, 9, 9, 161, 7, 7, 162, 7, 7, 163, 14, 14, 163, 20, 20, 163, 16, 16, 164, 11, 11, 163, 10, 10, 163, 14, 14, 162, 23, 23, 162, 28, 28, 163, 11, 11, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, + 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 35, 35, 150, 58, 58, 158, 43, 43, 164, 28, 28, 168, 19, 19, 172, 11, 11, 174, 8, 8, 175, 7, 7, 175, 7, 7, 176, 7, 7, 174, 7, 7, 171, 14, 14, 167, 19, 19, 163, 13, 13, 158, + 12, 12, 154, 11, 11, 155, 15, 15, 154, 22, 22, 154, 33, 33, 155, 24, 24, 155, 7, 7, 156, 7, 7, 157, 9, 9, 158, 10, 10, 158, 7, 7, 156, 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 162, 10, 10, 163, 25, 25, 163, 12, 12, 162, 7, 7, 162, 7, 7, 165, 7, 7, 166, + 12, 12, 167, 30, 30, 170, 40, 40, 171, 33, 33, 170, 25, 25, 170, 25, 25, 169, 24, 24, 168, 29, 29, 166, 28, 28, 165, 9, 9, 162, 7, 7, 158, 7, 7, 154, 7, 7, 148, 11, 11, 143, 12, 12, 142, 8, 8, 139, 8, 8, 140, 9, 9, 140, 14, 14, 140, 24, 24, 141, 25, 25, 141, + 11, 11, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 8, 8, 140, 9, 9, 140, + 9, 9, 140, 8, 8, 141, 8, 8, 140, 10, 10, 141, 10, 10, 141, 7, 7, 140, 7, 7, 140, 8, 8, 141, 11, 11, 141, 8, 8, 141, 7, 7, 140, 7, 7, 138, 7, 7, 139, 7, 7, 140, 11, 11, 140, 17, 17, 140, 21, 21, 140, 11, 11, 139, 7, 7, 135, 7, 7, 131, 7, 7, 126, + 7, 7, 121, 7, 7, 117, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 102, 7, 7, 98, 7, 7, 93, 7, 7, 86, 7, 7, 79, 7, 7, 67, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 76, 7, 7, 87, + 7, 7, 94, 7, 7, 102, 7, 7, 107, 7, 7, 111, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 134, 7, 7, 134, 9, 9, 134, 11, 11, 134, 10, 10, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 9, 9, 134, 10, 10, 134, 8, 8, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 12, 12, 135, 10, 10, 136, 7, 7, 137, 7, 7, 139, 7, 7, 137, 7, 7, 135, 8, 8, 134, 10, 10, 134, 8, 8, 134, 8, 8, 134, 8, 8, 134, 7, 7, 135, 7, 7, 137, 7, 7, 144, 7, 7, 151, 8, 8, 158, + 11, 11, 160, 9, 9, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 8, 8, 164, 9, 9, 164, 9, 9, 164, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 139, 7, 7, 142, 7, 7, 144, 38, 38, 154, 34, 34, 158, 15, 15, 164, 9, 9, 169, 8, 8, 172, 7, 7, 173, 7, 7, 174, 7, 7, 175, 7, 7, 176, + 7, 7, 175, 7, 7, 172, 14, 14, 169, 10, 10, 165, 8, 8, 161, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 8, 8, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 10, 10, 156, 9, 9, 156, 7, 7, 154, 7, 7, 156, 7, 7, 157, 7, 7, 159, 7, 7, 161, 8, 8, 161, + 10, 10, 162, 7, 7, 163, 7, 7, 164, 7, 7, 167, 14, 14, 168, 31, 31, 172, 27, 27, 172, 13, 13, 171, 8, 8, 171, 7, 7, 170, 7, 7, 169, 8, 8, 168, 9, 9, 166, 11, 11, 164, 13, 13, 163, 8, 8, 161, 7, 7, 157, 10, 10, 152, 20, 20, 146, 11, 11, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 11, 11, 140, 19, 19, 141, 16, 16, 140, 8, 8, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 8, 8, 139, 9, 9, 139, 8, 8, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 9, 9, 140, 10, 10, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 8, 8, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 8, 8, 140, 8, 8, 141, 8, 8, 141, + 8, 8, 141, 7, 7, 140, 7, 7, 138, 7, 7, 134, 7, 7, 128, 7, 7, 122, 7, 7, 118, 7, 7, 113, 7, 7, 111, 7, 7, 108, 7, 7, 106, 7, 7, 102, 7, 7, 98, 7, 7, 94, 7, 7, 86, 7, 7, 79, 7, 7, 68, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 76, 7, 7, 87, 7, 7, 94, 7, 7, 102, 7, 7, 107, 7, 7, 111, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 133, 8, 8, 134, 14, 14, 134, 9, 9, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 135, 8, 8, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 136, 7, 7, 141, 8, 8, 149, 10, 10, 156, 8, 8, 160, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 165, + 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 140, 7, 7, 144, 7, 7, 149, 20, 20, 156, 12, 12, 163, 7, 7, 167, 8, 8, 170, + 7, 7, 172, 7, 7, 173, 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 174, 10, 10, 170, 9, 9, 168, 7, 7, 165, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 8, 8, 156, 8, 8, 155, 7, 7, 153, + 7, 7, 155, 7, 7, 156, 7, 7, 158, 7, 7, 160, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 8, 8, 167, 20, 20, 169, 22, 22, 172, 9, 9, 171, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 8, 8, 164, 8, 8, 162, + 8, 8, 159, 17, 17, 153, 15, 15, 148, 8, 8, 143, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 16, 16, 141, 23, 23, 142, 9, 9, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 8, 8, 139, 12, 12, 139, 10, 10, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 8, 8, 140, 8, 8, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 140, 8, 8, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 135, 7, 7, 131, 7, 7, 124, 7, 7, 118, 7, 7, 114, 7, 7, 111, 7, 7, 108, 7, 7, 106, 7, 7, 102, 7, 7, 98, 7, 7, 94, 7, 7, 87, 7, 7, 79, + 7, 7, 68, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 76, 7, 7, 87, 7, 7, 94, 7, 7, 102, 7, 7, 106, 7, 7, 111, 7, 7, 114, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, + 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 134, 8, 8, 133, 16, 16, 135, 15, 15, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 8, 8, 135, 8, 8, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 139, 8, 8, 146, 10, 10, 155, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 8, 8, 163, 10, 10, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, + 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 144, 7, 7, 148, + 7, 7, 152, 13, 13, 159, 9, 9, 166, 8, 8, 171, 8, 8, 173, 7, 7, 174, 7, 7, 173, 7, 7, 173, 7, 7, 175, 7, 7, 176, 7, 7, 176, 8, 8, 175, 10, 10, 174, 8, 8, 170, 7, 7, 167, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 156, 7, 7, 153, 7, 7, 154, + 7, 7, 155, 7, 7, 156, 8, 8, 157, 9, 9, 157, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 160, 9, 9, 162, 13, 13, 163, 16, 16, 164, 10, 10, 165, 8, 8, 168, 14, 14, 171, 14, 14, 172, 7, 7, 172, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 169, + 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 8, 8, 159, 14, 14, 156, 11, 11, 150, 7, 7, 145, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 14, 14, 140, 27, 27, 141, 9, 9, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 9, 9, 140, 13, 13, 140, 8, 8, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 8, 8, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 132, 7, 7, 125, 7, 7, 119, 7, 7, 114, 7, 7, 110, 7, 7, 109, 7, 7, 106, + 7, 7, 103, 7, 7, 99, 7, 7, 94, 7, 7, 87, 7, 7, 79, 7, 7, 68, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 76, 7, 7, 87, 7, 7, 94, 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 114, 7, 7, 117, + 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 134, 8, 8, 133, 23, 23, 135, 13, 13, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 8, 8, 134, 9, 9, 134, 8, 8, 134, 8, 8, 135, 8, 8, 135, + 9, 9, 135, 8, 8, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 138, 8, 8, 143, 9, 9, 151, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 164, 7, 7, 164, + 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 163, 9, 9, 163, 21, 21, 164, 13, 13, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, + 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 145, 7, 7, 149, 7, 7, 155, 10, 10, 162, 9, 9, 169, 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 173, 8, 8, 175, 11, 11, 176, 12, 12, 177, 8, 8, 178, 9, 9, 175, 8, 8, 174, 7, 7, 171, 7, 7, 168, + 7, 7, 164, 7, 7, 162, 7, 7, 158, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 157, 8, 8, 159, 9, 9, 159, 8, 8, 159, 7, 7, 158, 8, 8, 158, 9, 9, 160, 13, 13, 160, 22, 22, 162, 30, 30, 165, 23, 23, 165, 12, 12, 166, 9, 9, 168, 17, 17, 170, 16, 16, 171, + 7, 7, 173, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 160, 9, 9, 157, 10, 10, 152, 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 142, 7, 7, 141, 8, 8, 139, 22, 22, 141, 22, 22, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 140, 14, 14, 141, 10, 10, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 133, 7, 7, 126, + 7, 7, 119, 7, 7, 115, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 103, 7, 7, 99, 7, 7, 95, 7, 7, 87, 7, 7, 79, 7, 7, 68, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 54, 7, 7, 77, 7, 7, 87, 7, 7, 94, + 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 114, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 131, + 7, 7, 132, 7, 7, 133, 8, 8, 133, 15, 15, 134, 11, 11, 134, 8, 8, 134, 8, 8, 134, 9, 9, 134, 10, 10, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 8, 8, 134, + 8, 8, 134, 8, 8, 134, 9, 9, 134, 9, 9, 135, 8, 8, 134, 8, 8, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 140, 10, 10, 146, 8, 8, 154, + 7, 7, 156, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 8, 8, 162, 7, 7, 162, 8, 8, 162, 8, 8, 162, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 163, 8, 8, 162, 11, 11, 162, 8, 8, 162, + 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, + 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 143, 7, 7, 145, 7, 7, 151, 8, 8, 157, 8, 8, 163, 7, 7, 168, 7, 7, 174, 7, 7, 176, 7, 7, 176, 8, 8, 173, 9, 9, 173, 10, 10, 173, 11, 11, 176, 10, 10, 177, + 9, 9, 179, 10, 10, 177, 9, 9, 176, 8, 8, 174, 7, 7, 171, 7, 7, 167, 7, 7, 165, 7, 7, 161, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 163, 8, 8, 163, 8, 8, 163, 8, 8, 163, 8, 8, 161, 8, 8, 160, 10, 10, 160, 13, 13, 161, 18, 18, 162, 17, 17, 164, + 12, 12, 165, 8, 8, 167, 8, 8, 167, 24, 24, 169, 24, 24, 171, 8, 8, 171, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 162, 8, 8, 159, 8, 8, 155, 7, 7, 151, 7, 7, 148, 7, 7, 144, + 7, 7, 142, 7, 7, 141, 14, 14, 141, 19, 19, 141, 10, 10, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 8, 8, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 9, 9, 141, 8, 8, 140, 7, 7, 140, 7, 7, 140, 8, 8, 140, 16, 16, 140, + 9, 9, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 133, 7, 7, 127, 7, 7, 121, 7, 7, 115, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 104, 7, 7, 100, 7, 7, 95, 7, 7, 87, 7, 7, 80, 7, 7, 68, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 39, 10, 10, 55, 7, 7, 77, 7, 7, 87, 7, 7, 93, 7, 7, 101, 7, 7, 105, 7, 7, 109, 7, 7, 113, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 8, 8, 134, 8, 8, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 10, 10, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, + 8, 8, 135, 7, 7, 135, 7, 7, 138, 10, 10, 142, 9, 9, 149, 7, 7, 153, 7, 7, 157, 7, 7, 159, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 163, 7, 7, 162, 8, 8, 162, 8, 8, 162, 8, 8, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, + 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 147, 7, 7, 151, 8, 8, 155, 8, 8, 161, 7, 7, 167, 7, 7, 172, 7, 7, 174, 7, 7, 173, + 7, 7, 171, 7, 7, 171, 8, 8, 171, 7, 7, 173, 7, 7, 176, 12, 12, 177, 14, 14, 178, 10, 10, 177, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 169, 7, 7, 168, 8, 8, 167, 7, 7, 166, + 7, 7, 163, 7, 7, 162, 8, 8, 161, 8, 8, 162, 8, 8, 164, 7, 7, 164, 7, 7, 167, 8, 8, 167, 31, 31, 170, 37, 37, 171, 9, 9, 171, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 164, + 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 152, 7, 7, 149, 7, 7, 145, 10, 10, 143, 17, 17, 141, 17, 17, 140, 9, 9, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 9, 9, 141, 9, 9, 140, 8, 8, 140, 7, 7, 141, 7, 7, 141, 8, 8, 141, 12, 12, 141, + 15, 15, 141, 8, 8, 139, 7, 7, 139, 9, 9, 139, 16, 16, 140, 8, 8, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 134, 7, 7, 127, 7, 7, 121, 7, 7, 116, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 104, 7, 7, 100, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, + 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 77, 7, 7, 87, 7, 7, 93, 7, 7, 101, 7, 7, 105, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, + 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 10, 10, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 11, 11, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 10, 10, 134, 7, 7, 134, 7, 7, 135, 9, 9, 139, 9, 9, 146, 8, 8, 151, 7, 7, 156, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 11, 11, 162, + 8, 8, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 146, 7, 7, 148, 7, 7, 150, 7, 7, 153, + 7, 7, 158, 7, 7, 163, 7, 7, 166, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 166, 8, 8, 170, 7, 7, 175, 8, 8, 177, 15, 15, 179, 10, 10, 178, 7, 7, 177, 7, 7, 175, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 171, 8, 8, 171, 8, 8, 173, + 7, 7, 174, 8, 8, 173, 8, 8, 173, 8, 8, 173, 7, 7, 171, 7, 7, 168, 7, 7, 166, 8, 8, 165, 8, 8, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 31, 31, 168, 39, 39, 170, 10, 10, 170, 7, 7, 170, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 167, + 8, 8, 168, 9, 9, 168, 8, 8, 167, 8, 8, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 157, 7, 7, 153, 8, 8, 148, 11, 11, 145, 17, 17, 142, 19, 19, 142, 12, 12, 140, 8, 8, 141, 7, 7, 141, 7, 7, 141, 8, 8, 141, 13, 13, 140, 11, 11, 140, + 8, 8, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 12, 12, 141, 22, 22, 141, 13, 13, 140, 7, 7, 139, 8, 8, 140, 11, 11, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 141, 8, 8, 140, 8, 8, 140, 8, 8, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 133, 7, 7, 128, 7, 7, 122, 7, 7, 116, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 105, + 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 77, 7, 7, 87, 7, 7, 94, 7, 7, 101, 7, 7, 105, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 118, + 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 130, 7, 7, 132, 7, 7, 132, 7, 7, 133, 9, 9, 134, 19, 19, 135, 12, 12, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 8, 8, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 11, 11, 135, 8, 8, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 9, 9, 134, 7, 7, 134, 7, 7, 135, 8, 8, 137, 8, 8, 144, 8, 8, 150, 7, 7, 156, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, + 7, 7, 163, 7, 7, 162, 7, 7, 162, 8, 8, 164, 12, 12, 164, 8, 8, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 164, 7, 7, 164, 9, 9, 164, 8, 8, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, + 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 148, 7, 7, 145, + 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 149, 7, 7, 150, 7, 7, 153, 7, 7, 157, 7, 7, 160, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 161, 7, 7, 171, 7, 7, 180, 8, 8, 179, 16, 16, 179, 9, 9, 179, 7, 7, 178, 7, 7, 176, 7, 7, 174, + 7, 7, 173, 7, 7, 173, 8, 8, 174, 8, 8, 176, 7, 7, 176, 8, 8, 176, 8, 8, 176, 7, 7, 176, 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 170, 8, 8, 169, 8, 8, 170, 7, 7, 169, 7, 7, 166, 7, 7, 166, 7, 7, 165, 20, 20, 168, 33, 33, 170, 12, 12, 168, + 7, 7, 170, 7, 7, 168, 7, 7, 167, 10, 10, 167, 18, 18, 168, 22, 22, 168, 15, 15, 167, 8, 8, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 161, 7, 7, 156, 7, 7, 150, 7, 7, 146, 9, 9, 143, 10, 10, 141, 10, 10, 141, 9, 9, 141, + 7, 7, 141, 7, 7, 141, 9, 9, 141, 12, 12, 140, 9, 9, 140, 7, 7, 139, 8, 8, 140, 8, 8, 140, 8, 8, 140, 11, 11, 140, 19, 19, 140, 20, 20, 140, 7, 7, 140, 7, 7, 140, 8, 8, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 8, 8, 141, 9, 9, 141, 11, 11, 140, 16, 16, 140, 16, 16, 140, 13, 13, 140, 8, 8, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 133, 7, 7, 128, 7, 7, 123, + 7, 7, 117, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 105, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 77, 7, 7, 87, 7, 7, 94, 7, 7, 101, + 7, 7, 105, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 117, 7, 7, 119, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 130, 7, 7, 132, 7, 7, 132, + 7, 7, 133, 8, 8, 134, 16, 16, 135, 15, 15, 135, 12, 12, 135, 9, 9, 134, 8, 8, 135, 8, 8, 134, 8, 8, 135, 8, 8, 134, 10, 10, 135, 9, 9, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 9, 9, 134, 9, 9, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 8, 8, 134, 14, 14, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 9, 9, 134, 11, 11, 134, 7, 7, 135, 9, 9, 138, 9, 9, 145, 7, 7, 151, + 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 164, 8, 8, 164, 12, 12, 166, 9, 9, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, 8, 8, 163, 8, 8, 164, 16, 16, 165, 28, 28, 166, 16, 16, 164, 7, 7, 163, 7, 7, 164, + 7, 7, 165, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 151, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 151, 7, 7, 152, 7, 7, 156, 7, 7, 157, 8, 8, 159, 7, 7, 158, 7, 7, 157, 7, 7, 165, 7, 7, 181, 7, 7, 182, 8, 8, 179, + 21, 21, 180, 13, 13, 180, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 175, 8, 8, 175, 8, 8, 176, 8, 8, 177, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 176, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 169, + 7, 7, 166, 7, 7, 165, 11, 11, 166, 27, 27, 169, 15, 15, 169, 10, 10, 169, 10, 10, 167, 15, 15, 166, 25, 25, 167, 33, 33, 168, 25, 25, 168, 11, 11, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 163, 7, 7, 157, 7, 7, 151, + 8, 8, 146, 8, 8, 143, 10, 10, 141, 13, 13, 141, 9, 9, 141, 7, 7, 142, 7, 7, 141, 9, 9, 141, 9, 9, 140, 9, 9, 140, 9, 9, 140, 8, 8, 140, 7, 7, 140, 7, 7, 140, 8, 8, 140, 13, 13, 140, 19, 19, 140, 9, 9, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 9, 9, 141, 14, 14, 141, 13, 13, 140, 24, 24, 141, 27, 27, 141, 22, 22, 142, 18, 18, 141, 14, 14, 141, 10, 10, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 129, 7, 7, 124, 7, 7, 118, 7, 7, 115, 7, 7, 112, 7, 7, 109, 7, 7, 105, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 55, 7, 7, 77, 7, 7, 87, 7, 7, 94, 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 113, 7, 7, 116, 7, 7, 117, 7, 7, 119, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 134, 7, 7, 134, 11, 11, 134, 18, 18, 135, 19, 19, 135, 18, 18, 135, 18, 18, 136, 16, 16, 136, 13, 13, 135, 16, 16, 135, 14, 14, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 15, 15, 135, 15, 15, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 18, 18, 135, 12, 12, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 8, 8, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, + 15, 15, 135, 11, 11, 135, 10, 10, 139, 13, 13, 145, 8, 8, 153, 7, 7, 157, 7, 7, 160, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 8, 8, 165, 13, 13, 166, 8, 8, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 8, 8, 165, + 12, 12, 164, 23, 23, 165, 12, 12, 165, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 168, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 145, 7, 7, 146, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 149, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 156, 7, 7, 154, + 7, 7, 154, 7, 7, 168, 7, 7, 185, 7, 7, 183, 9, 9, 180, 28, 28, 180, 19, 19, 180, 9, 9, 179, 7, 7, 178, 8, 8, 177, 7, 7, 176, 9, 9, 176, 8, 8, 177, 8, 8, 178, 7, 7, 178, 7, 7, 178, 7, 7, 177, 9, 9, 178, 8, 8, 177, 7, 7, 176, 7, 7, 174, + 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 175, 8, 8, 170, 7, 7, 166, 7, 7, 165, 10, 10, 166, 27, 27, 169, 28, 28, 169, 16, 16, 168, 10, 10, 167, 11, 11, 166, 15, 15, 167, 14, 14, 166, 9, 9, 166, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, + 7, 7, 167, 7, 7, 166, 7, 7, 163, 8, 8, 158, 9, 9, 152, 14, 14, 147, 21, 21, 144, 28, 28, 143, 22, 22, 143, 9, 9, 141, 7, 7, 141, 8, 8, 141, 10, 10, 141, 9, 9, 141, 9, 9, 140, 8, 8, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 8, 8, 140, + 17, 17, 141, 12, 12, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 10, 10, 141, 22, 22, 141, 12, 12, 140, 14, 14, 140, 19, 19, 141, 13, 13, 140, + 14, 14, 141, 24, 24, 141, 30, 30, 142, 17, 17, 140, 8, 8, 140, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 130, 7, 7, 125, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 110, 7, 7, 106, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, + 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 77, 7, 7, 88, 7, 7, 94, 7, 7, 102, 7, 7, 106, 7, 7, 110, 7, 7, 114, 7, 7, 116, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, + 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 9, 9, 134, 14, 14, 134, 13, 13, 135, 20, 20, 135, 22, 22, 136, 16, 16, 135, 11, 11, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 135, 17, 17, 135, 18, 18, 135, 9, 9, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 16, 16, 135, 14, 14, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 135, 14, 14, 135, 9, 9, 136, 13, 13, 139, 20, 20, 146, 9, 9, 154, 7, 7, 159, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 165, 8, 8, 165, 13, 13, 166, 8, 8, 165, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 8, 8, 165, 8, 8, 166, 7, 7, 165, 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 158, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 147, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 147, + 8, 8, 148, 8, 8, 151, 7, 7, 152, 7, 7, 154, 7, 7, 153, 7, 7, 150, 7, 7, 157, 7, 7, 179, 7, 7, 187, 8, 8, 183, 31, 31, 181, 28, 28, 180, 11, 11, 178, 8, 8, 178, 7, 7, 179, 7, 7, 177, 8, 8, 177, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 178, + 7, 7, 178, 12, 12, 178, 12, 12, 178, 9, 9, 176, 7, 7, 175, 7, 7, 174, 7, 7, 175, 7, 7, 176, 7, 7, 174, 7, 7, 170, 7, 7, 166, 7, 7, 164, 14, 14, 166, 32, 32, 168, 28, 28, 169, 15, 15, 168, 8, 8, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, + 7, 7, 166, 7, 7, 166, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 8, 8, 157, 10, 10, 151, 14, 14, 145, 29, 29, 144, 28, 28, 144, 13, 13, 142, 7, 7, 141, 8, 8, 141, 13, 13, 142, 17, 17, 142, 10, 10, 141, 8, 8, 140, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 12, 12, 140, 9, 9, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 11, 11, 140, + 23, 23, 141, 10, 10, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 8, 8, 140, 13, 13, 140, 23, 23, 140, 13, 13, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 136, 7, 7, 131, 7, 7, 126, 7, 7, 122, 7, 7, 117, 7, 7, 113, 7, 7, 110, 7, 7, 106, 7, 7, 101, + 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 55, 7, 7, 78, 7, 7, 88, 7, 7, 95, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 114, 7, 7, 117, 7, 7, 118, 7, 7, 120, + 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 9, 9, 134, 10, 10, 135, + 11, 11, 135, 10, 10, 135, 8, 8, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 8, 8, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 8, 8, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 136, 9, 9, 139, 12, 12, 147, 7, 7, 155, 7, 7, 161, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, + 7, 7, 165, 7, 7, 165, 7, 7, 165, 9, 9, 165, 8, 8, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 170, 7, 7, 171, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 169, + 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 145, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 145, 8, 8, 145, 7, 7, 146, 8, 8, 146, 7, 7, 148, 7, 7, 151, 7, 7, 152, 7, 7, 150, 7, 7, 145, 7, 7, 146, 7, 7, 154, 7, 7, 170, 7, 7, 178, 15, 15, 180, 22, 22, 180, 14, 14, 180, 8, 8, 179, 8, 8, 179, 7, 7, 178, + 7, 7, 178, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 178, 10, 10, 177, 11, 11, 177, 8, 8, 175, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 173, 7, 7, 170, 7, 7, 165, 7, 7, 163, 9, 9, 165, 14, 14, 166, 9, 9, 167, 7, 7, 167, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 164, 7, 7, 164, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 159, 8, 8, 154, 8, 8, 149, 9, 9, 144, 10, 10, 141, 8, 8, 141, 8, 8, 141, 7, 7, 142, 7, 7, 141, + 13, 13, 142, 18, 18, 142, 8, 8, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 9, 9, 139, 8, 8, 139, 7, 7, 139, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 137, 7, 7, 132, 7, 7, 126, 7, 7, 122, + 7, 7, 118, 7, 7, 113, 7, 7, 110, 7, 7, 106, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 55, 7, 7, 78, 7, 7, 89, 7, 7, 96, 7, 7, 104, 7, 7, 108, + 7, 7, 112, 7, 7, 115, 7, 7, 118, 7, 7, 119, 7, 7, 121, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 139, 7, 7, 148, 7, 7, 155, 7, 7, 161, + 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 168, 7, 7, 170, 7, 7, 172, + 7, 7, 172, 7, 7, 172, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 8, 8, 145, 10, 10, 147, 7, 7, 148, + 7, 7, 147, 7, 7, 148, 7, 7, 145, 7, 7, 142, 7, 7, 141, 8, 8, 141, 8, 8, 142, 7, 7, 143, 8, 8, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 152, 7, 7, 164, 7, 7, 172, + 7, 7, 178, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 180, 7, 7, 180, 7, 7, 180, 7, 7, 178, 8, 8, 176, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 164, + 7, 7, 162, 7, 7, 163, 7, 7, 165, 7, 7, 167, 7, 7, 166, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 154, 7, 7, 149, 7, 7, 145, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 136, 7, 7, 131, 7, 7, 127, 7, 7, 121, 7, 7, 117, 7, 7, 114, 7, 7, 110, 7, 7, 106, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 56, + 7, 7, 79, 7, 7, 90, 7, 7, 97, 7, 7, 105, 7, 7, 109, 7, 7, 113, 7, 7, 116, 7, 7, 118, 7, 7, 120, 7, 7, 122, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, + 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 141, 7, 7, 153, 7, 7, 158, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, + 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 172, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 143, 7, 7, 144, 7, 7, 144, 10, 10, 144, 8, 8, 144, 7, 7, 144, 7, 7, 144, 7, 7, 141, 7, 7, 140, 9, 9, 139, 8, 8, 139, 7, 7, 139, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 8, 8, 144, 8, 8, 144, 8, 8, 143, 7, 7, 142, 7, 7, 140, + 7, 7, 139, 7, 7, 140, 7, 7, 148, 7, 7, 154, 7, 7, 163, 7, 7, 170, 7, 7, 182, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 180, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 175, 7, 7, 173, 8, 8, 170, 7, 7, 168, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 163, 7, 7, 164, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 157, 7, 7, 156, + 7, 7, 153, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 130, 7, 7, 126, 7, 7, 120, 7, 7, 117, 7, 7, 114, 7, 7, 110, 7, 7, 106, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, 36, 36, 38, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 56, 7, 7, 80, 7, 7, 91, 7, 7, 98, 7, 7, 106, 7, 7, 110, 7, 7, 114, 7, 7, 117, 7, 7, 120, 7, 7, 122, 7, 7, 124, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 148, 7, 7, 160, 7, 7, 162, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 165, + 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 168, 7, 7, 170, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 161, + 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 8, 8, 138, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 142, 7, 7, 147, 7, 7, 153, 7, 7, 158, 7, 7, 181, 7, 7, 187, 7, 7, 186, 7, 7, 185, 7, 7, 185, 7, 7, 183, 7, 7, 181, 7, 7, 180, 7, 7, 181, 7, 7, 179, + 7, 7, 177, 7, 7, 175, 9, 9, 169, 11, 11, 168, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 9, 9, 160, 7, 7, 162, 7, 7, 163, 7, 7, 166, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, + 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 136, 7, 7, 133, 7, 7, 128, 7, 7, 124, 7, 7, 119, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 106, 7, 7, 102, 7, 7, 97, + 7, 7, 88, 7, 7, 80, 7, 7, 68, 7, 7, 45, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 56, 7, 7, 80, 7, 7, 92, 7, 7, 99, 7, 7, 107, 7, 7, 111, 7, 7, 115, 7, 7, 118, 7, 7, 121, 7, 7, 123, 7, 7, 125, 7, 7, 126, + 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 139, 7, 7, 159, 7, 7, 167, 7, 7, 169, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 171, 7, 7, 174, + 7, 7, 174, 7, 7, 175, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 167, 7, 7, 168, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 169, + 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 144, 7, 7, 149, 7, 7, 177, 7, 7, 192, 7, 7, 189, 7, 7, 191, 7, 7, 181, + 7, 7, 171, 7, 7, 175, 7, 7, 179, 7, 7, 183, 7, 7, 184, 7, 7, 179, 7, 7, 176, 8, 8, 170, 15, 15, 167, 9, 9, 165, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 162, 9, 9, 161, 9, 9, 163, 7, 7, 163, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 165, + 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 130, 7, 7, 126, 7, 7, 123, 7, 7, 119, 7, 7, 116, + 7, 7, 114, 7, 7, 111, 7, 7, 107, 7, 7, 102, 7, 7, 97, 7, 7, 89, 7, 7, 80, 7, 7, 69, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 57, 7, 7, 81, 7, 7, 93, 7, 7, 100, 7, 7, 108, 7, 7, 112, 7, 7, 116, + 7, 7, 119, 7, 7, 122, 7, 7, 124, 7, 7, 126, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 156, 7, 7, 171, 7, 7, 175, 7, 7, 178, 7, 7, 176, 7, 7, 177, + 7, 7, 175, 7, 7, 174, 7, 7, 176, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 169, + 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 141, + 7, 7, 166, 7, 7, 195, 7, 7, 194, 7, 7, 196, 7, 7, 173, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 173, 7, 7, 184, 7, 7, 188, 7, 7, 182, 7, 7, 174, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 163, 9, 9, 163, 7, 7, 165, 7, 7, 166, + 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 149, 7, 7, 150, + 7, 7, 150, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 134, 7, 7, 132, + 7, 7, 128, 7, 7, 124, 7, 7, 121, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 107, 7, 7, 102, 7, 7, 97, 7, 7, 89, 7, 7, 80, 7, 7, 69, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 57, 7, 7, 82, + 7, 7, 93, 7, 7, 100, 7, 7, 109, 7, 7, 113, 7, 7, 117, 7, 7, 120, 7, 7, 123, 7, 7, 125, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 137, 7, 7, 172, + 7, 7, 183, 7, 7, 184, 7, 7, 186, 7, 7, 188, 7, 7, 185, 7, 7, 181, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 177, 7, 7, 177, 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 173, 7, 7, 171, + 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 147, 7, 7, 189, 7, 7, 203, 7, 7, 187, 7, 7, 151, 7, 7, 147, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 158, 7, 7, 190, 7, 7, 190, 7, 7, 182, 8, 8, 176, 11, 11, 172, 10, 10, 169, + 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 171, 7, 7, 171, 8, 8, 171, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 149, + 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 129, 7, 7, 126, 7, 7, 124, 7, 7, 121, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 107, 7, 7, 103, 7, 7, 98, 7, 7, 89, 7, 7, 81, 7, 7, 69, 7, 7, 46, 36, 36, 38, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 58, 7, 7, 83, 7, 7, 94, 7, 7, 102, 7, 7, 109, 7, 7, 114, 7, 7, 118, 7, 7, 121, 7, 7, 124, 7, 7, 125, 7, 7, 128, 7, 7, 130, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 135, 7, 7, 171, 7, 7, 193, 7, 7, 194, 7, 7, 197, 7, 7, 196, 7, 7, 191, 7, 7, 186, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 184, 7, 7, 185, 7, 7, 185, 7, 7, 183, 7, 7, 181, 7, 7, 180, 7, 7, 179, + 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, + 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 148, 7, 7, 164, 7, 7, 148, 7, 7, 140, 7, 7, 141, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 154, + 7, 7, 184, 7, 7, 191, 7, 7, 183, 11, 11, 177, 12, 12, 174, 8, 8, 173, 7, 7, 174, 7, 7, 174, 7, 7, 175, 8, 8, 174, 8, 8, 175, 8, 8, 175, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, + 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, + 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 123, 7, 7, 121, 7, 7, 119, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 108, 7, 7, 103, 7, 7, 98, 7, 7, 90, + 7, 7, 81, 7, 7, 69, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 58, 7, 7, 84, 7, 7, 95, 7, 7, 103, 7, 7, 111, 7, 7, 115, 7, 7, 119, 7, 7, 122, 7, 7, 125, 7, 7, 126, 7, 7, 129, 7, 7, 131, 7, 7, 131, + 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 146, 7, 7, 174, 7, 7, 189, 7, 7, 188, 7, 7, 194, 7, 7, 197, 7, 7, 189, 7, 7, 185, 7, 7, 184, 7, 7, 185, 7, 7, 185, 7, 7, 185, + 7, 7, 184, 7, 7, 182, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, + 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 138, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 150, 7, 7, 184, 7, 7, 192, 7, 7, 183, 7, 7, 180, 7, 7, 177, 7, 7, 178, 7, 7, 177, 8, 8, 177, 8, 8, 177, 7, 7, 177, 7, 7, 176, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, + 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 115, + 7, 7, 112, 7, 7, 108, 7, 7, 104, 7, 7, 99, 7, 7, 90, 7, 7, 81, 7, 7, 70, 7, 7, 46, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 58, 7, 7, 84, 7, 7, 96, 7, 7, 104, 7, 7, 112, 7, 7, 116, 7, 7, 120, 7, 7, 123, + 7, 7, 125, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 135, 7, 7, 140, 7, 7, 138, 7, 7, 153, 7, 7, 192, 7, 7, 194, + 7, 7, 188, 7, 7, 186, 7, 7, 186, 7, 7, 186, 7, 7, 185, 7, 7, 183, 7, 7, 180, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 176, 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, + 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 156, 7, 7, 193, 7, 7, 189, 7, 7, 184, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 177, 7, 7, 177, + 7, 7, 177, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 128, 7, 7, 126, + 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 115, 7, 7, 112, 7, 7, 109, 7, 7, 104, 7, 7, 99, 7, 7, 91, 7, 7, 82, 7, 7, 70, 7, 7, 47, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 59, 7, 7, 85, 7, 7, 97, + 7, 7, 105, 7, 7, 113, 7, 7, 117, 7, 7, 121, 7, 7, 124, 7, 7, 126, 7, 7, 128, 7, 7, 130, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 165, 7, 7, 199, 7, 7, 193, 7, 7, 189, 7, 7, 187, 7, 7, 186, 7, 7, 183, 7, 7, 180, 7, 7, 176, 7, 7, 174, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 168, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, + 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 137, 7, 7, 169, 7, 7, 194, 7, 7, 187, 7, 7, 183, + 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 121, 7, 7, 118, 7, 7, 116, 7, 7, 113, 7, 7, 109, 7, 7, 105, 7, 7, 100, 7, 7, 91, 7, 7, 83, 7, 7, 71, 7, 7, 47, 36, 36, 38, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 40, 10, 10, 60, 7, 7, 86, 7, 7, 98, 7, 7, 106, 7, 7, 114, 7, 7, 118, 7, 7, 121, 7, 7, 125, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, + 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 163, 7, 7, 201, 7, 7, 195, 7, 7, 193, 7, 7, 191, 7, 7, 187, 7, 7, 183, 7, 7, 178, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 172, 7, 7, 172, + 7, 7, 172, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, + 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 145, 7, 7, 190, 7, 7, 190, 7, 7, 184, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 176, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 165, + 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 119, 7, 7, 117, 7, 7, 114, 7, 7, 110, 7, 7, 106, 7, 7, 101, 7, 7, 92, 7, 7, 84, + 7, 7, 71, 7, 7, 47, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 60, 7, 7, 86, 7, 7, 99, 7, 7, 106, 7, 7, 114, 7, 7, 118, 7, 7, 122, 7, 7, 125, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 142, 7, 7, 162, 7, 7, 191, 7, 7, 201, 7, 7, 197, 7, 7, 194, 7, 7, 192, 7, 7, 186, 7, 7, 181, 7, 7, 176, + 7, 7, 172, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 166, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 176, 7, 7, 194, 7, 7, 187, 7, 7, 184, 7, 7, 182, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 177, 7, 7, 175, + 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 114, + 7, 7, 111, 7, 7, 106, 7, 7, 101, 7, 7, 93, 7, 7, 85, 7, 7, 72, 7, 7, 48, 36, 36, 38, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 60, 7, 7, 87, 7, 7, 100, 7, 7, 107, 7, 7, 115, 7, 7, 119, 7, 7, 122, 7, 7, 126, 7, 7, 129, + 7, 7, 130, 7, 7, 131, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 141, 7, 7, 167, 7, 7, 193, 7, 7, 201, 7, 7, 199, 7, 7, 195, 7, 7, 194, + 7, 7, 193, 7, 7, 190, 7, 7, 185, 7, 7, 179, 7, 7, 174, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 165, + 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 162, 7, 7, 195, 7, 7, 190, 7, 7, 187, 7, 7, 185, 7, 7, 183, 7, 7, 181, 7, 7, 181, 7, 7, 181, + 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, + 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 115, 7, 7, 112, 7, 7, 107, 7, 7, 103, 7, 7, 94, 7, 7, 86, 7, 7, 73, 7, 7, 48, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 61, 7, 7, 88, 7, 7, 100, 7, 7, 107, + 7, 7, 115, 7, 7, 119, 7, 7, 122, 7, 7, 126, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 157, 7, 7, 189, 7, 7, 203, + 7, 7, 201, 7, 7, 198, 7, 7, 193, 7, 7, 191, 7, 7, 189, 7, 7, 187, 7, 7, 185, 7, 7, 181, 7, 7, 177, 7, 7, 172, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 167, 7, 7, 165, + 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 157, + 7, 7, 156, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 148, 7, 7, 192, 7, 7, 195, 7, 7, 192, + 7, 7, 188, 7, 7, 185, 7, 7, 183, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 181, 7, 7, 178, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, + 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 124, 7, 7, 121, 7, 7, 119, 7, 7, 116, 7, 7, 113, 7, 7, 109, 7, 7, 104, 7, 7, 96, 7, 7, 87, 7, 7, 74, 7, 7, 49, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 40, 10, 10, 61, 7, 7, 89, 7, 7, 101, 7, 7, 108, 7, 7, 116, 7, 7, 119, 7, 7, 123, 7, 7, 126, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 147, 7, 7, 193, 7, 7, 201, 7, 7, 201, 7, 7, 197, 7, 7, 194, 7, 7, 189, 7, 7, 185, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 178, 7, 7, 175, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, + 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, + 7, 7, 161, 7, 7, 158, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 138, 7, 7, 178, 7, 7, 199, 7, 7, 195, 7, 7, 190, 7, 7, 187, 7, 7, 184, 7, 7, 183, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 180, 7, 7, 176, 7, 7, 173, 7, 7, 171, 7, 7, 168, 7, 7, 167, + 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 114, 7, 7, 110, 7, 7, 105, 7, 7, 97, 7, 7, 88, 7, 7, 75, + 7, 7, 50, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 62, 7, 7, 90, 7, 7, 102, 7, 7, 109, 7, 7, 117, 7, 7, 120, 7, 7, 124, 7, 7, 128, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, + 7, 7, 136, 7, 7, 136, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 165, 7, 7, 197, 7, 7, 197, 7, 7, 197, 7, 7, 196, 7, 7, 192, 7, 7, 187, 7, 7, 182, 7, 7, 180, 7, 7, 178, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, + 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, + 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 152, 7, 7, 152, + 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 152, 7, 7, 195, 7, 7, 197, 7, 7, 193, 7, 7, 188, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 181, + 7, 7, 178, 7, 7, 175, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 115, + 7, 7, 111, 7, 7, 106, 7, 7, 98, 7, 7, 89, 7, 7, 76, 7, 7, 50, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 64, 7, 7, 91, 7, 7, 103, 7, 7, 110, 7, 7, 118, 7, 7, 122, 7, 7, 125, 7, 7, 128, 7, 7, 130, 7, 7, 131, + 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 137, 7, 7, 184, 7, 7, 195, 7, 7, 193, 7, 7, 195, 7, 7, 194, 7, 7, 191, 7, 7, 186, 7, 7, 180, 7, 7, 178, 7, 7, 176, + 7, 7, 174, 7, 7, 174, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 164, + 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 137, 7, 7, 174, 7, 7, 200, 7, 7, 194, 7, 7, 188, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 180, + 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 173, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 130, + 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 119, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 98, 7, 7, 90, 7, 7, 77, 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 65, 7, 7, 92, 7, 7, 104, 7, 7, 111, 7, 7, 119, + 7, 7, 123, 7, 7, 126, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 155, 7, 7, 194, 7, 7, 193, 7, 7, 193, 7, 7, 194, 7, 7, 195, + 7, 7, 192, 7, 7, 186, 7, 7, 180, 7, 7, 176, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, + 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 149, 7, 7, 151, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 160, 7, 7, 200, 7, 7, 193, + 7, 7, 188, 7, 7, 185, 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, + 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 99, 7, 7, 90, 7, 7, 78, 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, + 10, 10, 66, 7, 7, 93, 7, 7, 105, 7, 7, 113, 7, 7, 120, 7, 7, 124, 7, 7, 128, 7, 7, 129, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, + 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 142, 7, 7, 181, + 7, 7, 194, 7, 7, 191, 7, 7, 192, 7, 7, 194, 7, 7, 195, 7, 7, 193, 7, 7, 188, 7, 7, 180, 7, 7, 176, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, + 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 153, 7, 7, 154, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 151, 7, 7, 152, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 135, 7, 7, 134, 7, 7, 153, 7, 7, 199, 7, 7, 194, 7, 7, 189, 7, 7, 186, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 165, + 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 112, 7, 7, 107, 7, 7, 99, 7, 7, 90, 7, 7, 78, 7, 7, 53, + 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 66, 7, 7, 93, 7, 7, 106, 7, 7, 113, 7, 7, 121, 7, 7, 125, 7, 7, 128, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 137, + 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 235, 7, 7, 194, 7, 7, 192, 7, 7, 191, 7, 7, 192, 7, 7, 193, 7, 7, 195, 7, 7, 194, 7, 7, 190, 7, 7, 183, 133, 133, 199, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 164, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 150, 7, 7, 152, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 152, 7, 7, 155, + 7, 7, 154, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 143, 7, 7, 193, 7, 7, 197, 7, 7, 192, 7, 7, 188, 7, 7, 186, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 179, + 7, 7, 176, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 121, 7, 7, 117, 7, 7, 112, + 7, 7, 107, 7, 7, 99, 7, 7, 91, 7, 7, 79, 7, 7, 53, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 66, 7, 7, 94, 7, 7, 106, 7, 7, 114, 7, 7, 122, 7, 7, 126, 7, 7, 129, 7, 7, 131, 7, 7, 132, 7, 7, 133, 7, 7, 134, + 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 239, 7, 7, 193, 7, 7, 191, 7, 7, 190, 7, 7, 190, 7, 7, 191, 7, 7, 192, 7, 7, 193, 7, 7, 192, 7, 7, 187, 133, 133, 201, 255, 255, 255, 255, 255, 255, + 250, 250, 252, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 157, 7, 7, 153, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 159, 7, 7, 193, 7, 7, 198, 7, 7, 194, 7, 7, 190, 7, 7, 187, 7, 7, 184, 7, 7, 181, + 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, + 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, + 7, 7, 125, 7, 7, 124, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 99, 7, 7, 91, 7, 7, 79, 7, 7, 53, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 94, 7, 7, 106, 7, 7, 114, 7, 7, 122, 7, 7, 126, + 7, 7, 129, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 239, 7, 7, 194, 7, 7, 193, 7, 7, 193, 7, 7, 191, 7, 7, 190, 7, 7, 191, 7, 7, 190, + 7, 7, 171, 7, 7, 163, 133, 133, 197, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 151, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 153, 7, 7, 182, + 7, 7, 199, 7, 7, 194, 7, 7, 188, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 176, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 177, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, + 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 160, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 168, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 151, 151, 192, 255, 255, 255, 255, 255, 255, 225, 225, 235, 7, 7, 156, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, + 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 99, 7, 7, 92, 7, 7, 80, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, + 7, 7, 94, 7, 7, 106, 7, 7, 113, 7, 7, 122, 7, 7, 126, 7, 7, 130, 7, 7, 133, 7, 7, 134, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, + 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 185, 185, 204, + 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 236, 7, 7, 191, 7, 7, 190, + 7, 7, 194, 7, 7, 194, 7, 7, 191, 7, 7, 192, 7, 7, 172, 7, 7, 141, 7, 7, 137, 133, 133, 183, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 144, 7, 7, 187, 7, 7, 196, 7, 7, 189, 7, 7, 184, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 180, 7, 7, 177, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 177, 7, 7, 166, + 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 168, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 151, 151, 193, 255, 255, 255, 255, 255, 255, 225, 225, 235, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 112, 7, 7, 108, 7, 7, 100, 7, 7, 92, 7, 7, 81, 7, 7, 54, 36, 36, 39, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 94, 7, 7, 106, 7, 7, 113, 7, 7, 122, 7, 7, 126, 7, 7, 130, 7, 7, 134, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 144, 144, 183, 217, 217, 228, 244, 244, 247, 251, 251, 252, 233, 233, 239, 208, 208, 223, 119, 119, 173, 115, 115, 170, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 139, 139, 178, 216, 216, 227, 244, 244, 247, + 250, 250, 251, 230, 230, 236, 201, 201, 215, 89, 89, 152, 185, 185, 204, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 139, 139, 176, 216, 216, 226, 244, 244, 247, 250, 250, 251, 230, 230, 236, 201, 201, 215, 89, 89, 151, 185, 185, 204, + 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 138, 7, 7, 139, 7, 7, 153, 7, 7, 184, 7, 7, 195, 7, 7, 175, 7, 7, 144, 7, 7, 137, 231, 231, 237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 245, 7, 7, 156, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 104, 104, 171, 203, 203, 221, 239, 239, 244, 251, 251, 253, 246, 246, 249, 226, 226, 236, 174, 174, 204, 31, 31, 151, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 166, 7, 7, 197, 7, 7, 188, 7, 7, 183, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 183, 7, 7, 183, 7, 7, 181, 7, 7, 179, + 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 178, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 169, 7, 7, 157, 7, 7, 157, + 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 151, 151, 193, 255, 255, 255, 255, 255, 255, 225, 225, 235, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 108, + 7, 7, 100, 7, 7, 93, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 94, 7, 7, 106, 7, 7, 113, 7, 7, 122, 7, 7, 126, 7, 7, 131, 7, 7, 135, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 63, 63, 149, 204, 204, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 203, 203, 219, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 44, 44, 144, 195, 195, 213, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 249, 225, 225, 233, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 135, 44, 44, 139, 195, 195, 212, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 249, 225, 225, 233, 255, 255, 255, 255, 255, 255, 218, 218, 227, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 147, 7, 7, 161, 7, 7, 144, 7, 7, 138, 7, 7, 139, 231, 231, 237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 240, 240, 245, 7, 7, 154, 7, 7, 153, 18, 18, 152, 174, 174, 203, 250, 250, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 231, 238, 115, 115, 173, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, + 7, 7, 150, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, + 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 169, 7, 7, 196, 7, 7, 188, 7, 7, 183, 7, 7, 182, 7, 7, 182, + 7, 7, 183, 7, 7, 185, 7, 7, 185, 7, 7, 183, 7, 7, 180, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 178, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 251, 251, 253, + 255, 255, 255, 255, 255, 255, 86, 86, 169, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 151, 151, 193, 255, 255, 255, 255, 255, 255, 225, 225, 235, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 123, + 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 108, 7, 7, 101, 7, 7, 93, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 93, 7, 7, 105, 7, 7, 113, 7, 7, 122, 7, 7, 128, 7, 7, 132, + 7, 7, 136, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 217, 217, 228, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 225, 225, 233, 7, 7, 142, 7, 7, 142, 7, 7, 141, 208, 208, 222, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 136, + 208, 208, 221, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 227, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, + 221, 221, 231, 247, 247, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, 244, 248, 230, 230, 238, 7, 7, 152, 7, 7, 151, 190, 190, 213, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 252, 103, 103, 168, + 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 25, 25, 138, 173, 173, 198, 228, 228, 235, 247, 247, 249, 247, 247, 249, 225, 225, 232, 189, 189, 208, 54, 54, 142, 214, 214, 225, 255, 255, 255, 255, 255, 255, 104, 104, 165, 7, 7, 188, + 7, 7, 195, 7, 7, 189, 18, 18, 185, 169, 169, 216, 228, 228, 241, 248, 248, 251, 246, 246, 250, 221, 221, 239, 174, 174, 218, 18, 18, 182, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 179, 7, 7, 167, 7, 7, 166, 7, 7, 164, 18, 18, 163, 169, 169, 205, 228, 228, 238, 248, 248, 250, + 246, 246, 249, 221, 221, 234, 174, 174, 207, 18, 18, 161, 251, 251, 253, 255, 255, 255, 255, 255, 255, 86, 86, 169, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 231, 231, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 202, 202, 222, + 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 141, 141, 186, 215, 215, 229, 244, 244, 248, 252, 252, 253, 242, 242, 246, 212, 212, 225, 131, 131, 177, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 131, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 117, 7, 7, 113, 7, 7, 109, 7, 7, 101, 7, 7, 93, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 93, + 7, 7, 105, 7, 7, 113, 7, 7, 122, 7, 7, 128, 7, 7, 133, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 154, 154, 188, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 227, 235, 127, 127, 175, 44, 44, 147, + 78, 78, 155, 162, 162, 194, 246, 246, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 142, 7, 7, 142, 141, 141, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 227, 235, 129, 129, 172, 44, 44, 141, 82, 82, 152, 168, 168, 194, 248, 248, 250, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 141, 141, 178, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 227, 234, 129, 129, 171, 44, 44, 139, 82, 82, 149, 168, 168, 193, 248, 248, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 134, 7, 7, 135, 7, 7, 136, + 7, 7, 136, 7, 7, 138, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 133, 133, 178, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 145, 7, 7, 147, 7, 7, 150, 126, 126, 178, 253, 253, 254, 255, 255, 255, 255, 255, 255, 230, 230, 238, 132, 132, 181, 44, 44, 154, 87, 87, 165, + 177, 177, 206, 251, 251, 252, 255, 255, 255, 255, 255, 255, 225, 225, 234, 18, 18, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 152, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 104, 104, 160, 228, 228, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 237, 237, 241, + 232, 232, 238, 255, 255, 255, 255, 255, 255, 104, 104, 179, 7, 7, 198, 7, 7, 193, 91, 91, 198, 222, 222, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 226, 226, 240, 253, 253, 254, 255, 255, 255, 255, 255, 255, 86, 86, 180, 7, 7, 168, 7, 7, 166, + 91, 91, 176, 222, 222, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 226, 226, 236, 253, 253, 254, 255, 255, 255, 255, 255, 255, 86, 86, 169, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 231, 231, 239, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 202, 202, 222, 7, 7, 155, 7, 7, 154, 67, 67, 161, 204, 204, 222, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 197, 197, 215, 57, 57, 148, 7, 7, 140, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 114, 7, 7, 109, 7, 7, 100, 7, 7, 93, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 93, 7, 7, 105, 7, 7, 113, 7, 7, 123, 7, 7, 129, 7, 7, 134, 7, 7, 138, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 234, 234, 240, 255, 255, 255, + 255, 255, 255, 228, 228, 236, 25, 25, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 111, 111, 167, 252, 252, 253, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 142, 7, 7, 142, 233, 233, 239, 255, 255, 255, 255, 255, 255, 227, 227, 235, 25, 25, 139, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 121, 121, 167, 253, 253, 254, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 233, 233, 238, 255, 255, 255, 255, 255, 255, 227, 227, 234, 25, 25, 137, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 121, 121, 166, 253, 253, 254, 255, 255, 255, + 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 133, 133, 178, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 145, 7, 7, 146, 7, 7, 147, 229, 229, 237, 255, 255, 255, 255, 255, 255, + 231, 231, 238, 36, 36, 150, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, 141, 141, 186, 255, 255, 255, 255, 255, 255, 255, 255, 255, 156, 156, 193, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 51, 51, 143, 238, 238, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 252, 252, 253, 239, 239, 243, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 104, 104, 185, 7, 7, 198, 36, 36, 195, 233, 233, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 239, 239, 246, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 86, 86, 182, 7, 7, 169, 36, 36, 169, 233, 233, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 239, 239, 245, 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 168, 7, 7, 156, 7, 7, 156, 7, 7, 156, + 7, 7, 156, 7, 7, 157, 7, 7, 158, 209, 209, 226, 239, 239, 245, 255, 255, 255, 255, 255, 255, 249, 249, 251, 231, 231, 239, 183, 183, 211, 7, 7, 155, 7, 7, 154, 220, 220, 232, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 239, 239, 244, 254, 254, 254, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 210, 210, 223, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 117, 7, 7, 113, 7, 7, 108, 7, 7, 100, + 7, 7, 92, 7, 7, 80, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 66, 7, 7, 92, 7, 7, 105, 7, 7, 113, 7, 7, 123, 7, 7, 129, 7, 7, 134, 7, 7, 138, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 44, 44, 145, 253, 253, 254, 255, 255, 255, 255, 255, 255, 135, 135, 178, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 202, 202, 218, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 142, 91, 91, 159, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 128, 128, 173, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 204, 204, 218, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 91, 91, 153, 255, 255, 255, 255, 255, 255, 255, 255, 255, 128, 128, 171, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 204, 204, 218, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 143, 7, 7, 143, 133, 133, 179, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 146, + 7, 7, 146, 87, 87, 161, 255, 255, 255, 255, 255, 255, 255, 255, 255, 135, 135, 181, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 152, 217, 217, 229, 255, 255, 255, 255, 255, 255, 209, 209, 224, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, + 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 156, 7, 7, 156, 7, 7, 157, + 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 193, 193, 211, 255, 255, 255, 255, 255, 255, 251, 251, 252, 174, 174, 198, 44, 44, 140, 7, 7, 135, 44, 44, 139, 175, 175, 198, 251, 251, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 104, 104, 174, 7, 7, 194, 183, 183, 226, 255, 255, 255, 255, 255, 255, 251, 251, 253, 176, 176, 214, 44, 44, 155, + 7, 7, 136, 51, 51, 150, 182, 182, 221, 252, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 183, 7, 7, 171, 183, 183, 215, 255, 255, 255, 255, 255, 255, 251, 251, 252, 176, 176, 209, 44, 44, 165, 7, 7, 162, 51, 51, 166, 182, 182, 212, 252, 252, 253, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 86, 86, 168, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 151, 151, 196, 255, 255, 255, 255, 255, 255, 225, 225, 235, 7, 7, 156, 7, 7, 156, 7, 7, 156, 173, 173, 205, 255, 255, 255, 255, 255, 255, 252, 252, 253, 179, 179, 207, + 48, 48, 155, 7, 7, 149, 60, 60, 155, 192, 192, 213, 254, 254, 254, 255, 255, 255, 255, 255, 255, 155, 155, 188, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, + 7, 7, 121, 7, 7, 117, 7, 7, 113, 7, 7, 108, 7, 7, 99, 7, 7, 91, 7, 7, 80, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 66, 7, 7, 92, 7, 7, 105, 7, 7, 113, 7, 7, 122, 7, 7, 128, 7, 7, 133, 7, 7, 138, + 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 118, 118, 170, 255, 255, 255, 255, 255, 255, 254, 254, 254, 54, 54, 148, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 165, 165, 194, 255, 255, 255, 255, 255, 255, + 225, 225, 233, 7, 7, 142, 133, 133, 176, 255, 255, 255, 255, 255, 255, 253, 253, 253, 44, 44, 143, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 164, 164, 192, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 136, 133, 133, 174, 255, 255, 255, 255, 255, 255, + 253, 253, 253, 44, 44, 140, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 164, 164, 191, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 136, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 144, + 133, 133, 179, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 146, 7, 7, 146, 133, 133, 180, 255, 255, 255, 255, 255, 255, 253, 253, 254, 48, 48, 151, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 181, 181, 207, 255, 255, 255, 255, 255, 255, 229, 229, 237, + 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 148, 7, 7, 132, 7, 7, 122, 7, 7, 125, 7, 7, 140, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 247, 247, 249, 255, 255, 255, 255, 255, 255, 171, 171, 196, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 173, 173, 197, 255, 255, 255, 255, 255, 255, 255, 255, 255, 104, 104, 160, 7, 7, 160, 245, 245, 250, + 255, 255, 255, 255, 255, 255, 169, 169, 197, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 134, 7, 7, 161, 179, 179, 224, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 185, 7, 7, 173, 245, 245, 249, 255, 255, 255, 255, 255, 255, 169, 169, 206, 7, 7, 163, 7, 7, 163, 7, 7, 163, + 7, 7, 163, 7, 7, 163, 179, 179, 211, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 169, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 151, 151, 196, 255, 255, 255, 255, 255, 255, 225, 225, 235, 7, 7, 157, 7, 7, 157, 31, 31, 159, + 246, 246, 249, 255, 255, 255, 255, 255, 255, 175, 175, 205, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 194, 194, 214, 255, 255, 255, 255, 255, 255, 237, 237, 242, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 130, + 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 112, 7, 7, 107, 7, 7, 99, 7, 7, 91, 7, 7, 79, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 65, 7, 7, 92, 7, 7, 105, + 7, 7, 113, 7, 7, 122, 7, 7, 128, 7, 7, 132, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 125, 125, 173, 255, 255, 255, 255, 255, 255, 252, 252, 253, 36, 36, 146, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 157, 157, 190, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 141, 136, 136, 178, 255, 255, 255, 255, 255, 255, 254, 254, 254, 57, 57, 146, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 154, 154, 186, 255, 255, 255, 255, 255, 255, + 218, 218, 228, 7, 7, 137, 136, 136, 176, 255, 255, 255, 255, 255, 255, 254, 254, 254, 57, 57, 143, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 154, 154, 185, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 137, 7, 7, 137, 7, 7, 139, 7, 7, 140, + 7, 7, 141, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 133, 133, 179, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 146, 7, 7, 146, 133, 133, 180, 255, 255, 255, 255, 255, 255, 254, 254, 254, 51, 51, 152, 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 150, 180, 180, 207, 255, 255, 255, 255, 255, 255, 231, 231, 239, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 154, 7, 7, 141, 7, 7, 95, 7, 7, 42, 10, 10, 17, 8, 8, 11, 7, 7, 7, 7, 7, 8, 7, 7, 8, 7, 7, 17, 7, 7, 58, 7, 7, 109, 7, 7, 149, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 139, 7, 7, 138, 97, 97, 158, 255, 255, 255, 255, 255, 255, 250, 250, 251, 25, 25, 137, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 25, 25, 139, 251, 251, 252, + 255, 255, 255, 255, 255, 255, 104, 104, 160, 92, 92, 155, 255, 255, 255, 255, 255, 255, 249, 249, 251, 18, 18, 142, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 144, 31, 31, 187, 250, 250, 253, 255, 255, 255, 255, 255, 255, 86, 86, 187, 92, 92, 186, 255, 255, 255, 255, 255, 255, + 249, 249, 251, 18, 18, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 31, 31, 164, 250, 250, 252, 255, 255, 255, 255, 255, 255, 86, 86, 169, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 151, 151, 196, 255, 255, 255, + 255, 255, 255, 225, 225, 236, 7, 7, 158, 7, 7, 158, 123, 123, 183, 255, 255, 255, 255, 255, 255, 250, 250, 251, 25, 25, 155, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 76, 76, 156, 255, 255, 255, 255, 255, 255, 255, 255, 255, 87, 87, 157, 7, 7, 140, 7, 7, 139, + 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 98, 7, 7, 90, 7, 7, 79, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 40, 10, 10, 64, 7, 7, 91, 7, 7, 105, 7, 7, 113, 7, 7, 122, 7, 7, 126, 7, 7, 132, 7, 7, 136, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 54, 54, 149, 254, 254, 254, 255, 255, 255, 255, 255, 255, + 118, 118, 171, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 196, 196, 214, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 141, 100, 100, 161, 255, 255, 255, 255, 255, 255, 255, 255, 255, 139, 139, 178, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 194, 194, 212, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 138, 100, 100, 159, 255, 255, 255, 255, 255, 255, 255, 255, 255, 139, 139, 177, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 194, 194, 211, 255, 255, 255, 255, 255, 255, + 218, 218, 228, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 133, 133, 179, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 146, 7, 7, 146, 89, 89, 162, 255, 255, 255, 255, 255, 255, 255, 255, 255, 136, 136, 181, + 7, 7, 147, 7, 7, 149, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 150, 215, 215, 228, 255, 255, 255, 255, 255, 255, 213, 213, 227, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 156, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 156, 7, 7, 153, 7, 7, 108, 7, 7, 40, 9, 9, 15, 24, 24, 24, 51, 51, 51, 75, 75, 76, 88, 88, 88, 87, 87, 87, 72, 72, 72, 42, 42, 42, 19, 19, 20, 8, 8, 16, 7, 7, 49, 7, 7, 128, 7, 7, 152, + 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 141, 141, 179, 255, 255, 255, 255, 255, 255, 233, 233, 239, 7, 7, 137, 7, 7, 138, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 233, 233, 239, 255, 255, 255, 255, 255, 255, 104, 104, 160, 141, 141, 180, 255, 255, 255, 255, 255, 255, 233, 233, 239, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 166, 230, 230, 244, 255, 255, 255, + 255, 255, 255, 86, 86, 188, 141, 141, 201, 255, 255, 255, 255, 255, 255, 233, 233, 242, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 230, 230, 239, 255, 255, 255, 255, 255, 255, 86, 86, 169, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, + 7, 7, 158, 7, 7, 159, 7, 7, 159, 151, 151, 196, 255, 255, 255, 255, 255, 255, 225, 225, 236, 7, 7, 159, 7, 7, 159, 146, 146, 193, 255, 255, 255, 255, 255, 255, 233, 233, 241, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 245, 245, 248, + 255, 255, 255, 255, 255, 255, 121, 121, 171, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 98, 7, 7, 90, + 7, 7, 79, 7, 7, 53, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 64, 7, 7, 91, 7, 7, 105, 7, 7, 113, 7, 7, 122, 7, 7, 128, 7, 7, 132, 7, 7, 135, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 143, + 7, 7, 144, 7, 7, 144, 237, 237, 242, 255, 255, 255, 255, 255, 255, 218, 218, 229, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 86, 86, 157, 249, 249, 251, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 141, 7, 7, 141, 238, 238, 243, 255, 255, 255, 255, 255, 255, + 232, 232, 238, 41, 41, 143, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 104, 104, 161, 251, 251, 252, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 139, 7, 7, 139, 238, 238, 242, 255, 255, 255, 255, 255, 255, 232, 232, 238, 41, 41, 141, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 104, 104, 160, 251, 251, 252, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 137, 7, 7, 139, 7, 7, 139, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 145, 7, 7, 145, 7, 7, 146, 133, 133, 179, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 231, 231, 238, 255, 255, 255, 255, 255, 255, 230, 230, 238, 36, 36, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 150, 138, 138, 184, 255, 255, 255, 255, 255, 255, 255, 255, 255, 162, 162, 197, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 153, 7, 7, 97, 8, 8, 26, 16, 16, 20, 58, 58, 58, 103, 103, 103, 117, 117, 117, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, + 95, 95, 95, 47, 47, 47, 11, 11, 11, 7, 7, 26, 7, 7, 122, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 141, 7, 7, 142, 7, 7, 141, 103, 103, 163, 255, 255, 255, + 255, 255, 255, 247, 247, 249, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 247, 247, 249, 255, 255, 255, 255, 255, 255, 104, 104, 162, 101, 101, 163, 255, 255, 255, 255, 255, 255, 251, 251, 252, 31, 31, 147, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 140, 7, 7, 138, 7, 7, 147, 245, 245, 250, 255, 255, 255, 255, 255, 255, 86, 86, 189, 101, 101, 190, 255, 255, 255, 255, 255, 255, 251, 251, 252, 31, 31, 168, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, 245, 245, 248, 255, 255, 255, 255, 255, 255, + 86, 86, 169, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 159, 7, 7, 159, 7, 7, 160, 151, 151, 196, 255, 255, 255, 255, 255, 255, 225, 225, 236, 7, 7, 160, 7, 7, 160, 125, 125, 185, 255, 255, 255, 255, 255, 255, 250, 250, 252, 25, 25, 156, 7, 7, 154, 7, 7, 153, + 7, 7, 151, 7, 7, 150, 7, 7, 149, 72, 72, 157, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 160, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 120, + 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 98, 7, 7, 90, 7, 7, 78, 7, 7, 53, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 64, 7, 7, 91, 7, 7, 105, 7, 7, 114, 7, 7, 122, 7, 7, 128, 7, 7, 132, 7, 7, 135, 7, 7, 137, + 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 165, 165, 196, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 229, 118, 118, 171, 31, 31, 145, 60, 60, 149, 143, 143, 183, 240, 240, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 225, 225, 233, + 7, 7, 141, 7, 7, 141, 156, 156, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 230, 230, 237, 132, 132, 175, 44, 44, 143, 65, 65, 148, 156, 156, 188, 245, 245, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 229, 7, 7, 140, 7, 7, 140, 156, 156, 188, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 230, 230, 237, 132, 132, 174, 44, 44, 141, 65, 65, 146, 156, 156, 188, 245, 245, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 137, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 133, 133, 179, + 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 147, 7, 7, 147, 7, 7, 147, 132, 132, 179, 254, 254, 254, 255, 255, 255, 255, 255, 255, 228, 228, 236, 126, 126, 178, 36, 36, 152, 76, 76, 160, 172, 172, 202, 250, 250, 252, 255, 255, 255, 255, 255, 255, 228, 228, 237, 31, 31, 154, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 108, 7, 7, 24, 26, 26, 30, 88, 88, 88, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 116, 116, 116, 77, 77, 77, 13, 13, 13, 7, 7, 24, 7, 7, 123, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 17, 17, 144, 16, 16, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 12, 12, 144, 21, 21, 144, 7, 7, 143, 18, 18, 143, 249, 249, 251, 255, 255, 255, 255, 255, 255, 155, 155, 189, 10, 10, 144, 10, 10, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 157, 157, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 104, 104, 164, 7, 7, 144, 248, 248, 250, 255, 255, 255, + 255, 255, 255, 177, 177, 203, 7, 7, 144, 8, 8, 144, 11, 11, 143, 11, 11, 141, 7, 7, 139, 160, 160, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 190, 7, 7, 177, 248, 248, 251, 255, 255, 255, 255, 255, 255, 177, 177, 212, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, + 7, 7, 167, 160, 160, 203, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 170, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 151, 151, 197, 255, 255, 255, 255, 255, 255, 225, 225, 236, 7, 7, 162, 7, 7, 162, 41, 41, 165, 247, 247, 250, + 255, 255, 255, 255, 255, 255, 174, 174, 205, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 192, 192, 213, 255, 255, 255, 255, 255, 255, 239, 239, 244, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 130, + 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 122, 7, 7, 119, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 98, 7, 7, 90, 7, 7, 78, 7, 7, 53, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 64, 7, 7, 91, 7, 7, 105, 7, 7, 114, + 7, 7, 122, 7, 7, 128, 7, 7, 132, 7, 7, 135, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 224, 224, 233, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 254, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 142, 7, 7, 142, 7, 7, 141, 217, 217, 228, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 229, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 217, 217, 228, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 143, + 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 133, 133, 180, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 193, 193, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 250, 250, 251, 105, 105, 171, 9, 9, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 8, 8, 150, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 11, 11, 149, 10, 10, 150, 7, 7, 152, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 134, 7, 7, 41, 22, 22, 30, + 96, 96, 96, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, 119, 119, 118, 118, 118, 83, 83, 83, 12, 12, 13, 7, 7, 47, 7, 7, 149, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, + 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 146, 8, 8, 145, 11, 11, 144, 8, 8, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 8, 8, 144, 9, 9, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 25, 25, 146, 22, 22, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 8, 8, 145, 19, 19, 145, 26, 26, 145, 11, 11, 144, 7, 7, 143, 200, 200, 217, 255, 255, 255, 255, 255, 255, 247, 247, 250, 163, 163, 194, 31, 31, 146, 7, 7, 144, 18, 18, 145, 156, 156, 190, 247, 247, 249, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 105, 105, 165, 8, 8, 144, 195, 195, 214, 255, 255, 255, 255, 255, 255, 252, 252, 253, 180, 180, 204, 45, 45, 148, 15, 15, 144, 43, 43, 147, 169, 169, 197, 250, 250, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 191, 7, 7, 177, 195, 195, 223, 255, 255, 255, 255, 255, 255, + 252, 252, 253, 180, 180, 213, 44, 44, 171, 7, 7, 168, 31, 31, 169, 169, 169, 208, 250, 250, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 170, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 151, 151, 198, 255, 255, 255, 255, 255, 255, + 225, 225, 236, 7, 7, 164, 7, 7, 164, 7, 7, 163, 177, 177, 209, 255, 255, 255, 255, 255, 255, 251, 251, 253, 176, 176, 206, 36, 36, 156, 7, 7, 153, 51, 51, 157, 187, 187, 211, 254, 254, 254, 255, 255, 255, 255, 255, 255, 161, 161, 193, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, + 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 122, 7, 7, 119, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 98, 7, 7, 90, 7, 7, 78, 7, 7, 53, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 40, 10, 10, 65, 7, 7, 91, 7, 7, 105, 7, 7, 114, 7, 7, 122, 7, 7, 128, 7, 7, 132, 7, 7, 135, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 78, 78, 155, 213, 213, 225, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 184, 184, 206, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 142, 7, 7, 142, 7, 7, 142, 63, 63, 150, 205, 205, 220, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 250, 250, 251, 185, 185, 206, 255, 255, 255, 255, 255, 255, 218, 218, 229, 7, 7, 141, 7, 7, 141, 7, 7, 141, 63, 63, 149, 205, 205, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 251, 185, 185, 206, 255, 255, 255, 255, 255, 255, 218, 218, 228, + 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 133, 133, 180, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 25, 25, 148, 178, 178, 204, 251, 251, 252, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 230, 230, 238, 115, 115, 175, 18, 18, 153, 11, 11, 152, 7, 7, 151, 7, 7, 151, 8, 8, 151, 11, 11, 150, 9, 9, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 8, 8, 147, 30, 30, 150, 28, 28, 152, 8, 8, 152, 7, 7, 152, 7, 7, 152, 7, 7, 142, 7, 7, 123, 7, 7, 112, 8, 8, 97, 8, 8, 87, + 9, 9, 80, 8, 8, 67, 8, 8, 52, 7, 7, 25, 19, 19, 26, 41, 41, 42, 48, 48, 48, 55, 55, 55, 61, 61, 61, 76, 76, 76, 89, 89, 89, 84, 84, 84, 84, 84, 84, 99, 99, 99, 113, 113, 113, 118, 118, 118, 118, 118, 118, 119, 119, 119, 117, 117, 117, 55, 55, 55, 8, 8, 14, + 7, 7, 104, 7, 7, 156, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 148, 7, 7, 147, 7, 7, 146, 8, 8, 145, 8, 8, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 9, 9, 144, 15, 15, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 14, 14, 145, 11, 11, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 9, 9, 145, 10, 10, 144, 8, 8, 144, 7, 7, 145, 63, 63, 153, 241, 241, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 251, 252, 236, 236, 242, + 250, 250, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 106, 106, 165, 9, 9, 144, 56, 56, 152, 238, 238, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 237, 237, 242, 251, 251, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 86, 86, 192, 7, 7, 178, 54, 54, 178, 238, 238, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 237, 237, 244, 251, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 86, 86, 171, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, + 7, 7, 162, 7, 7, 163, 151, 151, 198, 255, 255, 255, 255, 255, 255, 225, 225, 237, 7, 7, 165, 7, 7, 164, 7, 7, 163, 18, 18, 163, 223, 223, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 251, 253, 237, 237, 243, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 208, 208, 223, + 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 121, 7, 7, 119, 7, 7, 115, 7, 7, 111, 7, 7, 107, 7, 7, 98, 7, 7, 89, 7, 7, 77, + 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 65, 7, 7, 92, 7, 7, 105, 7, 7, 114, 7, 7, 122, 7, 7, 126, 7, 7, 131, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 155, 155, 189, 221, 221, 231, 246, 246, 248, 253, 253, 253, 244, 244, 247, 209, 209, 223, 110, 110, 166, 115, 115, 168, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 146, 146, 184, + 219, 219, 229, 245, 245, 248, 252, 252, 253, 242, 242, 246, 205, 205, 219, 97, 97, 159, 128, 128, 174, 255, 255, 255, 255, 255, 255, 218, 218, 229, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 146, 146, 183, 219, 219, 229, 245, 245, 248, 252, 252, 253, 242, 242, 246, 205, 205, 219, + 97, 97, 158, 128, 128, 172, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 144, 7, 7, 145, 7, 7, 147, 7, 7, 148, 7, 7, 148, 133, 133, 180, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 108, 108, 168, 205, 205, 221, 240, 240, 245, 252, 252, 253, 247, 247, 250, 227, 227, 236, 173, 173, 203, 32, 32, 154, 8, 8, 152, 9, 9, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 10, 10, 151, 13, 13, 151, 10, 10, 150, 8, 8, 149, 7, 7, 149, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 8, 8, 147, 28, 28, 149, 18, 18, 151, 7, 7, 153, 7, 7, 144, 7, 7, 115, + 7, 7, 101, 7, 7, 89, 10, 10, 80, 10, 10, 67, 7, 7, 57, 10, 10, 49, 15, 15, 42, 17, 17, 35, 18, 18, 28, 17, 17, 22, 16, 16, 18, 14, 14, 14, 10, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 13, 13, 13, 48, 48, 48, 111, 111, 111, + 118, 118, 118, 119, 119, 119, 119, 119, 119, 105, 105, 104, 24, 24, 24, 7, 7, 52, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 143, 8, 8, 144, 11, 11, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 8, 8, 145, 9, 9, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 115, 115, 170, + 232, 232, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 230, 230, 237, 224, 224, 233, 255, 255, 255, 255, 255, 255, 104, 104, 165, 8, 8, 145, 11, 11, 146, 104, 104, 166, 228, 228, 236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 225, 225, 234, 228, 228, 235, 255, 255, 255, 255, 255, 255, 86, 86, 194, 7, 7, 180, 7, 7, 175, 104, 104, 186, 228, 228, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 225, 225, 237, 228, 228, 238, 255, 255, 255, 255, 255, 255, 86, 86, 172, + 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 164, 151, 151, 199, 255, 255, 255, 255, 255, 255, 225, 225, 237, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 162, 72, 72, 168, 207, 207, 225, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 254, 254, 254, 196, 196, 215, 54, 54, 151, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 115, + 7, 7, 111, 7, 7, 106, 7, 7, 97, 7, 7, 89, 7, 7, 76, 7, 7, 51, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 66, 7, 7, 92, 7, 7, 105, 7, 7, 113, 7, 7, 121, 7, 7, 126, 7, 7, 131, 7, 7, 134, 7, 7, 136, 7, 7, 137, + 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 8, 8, 151, 8, 8, 152, 8, 8, 152, 9, 9, 152, 8, 8, 152, 7, 7, 151, 7, 7, 151, + 9, 9, 151, 13, 13, 152, 10, 10, 151, 8, 8, 150, 8, 8, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 9, 9, 147, + 17, 17, 149, 8, 8, 151, 7, 7, 142, 7, 7, 117, 9, 9, 108, 32, 32, 102, 63, 63, 106, 86, 86, 113, 88, 88, 106, 75, 75, 91, 53, 53, 70, 68, 68, 75, 78, 78, 82, 79, 79, 82, 80, 80, 81, 79, 79, 79, 77, 77, 77, 74, 74, 74, 69, 69, 69, 60, 60, 60, 48, 48, 48, + 33, 33, 33, 19, 19, 19, 9, 9, 9, 7, 7, 7, 57, 57, 57, 112, 112, 112, 119, 119, 119, 119, 119, 119, 119, 119, 119, 61, 61, 61, 7, 7, 7, 7, 7, 151, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 8, 8, 144, 8, 8, 145, 8, 8, 146, 7, 7, 146, 7, 7, 145, 8, 8, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 41, 41, 147, 178, 178, 203, 218, 218, 229, 242, 242, 246, 246, 246, 249, 222, 222, 232, 182, 182, 206, 48, 48, 149, 214, 214, 226, 255, 255, 255, 255, 255, 255, 104, 104, 166, 7, 7, 145, 8, 8, 145, 7, 7, 145, 31, 31, 147, + 175, 175, 202, 230, 230, 237, 249, 249, 251, 246, 246, 248, 221, 221, 231, 176, 176, 202, 37, 37, 145, 220, 220, 230, 255, 255, 255, 255, 255, 255, 86, 86, 197, 7, 7, 183, 7, 7, 177, 7, 7, 174, 31, 31, 171, 175, 175, 211, 230, 230, 240, 249, 249, 251, 246, 246, 249, 221, 221, 235, 176, 176, 212, + 36, 36, 170, 220, 220, 234, 255, 255, 255, 255, 255, 255, 86, 86, 173, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 166, 151, 151, 199, 255, 255, 255, 255, 255, 255, 225, 225, 237, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, + 7, 7, 158, 143, 143, 190, 217, 217, 230, 245, 245, 248, 252, 252, 253, 243, 243, 247, 212, 212, 226, 126, 126, 178, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, + 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 118, 7, 7, 114, 7, 7, 110, 7, 7, 105, 7, 7, 97, 7, 7, 88, 7, 7, 76, 7, 7, 51, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 66, 7, 7, 92, 7, 7, 105, 7, 7, 113, 7, 7, 121, + 7, 7, 125, 7, 7, 130, 7, 7, 134, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 145, 7, 7, 146, + 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 150, 7, 7, 150, 8, 8, 151, 8, 8, 152, + 9, 9, 152, 10, 10, 152, 11, 11, 152, 11, 11, 152, 8, 8, 152, 9, 9, 152, 12, 12, 152, 10, 10, 150, 9, 9, 150, 8, 8, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 9, 9, 148, 10, 10, 150, 7, 7, 148, 7, 7, 125, 10, 10, 114, 49, 49, 115, 87, 87, 126, 103, 103, 131, 114, 114, 133, 118, 118, 131, 114, 114, 123, 102, 102, 109, 82, 82, 88, 93, 93, 96, 99, 99, 100, 98, 98, 98, 98, 98, 98, + 97, 97, 97, 96, 96, 96, 95, 95, 95, 92, 92, 92, 89, 89, 89, 83, 83, 83, 74, 74, 74, 56, 56, 56, 34, 34, 34, 32, 32, 32, 94, 94, 94, 119, 119, 119, 119, 119, 119, 119, 119, 119, 98, 98, 98, 8, 8, 8, 7, 7, 124, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 155, + 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 145, 8, 8, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 9, 9, 143, 24, 24, 144, 14, 14, 142, 7, 7, 147, 7, 7, 184, 7, 7, 191, 7, 7, 184, 7, 7, 179, 7, 7, 175, 7, 7, 172, 7, 7, 170, + 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, + 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 114, 7, 7, 110, 7, 7, 105, 7, 7, 96, 7, 7, 88, 7, 7, 76, 7, 7, 51, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, + 10, 10, 66, 7, 7, 92, 7, 7, 105, 7, 7, 113, 7, 7, 121, 7, 7, 125, 7, 7, 130, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 137, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 143, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 148, 7, 7, 150, 7, 7, 150, 8, 8, 151, 8, 8, 152, 9, 9, 152, 9, 9, 152, 10, 10, 153, 10, 10, 152, 8, 8, 152, 8, 8, 151, 12, 12, 152, 9, 9, 150, 8, 8, 150, 8, 8, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 10, 10, 149, 8, 8, 151, 7, 7, 140, 8, 8, 123, 34, 34, 117, 87, 87, 132, 108, 108, 138, 123, 123, 144, 133, 133, 148, 137, 137, 147, 133, 133, 140, 124, 124, 130, + 104, 104, 108, 95, 95, 97, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 105, 105, 105, 104, 104, 104, 102, 102, 102, 100, 100, 100, 97, 97, 97, 94, 94, 94, 87, 87, 87, 73, 73, 73, 45, 45, 45, 78, 78, 78, 119, 119, 119, 119, 119, 119, 119, 119, 119, 107, 107, 107, 20, 20, 21, + 10, 10, 111, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 151, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 8, 8, 145, 8, 8, 145, 8, 8, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 8, 8, 143, 22, 22, 143, 17, 17, 143, 7, 7, 144, 7, 7, 178, 7, 7, 188, + 7, 7, 185, 7, 7, 180, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 168, 7, 7, 169, + 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 141, + 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 109, 7, 7, 104, 7, 7, 96, 7, 7, 87, 7, 7, 76, 7, 7, 51, + 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 67, 7, 7, 93, 7, 7, 106, 7, 7, 113, 7, 7, 122, 7, 7, 126, 7, 7, 130, 7, 7, 134, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 150, 8, 8, 151, 8, 8, 152, 8, 8, 153, 9, 9, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 8, 8, 152, 12, 12, 152, 8, 8, 150, 7, 7, 150, 8, 8, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 8, 8, 148, 11, 11, 149, 7, 7, 152, 7, 7, 133, 13, 13, 120, 68, 68, 127, 101, 101, 140, 123, 123, 148, + 144, 144, 163, 166, 166, 177, 166, 166, 174, 153, 153, 158, 137, 137, 141, 120, 120, 122, 102, 102, 102, 109, 109, 109, 111, 111, 111, 111, 111, 111, 110, 110, 110, 109, 109, 109, 108, 108, 108, 106, 106, 106, 104, 104, 104, 102, 102, 102, 98, 98, 98, 93, 93, 93, 82, 82, 82, 43, 43, 43, 76, 76, 76, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 110, 110, 110, 30, 30, 30, 11, 11, 101, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 155, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 8, 8, 144, + 7, 7, 145, 8, 8, 145, 11, 11, 146, 8, 8, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 8, 8, 145, 8, 8, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 8, 8, 143, 7, 7, 141, 7, 7, 144, 7, 7, 176, 7, 7, 184, 7, 7, 184, 7, 7, 181, 7, 7, 178, 7, 7, 177, 7, 7, 175, 7, 7, 174, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 166, + 7, 7, 166, 7, 7, 167, 7, 7, 169, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, + 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 109, + 7, 7, 104, 7, 7, 96, 7, 7, 88, 7, 7, 76, 7, 7, 51, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 68, 7, 7, 94, 7, 7, 107, 7, 7, 115, 7, 7, 123, 7, 7, 128, 7, 7, 132, 7, 7, 135, 7, 7, 137, 7, 7, 137, 7, 7, 138, + 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 149, 7, 7, 151, 7, 7, 152, 8, 8, 152, 8, 8, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 8, 8, 152, + 12, 12, 152, 8, 8, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 9, 9, 149, 10, 10, 150, 7, 7, 154, + 8, 8, 129, 24, 24, 119, 83, 83, 132, 110, 110, 142, 136, 136, 158, 177, 177, 190, 216, 216, 222, 212, 212, 217, 178, 178, 181, 149, 149, 152, 129, 129, 131, 107, 107, 107, 109, 109, 109, 113, 113, 113, 112, 112, 112, 111, 111, 111, 110, 110, 110, 108, 108, 108, 107, 107, 107, 104, 104, 104, 101, 101, 101, + 96, 96, 96, 86, 86, 86, 61, 61, 61, 39, 39, 39, 77, 77, 77, 119, 119, 119, 120, 120, 120, 120, 120, 120, 107, 107, 108, 22, 22, 23, 10, 10, 105, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 8, 8, 145, 7, 7, 145, 8, 8, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 9, 9, 145, 8, 8, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 8, 8, 144, 11, 11, 144, 8, 8, 143, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 144, 7, 7, 176, 7, 7, 183, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 173, + 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 171, 7, 7, 173, 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, + 7, 7, 122, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 109, 7, 7, 104, 7, 7, 96, 7, 7, 88, 7, 7, 76, 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 69, 7, 7, 96, 7, 7, 109, 7, 7, 117, 7, 7, 126, 7, 7, 131, + 7, 7, 134, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, + 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, + 8, 8, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 8, 8, 152, 13, 13, 152, 9, 9, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 8, 8, 150, 8, 8, 149, 8, 8, 149, 8, 8, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 148, 13, 13, 149, 9, 9, 152, 7, 7, 158, 8, 8, 125, 29, 29, 117, 86, 86, 132, 114, 114, 144, 144, 144, 163, 195, 195, 205, 237, 237, 242, 232, 232, 236, 190, 190, 193, 153, 153, 156, 132, 132, 133, 108, 108, 108, 108, 108, 108, 113, 113, 113, 111, 111, 111, 110, 110, 110, + 109, 109, 109, 106, 106, 106, 103, 103, 103, 99, 99, 99, 93, 93, 93, 80, 80, 80, 52, 52, 52, 18, 18, 18, 25, 25, 25, 93, 93, 93, 120, 120, 120, 120, 120, 120, 120, 120, 120, 94, 94, 94, 9, 9, 9, 8, 8, 123, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 155, 7, 7, 151, + 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 8, 8, 145, 8, 8, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 8, 8, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, + 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 12, 12, 144, 14, 14, 144, 8, 8, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 145, 7, 7, 176, 7, 7, 186, 7, 7, 186, 7, 7, 185, 7, 7, 186, 7, 7, 187, 7, 7, 186, 7, 7, 182, + 7, 7, 178, 7, 7, 175, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 172, 7, 7, 173, 7, 7, 174, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 167, + 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 114, 7, 7, 110, 7, 7, 105, 7, 7, 97, 7, 7, 89, 7, 7, 77, 7, 7, 52, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 72, + 7, 7, 99, 7, 7, 112, 7, 7, 120, 7, 7, 129, 7, 7, 134, 7, 7, 137, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 142, + 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 8, 8, 152, 7, 7, 153, 8, 8, 152, 15, 15, 153, 10, 10, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 8, 8, 149, 10, 10, 149, 9, 9, 149, 8, 8, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 9, 9, 148, 13, 13, 150, 7, 7, 154, 7, 7, 159, 8, 8, 122, 20, 20, 111, 85, 85, 128, 114, 114, 142, 141, 141, 159, 181, 181, 190, 217, 217, 223, 211, 211, 215, 177, 177, 181, 150, 150, 152, 129, 129, 130, + 104, 104, 104, 106, 106, 106, 110, 110, 110, 108, 108, 108, 106, 106, 106, 103, 103, 103, 99, 99, 99, 94, 94, 94, 85, 85, 85, 62, 62, 62, 29, 29, 29, 9, 9, 9, 8, 8, 8, 46, 46, 46, 113, 113, 113, 120, 120, 120, 120, 120, 120, 120, 120, 120, 62, 62, 62, 8, 8, 12, 7, 7, 150, + 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 151, 7, 7, 147, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 10, 10, 143, 20, 20, 144, 10, 10, 143, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 8, 8, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 8, 8, 144, 10, 10, 143, 7, 7, 140, 7, 7, 144, 7, 7, 179, 7, 7, 192, 7, 7, 193, + 7, 7, 194, 7, 7, 195, 7, 7, 192, 7, 7, 193, 7, 7, 188, 7, 7, 182, 7, 7, 178, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 171, 7, 7, 173, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 172, + 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 140, + 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 115, 7, 7, 110, 7, 7, 106, 7, 7, 98, 7, 7, 90, 7, 7, 78, 7, 7, 53, 36, 36, 39, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 41, 10, 10, 75, 7, 7, 102, 7, 7, 116, 7, 7, 123, 7, 7, 133, 7, 7, 137, 7, 7, 140, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 143, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 153, 153, 188, 223, 223, 232, 248, 248, 250, 194, 194, 214, 7, 7, 148, 133, 133, 181, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 8, 8, 152, 9, 9, 153, 10, 10, 153, 7, 7, 153, 8, 8, 152, 17, 17, 152, 12, 12, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, + 8, 8, 149, 11, 11, 149, 9, 9, 149, 8, 8, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 16, 16, 148, 17, 17, 151, 7, 7, 155, 7, 7, 162, 7, 7, 127, 11, 11, 106, 62, 62, 113, 109, 109, 136, 130, 130, 146, 150, 150, 161, + 168, 168, 175, 166, 166, 171, 153, 153, 156, 138, 138, 139, 117, 117, 118, 94, 94, 94, 102, 102, 102, 102, 102, 102, 98, 98, 98, 94, 94, 94, 86, 86, 86, 71, 71, 71, 47, 47, 47, 24, 24, 24, 8, 8, 8, 9, 9, 9, 14, 14, 14, 52, 52, 52, 113, 113, 113, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 107, 107, 107, 26, 26, 26, 7, 7, 45, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 151, 7, 7, 148, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 8, 8, 144, 15, 15, 144, 13, 13, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 8, 8, 146, 8, 8, 146, 8, 8, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 9, 9, 145, 22, 22, 145, 29, 29, 145, + 7, 7, 140, 7, 7, 137, 7, 7, 156, 7, 7, 180, 7, 7, 176, 7, 7, 167, 7, 7, 154, 7, 7, 141, 7, 7, 159, 7, 7, 190, 7, 7, 186, 7, 7, 181, 7, 7, 179, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 178, 7, 7, 175, 7, 7, 173, 7, 7, 173, + 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, + 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 126, 7, 7, 123, 7, 7, 121, 7, 7, 119, 7, 7, 115, 7, 7, 111, 7, 7, 107, + 7, 7, 98, 7, 7, 91, 7, 7, 78, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 41, 10, 10, 78, 7, 7, 107, 7, 7, 120, 7, 7, 128, 7, 7, 137, 7, 7, 141, 7, 7, 143, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 183, 183, 206, 255, 255, 255, 255, 255, 255, 255, 255, 255, 198, 198, 216, 7, 7, 147, 133, 133, 181, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 8, 8, 151, 9, 9, 152, 8, 8, 152, 7, 7, 152, 8, 8, 152, 21, 21, 153, + 17, 17, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 11, 11, 149, 13, 13, 149, 8, 8, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 10, 10, 147, 27, 27, 149, 16, 16, 151, 7, 7, 156, 7, 7, 163, 7, 7, 146, + 7, 7, 103, 20, 20, 94, 89, 89, 117, 116, 116, 134, 132, 132, 142, 139, 139, 147, 141, 141, 145, 135, 135, 137, 121, 121, 123, 92, 92, 93, 81, 81, 81, 88, 88, 88, 80, 80, 80, 67, 67, 67, 49, 49, 49, 31, 31, 31, 15, 15, 15, 9, 9, 9, 10, 10, 10, 21, 21, 21, 33, 33, 33, + 66, 66, 66, 112, 112, 112, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 60, 60, 60, 8, 8, 12, 7, 7, 88, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 151, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 9, 9, 143, 10, 10, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 9, 9, 146, 11, 11, 146, 9, 9, 146, 8, 8, 145, 8, 8, 145, + 7, 7, 145, 7, 7, 145, 11, 11, 145, 20, 20, 145, 13, 13, 143, 7, 7, 140, 7, 7, 136, 7, 7, 133, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 139, 7, 7, 184, 7, 7, 189, 7, 7, 184, 7, 7, 182, 7, 7, 182, 7, 7, 184, 7, 7, 184, + 7, 7, 183, 7, 7, 180, 7, 7, 177, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 133, 133, 188, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 157, + 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 130, 7, 7, 126, 7, 7, 124, + 7, 7, 121, 7, 7, 119, 7, 7, 116, 7, 7, 112, 7, 7, 107, 7, 7, 99, 7, 7, 91, 7, 7, 79, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 41, 10, 10, 82, 7, 7, 112, 7, 7, 125, 7, 7, 133, 7, 7, 140, 7, 7, 143, 7, 7, 144, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 98, 98, 162, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 198, 198, 216, 7, 7, 147, 133, 133, 180, + 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 8, 8, 150, 8, 8, 151, + 8, 8, 152, 7, 7, 152, 7, 7, 152, 8, 8, 152, 23, 23, 152, 19, 19, 153, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 8, 8, 149, 11, 11, 150, 8, 8, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 14, 14, 148, + 27, 27, 151, 10, 10, 154, 7, 7, 159, 7, 7, 165, 7, 7, 166, 7, 7, 119, 7, 7, 88, 27, 27, 81, 82, 82, 103, 107, 107, 119, 118, 118, 124, 117, 117, 122, 107, 107, 110, 80, 80, 83, 41, 41, 43, 44, 44, 45, 35, 35, 35, 22, 22, 22, 13, 13, 13, 8, 8, 8, 8, 8, 8, + 14, 14, 14, 25, 25, 25, 34, 34, 34, 41, 41, 41, 51, 51, 51, 100, 100, 100, 120, 120, 120, 121, 121, 121, 121, 121, 121, 119, 119, 119, 86, 86, 86, 14, 14, 15, 7, 7, 33, 7, 7, 121, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 153, 7, 7, 149, + 7, 7, 145, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 145, + 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 8, 8, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, + 12, 12, 146, 15, 15, 145, 13, 13, 145, 10, 10, 144, 8, 8, 144, 7, 7, 144, 7, 7, 144, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 183, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 154, 7, 7, 190, 7, 7, 189, + 7, 7, 185, 7, 7, 184, 7, 7, 185, 7, 7, 188, 7, 7, 188, 7, 7, 186, 7, 7, 182, 227, 227, 240, 255, 255, 255, 255, 255, 255, 148, 148, 202, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, + 133, 133, 188, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 119, 7, 7, 116, 7, 7, 112, 7, 7, 108, 7, 7, 100, 7, 7, 92, 7, 7, 80, 7, 7, 54, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 41, 10, 10, 87, 7, 7, 119, + 7, 7, 133, 7, 7, 138, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 220, 220, 231, 255, 255, 255, 255, 255, 255, + 185, 185, 208, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 174, 174, 200, 255, 255, 255, 255, 255, 255, + 246, 246, 248, 133, 133, 179, 63, 63, 154, 7, 7, 148, 133, 133, 180, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 148, + 7, 7, 148, 7, 7, 149, 8, 8, 149, 8, 8, 151, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 11, 11, 151, 9, 9, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 8, 8, 151, 7, 7, 155, 7, 7, 161, 7, 7, 165, 7, 7, 168, 7, 7, 166, 7, 7, 115, 7, 7, 71, 11, 11, 62, 33, 33, 61, 50, 50, 65, 47, 47, 57, 30, 30, 39, 11, 11, 21, 7, 7, 13, 7, 7, 9, + 7, 7, 11, 7, 7, 9, 7, 7, 7, 24, 24, 23, 35, 35, 35, 42, 42, 42, 42, 42, 42, 41, 41, 41, 42, 42, 42, 82, 82, 82, 118, 118, 118, 121, 121, 121, 121, 121, 121, 119, 119, 119, 82, 82, 82, 17, 17, 17, 8, 8, 22, 7, 7, 87, 7, 7, 135, 7, 7, 162, 7, 7, 161, + 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 150, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 8, 8, 145, 10, 10, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 8, 8, 144, 8, 8, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 183, 7, 7, 136, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, + 7, 7, 132, 7, 7, 159, 7, 7, 189, 7, 7, 194, 7, 7, 189, 7, 7, 186, 7, 7, 187, 7, 7, 189, 7, 7, 194, 7, 7, 193, 7, 7, 188, 7, 7, 184, 227, 227, 240, 255, 255, 255, 255, 255, 255, 148, 148, 202, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, + 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 133, 133, 188, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 131, 7, 7, 129, 7, 7, 125, 7, 7, 123, 7, 7, 120, 7, 7, 117, 7, 7, 113, 7, 7, 109, 7, 7, 100, 7, 7, 93, 7, 7, 80, 7, 7, 54, 36, 36, 39, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 42, 10, 10, 91, 7, 7, 126, 7, 7, 139, 7, 7, 141, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 108, 108, 171, 204, 204, 221, 239, 239, 244, 252, 252, 253, 246, 246, 249, 225, 225, 234, 167, 167, 197, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 143, 197, 197, 215, 255, 255, 255, 255, 255, 255, 208, 208, 223, 7, 7, 146, 7, 7, 146, 231, 231, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 245, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 149, 8, 8, 149, 8, 8, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 151, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 151, 7, 7, 154, 7, 7, 159, 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 172, 7, 7, 173, 7, 7, 146, 7, 7, 91, 7, 7, 64, 8, 8, 55, + 7, 7, 51, 7, 7, 53, 8, 8, 67, 9, 9, 80, 7, 7, 83, 7, 7, 91, 7, 7, 75, 7, 7, 15, 10, 10, 10, 25, 25, 25, 38, 38, 38, 42, 42, 42, 41, 41, 41, 59, 59, 59, 110, 110, 110, 121, 121, 121, 118, 118, 118, 97, 97, 97, 51, 51, 51, 11, 11, 11, 8, 8, 24, + 7, 7, 81, 7, 7, 109, 7, 7, 146, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 143, 8, 8, 143, 10, 10, 143, 7, 7, 143, 7, 7, 145, 7, 7, 145, 7, 7, 146, 8, 8, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 11, 11, 145, 19, 19, 146, 10, 10, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 145, 12, 12, 146, 14, 14, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 214, 214, 226, 240, 240, 245, 240, 240, 244, 140, 140, 179, + 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 145, 7, 7, 192, 7, 7, 193, 7, 7, 189, 7, 7, 188, 7, 7, 188, 7, 7, 192, 7, 7, 197, 7, 7, 201, 7, 7, 197, 7, 7, 190, 7, 7, 185, 227, 227, 240, 255, 255, 255, 255, 255, 255, 148, 148, 202, + 7, 7, 171, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 133, 133, 187, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 151, + 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 126, 7, 7, 124, 7, 7, 121, 7, 7, 117, 7, 7, 114, 7, 7, 109, 7, 7, 101, + 7, 7, 93, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 40, 10, 10, 69, 7, 7, 111, 7, 7, 140, 7, 7, 144, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 172, 172, 202, 251, 251, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 220, 220, 230, 86, 86, 157, 7, 7, 142, 7, 7, 142, 227, 227, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 165, 165, 196, 231, 231, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 245, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 8, 8, 147, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 150, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 159, 7, 7, 162, 7, 7, 166, 7, 7, 168, 7, 7, 171, 7, 7, 174, + 7, 7, 177, 7, 7, 178, 7, 7, 177, 7, 7, 165, 7, 7, 158, 7, 7, 156, 7, 7, 157, 7, 7, 152, 7, 7, 116, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 78, 7, 7, 30, 7, 7, 10, 13, 13, 13, 20, 20, 21, 32, 32, 32, 78, 78, 78, 93, 93, 93, 77, 77, 77, + 40, 40, 40, 20, 20, 21, 8, 8, 16, 7, 7, 41, 7, 7, 91, 7, 7, 104, 7, 7, 120, 7, 7, 157, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 153, 7, 7, 150, 8, 8, 147, 10, 10, 145, 7, 7, 144, 7, 7, 145, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 10, 10, 143, 18, 18, 144, 8, 8, 144, 7, 7, 145, 7, 7, 145, 8, 8, 145, 12, 12, 146, 9, 9, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 8, 8, 145, 10, 10, 145, 9, 9, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 15, 15, 146, 24, 24, 146, 9, 9, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 145, 7, 7, 143, 7, 7, 141, 7, 7, 138, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 154, 7, 7, 195, 7, 7, 189, 7, 7, 188, 7, 7, 189, 7, 7, 192, 7, 7, 196, 7, 7, 194, 7, 7, 186, 7, 7, 199, 7, 7, 193, + 7, 7, 186, 227, 227, 241, 255, 255, 255, 255, 255, 255, 148, 148, 203, 7, 7, 172, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 231, 231, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 246, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 131, 7, 7, 128, 7, 7, 125, + 7, 7, 122, 7, 7, 118, 7, 7, 114, 7, 7, 109, 7, 7, 101, 7, 7, 93, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 70, 7, 7, 119, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, + 7, 7, 149, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 147, 7, 7, 148, 7, 7, 149, 186, 186, 210, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 238, 242, 44, 44, 146, 7, 7, 142, 227, 227, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 165, 165, 197, 221, 221, 232, 247, 247, 249, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 244, 244, 248, 230, 230, 238, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 8, 8, 146, 8, 8, 146, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 159, 7, 7, 163, + 7, 7, 165, 7, 7, 168, 7, 7, 169, 7, 7, 171, 7, 7, 174, 7, 7, 178, 7, 7, 180, 7, 7, 180, 7, 7, 178, 7, 7, 175, 7, 7, 170, 7, 7, 158, 7, 7, 123, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 100, 7, 7, 72, 7, 7, 43, + 7, 7, 19, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 12, 8, 8, 22, 7, 7, 57, 7, 7, 82, 7, 7, 102, 7, 7, 105, 7, 7, 108, 7, 7, 139, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 152, + 9, 9, 149, 17, 17, 147, 8, 8, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 9, 9, 143, 12, 12, 144, 8, 8, 145, 7, 7, 145, + 7, 7, 145, 10, 10, 146, 13, 13, 146, 10, 10, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 8, 8, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 15, 15, 146, 26, 26, 147, 227, 227, 235, + 255, 255, 255, 255, 255, 255, 119, 119, 173, 219, 219, 230, 247, 247, 250, 48, 48, 149, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 182, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 132, 44, 44, 136, 181, 181, 207, 219, 219, 239, 245, 245, 250, 243, 243, 249, 220, 220, 239, 177, 177, 224, + 31, 31, 197, 240, 240, 246, 255, 255, 255, 255, 255, 255, 60, 60, 196, 7, 7, 187, 227, 227, 241, 255, 255, 255, 255, 255, 255, 158, 158, 208, 193, 193, 221, 235, 235, 243, 251, 251, 253, 243, 243, 248, 209, 209, 227, 94, 94, 176, 7, 7, 160, 7, 7, 158, 7, 7, 157, 231, 231, 239, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 246, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 130, 7, 7, 126, 7, 7, 123, 7, 7, 119, 7, 7, 115, 7, 7, 110, 7, 7, 102, 7, 7, 94, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 97, + 7, 7, 146, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, + 7, 7, 147, 7, 7, 148, 110, 110, 170, 252, 252, 253, 255, 255, 255, 255, 255, 255, 218, 218, 229, 116, 116, 172, 25, 25, 146, 65, 65, 152, 161, 161, 193, 245, 245, 248, 255, 255, 255, 255, 255, 255, 184, 184, 206, 7, 7, 141, 190, 190, 210, 240, 240, 244, 255, 255, 255, 255, 255, 255, 239, 239, 244, + 214, 214, 227, 138, 138, 183, 7, 7, 148, 133, 133, 181, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 146, 8, 8, 146, 8, 8, 145, 7, 7, 146, 7, 7, 146, 8, 8, 146, + 8, 8, 146, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 156, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 159, 7, 7, 157, + 7, 7, 157, 7, 7, 158, 7, 7, 160, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 171, 7, 7, 172, 7, 7, 176, 7, 7, 179, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 176, 7, 7, 162, 7, 7, 124, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, + 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 97, 7, 7, 99, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 105, 7, 7, 106, 7, 7, 129, 7, 7, 157, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, + 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 8, 8, 151, 11, 11, 149, 8, 8, 146, 7, 7, 146, 7, 7, 146, 8, 8, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 8, 8, 144, 8, 8, 144, 8, 8, 145, 7, 7, 145, 7, 7, 144, 9, 9, 145, 8, 8, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 9, 9, 145, 21, 21, 146, 227, 227, 235, 255, 255, 255, 255, 255, 255, 241, 241, 245, 255, 255, 255, 255, 255, 255, 48, 48, 146, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 182, 7, 7, 134, 7, 7, 133, 7, 7, 133, 118, 118, 164, 234, 234, 239, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 229, 242, 247, 247, 249, 255, 255, 255, 255, 255, 255, 60, 60, 196, 7, 7, 187, 227, 227, 241, 255, 255, 255, 255, 255, 255, 251, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 242, 242, 247, + 117, 117, 181, 7, 7, 158, 7, 7, 157, 221, 221, 233, 247, 247, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, 244, 248, 230, 230, 239, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 124, 7, 7, 120, 7, 7, 116, 7, 7, 111, 7, 7, 102, 7, 7, 94, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 90, 7, 7, 144, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 146, 7, 7, 147, 220, 220, 231, 255, 255, 255, 255, 255, 255, 225, 225, 234, 36, 36, 150, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 128, 128, 175, 254, 254, 254, 255, 255, 255, 251, 251, 252, 76, 76, 153, + 7, 7, 141, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 145, 7, 7, 148, 7, 7, 148, 133, 133, 180, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 8, 8, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 8, 8, 145, 8, 8, 146, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 151, 7, 7, 159, 7, 7, 164, + 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 167, 7, 7, 168, 7, 7, 169, 7, 7, 171, 7, 7, 172, 7, 7, 174, 7, 7, 176, 7, 7, 178, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 171, 7, 7, 132, + 7, 7, 109, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 107, 7, 7, 125, 7, 7, 155, + 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 8, 8, 150, 7, 7, 147, 7, 7, 146, 7, 7, 146, 9, 9, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 8, 8, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 11, 11, 145, 227, 227, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 48, 48, 144, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, + 7, 7, 133, 67, 67, 143, 243, 243, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 253, 239, 239, 248, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 60, 196, 7, 7, 187, 227, 227, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 249, 249, 251, 248, 248, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 239, 239, 245, 25, 25, 158, 7, 7, 156, 7, 7, 156, 133, 133, 186, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 130, 7, 7, 125, 7, 7, 121, 7, 7, 117, 7, 7, 111, 7, 7, 102, 7, 7, 94, + 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 92, 7, 7, 144, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 146, 65, 65, 155, 253, 253, 253, 255, 255, 255, 255, 255, 255, 142, 142, 185, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 224, 224, 233, 255, 255, 255, 255, 255, 255, 155, 155, 188, 7, 7, 141, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 145, 7, 7, 147, 7, 7, 148, 133, 133, 181, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 8, 8, 145, 9, 9, 146, 8, 8, 146, 7, 7, 146, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 149, 7, 7, 154, 7, 7, 168, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 168, 7, 7, 170, 7, 7, 171, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 176, 7, 7, 179, + 7, 7, 180, 7, 7, 181, 7, 7, 176, 7, 7, 140, 7, 7, 111, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, + 7, 7, 105, 7, 7, 110, 7, 7, 129, 7, 7, 156, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 145, 9, 9, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 8, 8, 145, 8, 8, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 8, 8, 144, + 8, 8, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 227, 227, 235, 255, 255, 255, 255, 255, 255, 252, 252, 253, 169, 169, 196, 63, 63, 147, 7, 7, 138, + 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 182, 7, 7, 134, 7, 7, 133, 202, 202, 216, 255, 255, 255, 255, 255, 255, 247, 247, 249, 155, 155, 211, 18, 18, 195, 7, 7, 196, 63, 63, 204, 195, 195, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 60, 195, 7, 7, 187, + 227, 227, 241, 255, 255, 255, 255, 255, 255, 253, 253, 254, 159, 159, 208, 25, 25, 173, 7, 7, 167, 164, 164, 204, 255, 255, 255, 255, 255, 255, 255, 255, 255, 142, 142, 190, 7, 7, 156, 7, 7, 156, 133, 133, 185, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 159, 7, 7, 158, 7, 7, 158, + 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 128, + 7, 7, 123, 7, 7, 118, 7, 7, 112, 7, 7, 103, 7, 7, 94, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 97, 7, 7, 145, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 152, 7, 7, 154, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 220, 220, 230, 255, 255, 255, 255, 255, 255, 185, 185, 207, 7, 7, 145, 123, 123, 175, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 185, 185, 207, 7, 7, 141, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 146, 7, 7, 146, 7, 7, 147, 133, 133, 180, 255, 255, 255, 255, 255, 255, + 250, 250, 251, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 8, 8, 145, 8, 8, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 160, 7, 7, 176, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 169, 7, 7, 172, 7, 7, 174, + 7, 7, 175, 7, 7, 176, 7, 7, 176, 7, 7, 177, 7, 7, 178, 7, 7, 180, 7, 7, 178, 7, 7, 149, 7, 7, 113, 7, 7, 109, 7, 7, 108, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, + 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 111, 7, 7, 129, 7, 7, 147, 7, 7, 160, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 152, 7, 7, 149, 7, 7, 146, 8, 8, 144, 9, 9, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 8, 8, 143, 10, 10, 143, 7, 7, 142, 7, 7, 142, 8, 8, 143, 8, 8, 145, 17, 17, 146, 10, 10, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 8, 8, 144, 14, 14, 145, 10, 10, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 227, 227, 235, 255, 255, 255, + 255, 255, 255, 197, 197, 214, 7, 7, 139, 7, 7, 136, 7, 7, 136, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 18, 18, 134, 250, 250, 251, 255, 255, 255, 255, 255, 255, 156, 156, 186, 7, 7, 185, 7, 7, 195, 7, 7, 197, 7, 7, 200, 7, 7, 152, 206, 206, 218, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 60, 192, 7, 7, 185, 227, 227, 241, 255, 255, 255, 255, 255, 255, 201, 201, 227, 7, 7, 176, 7, 7, 172, 7, 7, 167, 7, 7, 164, 231, 231, 240, 255, 255, 255, 255, 255, 255, 181, 181, 210, 7, 7, 156, 7, 7, 156, 133, 133, 185, 255, 255, 255, + 255, 255, 255, 250, 250, 251, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 129, 7, 7, 124, 7, 7, 119, 7, 7, 113, 7, 7, 104, 7, 7, 94, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 101, 7, 7, 146, + 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 220, 220, 230, 255, 255, 255, 255, 255, 255, 185, 185, 207, 7, 7, 144, + 139, 139, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 197, 197, 214, 7, 7, 142, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 145, + 7, 7, 146, 7, 7, 146, 133, 133, 180, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 153, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 171, 7, 7, 168, + 7, 7, 167, 7, 7, 169, 7, 7, 171, 7, 7, 173, 7, 7, 176, 7, 7, 177, 7, 7, 177, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 153, 7, 7, 117, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, + 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 105, 7, 7, 123, 7, 7, 140, 7, 7, 140, 7, 7, 145, 7, 7, 152, 7, 7, 159, 7, 7, 161, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 160, 7, 7, 159, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 8, 8, 150, 8, 8, 147, 9, 9, 145, 9, 9, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 9, 9, 143, 18, 18, 144, 8, 8, 143, 7, 7, 143, 7, 7, 144, + 11, 11, 145, 23, 23, 147, 10, 10, 146, 8, 8, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 11, 11, 145, 19, 19, 145, 9, 9, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 227, 227, 235, 255, 255, 255, 255, 255, 255, 158, 158, 191, 7, 7, 139, 7, 7, 136, 7, 7, 136, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 106, 106, 158, 255, 255, 255, 255, 255, 255, 248, 248, 249, 7, 7, 136, 7, 7, 188, + 7, 7, 194, 7, 7, 194, 7, 7, 200, 7, 7, 180, 124, 124, 170, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 60, 191, 7, 7, 183, 227, 227, 240, 255, 255, 255, 255, 255, 255, 163, 163, 210, 7, 7, 174, 7, 7, 171, 7, 7, 167, 7, 7, 164, 206, 206, 225, 255, 255, 255, 255, 255, 255, + 191, 191, 215, 7, 7, 156, 7, 7, 156, 133, 133, 185, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 125, 7, 7, 120, 7, 7, 114, 7, 7, 104, 7, 7, 95, 7, 7, 81, 7, 7, 55, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 39, 10, 10, 44, 7, 7, 64, 7, 7, 100, 7, 7, 146, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 220, 220, 230, 255, 255, 255, 255, 255, 255, 185, 185, 207, 7, 7, 144, 112, 112, 169, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 238, 243, 233, 233, 240, 233, 233, 240, 233, 233, 239, 233, 233, 239, 233, 233, 239, 233, 233, 239, 233, 233, 239, 233, 233, 239, 233, 233, 239, 171, 171, 199, 7, 7, 142, + 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 145, 7, 7, 145, 7, 7, 145, 133, 133, 179, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, + 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 145, + 7, 7, 172, 7, 7, 183, 7, 7, 177, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 172, 7, 7, 174, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 161, 7, 7, 122, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, + 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 114, 7, 7, 148, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, + 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 8, 8, 150, 8, 8, 148, 9, 9, 145, 8, 8, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 8, 8, 143, 13, 13, 144, 9, 9, 143, 7, 7, 144, 7, 7, 144, 18, 18, 146, 28, 28, 147, 10, 10, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 16, 16, 145, 16, 16, 146, 8, 8, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 184, 7, 7, 139, 7, 7, 136, 7, 7, 135, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 141, 141, 177, + 255, 255, 255, 255, 255, 255, 232, 232, 238, 7, 7, 134, 7, 7, 184, 7, 7, 193, 7, 7, 193, 7, 7, 197, 7, 7, 198, 70, 70, 169, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 60, 189, 7, 7, 181, 227, 227, 240, 255, 255, 255, 255, 255, 255, 151, 151, 203, 7, 7, 172, 7, 7, 169, + 7, 7, 167, 7, 7, 164, 194, 194, 219, 255, 255, 255, 255, 255, 255, 193, 193, 216, 7, 7, 156, 7, 7, 156, 133, 133, 185, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 132, 7, 7, 126, 7, 7, 121, 7, 7, 115, 7, 7, 105, 7, 7, 95, 7, 7, 82, + 7, 7, 56, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 91, 7, 7, 144, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 220, 220, 230, 255, 255, 255, 255, 255, 255, 185, 185, 207, 7, 7, 144, 18, 18, 146, 242, 242, 246, 255, 255, 255, 255, 255, 255, 192, 192, 213, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 36, 36, 147, + 70, 70, 152, 70, 70, 152, 70, 70, 152, 31, 31, 144, 7, 7, 142, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 144, 7, 7, 144, 7, 7, 144, 133, 133, 179, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, + 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 154, 7, 7, 185, 7, 7, 182, 7, 7, 178, 7, 7, 174, 7, 7, 173, 7, 7, 173, 7, 7, 174, 7, 7, 176, 7, 7, 177, 7, 7, 179, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 171, 7, 7, 125, + 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 106, 7, 7, 137, 7, 7, 157, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, + 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 155, 7, 7, 154, 7, 7, 152, 8, 8, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 8, 8, 143, 10, 10, 143, 7, 7, 142, 7, 7, 141, 8, 8, 143, 9, 9, 144, 12, 12, 145, 7, 7, 145, 7, 7, 144, 22, 22, 146, 20, 20, 146, 8, 8, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 8, 8, 144, 15, 15, 145, 11, 11, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 8, 8, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 184, 7, 7, 139, 7, 7, 136, 7, 7, 135, 227, 227, 234, + 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 98, 98, 155, 255, 255, 255, 255, 255, 255, 246, 246, 248, 7, 7, 131, 7, 7, 166, 7, 7, 194, 7, 7, 194, 7, 7, 197, 7, 7, 201, 117, 117, 186, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 60, 188, 7, 7, 180, 227, 227, 240, + 255, 255, 255, 255, 255, 255, 148, 148, 201, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 163, 193, 193, 218, 255, 255, 255, 255, 255, 255, 193, 193, 216, 7, 7, 156, 7, 7, 156, 133, 133, 185, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 133, 7, 7, 128, + 7, 7, 121, 7, 7, 115, 7, 7, 105, 7, 7, 96, 7, 7, 83, 7, 7, 57, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 78, 7, 7, 121, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, + 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 207, 7, 7, 144, 7, 7, 145, 159, 159, 193, 255, 255, 255, 255, 255, 255, 255, 255, 255, 196, 196, 215, + 97, 97, 166, 7, 7, 147, 51, 51, 151, 137, 137, 181, 237, 237, 242, 255, 255, 255, 255, 255, 255, 239, 239, 243, 51, 51, 147, 7, 7, 142, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 142, 7, 7, 144, 7, 7, 144, 133, 133, 178, 255, 255, 255, 255, 255, 255, 250, 250, 251, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 168, 7, 7, 189, 7, 7, 183, 7, 7, 179, 7, 7, 177, 7, 7, 175, 7, 7, 176, 7, 7, 177, 7, 7, 180, 7, 7, 180, + 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 142, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 126, 7, 7, 155, 7, 7, 159, + 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, + 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 10, 10, 143, 20, 20, 144, 8, 8, 142, 7, 7, 142, 7, 7, 144, 9, 9, 145, 11, 11, 145, 7, 7, 145, 7, 7, 145, 14, 14, 145, 11, 11, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, + 7, 7, 144, 8, 8, 144, 10, 10, 145, 8, 8, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 9, 9, 145, 13, 13, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 227, 227, 235, 255, 255, 255, 255, 255, 255, + 148, 148, 184, 7, 7, 138, 7, 7, 136, 7, 7, 135, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 7, 7, 133, 249, 249, 250, 255, 255, 255, 255, 255, 255, 148, 148, 179, 7, 7, 139, 7, 7, 177, 7, 7, 193, 7, 7, 193, 7, 7, 175, 198, 198, 214, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 60, 60, 188, 7, 7, 179, 227, 227, 239, 255, 255, 255, 255, 255, 255, 148, 148, 201, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 164, 193, 193, 218, 255, 255, 255, 255, 255, 255, 193, 193, 216, 7, 7, 156, 7, 7, 156, 133, 133, 185, 255, 255, 255, 255, 255, 255, + 250, 250, 251, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 129, 7, 7, 122, 7, 7, 115, 7, 7, 106, 7, 7, 97, 7, 7, 84, 7, 7, 57, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 75, 7, 7, 89, 7, 7, 135, + 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 207, 7, 7, 145, 7, 7, 145, + 7, 7, 146, 206, 206, 222, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 251, 252, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 137, 137, 179, 7, 7, 142, 7, 7, 142, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 142, 7, 7, 143, + 7, 7, 143, 133, 133, 178, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 156, 7, 7, 190, 7, 7, 188, 7, 7, 182, 7, 7, 180, + 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 183, 7, 7, 173, 7, 7, 125, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 105, + 7, 7, 105, 7, 7, 114, 7, 7, 150, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, + 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 9, 9, 145, 13, 13, 145, 9, 9, 143, 7, 7, 144, 7, 7, 145, 12, 12, 145, 10, 10, 146, 7, 7, 145, 7, 7, 145, 8, 8, 145, + 8, 8, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 8, 8, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 15, 15, 145, 25, 25, 146, 8, 8, 145, + 7, 7, 144, 7, 7, 144, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 183, 7, 7, 136, 7, 7, 135, 7, 7, 135, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 7, 7, 133, 199, 199, 214, 255, 255, 255, 255, 255, 255, 245, 245, 247, 149, 149, 180, 7, 7, 136, + 7, 7, 143, 44, 44, 145, 183, 183, 203, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60, 60, 190, 7, 7, 181, 227, 227, 240, 255, 255, 255, 255, 255, 255, 148, 148, 201, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 165, 193, 193, 218, 255, 255, 255, 255, 255, 255, 193, 193, 216, + 7, 7, 156, 7, 7, 156, 133, 133, 185, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 134, 7, 7, 129, 7, 7, 122, 7, 7, 116, 7, 7, 106, 7, 7, 97, 7, 7, 85, 7, 7, 58, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 45, 7, 7, 65, 7, 7, 75, 7, 7, 83, 7, 7, 98, 7, 7, 139, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 220, 220, 231, + 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 145, 7, 7, 146, 7, 7, 146, 44, 44, 151, 187, 187, 210, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 247, 247, 250, 146, 146, 184, 7, 7, 142, 7, 7, 142, 7, 7, 142, 205, 205, 220, + 255, 255, 255, 255, 255, 255, 200, 200, 216, 7, 7, 141, 7, 7, 142, 7, 7, 143, 133, 133, 178, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 146, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, + 7, 7, 166, 7, 7, 195, 7, 7, 190, 7, 7, 186, 7, 7, 184, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 183, 7, 7, 183, 7, 7, 185, 7, 7, 161, 7, 7, 116, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, + 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 109, 7, 7, 139, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 8, 8, 147, 8, 8, 146, 9, 9, 146, 7, 7, 145, 7, 7, 145, + 14, 14, 146, 9, 9, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 8, 8, 145, 8, 8, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 13, 13, 144, 15, 15, 144, 8, 8, 142, 7, 7, 143, 7, 7, 143, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 183, 7, 7, 136, 7, 7, 135, 7, 7, 135, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 7, 7, 133, 65, 65, 143, + 243, 243, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 248, 248, 250, 237, 237, 241, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 51, 51, 190, 7, 7, 183, 227, 227, 240, 255, 255, 255, 255, 255, 255, 148, 148, 203, 7, 7, 173, 7, 7, 171, 7, 7, 170, + 7, 7, 167, 193, 193, 218, 255, 255, 255, 255, 255, 255, 193, 193, 217, 7, 7, 157, 7, 7, 156, 133, 133, 186, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 135, 7, 7, 129, 7, 7, 122, 7, 7, 115, 7, 7, 106, 7, 7, 98, 7, 7, 86, 7, 7, 59, + 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 83, 7, 7, 91, 7, 7, 102, 7, 7, 134, 7, 7, 164, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 220, 220, 231, 255, 255, 255, 255, 255, 255, 185, 185, 208, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 108, 108, 170, 204, 204, 220, 239, 239, 244, 251, 251, 252, 249, 249, 251, 234, 234, 240, 191, 191, 211, 82, 82, 156, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 205, 205, 220, 255, 255, 255, 255, 255, 255, 200, 200, 216, 7, 7, 141, 7, 7, 142, 7, 7, 142, 133, 133, 178, 255, 255, 255, 255, 255, 255, 250, 250, 251, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 138, 7, 7, 182, 7, 7, 194, 7, 7, 192, 7, 7, 189, 7, 7, 188, 7, 7, 188, 7, 7, 187, 7, 7, 186, 7, 7, 185, 7, 7, 185, 7, 7, 185, 7, 7, 186, 7, 7, 152, 7, 7, 113, 7, 7, 112, 7, 7, 111, + 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 130, 7, 7, 160, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, + 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 8, 8, 148, 7, 7, 147, 8, 8, 147, 13, 13, 147, 8, 8, 146, 7, 7, 146, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 227, 227, 235, 255, 255, 255, 255, 255, 255, 148, 148, 183, 7, 7, 136, 7, 7, 136, 7, 7, 135, 227, 227, 234, 255, 255, 255, + 255, 255, 255, 148, 148, 181, 7, 7, 134, 7, 7, 133, 7, 7, 133, 118, 118, 164, 235, 235, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 210, 210, 221, 251, 251, 252, 255, 255, 255, 254, 254, 254, 7, 7, 194, 7, 7, 187, 227, 227, 241, 255, 255, 255, + 255, 255, 255, 148, 148, 205, 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 171, 193, 193, 220, 255, 255, 255, 255, 255, 255, 193, 193, 217, 7, 7, 158, 7, 7, 158, 133, 133, 187, 255, 255, 255, 255, 255, 255, 250, 250, 252, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 139, 7, 7, 134, 7, 7, 128, 7, 7, 121, + 7, 7, 115, 7, 7, 106, 7, 7, 99, 7, 7, 87, 7, 7, 60, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 91, 7, 7, 96, 7, 7, 102, 7, 7, 132, 7, 7, 166, 7, 7, 165, 7, 7, 162, + 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, + 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 144, 7, 7, 193, 7, 7, 193, 7, 7, 193, 7, 7, 193, 7, 7, 196, 7, 7, 196, 7, 7, 195, 7, 7, 193, 7, 7, 189, 7, 7, 188, 7, 7, 189, + 7, 7, 189, 7, 7, 152, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 121, 7, 7, 156, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 152, 7, 7, 151, 7, 7, 150, 8, 8, 150, 8, 8, 148, 8, 8, 148, 9, 9, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 143, + 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 183, + 7, 7, 137, 7, 7, 136, 7, 7, 136, 227, 227, 234, 255, 255, 255, 255, 255, 255, 148, 148, 181, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 51, 51, 138, 183, 183, 203, 220, 220, 229, 245, 245, 247, 242, 242, 245, 217, 217, 226, 165, 165, 190, 103, 103, 154, 255, 255, 255, 255, 255, 255, + 241, 241, 245, 7, 7, 173, 7, 7, 181, 227, 227, 241, 255, 255, 255, 255, 255, 255, 148, 148, 209, 7, 7, 184, 7, 7, 183, 7, 7, 181, 7, 7, 176, 193, 193, 221, 255, 255, 255, 255, 255, 255, 193, 193, 218, 7, 7, 160, 7, 7, 159, 133, 133, 187, 255, 255, 255, 255, 255, 255, 250, 250, 252, + 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 141, 7, 7, 139, 7, 7, 134, 7, 7, 128, 7, 7, 121, 7, 7, 116, 7, 7, 107, 7, 7, 100, 7, 7, 88, 7, 7, 61, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 91, 7, 7, 96, + 7, 7, 100, 7, 7, 107, 7, 7, 149, 7, 7, 169, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 147, 7, 7, 196, 7, 7, 195, 7, 7, 195, 7, 7, 198, 7, 7, 185, 7, 7, 163, + 7, 7, 165, 7, 7, 186, 7, 7, 196, 7, 7, 196, 7, 7, 195, 7, 7, 196, 7, 7, 164, 7, 7, 116, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 114, 7, 7, 151, 7, 7, 166, + 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, + 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 149, 8, 8, 148, 8, 8, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 25, 25, 136, 144, 144, 178, 144, 144, 178, 144, 144, 178, 111, 111, 161, 7, 7, 133, 7, 7, 132, 7, 7, 132, + 7, 7, 131, 7, 7, 130, 198, 198, 212, 255, 255, 255, 255, 255, 255, 209, 209, 220, 7, 7, 132, 7, 7, 136, 7, 7, 143, 7, 7, 157, 7, 7, 176, 7, 7, 185, 7, 7, 187, 7, 7, 186, 7, 7, 188, 7, 7, 182, 7, 7, 176, 7, 7, 171, 7, 7, 167, 7, 7, 164, 7, 7, 162, + 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 141, 7, 7, 138, 7, 7, 133, 7, 7, 128, 7, 7, 121, 7, 7, 116, 7, 7, 107, 7, 7, 100, 7, 7, 88, 7, 7, 61, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, + 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 96, 7, 7, 100, 7, 7, 103, 7, 7, 119, 7, 7, 163, 7, 7, 171, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 144, 7, 7, 195, + 7, 7, 200, 7, 7, 199, 7, 7, 186, 7, 7, 148, 7, 7, 134, 7, 7, 134, 7, 7, 143, 7, 7, 168, 7, 7, 190, 7, 7, 198, 7, 7, 200, 7, 7, 179, 7, 7, 121, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, + 7, 7, 108, 7, 7, 110, 7, 7, 142, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, + 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 209, 209, 221, 255, 255, 255, + 255, 255, 255, 253, 253, 253, 185, 185, 205, 115, 115, 162, 57, 57, 140, 107, 107, 158, 194, 194, 210, 254, 254, 254, 255, 255, 255, 255, 255, 255, 117, 117, 161, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 132, 7, 7, 140, 7, 7, 143, 7, 7, 143, 7, 7, 162, 7, 7, 185, + 7, 7, 180, 7, 7, 173, 7, 7, 169, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 161, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 137, 7, 7, 133, 7, 7, 128, 7, 7, 121, 7, 7, 116, 7, 7, 108, 7, 7, 101, 7, 7, 88, 7, 7, 61, 36, 36, 39, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 66, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 97, 7, 7, 101, 7, 7, 104, 7, 7, 107, 7, 7, 131, 7, 7, 170, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 162, + 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 162, 7, 7, 171, 7, 7, 154, 7, 7, 138, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 138, 7, 7, 144, 7, 7, 149, 7, 7, 165, 7, 7, 137, 7, 7, 113, 7, 7, 112, 7, 7, 111, + 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 110, 7, 7, 133, 7, 7, 166, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, + 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 84, 84, 151, 236, 236, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 201, 201, 214, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 129, 7, 7, 164, 7, 7, 183, 7, 7, 177, 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, + 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 132, 7, 7, 128, 7, 7, 122, 7, 7, 117, + 7, 7, 108, 7, 7, 101, 7, 7, 89, 7, 7, 61, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 66, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 97, 7, 7, 101, 7, 7, 105, 7, 7, 107, 7, 7, 111, 7, 7, 144, 7, 7, 176, + 7, 7, 176, 7, 7, 175, 7, 7, 172, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 141, 7, 7, 155, 7, 7, 119, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 128, 7, 7, 162, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 170, + 7, 7, 171, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 143, 7, 7, 143, 7, 7, 144, 8, 8, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 70, 70, 146, 213, 213, 224, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 189, 189, 206, 18, 18, 131, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 136, 7, 7, 172, 7, 7, 182, 7, 7, 176, 7, 7, 171, 7, 7, 167, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 167, 7, 7, 169, + 7, 7, 171, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 141, 7, 7, 138, + 7, 7, 136, 7, 7, 132, 7, 7, 126, 7, 7, 122, 7, 7, 117, 7, 7, 108, 7, 7, 101, 7, 7, 89, 7, 7, 61, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 97, 7, 7, 101, + 7, 7, 104, 7, 7, 107, 7, 7, 108, 7, 7, 114, 7, 7, 169, 7, 7, 180, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 166, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 145, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 151, 7, 7, 148, 7, 7, 119, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 126, 7, 7, 161, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 171, 7, 7, 171, + 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 145, 7, 7, 144, 19, 19, 145, 19, 19, 145, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 101, 101, 158, 181, 181, 202, 202, 202, 216, 215, 215, 225, 205, 205, 218, + 174, 174, 196, 92, 92, 151, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 141, 7, 7, 171, 7, 7, 181, 7, 7, 176, 7, 7, 171, 7, 7, 168, + 7, 7, 166, 7, 7, 165, 7, 7, 166, 7, 7, 168, 7, 7, 171, 7, 7, 174, 7, 7, 176, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 169, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 150, + 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 131, 7, 7, 126, 7, 7, 121, 7, 7, 116, 7, 7, 108, 7, 7, 101, 7, 7, 88, 7, 7, 61, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, + 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 97, 7, 7, 101, 7, 7, 104, 7, 7, 106, 7, 7, 108, 7, 7, 117, 7, 7, 168, 7, 7, 178, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 153, + 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, + 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 135, 7, 7, 169, 7, 7, 164, 7, 7, 134, 7, 7, 121, 7, 7, 118, 7, 7, 123, 7, 7, 142, 7, 7, 171, 7, 7, 177, + 7, 7, 175, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 176, 7, 7, 176, 7, 7, 175, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, + 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 143, 7, 7, 143, 8, 8, 143, 10, 10, 143, 7, 7, 142, 7, 7, 144, 7, 7, 145, 7, 7, 145, 22, 22, 145, 21, 21, 145, 8, 8, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, + 7, 7, 132, 7, 7, 165, 7, 7, 181, 7, 7, 177, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 172, 7, 7, 176, 7, 7, 181, 7, 7, 182, 7, 7, 180, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, + 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 131, 7, 7, 125, 7, 7, 121, 7, 7, 116, 7, 7, 108, 7, 7, 100, 7, 7, 88, 7, 7, 61, 36, 36, 39, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 97, 7, 7, 100, 7, 7, 103, 7, 7, 110, 7, 7, 133, 7, 7, 161, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, + 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 139, 7, 7, 172, 7, 7, 188, 7, 7, 182, + 7, 7, 179, 7, 7, 183, 7, 7, 186, 7, 7, 184, 7, 7, 180, 7, 7, 177, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 177, 7, 7, 179, 7, 7, 179, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 172, 7, 7, 169, + 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 9, 9, 143, 17, 17, 144, 8, 8, 143, 7, 7, 145, 7, 7, 145, 8, 8, 145, 11, 11, 144, 8, 8, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 8, 8, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 130, 7, 7, 153, 7, 7, 179, 7, 7, 180, 7, 7, 175, 7, 7, 172, 7, 7, 171, 7, 7, 171, 7, 7, 174, 7, 7, 178, 7, 7, 182, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 178, + 7, 7, 174, 7, 7, 170, 7, 7, 167, 7, 7, 163, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 130, 7, 7, 125, 7, 7, 120, 7, 7, 115, 7, 7, 107, + 7, 7, 100, 7, 7, 88, 7, 7, 60, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 96, 7, 7, 100, 7, 7, 106, 7, 7, 145, 7, 7, 168, 7, 7, 173, 7, 7, 169, 7, 7, 167, + 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 139, 7, 7, 155, 7, 7, 166, 7, 7, 177, 7, 7, 196, 7, 7, 194, 7, 7, 186, 7, 7, 182, 7, 7, 179, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 180, 7, 7, 180, + 7, 7, 178, 7, 7, 175, 7, 7, 173, 7, 7, 172, 7, 7, 169, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 8, 8, 144, 14, 14, 144, 10, 10, 143, 7, 7, 145, 7, 7, 146, + 9, 9, 145, 8, 8, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 128, 7, 7, 147, 7, 7, 176, 7, 7, 182, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 175, 7, 7, 178, + 7, 7, 182, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 177, 7, 7, 173, 7, 7, 169, 7, 7, 165, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 137, 7, 7, 134, + 7, 7, 130, 7, 7, 125, 7, 7, 120, 7, 7, 115, 7, 7, 107, 7, 7, 100, 7, 7, 87, 7, 7, 60, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 96, 7, 7, 100, 7, 7, 123, + 7, 7, 166, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 138, 7, 7, 176, 7, 7, 197, 7, 7, 188, 7, 7, 183, 7, 7, 180, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 182, 7, 7, 181, + 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 8, 8, 145, 9, 9, 144, 12, 12, 145, 8, 8, 145, 7, 7, 145, 11, 11, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 137, 7, 7, 168, + 7, 7, 184, 7, 7, 182, 7, 7, 178, 7, 7, 177, 7, 7, 178, 7, 7, 180, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 175, 7, 7, 170, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 149, + 7, 7, 146, 7, 7, 143, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 131, 7, 7, 125, 7, 7, 120, 7, 7, 116, 7, 7, 108, 7, 7, 100, 7, 7, 88, 7, 7, 60, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, + 7, 7, 84, 7, 7, 91, 7, 7, 96, 7, 7, 101, 7, 7, 142, 7, 7, 166, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 152, 7, 7, 194, 7, 7, 189, 7, 7, 184, 7, 7, 181, + 7, 7, 181, 7, 7, 182, 7, 7, 184, 7, 7, 185, 7, 7, 183, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 183, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, + 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 147, 9, 9, 146, 11, 11, 145, 8, 8, 146, 8, 8, 146, 14, 14, 146, 8, 8, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, + 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 128, 7, 7, 150, 7, 7, 178, 7, 7, 184, 7, 7, 180, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 180, 7, 7, 176, 7, 7, 171, 7, 7, 166, 7, 7, 163, 7, 7, 160, + 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 141, 7, 7, 138, 7, 7, 135, 7, 7, 132, 7, 7, 126, 7, 7, 121, 7, 7, 117, 7, 7, 108, 7, 7, 101, 7, 7, 88, 7, 7, 60, 36, 36, 39, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 75, 7, 7, 84, 7, 7, 91, 7, 7, 96, 7, 7, 102, 7, 7, 149, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 138, 7, 7, 175, 7, 7, 193, 7, 7, 186, 7, 7, 183, 7, 7, 183, 7, 7, 184, 7, 7, 186, 7, 7, 187, 7, 7, 185, 7, 7, 184, 7, 7, 183, 7, 7, 183, 7, 7, 182, 7, 7, 180, 7, 7, 178, 7, 7, 175, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 169, + 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 9, 9, 148, 11, 11, 148, 8, 8, 147, 8, 8, 146, 15, 15, 147, 8, 8, 146, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 125, 7, 7, 138, 7, 7, 171, 7, 7, 183, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 180, 7, 7, 182, 7, 7, 182, + 7, 7, 178, 7, 7, 172, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 156, 7, 7, 152, 7, 7, 149, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 137, 7, 7, 133, 7, 7, 128, 7, 7, 122, 7, 7, 117, 7, 7, 109, 7, 7, 101, + 7, 7, 88, 7, 7, 60, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 75, 7, 7, 83, 7, 7, 91, 7, 7, 96, 7, 7, 102, 7, 7, 151, 7, 7, 163, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, + 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 148, 7, 7, 187, 7, 7, 190, 7, 7, 186, 7, 7, 185, 7, 7, 186, 7, 7, 187, 7, 7, 188, 7, 7, 187, 7, 7, 185, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 176, + 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 8, 8, 148, 8, 8, 149, 8, 8, 148, 9, 9, 147, 12, 12, 146, + 8, 8, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 132, 7, 7, 162, 7, 7, 183, 7, 7, 181, + 7, 7, 179, 7, 7, 178, 7, 7, 180, 7, 7, 184, 7, 7, 185, 7, 7, 182, 7, 7, 177, 7, 7, 171, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 154, 7, 7, 151, 7, 7, 147, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 134, + 7, 7, 129, 7, 7, 123, 7, 7, 118, 7, 7, 109, 7, 7, 102, 7, 7, 89, 7, 7, 61, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 64, 7, 7, 75, 7, 7, 83, 7, 7, 91, 7, 7, 96, 7, 7, 101, 7, 7, 142, 7, 7, 165, + 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 150, 7, 7, 181, 7, 7, 192, 7, 7, 189, 7, 7, 188, 7, 7, 189, 7, 7, 190, 7, 7, 188, 7, 7, 186, + 7, 7, 183, 7, 7, 182, 7, 7, 180, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 149, 7, 7, 148, 8, 8, 147, 8, 8, 146, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 124, 7, 7, 123, 7, 7, 129, 7, 7, 161, 7, 7, 184, 7, 7, 182, 7, 7, 180, 7, 7, 183, 7, 7, 175, 7, 7, 150, 7, 7, 154, 7, 7, 178, 7, 7, 176, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 159, 7, 7, 156, 7, 7, 153, + 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 140, 7, 7, 135, 7, 7, 130, 7, 7, 124, 7, 7, 119, 7, 7, 110, 7, 7, 102, 7, 7, 90, 7, 7, 62, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 75, 7, 7, 83, + 7, 7, 91, 7, 7, 96, 7, 7, 100, 7, 7, 115, 7, 7, 153, 7, 7, 166, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 142, 7, 7, 169, 7, 7, 190, + 7, 7, 195, 7, 7, 195, 7, 7, 195, 7, 7, 192, 7, 7, 188, 7, 7, 185, 7, 7, 182, 7, 7, 179, 7, 7, 177, 7, 7, 174, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 126, 7, 7, 147, 7, 7, 167, 7, 7, 174, 7, 7, 169, 7, 7, 135, 7, 7, 121, 7, 7, 122, 7, 7, 146, 7, 7, 177, 7, 7, 178, 7, 7, 175, 7, 7, 173, + 7, 7, 169, 7, 7, 165, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 152, 7, 7, 149, 7, 7, 145, 7, 7, 141, 7, 7, 137, 7, 7, 132, 7, 7, 125, 7, 7, 120, 7, 7, 111, 7, 7, 103, 7, 7, 91, 7, 7, 62, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 76, 7, 7, 83, 7, 7, 91, 7, 7, 96, 7, 7, 100, 7, 7, 104, 7, 7, 114, 7, 7, 139, 7, 7, 162, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 157, + 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, + 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 137, 7, 7, 154, 7, 7, 171, 7, 7, 181, 7, 7, 190, 7, 7, 196, 7, 7, 193, 7, 7, 188, 7, 7, 183, 7, 7, 180, 7, 7, 177, 7, 7, 174, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 171, + 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, + 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 126, 7, 7, 130, 7, 7, 128, 7, 7, 121, 7, 7, 121, 7, 7, 120, + 7, 7, 121, 7, 7, 153, 7, 7, 182, 7, 7, 182, 7, 7, 178, 7, 7, 172, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 150, 7, 7, 146, 7, 7, 142, 7, 7, 138, 7, 7, 133, 7, 7, 128, 7, 7, 121, 7, 7, 112, 7, 7, 104, 7, 7, 91, + 7, 7, 64, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 91, 7, 7, 96, 7, 7, 100, 7, 7, 104, 7, 7, 106, 7, 7, 109, 7, 7, 122, 7, 7, 155, 7, 7, 170, 7, 7, 168, 7, 7, 166, + 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 148, 7, 7, 149, + 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 137, 7, 7, 144, 7, 7, 167, 7, 7, 194, 7, 7, 194, 7, 7, 186, 7, 7, 182, 7, 7, 178, 7, 7, 175, 7, 7, 174, + 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 172, 7, 7, 168, 7, 7, 165, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 125, 7, 7, 159, 7, 7, 183, 7, 7, 184, 7, 7, 176, 7, 7, 169, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 151, 7, 7, 147, 7, 7, 143, 7, 7, 139, 7, 7, 134, + 7, 7, 129, 7, 7, 122, 7, 7, 113, 7, 7, 105, 7, 7, 92, 7, 7, 65, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 45, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 92, 7, 7, 96, 7, 7, 100, 7, 7, 105, 7, 7, 107, 7, 7, 108, + 7, 7, 110, 7, 7, 115, 7, 7, 149, 7, 7, 174, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, + 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 158, 7, 7, 192, + 7, 7, 190, 7, 7, 184, 7, 7, 179, 7, 7, 176, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 176, 7, 7, 175, 7, 7, 173, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, + 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 118, 7, 7, 119, 7, 7, 131, 7, 7, 159, 7, 7, 178, 7, 7, 172, 7, 7, 165, 7, 7, 161, 7, 7, 159, 7, 7, 155, + 7, 7, 151, 7, 7, 147, 7, 7, 143, 7, 7, 140, 7, 7, 136, 7, 7, 131, 7, 7, 124, 7, 7, 114, 7, 7, 107, 7, 7, 94, 7, 7, 65, 36, 36, 39, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 65, 7, 7, 76, 7, 7, 84, 7, 7, 92, + 7, 7, 97, 7, 7, 101, 7, 7, 105, 7, 7, 108, 7, 7, 109, 7, 7, 111, 7, 7, 111, 7, 7, 119, 7, 7, 149, 7, 7, 173, 7, 7, 175, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 135, 7, 7, 169, 7, 7, 194, 7, 7, 185, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 176, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 123, 7, 7, 160, + 7, 7, 176, 7, 7, 169, 7, 7, 164, 7, 7, 161, 7, 7, 157, 7, 7, 152, 7, 7, 148, 7, 7, 145, 7, 7, 141, 7, 7, 137, 7, 7, 133, 7, 7, 126, 7, 7, 116, 7, 7, 108, 7, 7, 94, 7, 7, 66, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 46, 7, 7, 66, 7, 7, 77, 7, 7, 84, 7, 7, 92, 7, 7, 97, 7, 7, 101, 7, 7, 105, 7, 7, 108, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 116, 7, 7, 141, 7, 7, 174, 7, 7, 175, 7, 7, 172, 7, 7, 171, 7, 7, 168, 7, 7, 166, + 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 151, 7, 7, 192, 7, 7, 183, 7, 7, 176, 7, 7, 171, 7, 7, 168, 7, 7, 169, 7, 7, 170, 7, 7, 172, 7, 7, 173, 7, 7, 171, 7, 7, 168, + 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, + 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 116, 7, 7, 132, 7, 7, 171, 7, 7, 174, 7, 7, 168, 7, 7, 163, 7, 7, 158, 7, 7, 153, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 139, 7, 7, 134, 7, 7, 128, 7, 7, 117, 7, 7, 109, 7, 7, 95, 7, 7, 66, + 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 46, 7, 7, 66, 7, 7, 77, 7, 7, 85, 7, 7, 93, 7, 7, 97, 7, 7, 102, 7, 7, 106, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 142, + 7, 7, 173, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 142, 7, 7, 183, 7, 7, 179, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 161, + 7, 7, 163, 7, 7, 168, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, + 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 120, 7, 7, 145, 7, 7, 146, 7, 7, 117, 7, 7, 117, 7, 7, 142, 7, 7, 176, 7, 7, 174, 7, 7, 167, 7, 7, 160, 7, 7, 155, 7, 7, 151, 7, 7, 148, 7, 7, 145, 7, 7, 140, 7, 7, 135, + 7, 7, 129, 7, 7, 118, 7, 7, 109, 7, 7, 96, 7, 7, 67, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 67, 7, 7, 77, 7, 7, 85, 7, 7, 93, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 111, + 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 117, 7, 7, 141, 7, 7, 175, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, + 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 139, 7, 7, 170, + 7, 7, 166, 7, 7, 158, 7, 7, 152, 7, 7, 150, 7, 7, 151, 7, 7, 154, 7, 7, 159, 7, 7, 163, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 123, 7, 7, 170, 7, 7, 183, 7, 7, 136, 7, 7, 116, 7, 7, 117, 7, 7, 146, 7, 7, 177, 7, 7, 170, 7, 7, 163, 7, 7, 157, + 7, 7, 153, 7, 7, 149, 7, 7, 146, 7, 7, 141, 7, 7, 136, 7, 7, 129, 7, 7, 118, 7, 7, 109, 7, 7, 96, 7, 7, 68, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 47, 7, 7, 67, 7, 7, 78, 7, 7, 86, 7, 7, 94, 7, 7, 99, + 7, 7, 103, 7, 7, 107, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 118, 7, 7, 137, 7, 7, 169, 7, 7, 177, 7, 7, 173, 7, 7, 169, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 157, + 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 130, 7, 7, 122, 9, 9, 115, 9, 9, 113, 8, 8, 118, 8, 8, 122, 8, 8, 127, 7, 7, 131, 7, 7, 136, 7, 7, 140, 7, 7, 145, 7, 7, 151, 7, 7, 157, 7, 7, 160, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, + 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 123, 7, 7, 169, 7, 7, 185, 7, 7, 173, 7, 7, 136, 7, 7, 117, + 7, 7, 130, 7, 7, 176, 7, 7, 172, 7, 7, 164, 7, 7, 158, 7, 7, 153, 7, 7, 150, 7, 7, 146, 7, 7, 141, 7, 7, 136, 7, 7, 129, 7, 7, 118, 7, 7, 110, 7, 7, 97, 7, 7, 68, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, + 7, 7, 68, 7, 7, 79, 7, 7, 86, 7, 7, 94, 7, 7, 99, 7, 7, 104, 7, 7, 107, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 132, 7, 7, 162, 7, 7, 178, 7, 7, 173, + 7, 7, 169, 7, 7, 166, 7, 7, 162, 7, 7, 160, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 152, 7, 7, 153, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 127, 8, 8, 122, 9, 9, 124, 10, 10, 125, 10, 10, 126, 9, 9, 127, 8, 8, 129, 8, 8, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 135, 7, 7, 144, 7, 7, 151, 7, 7, 157, 7, 7, 161, 7, 7, 161, + 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 126, + 7, 7, 172, 7, 7, 181, 7, 7, 183, 7, 7, 176, 7, 7, 158, 7, 7, 161, 7, 7, 179, 7, 7, 171, 7, 7, 163, 7, 7, 157, 7, 7, 153, 7, 7, 150, 7, 7, 146, 7, 7, 141, 7, 7, 136, 7, 7, 130, 7, 7, 119, 7, 7, 111, 7, 7, 97, 7, 7, 68, 36, 36, 40, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 87, 7, 7, 95, 7, 7, 100, 7, 7, 104, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, + 7, 7, 117, 7, 7, 117, 7, 7, 124, 7, 7, 158, 7, 7, 178, 7, 7, 173, 7, 7, 167, 7, 7, 163, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 128, 8, 8, 130, 8, 8, 131, 7, 7, 132, 9, 9, 133, 11, 11, 133, 13, 13, 133, 12, 12, 133, 9, 9, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 130, 7, 7, 144, 7, 7, 152, 7, 7, 158, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, + 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 133, 7, 7, 176, 7, 7, 178, 7, 7, 177, 7, 7, 180, 7, 7, 184, 7, 7, 183, 7, 7, 176, 7, 7, 168, 7, 7, 161, 7, 7, 156, 7, 7, 152, 7, 7, 149, 7, 7, 145, 7, 7, 141, 7, 7, 136, 7, 7, 130, + 7, 7, 120, 7, 7, 111, 7, 7, 98, 7, 7, 68, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 88, 7, 7, 96, 7, 7, 101, 7, 7, 105, 7, 7, 108, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, + 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 125, 7, 7, 164, 7, 7, 176, 7, 7, 169, 7, 7, 164, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 130, 8, 8, 132, 8, 8, 134, 8, 8, 134, 9, 9, 135, 10, 10, 135, 10, 10, 135, 11, 11, 135, 13, 13, 135, + 12, 12, 135, 8, 8, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 131, 7, 7, 129, 7, 7, 146, 7, 7, 155, 7, 7, 160, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 158, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, + 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 141, 7, 7, 179, 7, 7, 177, 7, 7, 176, 7, 7, 177, 7, 7, 179, 7, 7, 178, 7, 7, 172, 7, 7, 165, 7, 7, 159, 7, 7, 154, 7, 7, 151, + 7, 7, 148, 7, 7, 144, 7, 7, 140, 7, 7, 136, 7, 7, 131, 7, 7, 120, 7, 7, 112, 7, 7, 98, 7, 7, 69, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 70, 7, 7, 81, 7, 7, 88, 7, 7, 96, 7, 7, 101, 7, 7, 105, + 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 138, 7, 7, 176, 7, 7, 171, 7, 7, 165, 7, 7, 160, 7, 7, 157, 7, 7, 154, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, + 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 8, 8, 133, 8, 8, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 8, 8, 135, 8, 8, 135, 8, 8, 134, 8, 8, 134, 8, 8, 134, 7, 7, 132, 7, 7, 128, 7, 7, 130, 7, 7, 151, 7, 7, 156, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, + 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, + 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 159, 7, 7, 182, 7, 7, 177, 7, 7, 176, 7, 7, 177, 7, 7, 178, 7, 7, 176, + 7, 7, 170, 7, 7, 163, 7, 7, 158, 7, 7, 153, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 140, 7, 7, 136, 7, 7, 131, 7, 7, 121, 7, 7, 113, 7, 7, 99, 7, 7, 69, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 70, + 7, 7, 81, 7, 7, 89, 7, 7, 97, 7, 7, 101, 7, 7, 105, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 126, 7, 7, 173, + 7, 7, 173, 7, 7, 165, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 154, 7, 7, 155, + 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 133, + 7, 7, 132, 8, 8, 133, 10, 10, 135, 8, 8, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 9, 9, 134, 12, 12, 133, 8, 8, 131, 8, 8, 126, 7, 7, 140, 7, 7, 152, 7, 7, 158, + 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 148, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 120, 7, 7, 144, 7, 7, 182, 7, 7, 184, + 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 175, 7, 7, 168, 7, 7, 161, 7, 7, 156, 7, 7, 153, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 140, 7, 7, 136, 7, 7, 132, 7, 7, 122, 7, 7, 114, 7, 7, 100, 7, 7, 69, 36, 36, 40, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 70, 7, 7, 81, 7, 7, 89, 7, 7, 97, 7, 7, 102, 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, + 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 124, 7, 7, 172, 7, 7, 174, 7, 7, 166, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 150, 7, 7, 151, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 132, 7, 7, 132, 14, 14, 134, 12, 12, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 8, 8, 134, 13, 13, 134, + 11, 11, 133, 7, 7, 129, 7, 7, 128, 7, 7, 148, 7, 7, 155, 7, 7, 160, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, + 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 119, 7, 7, 145, 7, 7, 185, 7, 7, 189, 7, 7, 185, 7, 7, 180, 7, 7, 184, 7, 7, 186, 7, 7, 181, 7, 7, 174, 7, 7, 166, 7, 7, 160, 7, 7, 155, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 143, 7, 7, 140, 7, 7, 136, 7, 7, 132, 7, 7, 122, + 7, 7, 115, 7, 7, 102, 7, 7, 70, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, 7, 7, 81, 7, 7, 89, 7, 7, 97, 7, 7, 102, 7, 7, 106, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 115, + 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 126, 7, 7, 173, 7, 7, 173, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 130, 10, 10, 132, 19, 19, 134, 9, 9, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 11, 11, 134, 8, 8, 133, 7, 7, 129, 7, 7, 143, 7, 7, 151, 7, 7, 158, 7, 7, 162, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, + 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, + 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 148, 7, 7, 176, 7, 7, 164, 7, 7, 145, 7, 7, 132, 7, 7, 153, 7, 7, 184, 7, 7, 180, 7, 7, 171, 7, 7, 164, 7, 7, 158, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 146, + 7, 7, 142, 7, 7, 139, 7, 7, 135, 7, 7, 131, 7, 7, 122, 7, 7, 116, 7, 7, 103, 7, 7, 71, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, 7, 7, 81, 7, 7, 89, 7, 7, 97, 7, 7, 102, 7, 7, 106, 7, 7, 110, + 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 130, 7, 7, 175, 7, 7, 172, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 156, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 158, + 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 140, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 132, 8, 8, 132, 16, 16, 133, 12, 12, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, 8, 8, 134, 8, 8, 134, 7, 7, 132, 7, 7, 139, 7, 7, 148, 7, 7, 155, 7, 7, 161, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, + 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, + 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 120, 7, 7, 124, 7, 7, 119, 7, 7, 116, 7, 7, 116, 7, 7, 141, 7, 7, 181, 7, 7, 176, 7, 7, 168, 7, 7, 161, + 7, 7, 156, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 138, 7, 7, 134, 7, 7, 131, 7, 7, 122, 7, 7, 116, 7, 7, 104, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, 7, 7, 81, + 7, 7, 89, 7, 7, 98, 7, 7, 103, 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 132, 7, 7, 175, 7, 7, 172, + 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, + 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, + 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 8, 8, 133, 12, 12, 135, + 8, 8, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 9, 9, 134, 7, 7, 133, 7, 7, 135, 7, 7, 145, 7, 7, 153, + 7, 7, 161, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 153, + 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, + 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, + 7, 7, 156, 7, 7, 178, 7, 7, 172, 7, 7, 165, 7, 7, 158, 7, 7, 153, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 137, 7, 7, 133, 7, 7, 130, 7, 7, 122, 7, 7, 116, 7, 7, 104, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, + 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, 7, 7, 81, 7, 7, 89, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 118, 7, 7, 118, 7, 7, 137, 7, 7, 177, 7, 7, 171, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 135, 8, 8, 135, 8, 8, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, + 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 143, 7, 7, 151, 7, 7, 160, 7, 7, 167, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 163, + 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, + 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 163, 7, 7, 174, 7, 7, 167, 7, 7, 162, 7, 7, 156, 7, 7, 152, 7, 7, 148, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 138, 7, 7, 135, 7, 7, 133, 7, 7, 129, 7, 7, 121, 7, 7, 116, + 7, 7, 105, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, 7, 7, 81, 7, 7, 89, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, + 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 141, 7, 7, 178, 7, 7, 171, 7, 7, 166, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, + 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 8, 8, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 127, + 7, 7, 130, 7, 7, 133, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 133, 7, 7, 142, 7, 7, 151, 7, 7, 160, 7, 7, 167, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 167, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 123, 7, 7, 172, 7, 7, 170, 7, 7, 164, 7, 7, 159, 7, 7, 154, 7, 7, 151, 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 140, 7, 7, 138, + 7, 7, 135, 7, 7, 132, 7, 7, 129, 7, 7, 121, 7, 7, 116, 7, 7, 105, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 81, 7, 7, 89, 7, 7, 97, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 112, + 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 130, 7, 7, 173, 7, 7, 174, 7, 7, 167, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, + 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 8, 8, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 8, 8, 138, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 143, 7, 7, 151, 7, 7, 161, 7, 7, 168, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 170, + 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 169, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 130, 7, 7, 174, 7, 7, 167, 7, 7, 161, 7, 7, 156, 7, 7, 153, 7, 7, 150, + 7, 7, 147, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 130, 7, 7, 122, 7, 7, 117, 7, 7, 105, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 89, + 7, 7, 97, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 149, 7, 7, 174, 7, 7, 171, + 7, 7, 165, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, + 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 135, 8, 8, 135, 7, 7, 133, 7, 7, 134, 7, 7, 145, 7, 7, 154, 7, 7, 164, + 7, 7, 170, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 171, 7, 7, 171, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 169, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, + 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, + 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 137, 7, 7, 174, + 7, 7, 165, 7, 7, 159, 7, 7, 155, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 122, 7, 7, 117, 7, 7, 105, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, + 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 89, 7, 7, 97, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 118, 7, 7, 117, 7, 7, 122, 7, 7, 157, 7, 7, 175, 7, 7, 168, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, + 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, + 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 139, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 9, 9, 135, 9, 9, 135, + 7, 7, 131, 7, 7, 137, 7, 7, 149, 7, 7, 159, 7, 7, 167, 7, 7, 174, 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 173, 7, 7, 174, 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 169, 7, 7, 165, 7, 7, 162, + 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, + 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 142, 7, 7, 174, 7, 7, 164, 7, 7, 159, 7, 7, 155, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 123, 7, 7, 117, 7, 7, 105, + 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 80, 7, 7, 89, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, + 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 129, 7, 7, 168, 7, 7, 172, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, + 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 135, 8, 8, 134, 9, 9, 133, 7, 7, 130, 7, 7, 146, 7, 7, 157, 7, 7, 168, 7, 7, 174, 7, 7, 179, 7, 7, 182, 7, 7, 184, 7, 7, 184, 7, 7, 182, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 175, + 7, 7, 174, 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, + 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 150, 7, 7, 174, 7, 7, 164, 7, 7, 158, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 135, + 7, 7, 133, 7, 7, 130, 7, 7, 122, 7, 7, 118, 7, 7, 106, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 69, 7, 7, 81, 7, 7, 89, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 112, 7, 7, 113, 7, 7, 114, + 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 144, 7, 7, 175, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 160, + 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 100, 100, 173, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 208, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, + 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 9, 9, 133, 7, 7, 133, 7, 7, 129, 7, 7, 153, 7, 7, 170, 7, 7, 177, 7, 7, 181, 7, 7, 187, 7, 7, 192, 7, 7, 192, 7, 7, 190, 7, 7, 189, 7, 7, 182, + 7, 7, 178, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 173, 7, 7, 170, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, + 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 156, 7, 7, 173, 7, 7, 164, 7, 7, 158, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 146, + 7, 7, 143, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 122, 7, 7, 117, 7, 7, 106, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 70, 7, 7, 81, 7, 7, 90, 7, 7, 98, + 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 126, 7, 7, 172, + 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 100, 100, 173, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 208, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, + 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 8, 8, 134, 7, 7, 133, 7, 7, 131, 7, 7, 129, 7, 7, 143, 7, 7, 178, 7, 7, 185, 7, 7, 191, 7, 7, 190, + 7, 7, 172, 7, 7, 154, 7, 7, 154, 7, 7, 182, 7, 7, 186, 7, 7, 178, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 173, 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 120, 7, 7, 163, 7, 7, 172, 7, 7, 164, + 7, 7, 158, 7, 7, 154, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 122, 7, 7, 117, 7, 7, 105, 7, 7, 74, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, + 10, 10, 49, 7, 7, 70, 7, 7, 82, 7, 7, 90, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 161, 7, 7, 174, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 100, 100, 173, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 208, + 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 129, 7, 7, 129, + 7, 7, 154, 7, 7, 184, 7, 7, 192, 7, 7, 195, 7, 7, 171, 7, 7, 135, 7, 7, 129, 7, 7, 130, 7, 7, 163, 7, 7, 186, 7, 7, 178, 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 159, 7, 7, 158, + 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, + 7, 7, 117, 7, 7, 120, 7, 7, 162, 7, 7, 172, 7, 7, 164, 7, 7, 158, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 134, 7, 7, 131, 7, 7, 122, 7, 7, 116, 7, 7, 104, 7, 7, 74, + 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 71, 7, 7, 82, 7, 7, 90, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, + 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 149, 7, 7, 176, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, + 100, 100, 174, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 209, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 148, 7, 7, 180, 7, 7, 187, 7, 7, 189, 7, 7, 194, 7, 7, 160, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 160, 7, 7, 186, 7, 7, 178, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, + 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 138, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, + 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 153, 7, 7, 173, 7, 7, 164, 7, 7, 159, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 136, + 7, 7, 132, 7, 7, 121, 7, 7, 115, 7, 7, 103, 7, 7, 73, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 72, 7, 7, 82, 7, 7, 90, 7, 7, 98, 7, 7, 103, 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 115, + 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 141, 7, 7, 177, 7, 7, 174, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, + 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 100, 100, 174, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 209, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, + 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 134, 7, 7, 173, 7, 7, 184, 7, 7, 187, 7, 7, 186, 7, 7, 190, 7, 7, 173, 7, 7, 135, 7, 7, 129, 7, 7, 135, 7, 7, 175, 7, 7, 185, 7, 7, 177, + 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 100, 100, 167, 255, 255, 255, 255, 255, 255, 221, 221, 231, 7, 7, 144, 135, 135, 179, 219, 219, 229, 247, 247, 249, 250, 250, 251, 234, 234, 239, 184, 184, 205, 44, 44, 141, 7, 7, 137, 118, 118, 166, 213, 213, 225, + 245, 245, 247, 252, 252, 252, 240, 240, 244, 201, 201, 216, 82, 82, 152, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 54, 54, 142, 174, 174, 198, 225, 225, 233, 246, 246, 248, 251, 251, 252, 241, 241, 244, 216, 216, 226, 149, 149, 183, 7, 7, 137, 7, 7, 136, + 7, 7, 135, 232, 232, 237, 255, 255, 255, 255, 255, 255, 244, 244, 246, 31, 31, 133, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 130, 141, 141, 175, 255, 255, 255, 255, 255, 255, 255, 255, 255, 181, 181, 199, 7, 7, 124, 7, 7, 124, 7, 7, 124, 57, 57, 133, 176, 176, 195, 227, 227, 233, + 245, 245, 247, 251, 251, 252, 241, 241, 244, 209, 209, 219, 125, 125, 162, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 136, 7, 7, 173, 7, 7, 166, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, + 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 138, 7, 7, 133, 7, 7, 121, 7, 7, 114, 7, 7, 102, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 72, 7, 7, 83, 7, 7, 90, 7, 7, 98, 7, 7, 103, + 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 129, 7, 7, 172, + 48, 48, 181, 173, 173, 212, 223, 223, 237, 243, 243, 247, 252, 252, 253, 248, 248, 250, 230, 230, 239, 188, 188, 215, 101, 101, 175, 7, 7, 159, 100, 100, 175, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 209, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 160, 54, 54, 165, 174, 174, 206, + 225, 225, 236, 246, 246, 249, 251, 251, 252, 241, 241, 246, 216, 216, 230, 149, 149, 193, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 100, 100, 168, 255, 255, 255, 255, 255, 255, 222, 222, 232, 7, 7, 144, 138, 138, 181, 217, 217, 228, 245, 245, 248, 252, 252, 252, 240, 240, 244, + 201, 201, 218, 89, 89, 160, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 57, 57, 150, 176, 176, 201, 227, 227, 235, 245, 245, 247, 251, 251, 252, 241, 241, 245, 209, 209, 223, 125, 125, 174, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, + 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 8, 8, 135, 8, 8, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 125, 7, 7, 132, 7, 7, 179, 7, 7, 186, 7, 7, 186, 7, 7, 184, 7, 7, 186, 7, 7, 188, 7, 7, 164, + 7, 7, 148, 7, 7, 169, 7, 7, 187, 7, 7, 183, 7, 7, 177, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 149, 100, 100, 167, 255, 255, 255, 255, 255, 255, 249, 249, 251, 159, 159, 193, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 217, 217, 227, 134, 134, 175, 251, 251, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 238, 242, 65, 65, 146, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 100, 100, 158, 235, 235, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 212, 212, 223, 51, 51, 143, 7, 7, 136, 174, 174, 198, 255, 255, 255, 255, 255, 255, 255, 255, 255, 139, 139, 174, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 204, 204, 216, 255, 255, 255, 255, 255, 255, 252, 252, 253, 87, 87, 144, 7, 7, 125, + 7, 7, 125, 101, 101, 150, 235, 235, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, 175, 175, 194, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 120, 7, 7, 162, 7, 7, 169, 7, 7, 163, + 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 140, 7, 7, 134, 7, 7, 122, 7, 7, 114, 7, 7, 101, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, + 7, 7, 72, 7, 7, 83, 7, 7, 90, 7, 7, 98, 7, 7, 103, 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 120, 103, 103, 168, 234, 234, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 158, 158, 199, 7, 7, 159, 100, 100, 176, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 209, 7, 7, 158, + 7, 7, 158, 7, 7, 159, 100, 100, 176, 235, 235, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 212, 212, 227, 51, 51, 158, 7, 7, 152, 7, 7, 151, 7, 7, 150, 100, 100, 167, 255, 255, 255, 255, 255, 255, 250, 250, 251, 174, 174, 200, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 243, 243, 246, 94, 94, 162, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 101, 101, 163, 235, 235, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 253, + 175, 175, 201, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 133, 8, 8, 132, 7, 7, 132, 7, 7, 130, 7, 7, 127, 7, 7, 121, 7, 7, 121, 7, 7, 131, 7, 7, 173, 7, 7, 192, + 7, 7, 185, 7, 7, 184, 7, 7, 184, 7, 7, 189, 7, 7, 193, 7, 7, 193, 7, 7, 193, 7, 7, 187, 7, 7, 181, 7, 7, 177, 7, 7, 174, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, + 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 150, 7, 7, 150, 100, 100, 169, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 241, 241, 245, 243, 243, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 249, 250, 240, 240, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 175, 175, 199, 7, 7, 136, 7, 7, 136, 7, 7, 136, 44, 44, 140, 234, 234, 239, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 251, 252, 238, 238, 242, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 202, 202, 217, 7, 7, 136, 76, 76, 148, 251, 251, 252, 255, 255, 255, 255, 255, 255, 203, 203, 216, 7, 7, 131, 7, 7, 131, 7, 7, 131, 41, 41, 135, 246, 246, 248, + 255, 255, 255, 255, 255, 255, 216, 216, 225, 7, 7, 126, 7, 7, 126, 41, 41, 130, 231, 231, 236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 246, 246, 248, 237, 237, 241, 251, 251, 252, 255, 255, 255, 255, 255, 255, 254, 254, 254, 138, 138, 169, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, + 7, 7, 117, 7, 7, 116, 7, 7, 137, 7, 7, 170, 7, 7, 170, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 142, 7, 7, 135, 7, 7, 122, 7, 7, 114, 7, 7, 101, 7, 7, 72, 36, 36, 40, + 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 72, 7, 7, 83, 7, 7, 91, 7, 7, 98, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 51, 51, 126, 233, 233, 237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 253, 238, 238, 245, 249, 249, 251, 255, 255, 255, 245, 245, 248, 44, 44, 163, 7, 7, 160, 100, 100, 177, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 209, 7, 7, 158, 7, 7, 158, 44, 44, 162, 234, 234, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 251, 252, 238, 238, 244, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 202, 202, 220, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 100, 100, 167, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, 244, 247, 239, 239, 243, 253, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 202, 202, 219, 7, 7, 144, 7, 7, 144, 7, 7, 143, 41, 41, 146, 231, 231, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 246, 246, 249, 237, 237, 242, 251, 251, 252, 255, 255, 255, 255, 255, 255, 254, 254, 254, 138, 138, 181, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 128, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 119, 7, 7, 116, + 7, 7, 116, 7, 7, 127, 7, 7, 129, 7, 7, 151, 7, 7, 193, 7, 7, 187, 7, 7, 184, 7, 7, 183, 7, 7, 185, 7, 7, 187, 7, 7, 188, 7, 7, 186, 7, 7, 183, 7, 7, 180, 7, 7, 177, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 166, + 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 152, + 100, 100, 170, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 162, 162, 194, 7, 7, 144, 7, 7, 142, 196, 196, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 194, 194, 211, 25, 25, 138, 7, 7, 136, 170, 170, 195, 255, 255, 255, 255, 255, 255, 255, 255, 255, 213, 213, 224, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 165, 165, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 210, 210, 222, 48, 48, 142, 7, 7, 137, 74, 74, 149, 225, 225, 233, 255, 255, 255, 255, 255, 255, 255, 255, 255, 111, 111, 163, 7, 7, 135, 212, 212, 223, 255, 255, 255, 255, 255, 255, 246, 246, 247, + 36, 36, 134, 7, 7, 131, 7, 7, 131, 145, 145, 178, 255, 255, 255, 255, 255, 255, 255, 255, 255, 151, 151, 180, 7, 7, 128, 7, 7, 126, 158, 158, 183, 255, 255, 255, 255, 255, 255, 255, 255, 255, 186, 186, 202, 31, 31, 128, 7, 7, 125, 87, 87, 144, 231, 231, 236, 255, 255, 255, 255, 255, 255, + 222, 222, 228, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 133, 7, 7, 158, 7, 7, 170, 7, 7, 169, 7, 7, 164, 7, 7, 160, 7, 7, 157, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 145, 7, 7, 137, + 7, 7, 123, 7, 7, 115, 7, 7, 102, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 72, 7, 7, 83, 7, 7, 91, 7, 7, 99, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, + 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 162, 162, 183, 255, 255, 255, 255, 255, 255, 255, 255, 255, 219, 219, 228, 67, 67, 174, 7, 7, 178, 7, 7, 171, + 121, 121, 187, 146, 146, 195, 7, 7, 161, 7, 7, 161, 100, 100, 177, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 209, 7, 7, 158, 7, 7, 159, 165, 165, 203, 255, 255, 255, 255, 255, 255, 255, 255, 255, 210, 210, 226, 48, 48, 162, 7, 7, 157, 74, 74, 166, 225, 225, 235, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 111, 111, 173, 7, 7, 151, 7, 7, 150, 100, 100, 167, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 173, 173, 200, 18, 18, 144, 7, 7, 144, 131, 131, 177, 253, 253, 253, 255, 255, 255, 255, 255, 255, 238, 238, 242, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 158, 158, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 186, 186, 208, 31, 31, 145, 7, 7, 144, 87, 87, 159, 231, 231, 238, 255, 255, 255, 255, 255, 255, 222, 222, 231, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 129, 7, 7, 127, 7, 7, 124, 7, 7, 120, + 7, 7, 117, 7, 7, 112, 7, 7, 109, 7, 7, 109, 7, 7, 116, 7, 7, 125, 7, 7, 128, 7, 7, 128, 7, 7, 134, 7, 7, 184, 7, 7, 190, 7, 7, 185, 7, 7, 182, 7, 7, 182, 7, 7, 183, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 177, 7, 7, 175, + 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 100, 100, 170, 255, 255, 255, 255, 255, 255, 255, 255, 255, 234, 234, 240, 7, 7, 146, 7, 7, 144, 7, 7, 143, 89, 89, 158, 255, 255, 255, 255, 255, 255, 255, 255, 255, 245, 245, 247, 41, 41, 141, 7, 7, 137, 7, 7, 136, + 25, 25, 137, 247, 247, 249, 255, 255, 255, 255, 255, 255, 224, 224, 232, 7, 7, 136, 7, 7, 136, 7, 7, 136, 216, 216, 226, 255, 255, 255, 255, 255, 255, 251, 251, 252, 78, 78, 150, 7, 7, 137, 7, 7, 137, 7, 7, 137, 122, 122, 169, 255, 255, 255, 255, 255, 255, 255, 255, 255, 190, 190, 209, + 7, 7, 135, 144, 144, 178, 255, 255, 255, 255, 255, 255, 255, 255, 255, 144, 144, 178, 7, 7, 132, 7, 7, 132, 208, 208, 219, 255, 255, 255, 255, 255, 255, 244, 244, 246, 36, 36, 131, 7, 7, 128, 7, 7, 128, 214, 214, 223, 255, 255, 255, 255, 255, 255, 244, 244, 246, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 151, 151, 179, 255, 255, 255, 255, 255, 255, 251, 251, 252, 44, 44, 126, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 118, 7, 7, 132, 7, 7, 153, 7, 7, 165, 7, 7, 166, 7, 7, 162, 7, 7, 159, + 7, 7, 159, 7, 7, 159, 7, 7, 156, 7, 7, 149, 7, 7, 139, 7, 7, 125, 7, 7, 116, 7, 7, 103, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 72, 7, 7, 84, 7, 7, 91, 7, 7, 99, 7, 7, 103, 7, 7, 107, + 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 216, 216, 223, 255, 255, 255, 255, 255, 255, + 252, 252, 253, 94, 94, 143, 7, 7, 139, 7, 7, 175, 7, 7, 174, 7, 7, 169, 7, 7, 165, 7, 7, 163, 7, 7, 162, 100, 100, 177, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 209, 7, 7, 159, 7, 7, 160, 216, 216, 231, 255, 255, 255, 255, 255, 255, 251, 251, 252, 78, 78, 168, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 122, 122, 180, 255, 255, 255, 255, 255, 255, 255, 255, 255, 190, 190, 213, 7, 7, 150, 7, 7, 149, 100, 100, 167, 255, 255, 255, 255, 255, 255, 255, 255, 255, 236, 236, 241, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 223, 223, 232, 255, 255, 255, + 255, 255, 255, 249, 249, 250, 7, 7, 145, 7, 7, 144, 7, 7, 144, 214, 214, 226, 255, 255, 255, 255, 255, 255, 244, 244, 247, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 151, 151, 188, 255, 255, 255, 255, 255, 255, 251, 251, 252, 44, 44, 148, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 131, + 7, 7, 127, 7, 7, 123, 7, 7, 120, 7, 7, 114, 7, 7, 109, 7, 7, 105, 7, 7, 105, 7, 7, 110, 7, 7, 120, 7, 7, 128, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 164, 7, 7, 192, 7, 7, 186, 7, 7, 182, 7, 7, 180, 7, 7, 180, 7, 7, 180, + 7, 7, 180, 7, 7, 179, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, + 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 100, 100, 171, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 199, 218, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 142, 252, 252, 253, 255, 255, 255, + 255, 255, 255, 218, 218, 228, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 234, 234, 239, 255, 255, 255, 255, 255, 255, 226, 226, 233, 7, 7, 136, 7, 7, 136, 7, 7, 136, 237, 237, 241, 255, 255, 255, 255, 255, 255, 234, 234, 239, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 251, 251, 252, 255, 255, 255, 255, 255, 255, 214, 214, 224, 7, 7, 135, 25, 25, 136, 241, 241, 244, 255, 255, 255, 255, 255, 255, 206, 206, 218, 7, 7, 132, 44, 44, 137, 248, 248, 250, 255, 255, 255, 255, 255, 255, 194, 194, 209, 7, 7, 129, 7, 7, 129, 7, 7, 128, 233, 233, 238, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 145, 7, 7, 120, 7, 7, 120, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, + 7, 7, 115, 7, 7, 128, 7, 7, 147, 7, 7, 159, 7, 7, 160, 7, 7, 156, 7, 7, 150, 7, 7, 150, 7, 7, 154, 7, 7, 143, 7, 7, 128, 7, 7, 118, 7, 7, 104, 7, 7, 72, 36, 36, 40, 222, 222, 222, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 72, + 7, 7, 84, 7, 7, 91, 7, 7, 99, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 233, 233, 237, 255, 255, 255, 255, 255, 255, 236, 236, 240, 7, 7, 119, 7, 7, 121, 7, 7, 150, 7, 7, 178, 7, 7, 173, 7, 7, 168, 7, 7, 166, 7, 7, 164, 100, 100, 178, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 210, 7, 7, 160, 7, 7, 161, + 237, 237, 243, 255, 255, 255, 255, 255, 255, 234, 234, 241, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 251, 251, 252, 255, 255, 255, 255, 255, 255, 214, 214, 227, 7, 7, 150, 7, 7, 149, 100, 100, 166, 255, 255, 255, 255, 255, 255, 255, 255, 255, 200, 200, 217, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 145, 208, 208, 223, 255, 255, 255, 255, 255, 255, 251, 251, 252, 7, 7, 145, 7, 7, 145, 7, 7, 145, 233, 233, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 95, 95, 162, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 126, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 154, 7, 7, 192, + 7, 7, 186, 7, 7, 181, 7, 7, 178, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 179, 7, 7, 178, 7, 7, 176, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 163, 7, 7, 164, 7, 7, 165, + 7, 7, 165, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 100, 100, 172, 255, 255, 255, 255, 255, 255, 255, 255, 255, 186, 186, 210, 7, 7, 148, + 7, 7, 146, 7, 7, 145, 7, 7, 143, 251, 251, 252, 255, 255, 255, 255, 255, 255, 208, 208, 221, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 232, 232, 238, 255, 255, 255, 255, 255, 255, 226, 226, 233, 7, 7, 136, 7, 7, 136, 7, 7, 136, 243, 243, 246, 255, 255, 255, 255, 255, 255, + 225, 225, 233, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 243, 243, 246, 255, 255, 255, 255, 255, 255, 225, 225, 233, 7, 7, 135, 7, 7, 134, 189, 189, 206, 255, 255, 255, 255, 255, 255, 247, 247, 249, 44, 44, 137, 150, 150, 181, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 111, 111, 159, 7, 7, 129, 7, 7, 129, 7, 7, 129, 242, 242, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 109, 109, 153, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, + 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 113, 7, 7, 114, 7, 7, 110, 7, 7, 103, 7, 7, 106, 7, 7, 136, 7, 7, 148, 7, 7, 131, 7, 7, 120, 7, 7, 106, 9, 9, 72, 37, 37, 40, 222, 222, 222, + 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 49, 7, 7, 73, 7, 7, 84, 7, 7, 91, 7, 7, 98, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 243, 243, 245, 255, 255, 255, 255, 255, 255, 225, 225, 231, 7, 7, 120, 7, 7, 119, 7, 7, 123, 7, 7, 164, 7, 7, 177, 7, 7, 172, 7, 7, 169, 7, 7, 167, 100, 100, 180, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 179, 179, 210, 7, 7, 162, 7, 7, 163, 243, 243, 247, 255, 255, 255, 255, 255, 255, 225, 225, 236, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 243, 243, 246, 255, 255, 255, 255, 255, 255, 225, 225, 235, 7, 7, 150, 7, 7, 149, 100, 100, 166, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 186, 186, 208, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 204, 204, 221, 255, 255, 255, 255, 255, 255, 251, 251, 252, 7, 7, 147, 7, 7, 147, 7, 7, 146, 242, 242, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 109, 109, 167, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 128, 7, 7, 129, 7, 7, 169, 7, 7, 190, 7, 7, 184, 7, 7, 179, 7, 7, 176, 7, 7, 176, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 178, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, + 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 100, 100, 171, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 206, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 143, 251, 251, 252, 255, 255, 255, 255, 255, 255, 204, 204, 219, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 232, 232, 238, 255, 255, 255, 255, 255, 255, 226, 226, 234, 7, 7, 136, + 7, 7, 136, 7, 7, 137, 233, 233, 238, 255, 255, 255, 255, 255, 255, 234, 234, 239, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 251, 251, 252, 255, 255, 255, 255, 255, 255, 218, 218, 228, 7, 7, 135, 7, 7, 135, 101, 101, 157, 254, 254, 254, 255, 255, 255, 255, 255, 255, + 145, 145, 178, 208, 208, 220, 255, 255, 255, 255, 255, 255, 227, 227, 233, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 234, 234, 238, 255, 255, 255, 255, 255, 255, 248, 248, 249, 232, 232, 237, 232, 232, 237, 232, 232, 237, 232, 232, 237, 232, 232, 237, 232, 232, 237, 232, 232, 237, 232, 232, 237, + 100, 100, 148, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 104, 7, 7, 101, 7, 7, 98, 7, 7, 103, 7, 7, 139, 7, 7, 136, + 7, 7, 124, 7, 7, 109, 10, 10, 74, 46, 46, 49, 229, 229, 230, 255, 255, 255, 222, 222, 222, 37, 37, 39, 10, 10, 48, 7, 7, 73, 7, 7, 84, 7, 7, 91, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, + 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 239, 239, 242, 255, 255, 255, 255, 255, 255, 235, 235, 239, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 135, 7, 7, 174, + 7, 7, 177, 7, 7, 172, 7, 7, 170, 100, 100, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 210, 7, 7, 162, 7, 7, 164, 233, 233, 241, 255, 255, 255, 255, 255, 255, 234, 234, 242, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 251, 251, 252, 255, 255, 255, + 255, 255, 255, 218, 218, 230, 7, 7, 150, 7, 7, 149, 100, 100, 167, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 205, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 204, 204, 221, 255, 255, 255, 255, 255, 255, 251, 251, 252, 7, 7, 148, 7, 7, 148, 7, 7, 147, 234, 234, 240, + 255, 255, 255, 255, 255, 255, 248, 248, 250, 232, 232, 239, 232, 232, 239, 232, 232, 239, 232, 232, 239, 232, 232, 239, 232, 232, 239, 232, 232, 238, 232, 232, 238, 100, 100, 163, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, + 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 137, 7, 7, 188, 7, 7, 188, 7, 7, 182, 7, 7, 178, 7, 7, 175, 7, 7, 175, 7, 7, 176, 7, 7, 177, 7, 7, 178, 7, 7, 178, 7, 7, 175, 7, 7, 171, 7, 7, 169, + 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, + 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 100, 100, 171, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 206, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 251, 251, 252, 255, 255, 255, 255, 255, 255, 204, 204, 219, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 232, 232, 238, 255, 255, 255, 255, 255, 255, 226, 226, 234, 7, 7, 137, 7, 7, 137, 7, 7, 138, 212, 212, 224, 255, 255, 255, 255, 255, 255, 251, 251, 252, 82, 82, 151, 7, 7, 137, 7, 7, 137, 7, 7, 138, 126, 126, 171, 255, 255, 255, 255, 255, 255, 255, 255, 255, 193, 193, 210, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 223, 223, 231, 255, 255, 255, 255, 255, 255, 191, 191, 208, 243, 243, 245, 255, 255, 255, 255, 255, 255, 166, 166, 191, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 216, 216, 225, 255, 255, 255, 255, 255, 255, 240, 240, 243, 18, 18, 127, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 104, + 7, 7, 102, 7, 7, 98, 7, 7, 95, 7, 7, 113, 7, 7, 139, 7, 7, 130, 7, 7, 113, 10, 10, 75, 47, 47, 50, 230, 230, 230, 255, 255, 255, 222, 222, 222, 38, 38, 39, 12, 12, 49, 7, 7, 73, 7, 7, 84, 7, 7, 91, 7, 7, 98, 7, 7, 102, 7, 7, 105, 7, 7, 109, + 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 223, 223, 229, 255, 255, 255, 255, 255, 255, 251, 251, 252, + 87, 87, 140, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 163, 7, 7, 180, 7, 7, 175, 7, 7, 173, 100, 100, 184, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 210, 7, 7, 163, 7, 7, 164, 212, 212, 229, 255, 255, 255, 255, 255, 255, 251, 251, 252, 82, 82, 170, 7, 7, 159, + 7, 7, 158, 7, 7, 157, 126, 126, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 193, 193, 214, 7, 7, 150, 7, 7, 150, 100, 100, 167, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 205, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 204, 204, 221, 255, 255, 255, 255, 255, 255, + 251, 251, 252, 7, 7, 150, 7, 7, 149, 7, 7, 149, 216, 216, 229, 255, 255, 255, 255, 255, 255, 240, 240, 244, 18, 18, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 141, 7, 7, 190, 7, 7, 185, 7, 7, 180, 7, 7, 176, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 177, + 7, 7, 178, 7, 7, 178, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, + 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 100, 100, 170, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 206, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 251, 251, 252, 255, 255, 255, 255, 255, 255, + 204, 204, 219, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 232, 232, 238, 255, 255, 255, 255, 255, 255, 226, 226, 234, 7, 7, 138, 7, 7, 138, 7, 7, 138, 152, 152, 186, 255, 255, 255, 255, 255, 255, 255, 255, 255, 211, 211, 223, 51, 51, 144, 7, 7, 138, 76, 76, 150, 226, 226, 234, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 129, 129, 171, 7, 7, 136, 7, 7, 135, 7, 7, 135, 162, 162, 190, 255, 255, 255, 255, 255, 255, 225, 225, 232, 255, 255, 255, 255, 255, 255, 249, 249, 250, 63, 63, 139, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 158, 158, 184, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 203, 203, 215, 74, 74, 140, 7, 7, 126, 7, 7, 126, 7, 7, 125, 72, 72, 137, 153, 153, 179, 125, 125, 162, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, + 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 102, 7, 7, 98, 7, 7, 94, 7, 7, 92, 7, 7, 124, 7, 7, 135, 7, 7, 117, 10, 10, 66, 47, 47, 49, 230, 230, 230, 255, 255, 255, 230, 230, 230, 48, 48, 49, 13, 13, 49, 7, 7, 73, 7, 7, 84, + 7, 7, 91, 7, 7, 98, 7, 7, 102, 7, 7, 105, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 185, 185, 200, 255, 255, 255, 255, 255, 255, 255, 255, 255, 216, 216, 224, 65, 65, 131, 7, 7, 120, 7, 7, 119, 98, 98, 172, 197, 197, 226, 111, 111, 191, 7, 7, 174, 100, 100, 184, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 211, 7, 7, 163, 7, 7, 163, 152, 152, 199, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 211, 211, 227, 51, 51, 163, 7, 7, 158, 76, 76, 166, 226, 226, 236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 129, 129, 180, 7, 7, 151, 7, 7, 151, 100, 100, 168, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 206, 7, 7, 149, 7, 7, 149, + 7, 7, 150, 7, 7, 151, 204, 204, 222, 255, 255, 255, 255, 255, 255, 251, 251, 252, 7, 7, 151, 7, 7, 151, 7, 7, 151, 158, 158, 194, 255, 255, 255, 255, 255, 255, 255, 255, 255, 203, 203, 219, 74, 74, 157, 7, 7, 146, 7, 7, 145, 7, 7, 144, 72, 72, 154, 153, 153, 188, 125, 125, 174, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 137, 7, 7, 188, 7, 7, 185, 7, 7, 179, + 7, 7, 175, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 177, 7, 7, 173, 7, 7, 170, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 165, 7, 7, 166, 7, 7, 166, + 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 100, 100, 170, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 205, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 144, 251, 251, 252, 255, 255, 255, 255, 255, 255, 204, 204, 219, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 232, 232, 238, 255, 255, 255, 255, 255, 255, 226, 226, 234, 7, 7, 139, 7, 7, 139, 7, 7, 140, 25, 25, 141, 223, 223, 231, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 251, 251, 252, 238, 238, 242, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 214, 225, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 54, 54, 142, 248, 248, 250, 255, 255, 255, 254, 254, 254, 255, 255, 255, 255, 255, 255, 205, 205, 217, 7, 7, 131, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 41, 41, 132, 227, 227, 233, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 252, 239, 239, 242, 237, 237, 240, 246, 246, 248, 254, 254, 254, 255, 255, 255, 171, 171, 191, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 116, + 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 102, 7, 7, 99, 7, 7, 94, 7, 7, 89, 7, 7, 86, 7, 7, 94, 7, 7, 82, 10, 10, 43, 47, 47, 48, 230, 230, 230, 255, 255, 255, + 230, 230, 230, 48, 48, 49, 13, 13, 49, 7, 7, 73, 7, 7, 84, 7, 7, 91, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 85, 85, 139, 248, 248, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 252, 236, 236, 240, 242, 242, 244, 255, 255, 255, 255, 255, 255, 121, 121, 195, 7, 7, 175, 100, 100, 186, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 179, 179, 211, 7, 7, 164, 7, 7, 164, 25, 25, 165, 223, 223, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251, 251, 252, 238, 238, 244, 252, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 214, 228, 7, 7, 152, 7, 7, 152, 7, 7, 152, 100, 100, 170, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 179, 179, 206, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 204, 204, 222, 255, 255, 255, 255, 255, 255, 251, 251, 252, 7, 7, 152, 7, 7, 152, 7, 7, 152, 41, 41, 154, 227, 227, 236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 252, 252, 239, 239, 243, + 237, 237, 242, 246, 246, 248, 254, 254, 254, 255, 255, 255, 171, 171, 198, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, + 7, 7, 128, 7, 7, 133, 7, 7, 184, 7, 7, 184, 7, 7, 178, 7, 7, 175, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 177, 7, 7, 179, 7, 7, 180, 7, 7, 178, 7, 7, 174, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, + 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 100, 100, 169, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 179, 179, 205, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 251, 251, 252, 255, 255, 255, 255, 255, 255, 204, 204, 219, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 232, 232, 238, 255, 255, 255, 255, 255, 255, 226, 226, 234, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 140, 82, 82, 154, 226, 226, 234, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 222, 222, 230, 67, 67, 147, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 202, 202, 216, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 132, 132, 170, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 83, 83, 143, 225, 225, 232, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 171, 171, 191, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 99, 7, 7, 94, 7, 7, 89, 7, 7, 81, 7, 7, 74, + 7, 7, 64, 10, 10, 41, 47, 47, 48, 230, 230, 230, 255, 255, 255, 230, 230, 230, 48, 48, 49, 13, 13, 49, 7, 7, 73, 7, 7, 84, 7, 7, 91, 7, 7, 99, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 145, 145, 172, 249, 249, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 121, 121, 195, 7, 7, 176, 100, 100, 187, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 212, 7, 7, 165, 7, 7, 165, 7, 7, 165, 82, 82, 175, 226, 226, 237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 222, 222, 233, 67, 67, 161, + 7, 7, 153, 7, 7, 153, 7, 7, 154, 100, 100, 171, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 207, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 153, 204, 204, 222, 255, 255, 255, 255, 255, 255, 251, 251, 252, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 83, 83, 163, + 225, 225, 234, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 171, 171, 198, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, + 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 130, 7, 7, 178, 7, 7, 185, 7, 7, 179, 7, 7, 176, 7, 7, 176, 7, 7, 177, 7, 7, 178, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 178, 7, 7, 175, 7, 7, 173, 7, 7, 171, + 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 166, 7, 7, 168, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 170, 7, 7, 171, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 164, 7, 7, 160, 7, 7, 157, + 7, 7, 155, 7, 7, 154, 7, 7, 153, 100, 100, 169, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 205, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 251, 251, 252, 255, 255, 255, 255, 255, 255, 204, 204, 219, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 232, 232, 238, + 255, 255, 255, 255, 255, 255, 226, 226, 234, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 31, 31, 142, 165, 165, 194, 223, 223, 231, 244, 244, 246, 252, 252, 252, 244, 244, 247, 219, 219, 229, 159, 159, 190, 25, 25, 139, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 126, 126, 169, 255, 255, 255, 255, 255, 255, 255, 255, 255, 236, 236, 240, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 18, 18, 126, 158, 158, 183, 215, 215, 223, 240, 240, 243, 251, 251, 252, 251, 251, 252, + 242, 242, 244, 217, 217, 225, 159, 159, 183, 54, 54, 130, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 105, 7, 7, 103, + 7, 7, 99, 7, 7, 95, 7, 7, 90, 7, 7, 82, 7, 7, 74, 7, 7, 64, 10, 10, 42, 47, 47, 48, 230, 230, 230, 255, 255, 255, 230, 230, 230, 48, 48, 49, 13, 13, 48, 7, 7, 73, 7, 7, 85, 7, 7, 92, 7, 7, 99, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, + 7, 7, 114, 7, 7, 115, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 98, 98, 146, 196, 196, 209, 234, 234, 238, + 249, 249, 250, 253, 253, 253, 246, 246, 248, 225, 225, 237, 170, 170, 214, 36, 36, 179, 7, 7, 176, 100, 100, 188, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 213, 7, 7, 168, 7, 7, 168, 7, 7, 168, 7, 7, 168, 31, 31, 167, 165, 165, 204, 223, 223, 235, 244, 244, 247, 252, 252, 253, + 244, 244, 248, 219, 219, 232, 159, 159, 198, 25, 25, 157, 7, 7, 156, 7, 7, 155, 7, 7, 156, 7, 7, 156, 100, 100, 173, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 179, 207, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 204, 204, 222, 255, 255, 255, 255, 255, 255, 251, 251, 252, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 18, 18, 150, 158, 158, 193, 215, 215, 227, 240, 240, 244, 251, 251, 252, 251, 251, 252, 242, 242, 245, 217, 217, 228, 159, 159, 192, 54, 54, 149, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 161, 7, 7, 186, 7, 7, 181, 7, 7, 179, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 181, 7, 7, 181, + 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 167, 7, 7, 169, 7, 7, 172, 7, 7, 174, 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 173, 7, 7, 176, 7, 7, 177, 7, 7, 177, + 7, 7, 174, 7, 7, 169, 7, 7, 164, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, + 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 99, 7, 7, 95, 7, 7, 90, 7, 7, 82, 7, 7, 75, 7, 7, 65, 9, 9, 42, 47, 47, 48, 230, 230, 230, 255, 255, 255, 230, 230, 230, 48, 48, 49, 12, 12, 48, 7, 7, 74, 7, 7, 85, 7, 7, 92, + 7, 7, 100, 7, 7, 104, 7, 7, 107, 7, 7, 110, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 156, 7, 7, 181, 7, 7, 177, 7, 7, 176, 7, 7, 175, 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 173, + 7, 7, 170, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 137, 7, 7, 173, 7, 7, 186, 7, 7, 186, + 7, 7, 187, 7, 7, 188, 7, 7, 187, 7, 7, 185, 7, 7, 183, 7, 7, 180, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 170, 7, 7, 173, 7, 7, 177, 7, 7, 180, 7, 7, 181, 7, 7, 179, + 7, 7, 179, 7, 7, 181, 7, 7, 185, 7, 7, 186, 7, 7, 182, 7, 7, 176, 7, 7, 170, 7, 7, 164, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, + 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 99, 7, 7, 95, 7, 7, 90, 7, 7, 82, 7, 7, 75, 7, 7, 65, 10, 10, 41, 48, 48, 48, 230, 230, 231, 255, 255, 255, 230, 230, 230, + 48, 48, 49, 12, 12, 48, 7, 7, 74, 7, 7, 86, 7, 7, 93, 7, 7, 101, 7, 7, 104, 7, 7, 108, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 139, 7, 7, 176, 7, 7, 179, 7, 7, 176, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 175, + 7, 7, 176, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 174, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, + 7, 7, 128, 7, 7, 126, 7, 7, 140, 7, 7, 169, 7, 7, 180, 7, 7, 180, 7, 7, 185, 7, 7, 193, 7, 7, 190, 7, 7, 186, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 173, 7, 7, 175, + 7, 7, 179, 7, 7, 184, 7, 7, 179, 7, 7, 180, 7, 7, 184, 7, 7, 186, 7, 7, 184, 7, 7, 174, 7, 7, 177, 7, 7, 186, 7, 7, 178, 7, 7, 170, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 106, 7, 7, 103, 7, 7, 99, 7, 7, 95, 7, 7, 90, 7, 7, 82, 7, 7, 76, 7, 7, 66, + 12, 12, 42, 55, 55, 56, 237, 237, 237, 255, 255, 255, 231, 231, 231, 49, 49, 49, 13, 13, 48, 7, 7, 75, 7, 7, 87, 7, 7, 94, 7, 7, 101, 7, 7, 105, 7, 7, 108, 7, 7, 111, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 121, 7, 7, 152, 7, 7, 181, + 7, 7, 178, 7, 7, 176, 7, 7, 176, 7, 7, 177, 7, 7, 179, 7, 7, 182, 7, 7, 185, 7, 7, 185, 7, 7, 183, 7, 7, 184, 7, 7, 181, 7, 7, 176, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, + 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, + 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, + 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 130, 7, 7, 133, 7, 7, 132, 7, 7, 139, 7, 7, 164, 7, 7, 187, 7, 7, 192, 7, 7, 188, 7, 7, 187, 7, 7, 183, 7, 7, 181, 7, 7, 181, 7, 7, 185, + 7, 7, 184, 7, 7, 180, 7, 7, 178, 7, 7, 178, 7, 7, 182, 7, 7, 182, 7, 7, 158, 7, 7, 136, 7, 7, 136, 7, 7, 149, 7, 7, 156, 7, 7, 146, 7, 7, 130, 7, 7, 141, 7, 7, 181, 7, 7, 179, 7, 7, 170, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 99, + 7, 7, 95, 7, 7, 90, 7, 7, 82, 7, 7, 76, 7, 7, 66, 12, 12, 42, 58, 58, 59, 239, 239, 239, 255, 255, 255, 239, 239, 239, 59, 59, 59, 13, 13, 48, 7, 7, 76, 7, 7, 87, 7, 7, 94, 7, 7, 102, 7, 7, 106, 7, 7, 109, 7, 7, 112, 7, 7, 114, 7, 7, 115, + 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 121, 7, 7, 161, 7, 7, 182, 7, 7, 179, 7, 7, 179, 7, 7, 181, 7, 7, 185, 7, 7, 178, 7, 7, 154, 7, 7, 138, 7, 7, 131, 7, 7, 139, 7, 7, 164, 7, 7, 177, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 177, + 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, + 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 127, + 9, 9, 122, 8, 8, 119, 9, 9, 120, 7, 7, 127, 7, 7, 130, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 127, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 136, 7, 7, 154, 7, 7, 160, + 7, 7, 150, 7, 7, 135, 7, 7, 131, 7, 7, 131, 7, 7, 138, 7, 7, 153, 7, 7, 172, 7, 7, 183, 7, 7, 183, 7, 7, 172, 7, 7, 142, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 131, 7, 7, 174, 7, 7, 180, + 7, 7, 171, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, + 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 99, 7, 7, 95, 7, 7, 91, 7, 7, 83, 7, 7, 76, 7, 7, 66, 11, 11, 42, 58, 58, 59, 239, 239, 239, 255, 255, 255, 239, 239, 239, 59, 59, 59, 13, 13, 48, 7, 7, 77, 7, 7, 88, 7, 7, 95, 7, 7, 102, + 7, 7, 106, 7, 7, 109, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 133, 7, 7, 177, 7, 7, 182, 7, 7, 182, 7, 7, 185, 7, 7, 169, 7, 7, 135, 7, 7, 121, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 124, + 7, 7, 134, 7, 7, 143, 7, 7, 149, 7, 7, 160, 7, 7, 171, 7, 7, 180, 7, 7, 176, 7, 7, 171, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 157, + 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, + 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 9, 9, 130, 11, 11, 128, 12, 12, 123, 11, 11, 119, 10, 10, 115, 8, 8, 114, 8, 8, 119, 7, 7, 127, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 127, 7, 7, 128, 7, 7, 127, 7, 7, 127, + 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 126, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 126, 7, 7, 132, 7, 7, 141, 7, 7, 141, 7, 7, 132, 7, 7, 126, 7, 7, 125, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 129, 7, 7, 171, 7, 7, 179, 7, 7, 170, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, + 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 99, 7, 7, 95, 7, 7, 91, 7, 7, 83, 7, 7, 76, 7, 7, 66, 11, 11, 41, 58, 58, 58, 239, 239, 239, 255, 255, 255, 239, 239, 239, 58, 58, 59, + 13, 13, 48, 7, 7, 77, 7, 7, 89, 7, 7, 96, 7, 7, 103, 7, 7, 107, 7, 7, 109, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 119, 7, 7, 158, 7, 7, 184, 7, 7, 185, 7, 7, 169, 7, 7, 132, 7, 7, 119, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 122, 7, 7, 130, 7, 7, 163, 7, 7, 180, 7, 7, 174, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 163, 7, 7, 160, + 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 133, 9, 9, 133, 12, 12, 131, 13, 13, 130, 14, 14, 129, 12, 12, 127, 10, 10, 123, 8, 8, 118, 8, 8, 123, 7, 7, 130, 7, 7, 129, 7, 7, 129, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 127, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 129, 7, 7, 169, 7, 7, 178, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 120, 7, 7, 120, 7, 7, 119, + 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 106, 7, 7, 104, 7, 7, 103, 7, 7, 99, 7, 7, 96, 7, 7, 91, 7, 7, 83, 7, 7, 76, 7, 7, 66, 11, 11, 41, + 58, 58, 58, 239, 239, 239, 255, 255, 255, 239, 239, 239, 58, 58, 59, 12, 12, 45, 7, 7, 78, 7, 7, 90, 7, 7, 96, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 125, + 7, 7, 148, 7, 7, 149, 7, 7, 125, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 135, 7, 7, 180, 7, 7, 179, 7, 7, 176, 7, 7, 175, 7, 7, 175, + 7, 7, 175, 7, 7, 173, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, + 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, + 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 8, 8, 134, 8, 8, 134, 8, 8, 133, 7, 7, 133, 8, 8, 134, 10, 10, 132, + 12, 12, 129, 9, 9, 121, 8, 8, 120, 7, 7, 129, 7, 7, 130, 7, 7, 131, 7, 7, 130, 7, 7, 131, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 127, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 129, 7, 7, 169, 7, 7, 178, 7, 7, 169, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, + 7, 7, 157, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 100, 7, 7, 96, + 7, 7, 91, 7, 7, 83, 7, 7, 76, 7, 7, 66, 10, 10, 39, 58, 58, 58, 239, 239, 239, 255, 255, 255, 247, 247, 247, 69, 69, 69, 12, 12, 45, 7, 7, 77, 7, 7, 89, 7, 7, 96, 7, 7, 103, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, + 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 122, + 7, 7, 157, 7, 7, 182, 7, 7, 184, 7, 7, 183, 7, 7, 182, 7, 7, 182, 7, 7, 177, 7, 7, 171, 7, 7, 167, 7, 7, 163, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 158, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 147, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 131, 8, 8, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 9, 9, 134, + 10, 10, 134, 8, 8, 134, 8, 8, 135, 7, 7, 135, 7, 7, 134, 8, 8, 133, 10, 10, 130, 9, 9, 124, 8, 8, 122, 7, 7, 131, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 162, 7, 7, 178, 7, 7, 168, + 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 150, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, + 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, + 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 100, 7, 7, 96, 7, 7, 91, 7, 7, 83, 7, 7, 76, 7, 7, 66, 11, 11, 39, 68, 68, 69, 247, 247, 247, 255, 255, 255, 248, 248, 248, 70, 70, 70, 11, 11, 43, 7, 7, 77, 7, 7, 89, 7, 7, 96, 7, 7, 103, 7, 7, 107, + 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 123, + 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 125, 7, 7, 144, 7, 7, 159, 7, 7, 175, 7, 7, 186, 7, 7, 188, 7, 7, 181, 7, 7, 173, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, + 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 131, 7, 7, 130, 8, 8, 132, 8, 8, 132, 8, 8, 133, 8, 8, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 129, 8, 8, 132, 8, 8, 133, 8, 8, 134, 8, 8, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 8, 8, 134, 7, 7, 133, 9, 9, 132, 8, 8, 126, 7, 7, 128, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 124, 7, 7, 157, 7, 7, 178, 7, 7, 168, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 112, + 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 100, 7, 7, 96, 7, 7, 91, 7, 7, 83, 7, 7, 76, 7, 7, 66, 9, 9, 36, 69, 69, 69, 248, 248, 248, 255, 255, 255, 248, 248, 248, 69, 69, 69, 9, 9, 41, + 7, 7, 77, 7, 7, 89, 7, 7, 96, 7, 7, 103, 7, 7, 107, 7, 7, 109, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, + 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 128, 7, 7, 149, 7, 7, 186, 7, 7, 182, 7, 7, 174, 7, 7, 169, 7, 7, 166, 7, 7, 164, + 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 8, 8, 131, 8, 8, 131, 15, 15, 132, 18, 18, 132, 13, 13, 132, 11, 11, 132, 9, 9, 128, 9, 9, 124, 9, 9, 130, 8, 8, 132, 8, 8, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 8, 8, 135, 7, 7, 133, 8, 8, 131, 7, 7, 129, 7, 7, 132, + 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 155, 7, 7, 177, 7, 7, 167, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, + 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, + 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 100, 7, 7, 96, 7, 7, 91, 7, 7, 83, 7, 7, 76, 7, 7, 66, 9, 9, 35, 75, 75, 75, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 79, 79, 79, 9, 9, 40, 7, 7, 77, 7, 7, 88, 7, 7, 95, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, + 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 126, 7, 7, 162, 7, 7, 187, + 7, 7, 181, 7, 7, 174, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 132, 7, 7, 133, 7, 7, 133, 17, 17, 133, 31, 31, 134, 26, 26, 132, 18, 18, 130, 15, 15, 131, 11, 11, 123, 11, 11, 125, 9, 9, 130, 12, 12, 132, 10, 10, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 8, 8, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 157, 7, 7, 176, 7, 7, 166, 7, 7, 161, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, + 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, + 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 100, 7, 7, 96, 7, 7, 92, + 7, 7, 83, 7, 7, 77, 7, 7, 66, 8, 8, 33, 79, 79, 79, 255, 255, 255, 255, 255, 255, 255, 255, 255, 79, 79, 79, 7, 7, 37, 7, 7, 76, 7, 7, 87, 7, 7, 94, 7, 7, 102, 7, 7, 105, 7, 7, 108, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, + 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, + 7, 7, 119, 7, 7, 124, 7, 7, 163, 7, 7, 186, 7, 7, 184, 7, 7, 178, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 158, + 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 134, 8, 8, 134, 19, 19, 134, 19, 19, 133, 11, 11, 129, 16, 16, 130, 10, 10, 127, 12, 12, 124, 10, 10, 129, 19, 19, 132, 19, 19, 134, 9, 9, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, + 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 162, 7, 7, 175, 7, 7, 165, 7, 7, 160, + 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, + 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, + 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 107, + 7, 7, 105, 7, 7, 103, 7, 7, 100, 7, 7, 96, 7, 7, 92, 7, 7, 84, 7, 7, 77, 7, 7, 66, 7, 7, 31, 81, 81, 81, 255, 255, 255, 255, 255, 255, 255, 255, 255, 85, 85, 85, 7, 7, 35, 7, 7, 75, 7, 7, 87, 7, 7, 93, 7, 7, 101, 7, 7, 104, 7, 7, 107, + 7, 7, 109, 7, 7, 110, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 147, 7, 7, 182, 7, 7, 180, 7, 7, 177, 7, 7, 174, 7, 7, 171, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 169, 7, 7, 171, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, + 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 131, 7, 7, 132, 7, 7, 134, 11, 11, 134, 10, 10, 134, 7, 7, 132, 10, 10, 131, 11, 11, 131, 15, 15, 128, + 16, 16, 129, 15, 15, 132, 17, 17, 133, 9, 9, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 132, 8, 8, 131, + 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 129, 7, 7, 169, 7, 7, 173, 7, 7, 165, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, + 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 106, 7, 7, 103, 7, 7, 101, 7, 7, 97, 7, 7, 92, 7, 7, 84, 7, 7, 77, 7, 7, 66, 7, 7, 30, 89, 89, 89, 255, 255, 255, 255, 255, 255, 255, 255, 255, 89, 89, 89, 7, 7, 34, 7, 7, 75, + 7, 7, 86, 7, 7, 93, 7, 7, 100, 7, 7, 103, 7, 7, 106, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, + 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 124, 7, 7, 168, 7, 7, 178, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 169, + 7, 7, 171, 7, 7, 173, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 129, 7, 7, 130, 10, 10, 131, 9, 9, 133, + 7, 7, 133, 8, 8, 133, 9, 9, 133, 10, 10, 133, 11, 11, 132, 9, 9, 132, 11, 11, 133, 9, 9, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 10, 10, 132, 12, 12, 133, 10, 10, 131, 8, 8, 129, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 142, 7, 7, 177, 7, 7, 171, 7, 7, 164, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, + 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 106, 7, 7, 104, 7, 7, 101, 7, 7, 97, 7, 7, 93, 7, 7, 85, 7, 7, 78, 7, 7, 66, 7, 7, 27, 89, 89, 89, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 89, 89, 89, 7, 7, 31, 7, 7, 74, 7, 7, 85, 7, 7, 91, 7, 7, 99, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, + 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 128, 7, 7, 171, 7, 7, 173, 7, 7, 169, 7, 7, 168, 7, 7, 167, + 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 168, 7, 7, 170, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 125, 7, 7, 126, 10, 10, 129, 8, 8, 132, 7, 7, 133, 8, 8, 133, 7, 7, 134, 7, 7, 134, 8, 8, 134, 9, 9, 134, 9, 9, 134, 8, 8, 135, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 14, 14, 134, 16, 16, 132, 12, 12, 130, 10, 10, 129, 7, 7, 127, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 159, 7, 7, 177, 7, 7, 169, 7, 7, 163, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 104, 7, 7, 102, 7, 7, 98, 7, 7, 93, 7, 7, 85, + 7, 7, 78, 7, 7, 66, 7, 7, 26, 104, 104, 104, 255, 255, 255, 255, 255, 255, 255, 255, 255, 102, 102, 102, 7, 7, 29, 7, 7, 73, 7, 7, 84, 7, 7, 91, 7, 7, 98, 7, 7, 102, 7, 7, 105, 7, 7, 107, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 114, + 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 128, + 7, 7, 172, 7, 7, 172, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 168, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 163, 7, 7, 162, + 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 8, 8, 120, 8, 8, 122, 8, 8, 129, 8, 8, 132, 8, 8, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 10, 10, 134, 10, 10, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 9, 9, 134, 8, 8, 131, 11, 11, 130, 8, 8, 127, 8, 8, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 126, 7, 7, 173, 7, 7, 175, 7, 7, 168, 7, 7, 163, 7, 7, 160, 7, 7, 159, + 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, + 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, + 7, 7, 105, 7, 7, 102, 7, 7, 98, 7, 7, 94, 7, 7, 86, 7, 7, 78, 7, 7, 67, 7, 7, 25, 106, 106, 106, 255, 255, 255, 255, 255, 255, 255, 255, 255, 106, 106, 106, 7, 7, 25, 7, 7, 72, 7, 7, 83, 7, 7, 90, 7, 7, 98, 7, 7, 101, 7, 7, 104, 7, 7, 107, + 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 126, 7, 7, 170, 7, 7, 172, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 161, + 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 8, 8, 117, 8, 8, 125, 8, 8, 131, 10, 10, 134, 9, 9, 133, 8, 8, 133, 8, 8, 134, 8, 8, 133, 9, 9, 134, 8, 8, 134, + 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 131, 9, 9, 129, 9, 9, 127, + 8, 8, 127, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 131, 7, 7, 178, + 7, 7, 174, 7, 7, 167, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, + 7, 7, 112, 7, 7, 112, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 105, 7, 7, 102, 7, 7, 98, 7, 7, 94, 7, 7, 86, 7, 7, 78, 7, 7, 66, 7, 7, 21, 106, 106, 106, 255, 255, 255, 255, 255, 255, 255, 255, 255, 134, 134, 134, 9, 9, 23, 7, 7, 71, 7, 7, 82, + 7, 7, 90, 7, 7, 97, 7, 7, 101, 7, 7, 104, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, + 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 124, 7, 7, 166, 7, 7, 172, 7, 7, 166, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, + 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 165, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 8, 8, 123, 8, 8, 129, 12, 12, 134, 11, 11, 134, 8, 8, 134, + 9, 9, 134, 10, 10, 132, 11, 11, 133, 10, 10, 133, 8, 8, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 131, 8, 8, 132, 7, 7, 133, + 7, 7, 133, 7, 7, 134, 7, 7, 131, 8, 8, 129, 8, 8, 127, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 135, 7, 7, 179, 7, 7, 174, 7, 7, 167, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, + 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 118, 7, 7, 118, + 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 106, 7, 7, 103, 7, 7, 99, 7, 7, 94, 7, 7, 86, 7, 7, 78, 7, 7, 66, 7, 7, 20, 133, 133, 133, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 145, 145, 145, 11, 11, 20, 7, 7, 69, 7, 7, 81, 7, 7, 89, 7, 7, 96, 7, 7, 100, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, + 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 122, 7, 7, 163, 7, 7, 173, 7, 7, 167, 7, 7, 164, 7, 7, 163, 7, 7, 163, + 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 161, 7, 7, 163, 7, 7, 166, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 8, 8, 127, 10, 10, 132, 10, 10, 134, 8, 8, 134, 8, 8, 134, 10, 10, 134, 13, 13, 133, 15, 15, 133, 14, 14, 133, 9, 9, 133, 8, 8, 133, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 134, 7, 7, 133, 7, 7, 134, 8, 8, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 134, 7, 7, 132, 7, 7, 131, 8, 8, 132, 8, 8, 132, 8, 8, 133, 8, 8, 133, 7, 7, 131, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 143, 7, 7, 181, 7, 7, 173, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, + 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, + 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 123, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 103, 7, 7, 99, 7, 7, 94, 7, 7, 85, 7, 7, 77, + 7, 7, 65, 8, 8, 18, 144, 144, 144, 255, 255, 255, 255, 255, 255, 255, 255, 255, 158, 158, 158, 13, 13, 18, 7, 7, 68, 7, 7, 81, 7, 7, 88, 7, 7, 95, 7, 7, 100, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 114, 7, 7, 115, + 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 122, 7, 7, 164, + 7, 7, 173, 7, 7, 167, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 161, 7, 7, 164, 7, 7, 167, 7, 7, 169, 7, 7, 169, 7, 7, 168, + 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, + 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 132, 7, 7, 128, 8, 8, 132, 7, 7, 134, 7, 7, 134, 8, 8, 134, 10, 10, 134, 17, 17, 134, 23, 23, 134, 21, 21, 133, 14, 14, 134, 9, 9, 131, 7, 7, 131, 7, 7, 133, 8, 8, 133, 8, 8, 133, 8, 8, 131, + 9, 9, 132, 8, 8, 133, 8, 8, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 132, 8, 8, 132, 14, 14, 132, 17, 17, 132, 13, 13, 131, 10, 10, 130, 8, 8, 126, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 155, 7, 7, 180, 7, 7, 173, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 162, + 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 107, + 7, 7, 103, 7, 7, 99, 7, 7, 93, 7, 7, 85, 7, 7, 76, 7, 7, 64, 11, 11, 16, 159, 159, 159, 255, 255, 255, 255, 255, 255, 255, 255, 255, 173, 173, 173, 12, 12, 14, 7, 7, 66, 7, 7, 80, 7, 7, 88, 7, 7, 94, 7, 7, 99, 7, 7, 103, 7, 7, 106, 7, 7, 109, + 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 132, 7, 7, 172, 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 162, + 7, 7, 165, 7, 7, 168, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, + 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 132, 8, 8, 134, 7, 7, 133, 8, 8, 134, 12, 12, 134, 22, 22, 134, 30, 30, 134, 32, 32, 135, 22, 22, 134, 12, 12, 132, + 9, 9, 132, 9, 9, 132, 12, 12, 133, 14, 14, 132, 14, 14, 130, 13, 13, 132, 12, 12, 132, 9, 9, 133, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 13, 13, 133, 26, 26, 134, 24, 24, 132, 16, 16, 130, 12, 12, 129, 8, 8, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 124, 7, 7, 166, 7, 7, 179, 7, 7, 173, + 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, + 7, 7, 115, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 104, 7, 7, 99, 7, 7, 93, 7, 7, 85, 7, 7, 76, 7, 7, 62, 11, 11, 13, 182, 182, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 201, 201, 201, 10, 10, 11, 7, 7, 64, 7, 7, 79, 7, 7, 87, + 7, 7, 94, 7, 7, 99, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, + 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 124, 7, 7, 160, 7, 7, 176, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, + 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 169, 7, 7, 171, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 130, 7, 7, 130, 8, 8, 133, 10, 10, 132, 9, 9, 132, 8, 8, 133, 14, 14, 134, + 27, 27, 135, 39, 39, 136, 41, 41, 136, 32, 32, 134, 20, 20, 134, 13, 13, 133, 18, 18, 134, 22, 22, 134, 22, 22, 133, 22, 22, 132, 19, 19, 132, 18, 18, 133, 17, 17, 133, 11, 11, 133, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 13, 13, 134, 15, 15, 133, 10, 10, 130, + 13, 13, 129, 9, 9, 126, 8, 8, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 129, 7, 7, 128, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 125, 7, 7, 170, 7, 7, 180, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 148, + 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 118, + 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 107, 7, 7, 104, 7, 7, 99, 7, 7, 93, 7, 7, 84, 7, 7, 74, 7, 7, 59, 8, 8, 9, 201, 201, 201, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 216, 216, 216, 7, 7, 7, 7, 7, 62, 7, 7, 78, 7, 7, 86, 7, 7, 93, 7, 7, 98, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, + 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 121, 7, 7, 158, 7, 7, 175, 7, 7, 171, 7, 7, 166, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 163, 7, 7, 165, 7, 7, 167, 7, 7, 169, 7, 7, 172, 7, 7, 174, 7, 7, 175, 7, 7, 176, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 159, + 7, 7, 157, 7, 7, 155, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 130, 8, 8, 131, + 13, 13, 131, 13, 13, 131, 10, 10, 133, 10, 10, 133, 16, 16, 134, 28, 28, 135, 39, 39, 136, 43, 43, 137, 37, 37, 136, 31, 31, 135, 24, 24, 135, 24, 24, 134, 24, 24, 134, 24, 24, 134, 24, 24, 134, 23, 23, 134, 27, 27, 134, 20, 20, 133, 12, 12, 133, 9, 9, 133, 7, 7, 133, + 7, 7, 134, 8, 8, 134, 8, 8, 134, 7, 7, 133, 9, 9, 132, 10, 10, 131, 11, 11, 126, 9, 9, 126, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 135, + 7, 7, 173, 7, 7, 171, 7, 7, 137, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 157, 7, 7, 182, 7, 7, 179, 7, 7, 178, 7, 7, 176, 7, 7, 176, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 157, + 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, + 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, + 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 107, 7, 7, 104, 7, 7, 99, 7, 7, 92, 7, 7, 83, 7, 7, 73, 7, 7, 56, + 7, 7, 7, 219, 219, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, 232, 232, 232, 7, 7, 7, 7, 7, 57, 7, 7, 77, 7, 7, 85, 7, 7, 93, 7, 7, 98, 7, 7, 103, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 111, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, + 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 119, 7, 7, 150, 7, 7, 176, 7, 7, 171, 7, 7, 166, 7, 7, 163, + 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 169, 7, 7, 172, 7, 7, 176, 7, 7, 179, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 182, + 7, 7, 179, 7, 7, 173, 7, 7, 168, 7, 7, 164, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, + 7, 7, 144, 7, 7, 145, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 8, 8, 132, 15, 15, 132, 15, 15, 132, 13, 13, 133, 14, 14, 134, 17, 17, 133, 21, 21, 135, 28, 28, 135, 32, 32, 136, 31, 31, 136, 30, 30, 135, 25, 25, 135, 22, 22, 135, 19, 19, 134, 18, 18, 135, 15, 15, 134, 16, 16, 134, + 14, 14, 134, 8, 8, 132, 9, 9, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 8, 8, 134, 8, 8, 133, 9, 9, 131, 8, 8, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, + 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 157, 7, 7, 189, 7, 7, 189, 7, 7, 157, 7, 7, 121, 7, 7, 120, 7, 7, 121, 7, 7, 120, 7, 7, 129, 7, 7, 155, 7, 7, 167, 7, 7, 174, 7, 7, 178, 7, 7, 183, 7, 7, 181, 7, 7, 177, 7, 7, 173, + 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, 7, 7, 149, + 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, + 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 103, + 7, 7, 98, 7, 7, 91, 7, 7, 82, 7, 7, 72, 7, 7, 51, 7, 7, 7, 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 241, 241, 13, 13, 13, 7, 7, 53, 7, 7, 76, 7, 7, 85, 7, 7, 92, 7, 7, 98, 7, 7, 102, 7, 7, 106, 7, 7, 108, 7, 7, 109, + 7, 7, 111, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 142, + 7, 7, 176, 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 169, 7, 7, 174, 7, 7, 177, 7, 7, 165, + 7, 7, 152, 7, 7, 143, 7, 7, 139, 7, 7, 135, 7, 7, 139, 7, 7, 169, 7, 7, 179, 7, 7, 172, 7, 7, 167, 7, 7, 163, 7, 7, 160, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 134, 13, 13, 133, 13, 13, 133, 12, 12, 134, 14, 14, 134, 12, 12, 134, 13, 13, 134, 15, 15, 134, 18, 18, 134, 15, 15, 134, 13, 13, 134, 12, 12, 134, + 12, 12, 135, 12, 12, 134, 10, 10, 134, 9, 9, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 8, 8, 133, 7, 7, 133, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 161, 7, 7, 188, 7, 7, 187, 7, 7, 148, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 123, + 7, 7, 128, 7, 7, 151, 7, 7, 180, 7, 7, 179, 7, 7, 175, 7, 7, 171, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, + 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, + 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 106, 7, 7, 103, 7, 7, 97, 7, 7, 90, 7, 7, 81, 7, 7, 71, 7, 7, 47, 21, 21, 21, 242, 242, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 243, 243, 243, 25, 25, 25, 7, 7, 46, 7, 7, 75, 7, 7, 84, 7, 7, 91, + 7, 7, 97, 7, 7, 102, 7, 7, 105, 7, 7, 108, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 122, + 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, + 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 126, 7, 7, 166, 7, 7, 175, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 166, + 7, 7, 168, 7, 7, 173, 7, 7, 172, 7, 7, 143, 7, 7, 123, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 133, 7, 7, 166, 7, 7, 177, 7, 7, 170, 7, 7, 165, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, + 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, + 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 9, 9, 133, 9, 9, 133, 9, 9, 133, 8, 8, 134, 8, 8, 134, 8, 8, 134, + 8, 8, 134, 9, 9, 134, 8, 8, 134, 8, 8, 134, 8, 8, 134, 8, 8, 133, 8, 8, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 131, + 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 143, 7, 7, 182, 7, 7, 172, 7, 7, 130, 7, 7, 119, 7, 7, 120, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 124, 7, 7, 165, 7, 7, 181, 7, 7, 175, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, + 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 106, 7, 7, 102, 7, 7, 97, 7, 7, 89, 7, 7, 80, 7, 7, 69, 7, 7, 41, 25, 25, 25, 243, 243, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 248, 248, 248, + 49, 49, 49, 11, 11, 38, 7, 7, 74, 7, 7, 84, 7, 7, 91, 7, 7, 97, 7, 7, 102, 7, 7, 105, 7, 7, 108, 7, 7, 109, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 142, 7, 7, 176, 7, 7, 171, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 167, 7, 7, 168, 7, 7, 172, 7, 7, 174, 7, 7, 142, 7, 7, 119, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 136, 7, 7, 177, 7, 7, 173, 7, 7, 167, 7, 7, 162, + 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 8, 8, 134, + 8, 8, 134, 8, 8, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 8, 8, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 122, 7, 7, 138, + 7, 7, 132, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 153, 7, 7, 182, 7, 7, 175, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 165, + 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, + 7, 7, 144, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 105, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 79, 7, 7, 68, 8, 8, 34, 48, 48, 48, + 248, 248, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 85, 85, 85, 8, 8, 30, 7, 7, 73, 7, 7, 84, 7, 7, 90, 7, 7, 97, 7, 7, 101, 7, 7, 105, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, + 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 147, 7, 7, 177, 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, + 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 163, 7, 7, 165, 7, 7, 168, 7, 7, 171, 7, 7, 174, 7, 7, 176, 7, 7, 153, 7, 7, 119, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 121, 7, 7, 168, 7, 7, 175, 7, 7, 169, 7, 7, 164, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 133, 8, 8, 133, 7, 7, 133, + 8, 8, 133, 8, 8, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 9, 9, 134, 9, 9, 134, 8, 8, 133, 7, 7, 133, 7, 7, 130, 7, 7, 128, 7, 7, 127, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 118, 7, 7, 147, 7, 7, 183, 7, 7, 177, 7, 7, 173, + 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, + 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 111, 7, 7, 109, 7, 7, 105, 7, 7, 100, 7, 7, 95, + 7, 7, 87, 7, 7, 78, 7, 7, 64, 8, 8, 26, 85, 85, 85, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 120, 120, 120, 7, 7, 22, 7, 7, 69, 7, 7, 84, 7, 7, 90, 7, 7, 96, 7, 7, 101, 7, 7, 105, 7, 7, 109, 7, 7, 110, 7, 7, 111, + 7, 7, 112, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, + 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 124, 7, 7, 160, 7, 7, 176, + 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 166, 7, 7, 169, 7, 7, 173, 7, 7, 177, 7, 7, 178, 7, 7, 155, 7, 7, 123, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 122, 7, 7, 169, 7, 7, 176, 7, 7, 169, 7, 7, 164, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, + 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 8, 8, 134, 9, 9, 133, 8, 8, 133, 10, 10, 132, 9, 9, 132, 8, 8, 132, 8, 8, 133, 8, 8, 133, 10, 10, 134, 9, 9, 134, 8, 8, 133, 7, 7, 133, 8, 8, 131, 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, + 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, + 7, 7, 118, 7, 7, 134, 7, 7, 177, 7, 7, 181, 7, 7, 177, 7, 7, 174, 7, 7, 171, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, + 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, + 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 113, + 7, 7, 110, 7, 7, 108, 7, 7, 104, 7, 7, 100, 7, 7, 94, 7, 7, 85, 7, 7, 76, 7, 7, 60, 7, 7, 20, 125, 125, 125, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 150, 150, 150, 11, 11, 21, 8, 8, 66, 7, 7, 83, 7, 7, 90, 7, 7, 96, + 7, 7, 101, 7, 7, 106, 7, 7, 109, 7, 7, 110, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, + 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, + 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 125, 7, 7, 155, 7, 7, 174, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 164, 7, 7, 166, 7, 7, 169, 7, 7, 174, 7, 7, 179, 7, 7, 183, 7, 7, 153, 7, 7, 122, + 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 128, 7, 7, 174, 7, 7, 174, 7, 7, 168, 7, 7, 163, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 151, + 7, 7, 149, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 9, 9, 134, 13, 13, 134, 17, 17, 134, 16, 16, 132, 12, 12, 131, 14, 14, 133, 14, 14, 133, 10, 10, 133, 9, 9, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 131, 8, 8, 130, + 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 119, 7, 7, 143, 7, 7, 179, 7, 7, 182, 7, 7, 177, 7, 7, 173, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, + 7, 7, 157, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, + 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, + 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, + 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 103, 7, 7, 99, 7, 7, 93, 7, 7, 84, 7, 7, 75, 7, 7, 56, 10, 10, 19, 153, 153, 153, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 181, 181, 181, + 16, 16, 20, 9, 9, 61, 7, 7, 82, 7, 7, 89, 7, 7, 96, 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 118, 7, 7, 153, 7, 7, 176, 7, 7, 176, 7, 7, 175, 7, 7, 174, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 166, 7, 7, 168, 7, 7, 173, + 7, 7, 177, 7, 7, 182, 7, 7, 180, 7, 7, 125, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 138, 7, 7, 179, 7, 7, 172, 7, 7, 167, 7, 7, 163, 7, 7, 160, + 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, + 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 131, 9, 9, 132, 7, 7, 133, 7, 7, 133, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 9, 9, 134, 15, 15, 134, 21, 21, 134, 23, 23, 135, 19, 19, 134, 22, 22, 134, 16, 16, 133, 10, 10, 133, 8, 8, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 132, 7, 7, 131, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 147, 7, 7, 181, 7, 7, 183, 7, 7, 176, 7, 7, 172, 7, 7, 169, 7, 7, 168, 7, 7, 167, + 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 103, 7, 7, 99, 7, 7, 92, 7, 7, 83, 7, 7, 73, 8, 8, 53, 16, 16, 19, 181, 181, 181, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 213, 213, 213, 19, 19, 19, 7, 7, 56, 7, 7, 81, 7, 7, 89, 7, 7, 95, 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, + 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 117, 7, 7, 136, 7, 7, 156, 7, 7, 159, 7, 7, 167, 7, 7, 175, + 7, 7, 172, 7, 7, 169, 7, 7, 169, 7, 7, 172, 7, 7, 176, 7, 7, 181, 7, 7, 185, 7, 7, 178, 7, 7, 120, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 145, + 7, 7, 180, 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 133, + 7, 7, 130, 9, 9, 130, 9, 9, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 8, 8, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 12, 12, 134, 19, 19, 135, 22, 22, 135, + 18, 18, 135, 12, 12, 134, 9, 9, 133, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 133, 8, 8, 132, 7, 7, 130, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 143, 7, 7, 178, + 7, 7, 181, 7, 7, 176, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 150, + 7, 7, 150, 7, 7, 150, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 106, 7, 7, 102, 7, 7, 98, 7, 7, 91, 7, 7, 82, + 7, 7, 71, 7, 7, 47, 20, 20, 20, 222, 222, 222, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 249, 249, 22, 22, 22, 7, 7, 47, 7, 7, 79, 7, 7, 88, 7, 7, 95, 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 114, + 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, + 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 123, 7, 7, 153, 7, 7, 175, 7, 7, 173, 7, 7, 173, 7, 7, 175, 7, 7, 180, 7, 7, 184, 7, 7, 187, 7, 7, 173, 7, 7, 118, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, + 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 148, 7, 7, 180, 7, 7, 172, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, + 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, + 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 133, 8, 8, 131, 9, 9, 132, 9, 9, 132, 10, 10, 133, 9, 9, 133, 8, 8, 132, 7, 7, 133, 7, 7, 131, 7, 7, 131, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 9, 9, 135, 14, 14, 134, 17, 17, 135, 14, 14, 134, 9, 9, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 129, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, + 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, + 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 118, 7, 7, 137, 7, 7, 179, 7, 7, 180, 7, 7, 176, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 124, 7, 7, 123, + 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 111, 7, 7, 108, + 7, 7, 106, 7, 7, 102, 7, 7, 97, 7, 7, 90, 7, 7, 81, 7, 7, 70, 7, 7, 39, 27, 27, 27, 249, 249, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 40, 40, 40, 10, 10, 38, 7, 7, 78, 7, 7, 87, 7, 7, 95, 7, 7, 101, + 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, + 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 121, 7, 7, 160, 7, 7, 178, 7, 7, 177, 7, 7, 179, 7, 7, 182, 7, 7, 176, 7, 7, 167, 7, 7, 144, 7, 7, 115, 7, 7, 114, 7, 7, 115, + 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 139, 7, 7, 178, 7, 7, 174, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 155, + 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 133, 11, 11, 133, 13, 13, 134, 11, 11, 133, 9, 9, 132, 8, 8, 132, 8, 8, 133, 8, 8, 133, 9, 9, 132, 8, 8, 132, 11, 11, 133, + 10, 10, 132, 8, 8, 133, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 9, 9, 134, 11, 11, 134, 10, 10, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 133, 7, 7, 131, 7, 7, 130, 7, 7, 127, + 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 122, + 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 118, 7, 7, 167, 7, 7, 182, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 164, + 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 129, + 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, + 7, 7, 116, 7, 7, 115, 7, 7, 113, 7, 7, 110, 7, 7, 108, 7, 7, 105, 7, 7, 101, 7, 7, 96, 7, 7, 89, 7, 7, 80, 7, 7, 69, 7, 7, 33, 45, 45, 45, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 81, 81, 81, + 9, 9, 22, 7, 7, 75, 7, 7, 86, 7, 7, 94, 7, 7, 101, 7, 7, 106, 7, 7, 110, 7, 7, 112, 7, 7, 113, 7, 7, 115, 7, 7, 115, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, + 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 124, 7, 7, 156, 7, 7, 170, 7, 7, 169, 7, 7, 144, 7, 7, 122, + 7, 7, 115, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 120, 7, 7, 156, 7, 7, 175, 7, 7, 176, 7, 7, 174, 7, 7, 170, 7, 7, 168, + 7, 7, 168, 7, 7, 167, 7, 7, 165, 7, 7, 162, 7, 7, 158, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 11, 11, 134, 8, 8, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 8, 8, 132, 15, 15, 133, 16, 16, 133, 16, 16, 133, 22, 22, 134, 15, 15, 133, 9, 9, 133, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 9, 9, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, + 8, 8, 133, 8, 8, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 162, 7, 7, 181, 7, 7, 177, 7, 7, 175, 7, 7, 174, 7, 7, 173, + 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, + 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 104, 7, 7, 100, 7, 7, 95, 7, 7, 88, 7, 7, 79, 7, 7, 65, 7, 7, 19, 80, 80, 80, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 146, 146, 146, 7, 7, 13, 8, 8, 61, 7, 7, 85, 7, 7, 93, 7, 7, 100, 7, 7, 105, 7, 7, 109, 7, 7, 111, 7, 7, 113, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, + 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 114, + 7, 7, 115, 7, 7, 119, 7, 7, 118, 7, 7, 114, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 117, + 7, 7, 131, 7, 7, 146, 7, 7, 160, 7, 7, 171, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 169, 7, 7, 163, 7, 7, 159, 7, 7, 156, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, + 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 133, 7, 7, 133, 8, 8, 133, 12, 12, 133, 23, 23, 133, 28, 28, 133, 22, 22, 134, 12, 12, 133, 9, 9, 134, 8, 8, 134, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 133, 8, 8, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 117, 7, 7, 167, + 7, 7, 181, 7, 7, 177, 7, 7, 174, 7, 7, 172, 7, 7, 171, 7, 7, 171, 7, 7, 171, 7, 7, 169, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, + 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 103, 7, 7, 99, 7, 7, 93, 7, 7, 85, 7, 7, 78, 7, 7, 52, + 9, 9, 13, 149, 149, 149, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 202, 202, 202, 25, 25, 26, 8, 8, 46, 7, 7, 83, 7, 7, 90, 7, 7, 99, 7, 7, 104, 7, 7, 107, 7, 7, 110, 7, 7, 112, 7, 7, 114, 7, 7, 116, + 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, + 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 117, + 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 115, 7, 7, 118, 7, 7, 130, 7, 7, 144, 7, 7, 145, 7, 7, 143, 7, 7, 158, 7, 7, 172, 7, 7, 169, 7, 7, 163, 7, 7, 159, 7, 7, 157, 7, 7, 154, 7, 7, 152, 7, 7, 149, + 7, 7, 147, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 135, 8, 8, 133, 8, 8, 132, 9, 9, 130, 20, 20, 129, 28, 28, 131, 18, 18, 133, 11, 11, 134, 8, 8, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 132, 8, 8, 131, 15, 15, 131, 18, 18, 132, 13, 13, 131, 9, 9, 130, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, + 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 155, 7, 7, 179, 7, 7, 178, 7, 7, 176, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 158, + 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, + 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 113, 7, 7, 111, 7, 7, 108, 7, 7, 106, 7, 7, 102, + 7, 7, 97, 7, 7, 91, 7, 7, 82, 7, 7, 75, 7, 7, 39, 29, 29, 30, 209, 209, 209, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 246, 246, 246, 54, 54, 54, 7, 7, 30, 7, 7, 79, 7, 7, 88, 7, 7, 97, 7, 7, 103, + 7, 7, 106, 7, 7, 109, 7, 7, 111, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, + 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, + 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 118, 7, 7, 154, 7, 7, 174, 7, 7, 167, + 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 140, + 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 133, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 128, 7, 7, 126, 9, 9, 127, 15, 15, 129, + 12, 12, 133, 8, 8, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 8, 8, 130, 9, 9, 128, 30, 30, 129, 44, 44, 131, 30, 30, 129, 16, 16, 128, 11, 11, 127, 7, 7, 125, 7, 7, 126, 7, 7, 126, + 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, + 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 121, 7, 7, 143, 7, 7, 156, 7, 7, 172, 7, 7, 176, 7, 7, 173, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, + 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 126, + 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, + 7, 7, 113, 7, 7, 110, 7, 7, 107, 7, 7, 105, 7, 7, 101, 7, 7, 95, 7, 7, 89, 7, 7, 80, 7, 7, 70, 7, 7, 28, 61, 61, 61, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 109, 109, 109, + 10, 10, 13, 7, 7, 73, 7, 7, 86, 7, 7, 94, 7, 7, 102, 7, 7, 105, 7, 7, 109, 7, 7, 111, 7, 7, 113, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, + 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, + 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, + 7, 7, 113, 7, 7, 113, 7, 7, 130, 7, 7, 173, 7, 7, 170, 7, 7, 166, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 155, 7, 7, 151, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 132, 7, 7, 128, 17, 17, 125, 16, 16, 127, 9, 9, 132, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 129, 23, 23, 127, 54, 54, 129, 33, 33, 124, 14, 14, 123, + 17, 17, 125, 9, 9, 124, 8, 8, 124, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, + 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 122, 7, 7, 151, 7, 7, 172, 7, 7, 172, + 7, 7, 167, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 157, 7, 7, 155, + 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, + 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, + 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 110, 7, 7, 107, 7, 7, 104, 7, 7, 100, 7, 7, 94, 7, 7, 86, 7, 7, 77, 7, 7, 64, 8, 8, 11, 102, 102, 102, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 185, 185, 185, 10, 10, 10, 7, 7, 56, 7, 7, 83, 7, 7, 92, 7, 7, 100, 7, 7, 105, 7, 7, 108, 7, 7, 111, 7, 7, 113, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, + 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, + 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, + 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, + 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 121, 7, 7, 169, 7, 7, 171, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 162, 7, 7, 157, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 147, + 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, + 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 9, 9, 130, 15, 15, 126, 10, 10, 128, 8, 8, 132, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 133, + 10, 10, 129, 32, 32, 128, 22, 22, 121, 10, 10, 120, 13, 13, 125, 10, 10, 125, 11, 11, 124, 9, 9, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, + 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, + 7, 7, 113, 7, 7, 113, 7, 7, 116, 7, 7, 144, 7, 7, 171, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 162, 7, 7, 166, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, + 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, + 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, + 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 107, 7, 7, 104, 7, 7, 99, 7, 7, 93, 7, 7, 84, 7, 7, 75, 7, 7, 47, 10, 10, 10, 182, 182, 182, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 233, 233, 233, 39, 39, 39, 8, 8, 37, 7, 7, 81, 7, 7, 89, 7, 7, 99, 7, 7, 104, 7, 7, 108, 7, 7, 111, 7, 7, 114, 7, 7, 116, 7, 7, 117, + 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, + 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, + 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 121, 7, 7, 169, 7, 7, 171, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 164, 7, 7, 159, 7, 7, 155, + 7, 7, 152, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 132, + 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 8, 8, 131, 7, 7, 129, 8, 8, 130, 10, 10, 133, 8, 8, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, + 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 8, 8, 133, 13, 13, 131, 14, 14, 128, 14, 14, 126, 10, 10, 127, 10, 10, 129, 10, 10, 129, 8, 8, 127, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, + 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, + 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 118, 7, 7, 156, 7, 7, 171, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 162, 7, 7, 164, + 7, 7, 169, 7, 7, 173, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 160, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 147, 7, 7, 145, + 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, + 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 109, 7, 7, 107, 7, 7, 103, 7, 7, 98, 7, 7, 91, + 7, 7, 81, 7, 7, 72, 7, 7, 29, 40, 40, 40, 234, 234, 234, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 92, 92, 92, 7, 7, 18, 7, 7, 71, 7, 7, 86, 7, 7, 97, 7, 7, 103, + 7, 7, 109, 7, 7, 112, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 118, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 122, + 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, + 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, + 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 120, 7, 7, 167, 7, 7, 170, 7, 7, 167, + 7, 7, 166, 7, 7, 166, 7, 7, 164, 7, 7, 160, 7, 7, 156, 7, 7, 153, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 138, + 7, 7, 137, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 8, 8, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 132, 8, 8, 132, 9, 9, 132, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 133, 8, 8, 133, 9, 9, 132, 8, 8, 131, 8, 8, 131, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 127, 7, 7, 126, 7, 7, 125, 7, 7, 124, + 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, + 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 125, 7, 7, 169, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 171, 7, 7, 171, + 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 167, 7, 7, 172, 7, 7, 175, 7, 7, 175, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, 7, 7, 135, 7, 7, 132, 7, 7, 130, 7, 7, 126, 7, 7, 124, 7, 7, 123, + 7, 7, 121, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, + 7, 7, 109, 7, 7, 106, 7, 7, 102, 7, 7, 97, 7, 7, 89, 7, 7, 78, 7, 7, 62, 7, 7, 15, 107, 107, 107, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 170, 170, 170, + 7, 7, 7, 7, 7, 43, 7, 7, 83, 7, 7, 93, 7, 7, 103, 7, 7, 108, 7, 7, 112, 7, 7, 114, 7, 7, 116, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, + 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, + 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, + 7, 7, 110, 7, 7, 114, 7, 7, 153, 7, 7, 172, 7, 7, 167, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 156, 7, 7, 153, 7, 7, 151, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, + 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 130, 7, 7, 132, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 131, 7, 7, 129, 7, 7, 127, 7, 7, 125, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, + 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 131, + 7, 7, 148, 7, 7, 158, 7, 7, 157, 7, 7, 148, 7, 7, 145, 7, 7, 152, 7, 7, 167, 7, 7, 171, 7, 7, 170, 7, 7, 171, 7, 7, 175, 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 174, 7, 7, 176, 7, 7, 173, 7, 7, 168, 7, 7, 163, 7, 7, 159, 7, 7, 156, + 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 150, 7, 7, 148, 7, 7, 146, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 136, + 7, 7, 133, 7, 7, 131, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, + 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 107, 7, 7, 104, 7, 7, 101, 7, 7, 95, 7, 7, 85, 7, 7, 74, 7, 7, 36, 7, 7, 7, 183, 183, 183, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 49, 49, 49, 7, 7, 16, 7, 7, 67, 7, 7, 89, 7, 7, 100, 7, 7, 107, 7, 7, 111, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, + 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 117, 7, 7, 117, + 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 111, + 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, + 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 123, 7, 7, 167, 7, 7, 168, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 153, 7, 7, 150, 7, 7, 149, 7, 7, 148, 7, 7, 148, 7, 7, 147, + 7, 7, 146, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 127, 7, 7, 130, 7, 7, 132, 7, 7, 134, 7, 7, 133, + 7, 7, 133, 7, 7, 134, 7, 7, 133, 8, 8, 133, 8, 8, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, + 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 111, 7, 7, 111, 7, 7, 111, + 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 111, 7, 7, 114, 7, 7, 114, 7, 7, 111, 7, 7, 110, 7, 7, 112, 7, 7, 124, 7, 7, 145, 7, 7, 160, 7, 7, 168, 7, 7, 169, 7, 7, 168, 7, 7, 172, 7, 7, 174, 7, 7, 170, 7, 7, 161, + 7, 7, 168, 7, 7, 171, 7, 7, 165, 7, 7, 160, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 151, 7, 7, 148, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 143, 7, 7, 143, 7, 7, 141, 7, 7, 140, + 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 131, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, + 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 99, 7, 7, 92, 7, 7, 81, 7, 7, 57, 8, 8, 15, 62, 62, 62, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 178, 178, 178, 18, 18, 18, 7, 7, 34, 7, 7, 84, 7, 7, 97, 7, 7, 105, 7, 7, 111, 7, 7, 113, 7, 7, 115, 7, 7, 115, 7, 7, 115, + 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 118, 7, 7, 118, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, + 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, + 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 111, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, + 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 143, 7, 7, 169, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 159, 7, 7, 156, 7, 7, 152, + 7, 7, 149, 7, 7, 147, 7, 7, 147, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 126, + 7, 7, 127, 7, 7, 130, 7, 7, 132, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 8, 8, 134, 8, 8, 133, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 8, 8, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 132, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, 7, 7, 121, + 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 120, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 112, 7, 7, 119, 7, 7, 118, + 7, 7, 116, 7, 7, 124, 7, 7, 133, 7, 7, 120, 7, 7, 111, 7, 7, 126, 7, 7, 166, 7, 7, 166, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 151, 7, 7, 147, 7, 7, 145, 7, 7, 143, + 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 131, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 116, 7, 7, 116, 7, 7, 116, + 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 101, 7, 7, 96, 7, 7, 88, 7, 7, 75, 7, 7, 30, + 20, 20, 20, 184, 184, 184, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 97, 97, 97, 7, 7, 9, 7, 7, 59, 7, 7, 90, 7, 7, 100, + 7, 7, 107, 7, 7, 111, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 116, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, + 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, + 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 116, 7, 7, 163, 7, 7, 167, + 7, 7, 163, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 151, 7, 7, 148, 7, 7, 146, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 131, + 7, 7, 129, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 127, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 128, 7, 7, 124, 7, 7, 122, 7, 7, 119, + 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 109, + 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, + 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 142, 7, 7, 166, 7, 7, 161, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, + 7, 7, 153, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 142, 7, 7, 142, 7, 7, 141, 7, 7, 140, 7, 7, 139, 7, 7, 139, 7, 7, 138, 7, 7, 138, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, + 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 101, + 7, 7, 97, 7, 7, 90, 7, 7, 80, 7, 7, 52, 7, 7, 9, 97, 97, 97, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 213, 213, 213, 37, 37, 37, 7, 7, 24, 7, 7, 80, 7, 7, 94, 7, 7, 103, 7, 7, 108, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 114, + 7, 7, 115, 7, 7, 115, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 111, + 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, + 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, + 7, 7, 105, 7, 7, 105, 7, 7, 107, 7, 7, 151, 7, 7, 169, 7, 7, 165, 7, 7, 161, 7, 7, 159, 7, 7, 155, 7, 7, 150, 7, 7, 147, 7, 7, 145, 7, 7, 143, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, + 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 125, 7, 7, 127, 7, 7, 130, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, + 7, 7, 132, 7, 7, 128, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 112, + 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, + 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 123, 7, 7, 164, 7, 7, 162, 7, 7, 159, 7, 7, 159, + 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 152, 7, 7, 148, 7, 7, 145, 7, 7, 142, 7, 7, 141, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 137, 7, 7, 136, 7, 7, 135, 7, 7, 132, + 7, 7, 130, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, + 7, 7, 105, 7, 7, 104, 7, 7, 101, 7, 7, 100, 7, 7, 97, 7, 7, 92, 7, 7, 84, 7, 7, 69, 7, 7, 22, 38, 38, 38, 211, 211, 211, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 132, 132, 132, 7, 7, 7, 7, 7, 48, 7, 7, 85, 7, 7, 95, 7, 7, 102, 7, 7, 107, 7, 7, 108, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 110, 7, 7, 110, + 7, 7, 110, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 112, 7, 7, 113, 7, 7, 114, 7, 7, 114, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 113, 7, 7, 113, 7, 7, 113, + 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 106, + 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, + 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 136, 7, 7, 169, 7, 7, 166, 7, 7, 162, 7, 7, 158, 7, 7, 154, 7, 7, 149, 7, 7, 146, 7, 7, 143, 7, 7, 141, 7, 7, 141, 7, 7, 140, 7, 7, 139, + 7, 7, 139, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 137, 7, 7, 135, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 124, 7, 7, 127, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 135, 7, 7, 134, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 8, 8, 133, 8, 8, 131, 7, 7, 128, 7, 7, 123, 7, 7, 119, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 116, 7, 7, 115, + 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, + 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 102, + 7, 7, 110, 7, 7, 156, 7, 7, 165, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 156, 7, 7, 154, 7, 7, 152, 7, 7, 150, 7, 7, 146, 7, 7, 144, 7, 7, 141, 7, 7, 140, 7, 7, 140, 7, 7, 140, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, + 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 118, 7, 7, 116, 7, 7, 115, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, + 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 98, 7, 7, 96, 7, 7, 91, 7, 7, 84, 7, 7, 73, 7, 7, 40, 8, 8, 8, 135, 135, 135, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 250, 53, 53, 53, 7, 7, 9, 7, 7, 40, 7, 7, 83, 7, 7, 95, 7, 7, 100, 7, 7, 103, 7, 7, 103, 7, 7, 103, + 7, 7, 103, 7, 7, 105, 7, 7, 106, 7, 7, 107, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 111, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, + 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, + 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 121, 7, 7, 167, 7, 7, 166, 7, 7, 160, 7, 7, 156, 7, 7, 152, 7, 7, 148, 7, 7, 144, + 7, 7, 141, 7, 7, 139, 7, 7, 138, 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 137, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 122, 7, 7, 122, 7, 7, 123, 7, 7, 128, + 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 8, 8, 134, 12, 12, 133, 10, 10, 132, 9, 9, 128, 8, 8, 120, 7, 7, 116, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 115, 7, 7, 114, 7, 7, 114, + 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, + 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 102, + 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 131, 7, 7, 163, 7, 7, 164, 7, 7, 161, 7, 7, 158, 7, 7, 155, 7, 7, 152, 7, 7, 150, 7, 7, 148, 7, 7, 147, 7, 7, 144, 7, 7, 141, 7, 7, 139, 7, 7, 137, 7, 7, 137, + 7, 7, 137, 7, 7, 136, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 118, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 110, + 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 100, 7, 7, 99, 7, 7, 96, 7, 7, 93, 7, 7, 88, 7, 7, 83, 7, 7, 71, 7, 7, 33, 8, 8, 9, 61, 61, 61, 250, 250, 250, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 232, 232, 232, 79, 79, 79, 12, 12, 12, 7, 7, 29, + 7, 7, 82, 7, 7, 92, 7, 7, 95, 7, 7, 97, 7, 7, 98, 7, 7, 100, 7, 7, 101, 7, 7, 102, 7, 7, 103, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, + 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, + 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 102, 7, 7, 102, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, + 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 110, 7, 7, 160, 7, 7, 163, + 7, 7, 157, 7, 7, 153, 7, 7, 150, 7, 7, 146, 7, 7, 143, 7, 7, 140, 7, 7, 138, 7, 7, 136, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 132, 7, 7, 131, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 124, + 7, 7, 122, 7, 7, 120, 7, 7, 121, 7, 7, 121, 7, 7, 126, 7, 7, 130, 7, 7, 132, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, + 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 11, 11, 135, 14, 14, 133, 12, 12, 130, 11, 11, 125, 8, 8, 117, 7, 7, 113, 7, 7, 112, 7, 7, 112, + 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 103, + 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, + 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 100, 7, 7, 118, 7, 7, 146, 7, 7, 161, 7, 7, 157, 7, 7, 152, 7, 7, 149, 7, 7, 147, 7, 7, 145, 7, 7, 143, + 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 129, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 119, 7, 7, 117, + 7, 7, 115, 7, 7, 112, 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 96, 7, 7, 93, 7, 7, 90, 7, 7, 85, 7, 7, 81, 7, 7, 69, 7, 7, 25, + 12, 12, 13, 85, 85, 85, 241, 241, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 248, 248, 248, 105, 105, 105, 11, 11, 11, 7, 7, 27, 7, 7, 71, 7, 7, 89, 7, 7, 91, 7, 7, 91, 7, 7, 93, 7, 7, 95, 7, 7, 98, 7, 7, 99, 7, 7, 100, 7, 7, 101, 7, 7, 102, 7, 7, 102, 7, 7, 103, 7, 7, 103, 7, 7, 104, + 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, + 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, + 7, 7, 100, 7, 7, 100, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, + 7, 7, 96, 7, 7, 96, 7, 7, 103, 7, 7, 152, 7, 7, 158, 7, 7, 152, 7, 7, 149, 7, 7, 146, 7, 7, 144, 7, 7, 142, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 133, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 131, 7, 7, 130, 7, 7, 129, + 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 121, 7, 7, 120, 7, 7, 118, 7, 7, 118, 7, 7, 120, 7, 7, 124, 7, 7, 128, 7, 7, 131, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 132, 7, 7, 133, + 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 8, 8, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 133, 7, 7, 134, 7, 7, 134, 8, 8, 134, 8, 8, 131, 11, 11, 128, + 8, 8, 121, 8, 8, 115, 7, 7, 110, 7, 7, 109, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, + 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, + 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 102, 7, 7, 142, 7, 7, 157, + 7, 7, 151, 7, 7, 147, 7, 7, 144, 7, 7, 142, 7, 7, 140, 7, 7, 138, 7, 7, 135, 7, 7, 133, 7, 7, 131, 7, 7, 130, 7, 7, 129, 7, 7, 129, 7, 7, 129, 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 126, 7, 7, 125, 7, 7, 123, + 7, 7, 122, 7, 7, 120, 7, 7, 118, 7, 7, 116, 7, 7, 114, 7, 7, 112, 7, 7, 111, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 104, 7, 7, 102, 7, 7, 101, 7, 7, 99, 7, 7, 98, 7, 7, 97, 7, 7, 96, 7, 7, 95, 7, 7, 92, 7, 7, 89, 7, 7, 86, + 7, 7, 83, 7, 7, 79, 7, 7, 61, 7, 7, 24, 13, 13, 13, 107, 107, 107, 243, 243, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 250, 250, 134, 134, 134, 7, 7, 7, 7, 7, 19, 7, 7, 62, 7, 7, 81, 7, 7, 85, 7, 7, 88, 7, 7, 89, 7, 7, 91, 7, 7, 92, 7, 7, 93, 7, 7, 95, + 7, 7, 95, 7, 7, 97, 7, 7, 99, 7, 7, 99, 7, 7, 100, 7, 7, 101, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 103, 7, 7, 103, 7, 7, 103, 7, 7, 103, + 7, 7, 103, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 96, + 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 97, 7, 7, 96, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, + 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 92, 7, 7, 98, 7, 7, 142, 7, 7, 154, 7, 7, 148, 7, 7, 145, 7, 7, 143, 7, 7, 142, 7, 7, 141, 7, 7, 139, 7, 7, 136, 7, 7, 133, 7, 7, 131, 7, 7, 129, 7, 7, 128, + 7, 7, 128, 7, 7, 128, 7, 7, 126, 7, 7, 125, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 115, 7, 7, 115, 7, 7, 117, 7, 7, 120, 7, 7, 125, 7, 7, 130, 7, 7, 132, 7, 7, 131, 8, 8, 131, 7, 7, 132, + 7, 7, 131, 8, 8, 130, 8, 8, 129, 8, 8, 129, 7, 7, 131, 7, 7, 131, 8, 8, 133, 7, 7, 133, 7, 7, 132, 7, 7, 132, 7, 7, 133, 7, 7, 133, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 133, 7, 7, 131, 8, 8, 132, + 7, 7, 133, 7, 7, 133, 7, 7, 133, 8, 8, 130, 9, 9, 124, 9, 9, 117, 8, 8, 111, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, + 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 95, + 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, + 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 112, 7, 7, 151, 7, 7, 150, 7, 7, 145, 7, 7, 142, 7, 7, 139, 7, 7, 137, 7, 7, 134, 7, 7, 132, 7, 7, 130, 7, 7, 128, 7, 7, 125, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 123, + 7, 7, 123, 7, 7, 123, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 119, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 104, 7, 7, 102, 7, 7, 101, 7, 7, 99, 7, 7, 97, 7, 7, 95, 7, 7, 94, 7, 7, 92, + 7, 7, 91, 7, 7, 89, 7, 7, 87, 7, 7, 84, 7, 7, 80, 7, 7, 75, 7, 7, 51, 7, 7, 18, 7, 7, 7, 129, 129, 129, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 168, 168, 168, 27, 27, 27, 7, 7, 7, 7, 7, 23, 7, 7, 50, 7, 7, 73, + 7, 7, 80, 7, 7, 84, 7, 7, 86, 7, 7, 87, 7, 7, 88, 7, 7, 89, 7, 7, 90, 7, 7, 91, 7, 7, 92, 7, 7, 93, 7, 7, 94, 7, 7, 95, 7, 7, 96, 7, 7, 96, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, 7, 7, 97, + 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 92, + 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 92, + 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 122, 7, 7, 149, 7, 7, 143, 7, 7, 141, 7, 7, 139, 7, 7, 139, 7, 7, 139, 7, 7, 137, + 7, 7, 134, 7, 7, 131, 7, 7, 128, 7, 7, 126, 7, 7, 124, 7, 7, 124, 7, 7, 123, 7, 7, 122, 7, 7, 121, 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 113, 7, 7, 116, 7, 7, 120, + 7, 7, 125, 7, 7, 127, 7, 7, 128, 8, 8, 129, 8, 8, 126, 10, 10, 125, 11, 11, 122, 9, 9, 122, 10, 10, 124, 11, 11, 126, 8, 8, 128, 8, 8, 131, 7, 7, 131, 7, 7, 133, 7, 7, 132, 7, 7, 132, 9, 9, 133, 10, 10, 134, 8, 8, 134, 7, 7, 134, 7, 7, 135, + 7, 7, 134, 7, 7, 134, 7, 7, 131, 7, 7, 130, 8, 8, 132, 8, 8, 132, 8, 8, 132, 8, 8, 131, 8, 8, 126, 8, 8, 119, 8, 8, 110, 7, 7, 105, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 102, 7, 7, 101, 7, 7, 101, 7, 7, 100, + 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 92, + 7, 7, 92, 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 89, 7, 7, 88, + 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 91, 7, 7, 131, 7, 7, 150, 7, 7, 144, 7, 7, 139, 7, 7, 136, 7, 7, 133, 7, 7, 130, 7, 7, 126, 7, 7, 124, 7, 7, 122, 7, 7, 120, 7, 7, 119, + 7, 7, 119, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 114, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 105, 7, 7, 103, 7, 7, 101, 7, 7, 99, 7, 7, 97, 7, 7, 95, + 7, 7, 93, 7, 7, 92, 7, 7, 90, 7, 7, 88, 7, 7, 87, 7, 7, 85, 7, 7, 82, 7, 7, 78, 7, 7, 68, 7, 7, 45, 7, 7, 20, 7, 7, 7, 38, 38, 38, 165, 165, 165, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 221, 221, 221, 141, 141, 141, 50, 50, 50, 9, 9, 12, 7, 7, 19, 7, 7, 43, 7, 7, 64, 7, 7, 75, 7, 7, 78, 7, 7, 80, 7, 7, 81, 7, 7, 83, 7, 7, 85, 7, 7, 87, 7, 7, 88, 7, 7, 88, 7, 7, 89, 7, 7, 90, 7, 7, 91, 7, 7, 91, 7, 7, 91, + 7, 7, 92, 7, 7, 92, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 93, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, 7, 7, 90, + 7, 7, 90, 7, 7, 89, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 89, 7, 7, 89, + 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 85, 7, 7, 85, 7, 7, 85, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 83, 7, 7, 103, 7, 7, 142, 7, 7, 138, + 7, 7, 136, 7, 7, 135, 7, 7, 135, 7, 7, 135, 7, 7, 133, 7, 7, 130, 7, 7, 125, 7, 7, 123, 7, 7, 121, 7, 7, 119, 7, 7, 118, 7, 7, 117, 7, 7, 116, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 108, + 7, 7, 107, 7, 7, 106, 7, 7, 107, 7, 7, 109, 7, 7, 113, 7, 7, 117, 7, 7, 120, 7, 7, 123, 7, 7, 123, 13, 13, 120, 19, 19, 113, 14, 14, 108, 12, 12, 106, 14, 14, 110, 11, 11, 113, 8, 8, 120, 7, 7, 125, 10, 10, 128, 10, 10, 130, 8, 8, 131, 9, 9, 132, + 12, 12, 134, 10, 10, 133, 8, 8, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 131, 8, 8, 130, 8, 8, 130, 14, 14, 130, 16, 16, 128, 10, 10, 124, 9, 9, 117, 7, 7, 108, 7, 7, 102, 7, 7, 98, 7, 7, 97, 7, 7, 97, 7, 7, 96, 7, 7, 96, + 7, 7, 96, 7, 7, 96, 7, 7, 96, 7, 7, 95, 7, 7, 95, 7, 7, 94, 7, 7, 94, 7, 7, 94, 7, 7, 93, 7, 7, 93, 7, 7, 92, 7, 7, 92, 7, 7, 91, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 88, + 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, 7, 7, 85, 7, 7, 85, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 84, 7, 7, 83, + 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 83, 7, 7, 110, 7, 7, 146, 7, 7, 140, 7, 7, 135, 7, 7, 131, 7, 7, 126, 7, 7, 123, + 7, 7, 120, 7, 7, 119, 7, 7, 117, 7, 7, 115, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 113, 7, 7, 114, 7, 7, 113, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 102, 7, 7, 101, + 7, 7, 98, 7, 7, 96, 7, 7, 94, 7, 7, 92, 7, 7, 91, 7, 7, 88, 7, 7, 85, 7, 7, 83, 7, 7, 80, 7, 7, 77, 7, 7, 73, 7, 7, 61, 7, 7, 41, 7, 7, 17, 13, 13, 15, 55, 55, 55, 142, 142, 142, 224, 224, 224, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 238, 238, 163, 163, 163, 61, 61, 61, 18, 18, 18, 7, 7, 15, 9, 9, 33, 7, 7, 46, 7, 7, 61, 7, 7, 71, 7, 7, 74, 7, 7, 76, 7, 7, 77, 7, 7, 78, 7, 7, 80, + 7, 7, 81, 7, 7, 82, 7, 7, 83, 7, 7, 84, 7, 7, 85, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 86, + 7, 7, 86, 7, 7, 86, 7, 7, 86, 7, 7, 85, 7, 7, 85, 7, 7, 84, 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 81, 7, 7, 81, 7, 7, 81, + 7, 7, 81, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 83, 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 78, 7, 7, 78, + 7, 7, 77, 7, 7, 77, 7, 7, 86, 7, 7, 133, 7, 7, 134, 7, 7, 131, 7, 7, 130, 7, 7, 130, 7, 7, 130, 7, 7, 128, 7, 7, 124, 7, 7, 120, 7, 7, 117, 7, 7, 115, 7, 7, 113, 7, 7, 112, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, + 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 101, 7, 7, 100, 7, 7, 101, 7, 7, 103, 7, 7, 107, 7, 7, 109, 7, 7, 113, 10, 10, 113, 16, 16, 112, 13, 13, 99, 8, 8, 88, 8, 8, 84, 8, 8, 89, 7, 7, 94, 7, 7, 102, + 11, 11, 109, 16, 16, 117, 12, 12, 121, 9, 9, 126, 8, 8, 128, 8, 8, 129, 8, 8, 131, 7, 7, 133, 7, 7, 133, 7, 7, 133, 7, 7, 132, 7, 7, 130, 7, 7, 130, 7, 7, 129, 15, 15, 128, 26, 26, 126, 19, 19, 120, 12, 12, 112, 9, 9, 105, 7, 7, 96, 7, 7, 92, + 7, 7, 91, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 86, 7, 7, 85, 7, 7, 85, 7, 7, 85, 7, 7, 85, + 7, 7, 85, 7, 7, 84, 7, 7, 84, 7, 7, 83, 7, 7, 83, 7, 7, 83, 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, + 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 76, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 76, 7, 7, 76, 7, 7, 88, 7, 7, 134, + 7, 7, 136, 7, 7, 131, 7, 7, 125, 7, 7, 120, 7, 7, 117, 7, 7, 114, 7, 7, 112, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 104, 7, 7, 102, 7, 7, 100, + 7, 7, 98, 7, 7, 97, 7, 7, 96, 7, 7, 95, 7, 7, 93, 7, 7, 90, 7, 7, 88, 7, 7, 86, 7, 7, 83, 7, 7, 81, 7, 7, 79, 7, 7, 75, 7, 7, 70, 7, 7, 62, 7, 7, 46, 10, 10, 34, 7, 7, 14, 18, 18, 18, 61, 61, 61, 169, 169, 169, 232, 232, 232, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 204, 204, 204, 105, 105, 105, 65, 65, 65, 17, 17, 17, 7, 7, 7, 7, 7, 17, + 7, 7, 27, 8, 8, 40, 8, 8, 51, 7, 7, 61, 7, 7, 70, 7, 7, 71, 7, 7, 72, 7, 7, 73, 7, 7, 75, 7, 7, 76, 7, 7, 76, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 78, 7, 7, 78, 7, 7, 78, + 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 77, 7, 7, 77, 7, 7, 76, 7, 7, 76, 7, 7, 75, 7, 7, 74, 7, 7, 73, 7, 7, 73, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, + 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 73, 7, 7, 73, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 73, 7, 7, 73, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 72, 7, 7, 71, + 7, 7, 71, 7, 7, 71, 7, 7, 70, 7, 7, 70, 7, 7, 69, 7, 7, 69, 7, 7, 68, 7, 7, 74, 7, 7, 118, 7, 7, 123, 7, 7, 120, 7, 7, 118, 7, 7, 118, 7, 7, 117, 7, 7, 115, 7, 7, 112, 7, 7, 108, 7, 7, 106, 7, 7, 103, 7, 7, 101, 7, 7, 100, + 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 98, 7, 7, 97, 7, 7, 96, 7, 7, 95, 7, 7, 94, 7, 7, 93, 7, 7, 91, 7, 7, 90, 7, 7, 90, 7, 7, 91, 7, 7, 93, 7, 7, 96, 7, 7, 98, 8, 8, 98, 8, 8, 97, 7, 7, 90, + 7, 7, 74, 7, 7, 61, 7, 7, 64, 7, 7, 73, 7, 7, 80, 9, 9, 86, 10, 10, 94, 8, 8, 101, 7, 7, 110, 8, 8, 116, 7, 7, 122, 8, 8, 126, 8, 8, 128, 7, 7, 129, 7, 7, 128, 7, 7, 125, 7, 7, 123, 7, 7, 123, 8, 8, 121, 14, 14, 117, 13, 13, 110, + 8, 8, 103, 8, 8, 96, 7, 7, 88, 7, 7, 83, 7, 7, 82, 7, 7, 81, 7, 7, 81, 7, 7, 81, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 80, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 79, 7, 7, 78, 7, 7, 78, 7, 7, 78, 7, 7, 77, + 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 77, 7, 7, 76, 7, 7, 76, 7, 7, 75, 7, 7, 75, 7, 7, 74, 7, 7, 74, 7, 7, 74, 7, 7, 73, 7, 7, 72, 7, 7, 72, 7, 7, 71, 7, 7, 71, 7, 7, 71, 7, 7, 70, 7, 7, 70, + 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 68, 7, 7, 68, 7, 7, 68, 7, 7, 69, + 7, 7, 69, 7, 7, 68, 7, 7, 68, 7, 7, 69, 7, 7, 104, 7, 7, 125, 7, 7, 119, 7, 7, 113, 7, 7, 109, 7, 7, 106, 7, 7, 103, 7, 7, 101, 7, 7, 100, 7, 7, 99, 7, 7, 98, 7, 7, 99, 7, 7, 99, 7, 7, 99, 7, 7, 98, 7, 7, 98, 7, 7, 97, + 7, 7, 95, 7, 7, 94, 7, 7, 92, 7, 7, 91, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 86, 7, 7, 85, 7, 7, 83, 7, 7, 81, 7, 7, 78, 7, 7, 74, 7, 7, 67, 7, 7, 53, 9, 9, 41, 7, 7, 25, 7, 7, 16, 7, 7, 7, 12, 12, 12, 51, 51, 51, + 96, 96, 96, 204, 204, 204, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 240, 240, 240, 176, 176, 176, 120, 120, 120, 81, 81, 81, 53, 53, 53, 19, 19, 21, 7, 7, 10, 7, 7, 12, 10, 10, 17, 9, 9, 22, 7, 7, 26, 7, 7, 31, 7, 7, 40, 7, 7, 46, 9, 9, 51, 9, 9, 53, 9, 9, 54, 8, 8, 56, 7, 7, 56, + 7, 7, 58, 7, 7, 60, 7, 7, 62, 7, 7, 64, 7, 7, 66, 7, 7, 66, 7, 7, 68, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 68, 7, 7, 68, 7, 7, 67, 7, 7, 67, 7, 7, 66, 7, 7, 65, 7, 7, 65, 7, 7, 65, + 7, 7, 64, 7, 7, 64, 7, 7, 64, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 64, 7, 7, 64, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 65, 7, 7, 64, 7, 7, 64, 7, 7, 64, 7, 7, 64, + 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 62, 7, 7, 61, 7, 7, 61, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 59, 7, 7, 60, 7, 7, 85, 7, 7, 112, 7, 7, 112, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 104, 7, 7, 101, + 7, 7, 97, 7, 7, 94, 7, 7, 92, 7, 7, 90, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 89, 7, 7, 88, 7, 7, 87, 7, 7, 87, 7, 7, 85, 7, 7, 84, 7, 7, 83, 7, 7, 81, 7, 7, 80, 7, 7, 79, 7, 7, 80, + 7, 7, 82, 7, 7, 82, 7, 7, 82, 7, 7, 81, 7, 7, 80, 7, 7, 74, 7, 7, 58, 7, 7, 53, 7, 7, 56, 7, 7, 60, 7, 7, 64, 7, 7, 71, 7, 7, 78, 7, 7, 89, 7, 7, 100, 7, 7, 108, 7, 7, 114, 10, 10, 117, 11, 11, 117, 8, 8, 115, 8, 8, 112, + 7, 7, 110, 7, 7, 107, 8, 8, 103, 8, 8, 97, 7, 7, 90, 7, 7, 85, 7, 7, 79, 7, 7, 75, 7, 7, 73, 7, 7, 72, 7, 7, 71, 7, 7, 71, 7, 7, 71, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, 7, 7, 70, + 7, 7, 70, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 69, 7, 7, 68, 7, 7, 68, 7, 7, 68, 7, 7, 67, 7, 7, 67, 7, 7, 66, 7, 7, 65, 7, 7, 65, 7, 7, 64, 7, 7, 62, + 7, 7, 62, 7, 7, 62, 7, 7, 61, 7, 7, 61, 7, 7, 61, 7, 7, 61, 7, 7, 61, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, 7, 7, 60, + 7, 7, 59, 7, 7, 59, 7, 7, 59, 7, 7, 59, 7, 7, 60, 7, 7, 60, 7, 7, 59, 7, 7, 59, 7, 7, 58, 7, 7, 78, 7, 7, 112, 7, 7, 106, 7, 7, 101, 7, 7, 98, 7, 7, 94, 7, 7, 92, 7, 7, 90, 7, 7, 88, 7, 7, 87, 7, 7, 86, 7, 7, 84, + 7, 7, 84, 7, 7, 83, 7, 7, 82, 7, 7, 79, 7, 7, 75, 7, 7, 73, 8, 8, 69, 8, 8, 67, 9, 9, 64, 9, 9, 60, 9, 9, 57, 7, 7, 51, 7, 7, 44, 7, 7, 36, 7, 7, 31, 9, 9, 25, 10, 10, 18, 7, 7, 12, 8, 8, 12, 17, 17, 18, 52, 52, 52, + 81, 81, 81, 136, 136, 136, 177, 177, 177, 241, 241, 241, 251, 251, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 236, 236, 236, 210, 210, 210, 196, 196, 196, 167, 167, 167, 134, 134, 134, 117, 117, 117, 87, 87, 87, 56, 56, 56, 47, 47, 47, 39, 39, 40, + 37, 37, 37, 35, 35, 37, 30, 30, 32, 28, 28, 32, 22, 22, 27, 20, 20, 27, 17, 17, 24, 13, 13, 22, 11, 11, 21, 11, 11, 21, 8, 8, 18, 7, 7, 18, 7, 7, 19, 7, 7, 19, 7, 7, 19, 7, 7, 19, 7, 7, 20, 9, 9, 22, 9, 9, 22, 9, 9, 22, 9, 9, 23, + 9, 9, 23, 9, 9, 23, 9, 9, 23, 9, 9, 22, 9, 9, 22, 9, 9, 22, 9, 9, 22, 9, 9, 22, 9, 9, 22, 9, 9, 22, 10, 10, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 25, 11, 11, 25, 11, 11, 25, 11, 11, 25, 11, 11, 25, + 11, 11, 25, 11, 11, 25, 11, 11, 25, 11, 11, 25, 11, 11, 25, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 25, 11, 11, 35, 11, 11, 38, + 11, 11, 38, 11, 11, 37, 11, 11, 37, 11, 11, 36, 11, 11, 34, 11, 11, 34, 11, 11, 33, 11, 11, 32, 11, 11, 32, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 31, 11, 11, 30, + 11, 11, 30, 11, 11, 29, 11, 11, 29, 11, 11, 29, 11, 11, 28, 11, 11, 29, 11, 11, 29, 11, 11, 29, 11, 11, 29, 11, 11, 28, 11, 11, 28, 11, 11, 26, 11, 11, 24, 11, 11, 23, 11, 11, 25, 11, 11, 27, 11, 11, 32, 11, 11, 44, 11, 11, 57, 10, 10, 71, 9, 9, 81, + 12, 12, 89, 16, 16, 93, 14, 14, 93, 11, 11, 88, 10, 10, 82, 10, 10, 74, 11, 11, 66, 11, 11, 56, 11, 11, 47, 11, 11, 39, 11, 11, 33, 11, 11, 29, 11, 11, 27, 11, 11, 27, 11, 11, 27, 11, 11, 27, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, + 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 26, 11, 11, 25, 11, 11, 25, 11, 11, 25, + 11, 11, 25, 11, 11, 25, 11, 11, 25, 11, 11, 25, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 24, + 11, 11, 24, 11, 11, 24, 11, 11, 24, 11, 11, 23, 11, 11, 23, 11, 11, 23, 9, 9, 22, 9, 9, 21, 9, 9, 21, 9, 9, 22, 9, 9, 22, 9, 9, 21, 9, 9, 21, 9, 9, 21, 9, 9, 25, 9, 9, 33, 9, 9, 32, 9, 9, 30, 9, 9, 29, 9, 9, 28, 7, 7, 25, + 7, 7, 24, 7, 7, 23, 7, 7, 23, 7, 7, 22, 7, 7, 21, 11, 11, 24, 11, 11, 25, 11, 11, 24, 13, 13, 24, 17, 17, 26, 20, 20, 28, 23, 23, 29, 28, 28, 33, 30, 30, 33, 35, 35, 37, 36, 36, 38, 40, 40, 40, 47, 47, 47, 67, 67, 67, 87, 87, 87, 106, 106, 106, + 134, 134, 134, 167, 167, 167, 197, 197, 197, 208, 208, 208, 235, 235, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 240, 229, 229, 229, 224, 224, 224, 212, 212, 212, 208, 208, 208, 197, 197, 197, 192, 192, 192, 183, 183, 183, 174, 174, 174, 169, 169, 169, 169, 169, 169, 160, 160, 160, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 148, 148, 148, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 121, 121, 121, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 118, 118, 119, 117, 117, 120, 114, 114, 120, 111, 111, 121, 109, 109, 121, 108, 108, 122, 108, 108, 122, 110, 110, 121, 113, 113, 120, 115, 115, 120, 117, 117, 119, 118, 118, 119, 118, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 130, 130, 130, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 148, 148, 148, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 168, 168, 168, 169, 169, 169, 169, 169, 169, 174, 174, 174, 182, 182, 182, 192, 192, 192, 197, 197, 197, 208, 208, 208, 212, 212, 212, 224, 224, 224, 229, 229, 229, + 240, 240, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 254, 251, 251, 252, 250, 250, 252, 250, 250, 251, 250, 250, 251, 252, 252, 252, 253, 253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,}; +const char* DistrhoArtworkCloneChannel::backgroundData = (const char*)temp_background_1; + +static const unsigned char temp_switch_left_2[] = { + 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 155, 7, 7, 161, 7, 7, 155, + 7, 7, 144, 7, 7, 128, 8, 8, 118, 8, 8, 121, 7, 7, 136, 8, 8, 153, 7, 7, 161, 7, 7, 164, 7, 7, 155, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 151, 7, 7, 153, 7, 7, 155, 7, 7, 156, 7, 7, 157, 7, 7, 156, 40, 40, 158, 71, 71, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, + 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 161, 7, 7, 149, 8, 8, 98, 7, 7, 46, 7, 7, 15, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 17, 7, 7, 60, 8, 8, 114, 7, 7, 157, 7, 7, 159, 7, 7, 152, 7, 7, 153, + 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 153, 7, 7, 156, 7, 7, 158, 7, 7, 160, 7, 7, 160, 7, 7, 159, 19, 19, 157, 67, 67, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, + 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 162, 7, 7, 115, 7, 7, 32, 7, 7, 7, 19, 19, 13, 51, 51, 49, 76, 76, 75, 89, 89, 88, + 88, 88, 87, 73, 73, 72, 41, 41, 37, 12, 12, 7, 7, 7, 7, 7, 7, 50, 7, 7, 136, 7, 7, 159, 7, 7, 151, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 152, 7, 7, 156, 7, 7, 159, + 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 160, 8, 8, 158, 52, 52, 160, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, + 7, 7, 163, 7, 7, 94, 7, 7, 9, 10, 10, 7, 61, 61, 64, 109, 109, 110, 124, 124, 125, 124, 124, 124, 123, 123, 123, 123, 123, 124, 124, 124, 124, 124, 124, 125, 102, 102, 104, 49, 49, 49, 7, 7, 7, 7, 7, 20, 7, 7, 125, 7, 7, 161, 7, 7, 153, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 154, 7, 7, 158, 7, 7, 160, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 159, 34, 34, 159, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 161, + 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 156, 7, 7, 164, 7, 7, 107, 7, 7, 7, 19, 19, 19, 91, 91, 93, 125, 125, 125, 119, 119, 119, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 117, + 123, 123, 123, 124, 124, 124, 76, 76, 79, 10, 10, 8, 7, 7, 21, 7, 7, 133, 7, 7, 160, 7, 7, 154, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 152, 7, 7, 157, 7, 7, 158, 7, 7, 160, 7, 7, 162, 7, 7, 163, 7, 7, 162, + 7, 7, 161, 7, 7, 160, 24, 24, 159, 7, 7, 160, 7, 7, 160, 10, 10, 160, 13, 13, 161, 7, 7, 162, 7, 7, 160, 7, 7, 161, 7, 7, 166, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 174, 8, 8, 146, 7, 7, 25, 23, 23, 22, 106, 106, 107, + 133, 133, 133, 123, 123, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 117, 117, 117, 117, 117, 117, 118, 118, 118, 129, 129, 129, 82, 82, 84, 7, 7, 7, 8, 8, 45, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 156, 7, 7, 155, + 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 156, 10, 10, 160, 18, 18, 161, 8, 8, 162, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 17, 17, 159, 7, 7, 160, 7, 7, 161, 27, 27, 163, 44, 44, 164, 7, 7, 158, 8, 8, 167, 7, 7, 167, 8, 8, 144, 7, 7, 108, + 7, 7, 92, 7, 7, 78, 9, 9, 69, 8, 8, 65, 7, 7, 57, 7, 7, 35, 7, 7, 7, 20, 20, 21, 43, 43, 43, 44, 44, 44, 53, 53, 53, 61, 61, 61, 75, 75, 75, 90, 90, 90, 85, 85, 85, 84, 84, 84, 100, 100, 100, 120, 120, 120, 120, 120, 120, 118, 118, 118, 117, 117, 117, + 128, 128, 128, 56, 56, 57, 7, 7, 7, 8, 8, 109, 7, 7, 166, 7, 7, 155, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 8, 8, 156, 7, 7, 157, 18, 18, 159, 13, 13, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 162, 7, 7, 159, 12, 12, 158, + 7, 7, 160, 11, 11, 161, 43, 43, 165, 22, 22, 160, 7, 7, 165, 9, 9, 141, 7, 7, 65, 7, 7, 19, 7, 7, 7, 13, 13, 7, 12, 12, 7, 7, 7, 7, 9, 9, 7, 18, 18, 9, 18, 18, 13, 19, 19, 19, 16, 16, 16, 11, 11, 11, 10, 10, 10, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 49, 49, 49, 112, 112, 112, 120, 120, 120, 118, 118, 118, 120, 120, 120, 113, 113, 115, 20, 20, 17, 7, 7, 48, 7, 7, 161, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 157, + 7, 7, 158, 9, 9, 159, 8, 8, 160, 7, 7, 160, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 8, 8, 157, 7, 7, 160, 22, 22, 161, 37, 37, 161, 7, 7, 160, 7, 7, 143, 7, 7, 68, 7, 7, 35, 40, 40, 42, 76, 76, 77, 96, 96, 97, 94, 94, 95, 75, 75, 77, + 52, 52, 53, 67, 67, 69, 80, 80, 81, 79, 79, 79, 79, 79, 79, 79, 79, 79, 77, 77, 77, 73, 73, 73, 68, 68, 68, 58, 58, 58, 47, 47, 47, 32, 32, 32, 19, 19, 19, 7, 7, 7, 7, 7, 7, 54, 54, 54, 119, 119, 119, 119, 119, 119, 117, 117, 117, 126, 126, 128, 61, 61, 58, + 7, 7, 7, 8, 8, 147, 7, 7, 160, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 158, 7, 7, 157, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 8, 8, 160, 32, 32, 161, 18, 18, 159, + 7, 7, 158, 8, 8, 100, 9, 9, 64, 64, 64, 75, 118, 118, 119, 129, 129, 129, 131, 131, 131, 131, 131, 131, 125, 125, 125, 107, 107, 107, 83, 83, 83, 96, 96, 96, 102, 102, 102, 100, 100, 100, 100, 100, 100, 99, 99, 99, 98, 98, 98, 97, 97, 97, 96, 96, 96, 93, 93, 93, 88, 88, 88, + 77, 77, 77, 55, 55, 55, 33, 33, 33, 25, 25, 25, 95, 95, 95, 123, 123, 123, 117, 117, 117, 123, 123, 124, 99, 99, 99, 7, 7, 7, 7, 7, 120, 7, 7, 164, 7, 7, 157, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 160, + 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 158, 7, 7, 156, 14, 14, 161, 39, 39, 162, 8, 8, 161, 7, 7, 136, 7, 7, 87, 51, 51, 75, 121, 121, 124, 134, 134, 134, 143, 143, 143, 148, 148, 148, 147, 147, 147, 140, 140, 140, 130, 130, 130, 106, 106, 106, 95, 95, 95, + 108, 108, 108, 107, 107, 107, 107, 107, 107, 106, 106, 106, 105, 105, 105, 104, 104, 104, 103, 103, 103, 101, 101, 101, 98, 98, 98, 96, 96, 96, 91, 91, 91, 79, 79, 79, 42, 42, 42, 74, 74, 74, 124, 124, 124, 117, 117, 117, 122, 122, 123, 110, 110, 111, 19, 19, 16, 8, 8, 104, 7, 7, 167, + 7, 7, 156, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 156, 44, 44, 164, 40, 40, 164, 7, 7, 165, 7, 7, 112, 16, 16, 74, 99, 99, 108, + 132, 132, 133, 148, 148, 148, 167, 167, 167, 182, 182, 182, 177, 177, 177, 159, 159, 159, 141, 141, 141, 123, 123, 123, 100, 100, 100, 109, 109, 109, 112, 112, 112, 111, 111, 111, 110, 110, 110, 110, 110, 110, 108, 108, 108, 107, 107, 107, 105, 105, 105, 102, 102, 102, 99, 99, 99, 93, 93, 93, 89, 89, 89, + 39, 39, 39, 72, 72, 72, 125, 125, 125, 118, 118, 118, 121, 121, 121, 115, 115, 116, 30, 30, 24, 7, 7, 94, 7, 7, 168, 7, 7, 157, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 157, 7, 7, 155, 96, 96, 175, 25, 25, 166, 7, 7, 172, 7, 7, 90, 35, 35, 58, 118, 118, 121, 139, 139, 139, 162, 162, 162, 203, 203, 203, 238, 238, 238, 227, 227, 227, 183, 183, 183, 151, 151, 151, 133, 133, 133, 106, 106, 106, 108, 108, 108, 115, 115, 115, 112, 112, 112, + 112, 112, 112, 110, 110, 110, 109, 109, 109, 107, 107, 107, 105, 105, 105, 101, 101, 101, 97, 97, 97, 91, 91, 91, 68, 68, 68, 34, 34, 34, 72, 72, 72, 126, 126, 126, 118, 118, 118, 122, 122, 122, 112, 112, 113, 21, 21, 17, 7, 7, 99, 7, 7, 168, 7, 7, 157, 7, 7, 159, 7, 7, 160, + 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 157, 7, 7, 155, 7, 7, 154, 109, 109, 184, 10, 10, 171, 7, 7, 181, 7, 7, 70, 43, 43, 49, 121, 121, 123, 142, 142, 142, 169, 169, 169, 222, 222, 222, + 255, 255, 255, 252, 252, 252, 197, 197, 197, 155, 155, 155, 135, 135, 135, 108, 108, 108, 107, 107, 107, 114, 114, 114, 112, 112, 112, 111, 111, 111, 109, 109, 109, 107, 107, 107, 104, 104, 104, 101, 101, 101, 97, 97, 97, 86, 86, 86, 51, 51, 51, 15, 15, 15, 17, 17, 17, 93, 93, 93, 124, 124, 124, + 118, 118, 118, 124, 124, 124, 96, 96, 96, 8, 8, 7, 8, 8, 118, 7, 7, 167, 7, 7, 158, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 92, 92, 186, 7, 7, 178, 11, 11, 188, 7, 7, 58, 26, 26, 22, 116, 116, 117, 139, 139, 139, 160, 160, 160, 201, 201, 201, 234, 234, 234, 223, 223, 223, 181, 181, 181, 151, 151, 151, 131, 131, 131, 103, 103, 103, 105, 105, 105, 111, 111, 111, 108, 108, 108, 106, 106, 106, 104, 104, 104, 101, 101, 101, + 97, 97, 97, 86, 86, 86, 60, 60, 60, 26, 26, 26, 7, 7, 7, 7, 7, 7, 45, 45, 45, 120, 120, 120, 120, 120, 120, 118, 118, 118, 128, 128, 128, 60, 60, 58, 7, 7, 11, 8, 8, 147, 7, 7, 164, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 78, 78, 187, 7, 7, 182, 9, 9, 197, 7, 7, 92, 9, 9, 7, 84, 84, 87, 135, 135, 135, 145, 145, 145, 164, 164, 164, 179, 179, 179, 174, 174, 174, 156, 156, 156, + 140, 140, 140, 120, 120, 120, 92, 92, 92, 103, 103, 103, 105, 105, 105, 102, 102, 102, 98, 98, 98, 90, 90, 90, 75, 75, 75, 49, 49, 49, 25, 25, 25, 7, 7, 7, 7, 7, 7, 9, 9, 9, 52, 52, 52, 114, 114, 114, 122, 122, 121, 119, 119, 119, 121, 121, 121, 117, 117, 118, 22, 22, 17, + 7, 7, 44, 8, 8, 164, 7, 7, 161, 7, 7, 160, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 50, 50, 183, 7, 7, 181, 8, 8, 194, + 7, 7, 154, 7, 7, 8, 24, 24, 26, 105, 105, 106, 136, 136, 136, 141, 141, 141, 146, 146, 146, 145, 145, 145, 139, 139, 139, 128, 128, 128, 95, 95, 95, 82, 82, 82, 94, 94, 94, 83, 83, 83, 68, 68, 68, 48, 48, 48, 28, 28, 28, 11, 11, 11, 7, 7, 7, 7, 7, 7, 21, 21, 21, + 30, 30, 30, 64, 64, 64, 121, 121, 121, 123, 123, 123, 120, 120, 120, 119, 119, 120, 129, 129, 129, 62, 62, 64, 7, 7, 7, 8, 8, 93, 7, 7, 168, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, + 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 16, 16, 178, 7, 7, 182, 7, 7, 181, 7, 7, 192, 7, 7, 96, 7, 7, 7, 25, 25, 26, 89, 89, 92, 120, 120, 121, 129, 129, 131, 126, 126, 129, 113, 113, 115, 77, 77, 80, 37, 37, 38, 43, 43, 43, + 33, 33, 32, 19, 19, 19, 10, 10, 10, 7, 7, 7, 7, 7, 7, 13, 13, 13, 26, 26, 26, 37, 37, 37, 42, 42, 42, 49, 49, 49, 106, 106, 106, 123, 123, 123, 119, 119, 119, 120, 120, 120, 128, 128, 128, 86, 86, 88, 8, 8, 7, 7, 7, 28, 7, 7, 129, 7, 7, 164, 7, 7, 161, + 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 185, 7, 7, 94, + 7, 7, 7, 7, 7, 7, 35, 35, 28, 53, 53, 47, 49, 49, 42, 30, 30, 21, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7, 7, 7, 24, 24, 25, 39, 39, 39, 43, 43, 44, 43, 43, 43, 43, 43, 43, 37, 37, 37, 80, 80, 80, 121, 121, 121, 119, 119, 119, + 123, 123, 123, 128, 128, 128, 82, 82, 84, 14, 14, 13, 8, 8, 17, 7, 7, 89, 7, 7, 139, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, + 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 180, 7, 7, 182, 7, 7, 194, 7, 7, 147, 7, 7, 73, 7, 7, 37, 7, 7, 29, 7, 7, 32, 7, 7, 41, 8, 8, 67, 9, 9, 81, 7, 7, 79, 8, 8, 96, 8, 8, 76, 7, 7, 10, + 10, 10, 7, 27, 27, 28, 40, 40, 42, 44, 44, 45, 40, 40, 40, 61, 61, 61, 119, 119, 119, 129, 129, 129, 125, 125, 125, 105, 105, 106, 52, 52, 52, 7, 7, 7, 7, 7, 18, 8, 8, 84, 7, 7, 111, 7, 7, 147, 7, 7, 164, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 160, + 7, 7, 160, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 183, 7, 7, 190, 7, 7, 195, 8, 8, 177, + 9, 9, 167, 8, 8, 166, 7, 7, 171, 7, 7, 165, 7, 7, 124, 7, 7, 108, 7, 7, 106, 7, 7, 109, 7, 7, 83, 7, 7, 28, 7, 7, 7, 12, 12, 7, 20, 20, 18, 31, 31, 29, 80, 80, 79, 98, 98, 97, 77, 77, 76, 37, 37, 34, 16, 16, 9, 7, 7, 7, 7, 7, 42, + 7, 7, 97, 7, 7, 106, 7, 7, 119, 7, 7, 160, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, + 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 184, 7, 7, 183, 7, 7, 181, 7, 7, 181, 7, 7, 178, 7, 7, 175, 7, 7, 161, 7, 7, 117, 7, 7, 101, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 108, 7, 7, 106, 7, 7, 73, 7, 7, 45, + 7, 7, 20, 7, 7, 10, 7, 7, 8, 7, 7, 7, 7, 7, 10, 7, 7, 20, 7, 7, 55, 8, 8, 86, 7, 7, 108, 7, 7, 109, 7, 7, 104, 7, 7, 141, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 162, + 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 182, 7, 7, 184, 7, 7, 184, 7, 7, 184, 7, 7, 181, 7, 7, 179, 7, 7, 166, 7, 7, 123, + 7, 7, 105, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 110, 7, 7, 108, 7, 7, 102, 7, 7, 99, 7, 7, 93, 8, 8, 96, 8, 8, 103, 8, 8, 105, 7, 7, 112, 7, 7, 111, 7, 7, 106, 7, 7, 103, 7, 7, 126, 7, 7, 161, + 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 179, 7, 7, 179, 7, 7, 179, + 7, 7, 179, 7, 7, 181, 7, 7, 183, 7, 7, 184, 7, 7, 183, 7, 7, 183, 7, 7, 175, 7, 7, 132, 7, 7, 105, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 102, 7, 7, 103, 7, 7, 105, 7, 7, 106, 7, 7, 107, + 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 124, 7, 7, 159, 7, 7, 163, 7, 7, 161, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, + 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 180, 7, 7, 180, 7, 7, 180, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 182, 7, 7, 184, 7, 7, 181, 7, 7, 139, 7, 7, 107, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, + 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 107, 7, 7, 131, 7, 7, 159, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, + 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 181, + 7, 7, 182, 7, 7, 184, 7, 7, 149, 7, 7, 110, 7, 7, 110, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 103, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 103, 7, 7, 106, 7, 7, 111, + 7, 7, 128, 7, 7, 148, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 164, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 184, 7, 7, 157, 7, 7, 112, 7, 7, 110, 7, 7, 110, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 104, + 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 102, 7, 7, 123, 7, 7, 141, 7, 7, 139, 7, 7, 145, 7, 7, 154, 7, 7, 161, 7, 7, 164, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, + 7, 7, 158, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 183, 7, 7, 165, 7, 7, 118, 7, 7, 110, + 7, 7, 111, 7, 7, 109, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, 7, 7, 102, 7, 7, 112, 7, 7, 153, 7, 7, 163, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 162, 7, 7, 164, + 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, + 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 183, 7, 7, 172, 7, 7, 124, 7, 7, 109, 7, 7, 113, 7, 7, 111, 7, 7, 110, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 104, + 7, 7, 139, 7, 7, 160, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, + 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 184, 7, 7, 142, 7, 7, 109, 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, + 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 102, 7, 7, 124, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 166, + 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 182, 7, 7, 183, 7, 7, 182, + 7, 7, 185, 7, 7, 177, 7, 7, 122, 7, 7, 110, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 103, 7, 7, 113, 7, 7, 152, 7, 7, 161, 7, 7, 159, 7, 7, 159, + 7, 7, 159, 7, 7, 159, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 164, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 154, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 183, 7, 7, 183, 7, 7, 183, 7, 7, 188, 7, 7, 162, 7, 7, 113, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 108, + 7, 7, 108, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 142, 7, 7, 163, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 161, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 157, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 185, 7, 7, 185, 7, 7, 185, 7, 7, 190, 7, 7, 152, 7, 7, 110, + 7, 7, 113, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 108, 7, 7, 108, 7, 7, 108, 7, 7, 104, 7, 7, 130, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, + 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 189, 7, 7, 188, 7, 7, 188, 7, 7, 194, 7, 7, 151, 7, 7, 110, 7, 7, 113, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 109, 7, 7, 105, 7, 7, 118, + 7, 7, 160, 7, 7, 167, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, + 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 201, 7, 7, 198, 7, 7, 196, 7, 7, 201, 7, 7, 164, 7, 7, 112, 7, 7, 113, 7, 7, 111, 7, 7, 110, + 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 109, 7, 7, 107, 7, 7, 112, 7, 7, 153, 7, 7, 169, 7, 7, 166, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 166, 7, 7, 166, 7, 7, 165, + 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 167, 7, 7, 192, 7, 7, 197, 7, 7, 204, 7, 7, 183, 7, 7, 117, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 110, 7, 7, 110, 7, 7, 110, 7, 7, 109, 7, 7, 107, 7, 7, 144, 7, 7, 170, 7, 7, 168, 7, 7, 168, 7, 7, 168, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, + 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 132, 7, 7, 139, 7, 7, 146, 7, 7, 150, 7, 7, 172, 7, 7, 136, 7, 7, 111, 7, 7, 113, 7, 7, 111, 7, 7, 111, 7, 7, 111, 7, 7, 111, + 7, 7, 110, 7, 7, 110, 7, 7, 106, 7, 7, 133, 7, 7, 169, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, + 7, 7, 164, 7, 7, 164, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 130, 7, 7, 141, 7, 7, 159, 7, 7, 118, 7, 7, 111, 7, 7, 113, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 112, 7, 7, 107, 7, 7, 123, 7, 7, 167, 7, 7, 173, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 171, 7, 7, 171, + 7, 7, 171, 7, 7, 171, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 135, 7, 7, 134, 7, 7, 135, 7, 7, 135, 7, 7, 132, 7, 7, 155, 7, 7, 154, 7, 7, 114, 7, 7, 110, 7, 7, 112, 7, 7, 112, 7, 7, 111, 7, 7, 108, 7, 7, 124, 7, 7, 165, + 7, 7, 176, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 164, 7, 7, 164, 7, 7, 163, + 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 172, 7, 7, 170, 7, 7, 132, 7, 7, 119, 7, 7, 116, 7, 7, 121, 7, 7, 142, 7, 7, 173, 7, 7, 180, 7, 7, 175, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 176, 7, 7, 177, 7, 7, 176, + 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 137, 7, 7, 177, 7, 7, 197, 7, 7, 186, 7, 7, 182, 7, 7, 184, 7, 7, 190, 7, 7, 187, 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 176, + 7, 7, 176, 7, 7, 177, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, + 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151,}; +const char* DistrhoArtworkCloneChannel::switch_leftData = (const char*)temp_switch_left_2; + +static const unsigned char temp_switch_right_3[] = { + 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 153, 7, 7, 155, 7, 7, 161, 7, 7, 155, + 7, 7, 144, 7, 7, 128, 8, 8, 118, 8, 8, 121, 7, 7, 136, 8, 8, 153, 7, 7, 161, 7, 7, 164, 7, 7, 155, 7, 7, 153, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 157, + 7, 7, 157, 7, 7, 156, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 161, 7, 7, 149, 8, 8, 98, 7, 7, 46, 7, 7, 15, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 17, 7, 7, 60, 8, 8, 114, 7, 7, 157, 7, 7, 159, 7, 7, 152, 7, 7, 153, + 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 149, 7, 7, 149, 7, 7, 148, 7, 7, 147, 7, 7, 146, 7, 7, 145, 7, 7, 144, 7, 7, 144, 7, 7, 163, 7, 7, 163, 7, 7, 162, + 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 158, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 162, 7, 7, 115, 7, 7, 32, 7, 7, 7, 19, 19, 13, 51, 51, 49, 76, 76, 75, 89, 89, 88, + 88, 88, 87, 73, 73, 72, 41, 41, 37, 12, 12, 7, 7, 7, 7, 7, 7, 50, 7, 7, 136, 7, 7, 159, 7, 7, 151, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 150, 7, 7, 151, 7, 7, 151, + 7, 7, 150, 7, 7, 149, 7, 7, 145, 7, 7, 145, 7, 7, 144, 7, 7, 143, 7, 7, 165, 8, 8, 165, 9, 9, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 158, 7, 7, 156, + 7, 7, 163, 7, 7, 94, 7, 7, 9, 10, 10, 7, 61, 61, 64, 109, 109, 110, 124, 124, 125, 124, 124, 124, 123, 123, 123, 123, 123, 124, 124, 124, 124, 124, 124, 125, 102, 102, 104, 49, 49, 49, 7, 7, 7, 7, 7, 20, 7, 7, 125, 7, 7, 161, 7, 7, 153, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 150, 7, 7, 147, 7, 7, 144, 7, 7, 144, 7, 7, 144, 7, 7, 168, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 163, 7, 7, 161, + 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 158, 7, 7, 165, 7, 7, 107, 7, 7, 7, 21, 21, 20, 92, 92, 94, 126, 126, 126, 121, 121, 121, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 121, 121, 121, 123, 123, 123, 75, 75, 77, 9, 9, 7, 7, 7, 20, 7, 7, 133, 7, 7, 159, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 151, 7, 7, 148, + 7, 7, 147, 7, 7, 149, 7, 7, 149, 7, 7, 172, 13, 13, 175, 16, 16, 172, 9, 9, 169, 7, 7, 166, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 159, 7, 7, 164, 7, 7, 143, 7, 7, 24, 17, 17, 15, 98, 98, 100, + 125, 125, 125, 117, 117, 117, 117, 117, 117, 119, 119, 119, 122, 122, 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, 124, 124, 124, 124, 124, 124, 124, 124, 124, 136, 136, 136, 90, 90, 92, 11, 11, 8, 8, 8, 45, 7, 7, 164, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, + 7, 7, 160, 7, 7, 152, 7, 7, 151, 7, 7, 153, 8, 8, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 8, 8, 150, 7, 7, 151, 7, 7, 153, 7, 7, 153, 12, 12, 175, 38, 38, 176, 11, 11, 171, 8, 8, 169, 7, 7, 167, 8, 8, 166, 7, 7, 163, 7, 7, 162, 7, 7, 161, + 7, 7, 161, 7, 7, 161, 7, 7, 161, 7, 7, 160, 7, 7, 169, 7, 7, 75, 8, 8, 7, 81, 81, 83, 126, 126, 126, 117, 117, 117, 118, 118, 118, 120, 120, 120, 115, 115, 115, 97, 97, 97, 85, 85, 85, 84, 84, 84, 79, 79, 79, 65, 65, 65, 53, 53, 53, 46, 46, 46, 38, 38, 38, + 43, 43, 43, 9, 9, 9, 7, 7, 7, 7, 7, 41, 8, 8, 59, 9, 9, 68, 7, 7, 77, 7, 7, 85, 7, 7, 98, 8, 8, 130, 7, 7, 159, 9, 9, 161, 7, 7, 151, 18, 18, 154, 10, 10, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 154, 7, 7, 154, 7, 7, 153, + 19, 19, 174, 29, 29, 174, 9, 9, 172, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 165, 8, 8, 148, 7, 7, 15, 39, 39, 36, 123, 123, 123, 118, 118, 118, 118, 118, 118, 122, 122, 122, 106, 106, 106, + 44, 44, 44, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 11, 11, 12, 12, 12, 18, 18, 18, 19, 19, 19, 18, 18, 11, 9, 9, 7, 7, 7, 7, 12, 12, 7, 13, 13, 7, 7, 7, 7, 7, 7, 7, 7, 7, 50, 9, 9, 129, + 7, 7, 155, 17, 17, 154, 15, 15, 153, 12, 12, 152, 9, 9, 152, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 13, 13, 172, 10, 10, 170, 8, 8, 170, 7, 7, 170, 7, 7, 169, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 163, 7, 7, 160, + 7, 7, 172, 7, 7, 111, 8, 8, 7, 91, 91, 92, 124, 124, 124, 117, 117, 117, 120, 120, 120, 113, 113, 113, 52, 52, 52, 15, 15, 15, 16, 16, 16, 33, 33, 33, 45, 45, 45, 57, 57, 57, 67, 67, 67, 73, 73, 73, 77, 77, 77, 79, 79, 79, 80, 80, 80, 79, 79, 79, 79, 79, 79, + 68, 68, 70, 52, 52, 53, 73, 73, 75, 93, 93, 95, 95, 95, 97, 81, 81, 82, 41, 41, 42, 7, 7, 9, 7, 7, 36, 7, 7, 130, 7, 7, 154, 38, 38, 156, 20, 20, 154, 8, 8, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 8, 8, 171, 7, 7, 169, 7, 7, 169, + 7, 7, 169, 7, 7, 171, 7, 7, 171, 7, 7, 170, 7, 7, 166, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 161, 7, 7, 175, 7, 7, 86, 24, 24, 13, 115, 115, 118, 120, 120, 120, 118, 118, 118, 123, 123, 123, 66, 66, 66, 47, 47, 47, 62, 62, 62, 74, 74, 74, 88, 88, 88, + 93, 93, 93, 95, 95, 95, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 100, 100, 100, 100, 101, 101, 101, 96, 96, 96, 83, 83, 83, 104, 104, 104, 124, 124, 124, 131, 131, 131, 132, 132, 132, 130, 130, 130, 120, 120, 120, 72, 72, 75, 10, 10, 23, 7, 7, 64, 7, 7, 146, 43, 43, 158, + 32, 32, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 172, 7, 7, 170, 7, 7, 170, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 162, 8, 8, 172, 7, 7, 73, 39, 39, 28, + 126, 126, 129, 117, 117, 117, 121, 121, 121, 109, 109, 109, 47, 47, 47, 79, 79, 79, 90, 90, 90, 96, 96, 96, 98, 98, 98, 100, 100, 100, 103, 103, 103, 105, 105, 105, 105, 105, 105, 106, 106, 106, 107, 107, 107, 107, 107, 107, 108, 108, 108, 96, 96, 96, 104, 104, 104, 129, 129, 129, 139, 139, 139, + 146, 146, 146, 149, 149, 149, 144, 144, 144, 134, 134, 134, 125, 125, 125, 59, 59, 62, 7, 7, 27, 7, 7, 103, 23, 23, 158, 39, 39, 157, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 153, 7, 7, 174, 7, 7, 171, 7, 7, 171, 7, 7, 173, 7, 7, 174, 7, 7, 171, + 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 166, 7, 7, 165, 7, 7, 163, 8, 8, 171, 7, 7, 70, 47, 47, 38, 128, 128, 130, 117, 117, 118, 124, 124, 124, 99, 99, 99, 49, 49, 49, 85, 85, 85, 93, 93, 93, 98, 98, 98, 102, 102, 102, 105, 105, 105, 106, 106, 106, 108, 108, 108, + 110, 110, 110, 110, 110, 110, 111, 111, 111, 112, 112, 112, 110, 110, 110, 100, 100, 100, 121, 121, 121, 140, 140, 140, 156, 156, 156, 176, 176, 176, 183, 183, 183, 168, 168, 168, 149, 149, 149, 135, 135, 135, 107, 107, 109, 21, 21, 14, 7, 7, 59, 11, 11, 153, 34, 34, 157, 7, 7, 153, 7, 7, 153, + 7, 7, 152, 7, 7, 152, 7, 7, 153, 8, 8, 176, 7, 7, 171, 7, 7, 171, 7, 7, 173, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 166, 7, 7, 163, 8, 8, 171, 7, 7, 69, 38, 38, 28, 129, 129, 131, 118, 118, 118, 123, 123, 123, + 109, 109, 109, 44, 44, 44, 74, 74, 74, 90, 90, 90, 98, 98, 98, 101, 101, 101, 105, 105, 105, 107, 107, 107, 109, 109, 109, 110, 110, 110, 112, 112, 112, 112, 112, 112, 115, 115, 115, 109, 109, 109, 105, 105, 105, 131, 131, 131, 149, 149, 149, 179, 179, 179, 223, 223, 223, 240, 240, 240, 207, 207, 207, + 165, 165, 165, 141, 141, 141, 122, 122, 122, 43, 43, 38, 7, 7, 33, 7, 7, 151, 28, 28, 155, 8, 8, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 153, 12, 12, 178, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 172, 7, 7, 171, + 7, 7, 169, 7, 7, 167, 7, 7, 162, 8, 8, 175, 7, 7, 86, 24, 24, 11, 115, 115, 118, 121, 121, 121, 119, 119, 119, 124, 124, 124, 61, 61, 61, 31, 31, 31, 51, 51, 51, 85, 85, 85, 97, 97, 97, 101, 101, 101, 104, 104, 104, 106, 106, 106, 109, 109, 109, 111, 111, 111, 112, 112, 112, + 114, 114, 114, 108, 108, 108, 105, 105, 105, 133, 133, 133, 152, 152, 152, 190, 190, 190, 247, 247, 247, 255, 255, 255, 228, 228, 228, 173, 173, 173, 144, 144, 144, 124, 124, 125, 50, 50, 46, 7, 7, 28, 7, 7, 154, 22, 22, 155, 14, 14, 154, 7, 7, 153, 7, 7, 152, 7, 7, 153, 7, 7, 153, + 22, 22, 180, 7, 7, 175, 7, 7, 172, 7, 7, 170, 7, 7, 172, 7, 7, 175, 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 162, 7, 7, 173, 9, 9, 110, 10, 10, 7, 93, 93, 95, 126, 126, 126, 118, 118, 118, 122, 122, 122, 114, 114, 114, 41, 41, 41, + 7, 7, 7, 24, 24, 24, 59, 59, 59, 85, 85, 85, 97, 97, 97, 101, 101, 101, 103, 103, 103, 106, 106, 106, 108, 108, 108, 111, 111, 111, 106, 106, 106, 101, 101, 101, 130, 130, 130, 148, 148, 148, 177, 177, 177, 219, 219, 219, 234, 234, 234, 204, 204, 204, 164, 164, 164, 140, 140, 140, 119, 119, 120, + 34, 34, 29, 7, 7, 31, 7, 7, 157, 13, 13, 152, 32, 32, 155, 8, 8, 153, 7, 7, 153, 7, 7, 153, 7, 7, 154, 37, 37, 183, 7, 7, 176, 7, 7, 172, 7, 7, 172, 7, 7, 174, 7, 7, 179, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 170, 7, 7, 168, 7, 7, 163, + 7, 7, 166, 8, 8, 145, 7, 7, 12, 43, 43, 39, 126, 126, 128, 118, 118, 118, 119, 119, 119, 124, 124, 124, 100, 100, 100, 29, 29, 29, 7, 7, 7, 7, 7, 7, 22, 22, 22, 48, 48, 48, 73, 73, 73, 90, 90, 90, 98, 98, 98, 102, 102, 102, 105, 105, 105, 103, 103, 103, 91, 91, 91, + 117, 117, 117, 139, 139, 139, 154, 154, 154, 172, 172, 172, 179, 179, 179, 166, 166, 166, 147, 147, 147, 135, 135, 135, 91, 91, 93, 11, 11, 7, 7, 7, 61, 8, 8, 160, 8, 8, 151, 28, 28, 156, 8, 8, 154, 8, 8, 154, 8, 8, 154, 7, 7, 153, 38, 38, 184, 7, 7, 179, 8, 8, 177, + 7, 7, 177, 7, 7, 179, 7, 7, 180, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 165, 7, 7, 57, 7, 7, 7, 90, 90, 92, 129, 129, 130, 119, 119, 119, 120, 120, 120, 122, 122, 122, 77, 77, 77, 33, 33, 33, 21, 21, 21, + 7, 7, 7, 7, 7, 7, 10, 10, 10, 26, 26, 26, 49, 49, 49, 67, 67, 67, 83, 83, 83, 94, 94, 95, 83, 83, 83, 92, 92, 92, 126, 126, 126, 138, 138, 138, 144, 144, 144, 146, 146, 146, 142, 142, 142, 136, 136, 136, 110, 110, 110, 29, 29, 31, 7, 7, 7, 8, 8, 118, 9, 9, 161, + 7, 7, 151, 18, 18, 155, 9, 9, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 15, 15, 179, 7, 7, 182, 7, 7, 181, 7, 7, 180, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 177, 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 110, + 7, 7, 14, 17, 17, 17, 100, 100, 101, 128, 128, 128, 118, 118, 118, 122, 122, 122, 109, 109, 109, 53, 53, 53, 42, 42, 42, 38, 38, 38, 28, 28, 28, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 18, 19, 33, 33, 33, 43, 43, 43, 37, 37, 38, 74, 74, 76, 112, 112, 114, + 126, 126, 129, 129, 129, 130, 121, 121, 122, 92, 92, 93, 32, 32, 33, 7, 7, 7, 7, 7, 73, 7, 7, 160, 8, 8, 153, 7, 7, 153, 10, 10, 154, 8, 8, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 179, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 182, + 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 172, 7, 7, 168, 7, 7, 165, 7, 7, 162, 7, 7, 159, 7, 7, 130, 7, 7, 75, 7, 7, 9, 18, 18, 18, 99, 99, 101, 131, 131, 131, 121, 121, 121, 121, 121, 121, 87, 87, 87, 38, 38, 38, 42, 42, 42, 44, 44, 44, 42, 42, 42, + 40, 40, 40, 32, 32, 32, 13, 13, 13, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 27, 27, 19, 48, 48, 43, 53, 53, 47, 38, 38, 32, 10, 10, 7, 7, 7, 7, 8, 8, 68, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 183, 7, 7, 183, 7, 7, 181, 7, 7, 178, 7, 7, 173, 7, 7, 169, 7, 7, 165, 7, 7, 162, 7, 7, 162, 7, 7, 135, 7, 7, 109, 8, 8, 77, 7, 7, 8, + 11, 11, 7, 69, 69, 70, 117, 117, 118, 131, 131, 131, 122, 122, 122, 68, 68, 69, 40, 40, 40, 44, 44, 44, 43, 43, 43, 37, 37, 38, 23, 23, 23, 9, 9, 7, 7, 7, 20, 7, 7, 79, 7, 7, 80, 9, 9, 74, 8, 8, 66, 7, 7, 43, 7, 7, 26, 7, 7, 29, 7, 7, 34, + 7, 7, 58, 8, 8, 115, 7, 7, 159, 7, 7, 155, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 184, 7, 7, 184, 7, 7, 182, 7, 7, 179, + 7, 7, 175, 7, 7, 170, 7, 7, 166, 7, 7, 163, 7, 7, 162, 7, 7, 150, 7, 7, 107, 7, 7, 108, 7, 7, 84, 7, 7, 27, 7, 7, 7, 23, 23, 16, 51, 51, 49, 85, 85, 84, 85, 85, 84, 36, 36, 35, 27, 27, 25, 16, 16, 13, 9, 9, 7, 7, 7, 7, 7, 7, 42, + 7, 7, 96, 7, 7, 110, 7, 7, 109, 7, 7, 122, 7, 7, 163, 7, 7, 167, 9, 9, 152, 8, 8, 153, 8, 8, 157, 7, 7, 165, 7, 7, 162, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 151, + 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 184, 7, 7, 185, 7, 7, 183, 7, 7, 180, 7, 7, 176, 7, 7, 172, 7, 7, 168, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 130, 7, 7, 101, 7, 7, 109, 7, 7, 106, 8, 8, 74, 7, 7, 43, + 7, 7, 16, 7, 7, 7, 7, 7, 7, 7, 7, 9, 7, 7, 13, 7, 7, 24, 7, 7, 57, 7, 7, 85, 7, 7, 108, 7, 7, 109, 7, 7, 104, 7, 7, 105, 7, 7, 101, 7, 7, 110, 7, 7, 148, 7, 7, 162, 7, 7, 159, 7, 7, 158, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 179, 7, 7, 182, 7, 7, 184, 7, 7, 184, 7, 7, 184, 7, 7, 182, 7, 7, 178, 7, 7, 173, 7, 7, 169, + 7, 7, 166, 7, 7, 162, 7, 7, 161, 7, 7, 153, 7, 7, 115, 7, 7, 100, 7, 7, 103, 7, 7, 110, 8, 8, 109, 8, 8, 103, 7, 7, 100, 7, 7, 93, 7, 7, 95, 7, 7, 102, 7, 7, 104, 7, 7, 111, 7, 7, 111, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, + 7, 7, 106, 7, 7, 103, 7, 7, 113, 7, 7, 151, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 179, 7, 7, 179, 7, 7, 179, + 7, 7, 179, 7, 7, 181, 7, 7, 183, 7, 7, 184, 7, 7, 184, 7, 7, 182, 7, 7, 179, 7, 7, 174, 7, 7, 170, 7, 7, 167, 7, 7, 163, 7, 7, 160, 7, 7, 160, 7, 7, 148, 7, 7, 113, 7, 7, 100, 7, 7, 102, 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 107, + 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 102, 7, 7, 121, 7, 7, 155, 7, 7, 159, 7, 7, 157, 7, 7, 157, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 154, + 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151, 7, 7, 151, 7, 7, 180, 7, 7, 180, 7, 7, 180, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 183, 7, 7, 183, 7, 7, 182, 7, 7, 179, 7, 7, 175, 7, 7, 170, 7, 7, 167, 7, 7, 164, 7, 7, 161, + 7, 7, 159, 7, 7, 159, 7, 7, 149, 7, 7, 120, 7, 7, 103, 7, 7, 101, 7, 7, 103, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, + 7, 7, 102, 7, 7, 121, 7, 7, 155, 7, 7, 159, 7, 7, 156, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 181, + 7, 7, 182, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 175, 7, 7, 170, 7, 7, 167, 7, 7, 165, 7, 7, 162, 7, 7, 160, 7, 7, 158, 7, 7, 158, 7, 7, 154, 7, 7, 138, 7, 7, 119, 7, 7, 109, 7, 7, 105, 7, 7, 104, 7, 7, 103, 7, 7, 105, 7, 7, 105, + 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 102, 7, 7, 130, 7, 7, 158, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, + 7, 7, 152, 7, 7, 152, 7, 7, 152, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 179, 7, 7, 179, 7, 7, 180, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 179, 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 165, 7, 7, 163, 7, 7, 161, 7, 7, 160, 7, 7, 157, + 7, 7, 157, 7, 7, 158, 7, 7, 156, 7, 7, 150, 7, 7, 144, 7, 7, 141, 7, 7, 124, 7, 7, 103, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, + 7, 7, 134, 7, 7, 158, 7, 7, 156, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 180, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 180, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 182, + 7, 7, 179, 7, 7, 175, 7, 7, 171, 7, 7, 168, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 157, 7, 7, 156, 7, 7, 157, 7, 7, 160, 7, 7, 161, 7, 7, 162, 7, 7, 155, 7, 7, 115, 7, 7, 103, 7, 7, 105, 7, 7, 105, 7, 7, 106, + 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 103, 7, 7, 107, 7, 7, 142, 7, 7, 157, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, + 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 181, 7, 7, 182, 7, 7, 183, 7, 7, 183, 7, 7, 182, 7, 7, 180, 7, 7, 176, 7, 7, 172, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 161, 7, 7, 159, 7, 7, 158, 7, 7, 158, + 7, 7, 158, 7, 7, 158, 7, 7, 158, 7, 7, 161, 7, 7, 142, 7, 7, 106, 7, 7, 104, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 103, 7, 7, 109, 7, 7, 146, + 7, 7, 156, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 181, 7, 7, 182, 7, 7, 182, 7, 7, 182, 7, 7, 183, 7, 7, 183, 7, 7, 184, 7, 7, 184, 7, 7, 183, 7, 7, 181, 7, 7, 177, 7, 7, 173, + 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 162, 7, 7, 160, 7, 7, 159, 7, 7, 158, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 129, 7, 7, 103, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 107, 7, 7, 107, + 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 102, 7, 7, 121, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 182, 7, 7, 183, 7, 7, 183, + 7, 7, 184, 7, 7, 184, 7, 7, 185, 7, 7, 184, 7, 7, 184, 7, 7, 183, 7, 7, 181, 7, 7, 178, 7, 7, 175, 7, 7, 172, 7, 7, 171, 7, 7, 169, 7, 7, 167, 7, 7, 166, 7, 7, 164, 7, 7, 161, 7, 7, 160, 7, 7, 159, 7, 7, 159, 7, 7, 159, 7, 7, 159, + 7, 7, 159, 7, 7, 160, 7, 7, 154, 7, 7, 115, 7, 7, 104, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 107, 7, 7, 145, 7, 7, 156, 7, 7, 153, + 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 183, 7, 7, 183, 7, 7, 184, 7, 7, 185, 7, 7, 187, 7, 7, 186, 7, 7, 185, 7, 7, 183, 7, 7, 182, 7, 7, 181, 7, 7, 179, 7, 7, 176, 7, 7, 174, 7, 7, 173, 7, 7, 171, + 7, 7, 169, 7, 7, 167, 7, 7, 165, 7, 7, 163, 7, 7, 162, 7, 7, 161, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 160, 7, 7, 162, 7, 7, 145, 7, 7, 107, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, + 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 102, 7, 7, 133, 7, 7, 157, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 185, 7, 7, 185, 7, 7, 186, 7, 7, 187, 7, 7, 189, 7, 7, 188, + 7, 7, 184, 7, 7, 182, 7, 7, 180, 7, 7, 180, 7, 7, 179, 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 168, 7, 7, 166, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 162, 7, 7, 161, 7, 7, 161, + 7, 7, 163, 7, 7, 133, 7, 7, 104, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 101, 7, 7, 125, 7, 7, 157, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, + 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 189, 7, 7, 188, 7, 7, 189, 7, 7, 192, 7, 7, 193, 7, 7, 189, 7, 7, 184, 7, 7, 181, 7, 7, 179, 7, 7, 178, 7, 7, 178, 7, 7, 177, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 167, + 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 164, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 163, 7, 7, 164, 7, 7, 161, 7, 7, 121, 7, 7, 104, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, + 7, 7, 105, 7, 7, 105, 7, 7, 101, 7, 7, 125, 7, 7, 157, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 152, 7, 7, 201, 7, 7, 198, 7, 7, 197, 7, 7, 198, 7, 7, 196, 7, 7, 190, 7, 7, 185, 7, 7, 181, 7, 7, 178, + 7, 7, 178, 7, 7, 178, 7, 7, 178, 7, 7, 176, 7, 7, 175, 7, 7, 173, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 167, 7, 7, 166, 7, 7, 166, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 165, 7, 7, 168, 7, 7, 154, + 7, 7, 113, 7, 7, 105, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 102, 7, 7, 130, 7, 7, 157, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 155, 7, 7, 155, 7, 7, 154, 7, 7, 153, + 7, 7, 167, 7, 7, 192, 7, 7, 198, 7, 7, 201, 7, 7, 203, 7, 7, 194, 7, 7, 186, 7, 7, 182, 7, 7, 180, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 177, 7, 7, 175, 7, 7, 173, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 168, 7, 7, 168, + 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 167, 7, 7, 168, 7, 7, 167, 7, 7, 168, 7, 7, 144, 7, 7, 107, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 102, + 7, 7, 137, 7, 7, 157, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 132, 7, 7, 139, 7, 7, 146, 7, 7, 149, 7, 7, 178, 7, 7, 200, 7, 7, 189, 7, 7, 184, 7, 7, 181, 7, 7, 180, 7, 7, 179, 7, 7, 179, + 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 169, 7, 7, 169, 7, 7, 168, 7, 7, 169, 7, 7, 169, 7, 7, 169, 7, 7, 170, 7, 7, 169, 7, 7, 168, 7, 7, 167, 7, 7, 134, 7, 7, 104, + 7, 7, 106, 7, 7, 106, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 104, 7, 7, 104, 7, 7, 102, 7, 7, 111, 7, 7, 149, 7, 7, 155, 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 134, 7, 7, 133, 7, 7, 132, + 7, 7, 130, 7, 7, 139, 7, 7, 188, 7, 7, 197, 7, 7, 186, 7, 7, 184, 7, 7, 182, 7, 7, 181, 7, 7, 181, 7, 7, 180, 7, 7, 178, 7, 7, 175, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 170, 7, 7, 170, 7, 7, 171, 7, 7, 171, 7, 7, 171, 7, 7, 171, + 7, 7, 171, 7, 7, 171, 7, 7, 172, 7, 7, 172, 7, 7, 171, 7, 7, 170, 7, 7, 169, 7, 7, 163, 7, 7, 123, 7, 7, 103, 7, 7, 107, 7, 7, 106, 7, 7, 105, 7, 7, 105, 7, 7, 105, 7, 7, 103, 7, 7, 102, 7, 7, 134, 7, 7, 157, 7, 7, 154, 7, 7, 153, + 7, 7, 153, 7, 7, 153, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 152, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 135, 7, 7, 131, 7, 7, 156, 7, 7, 199, 7, 7, 192, 7, 7, 186, 7, 7, 185, 7, 7, 185, 7, 7, 184, 7, 7, 182, 7, 7, 180, 7, 7, 177, + 7, 7, 174, 7, 7, 173, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 172, 7, 7, 173, 7, 7, 173, 7, 7, 173, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 173, 7, 7, 171, 7, 7, 169, 7, 7, 169, 7, 7, 157, 7, 7, 116, 7, 7, 103, 7, 7, 104, + 7, 7, 105, 7, 7, 104, 7, 7, 102, 7, 7, 102, 7, 7, 125, 7, 7, 154, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, + 7, 7, 174, 7, 7, 200, 7, 7, 193, 7, 7, 189, 7, 7, 189, 7, 7, 188, 7, 7, 186, 7, 7, 182, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 174, 7, 7, 175, 7, 7, 175, 7, 7, 175, 7, 7, 176, 7, 7, 177, 7, 7, 176, + 7, 7, 175, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 166, 7, 7, 156, 7, 7, 129, 7, 7, 111, 7, 7, 106, 7, 7, 107, 7, 7, 114, 7, 7, 135, 7, 7, 155, 7, 7, 156, 7, 7, 154, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, + 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 135, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 134, 7, 7, 133, 7, 7, 136, 7, 7, 176, 7, 7, 202, 7, 7, 202, 7, 7, 201, 7, 7, 196, 7, 7, 190, 7, 7, 185, 7, 7, 181, 7, 7, 178, 7, 7, 176, 7, 7, 176, + 7, 7, 176, 7, 7, 177, 7, 7, 176, 7, 7, 176, 7, 7, 176, 7, 7, 178, 7, 7, 179, 7, 7, 179, 7, 7, 178, 7, 7, 176, 7, 7, 174, 7, 7, 172, 7, 7, 170, 7, 7, 167, 7, 7, 164, 7, 7, 164, 7, 7, 162, 7, 7, 153, 7, 7, 146, 7, 7, 148, 7, 7, 154, + 7, 7, 159, 7, 7, 156, 7, 7, 155, 7, 7, 154, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 153, 7, 7, 152, 7, 7, 152, 7, 7, 151,}; +const char* DistrhoArtworkCloneChannel::switch_rightData = (const char*)temp_switch_right_3; + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoArtworkCloneChannel.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoArtworkCloneChannel.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,25 @@ +/* (Auto-generated binary data file). */ + +#ifndef BINARY_DISTRHOARTWORKCLONECHANNEL_HPP +#define BINARY_DISTRHOARTWORKCLONECHANNEL_HPP + +namespace DistrhoArtworkCloneChannel +{ + extern const char* backgroundData; + const unsigned int backgroundDataSize = 283560; + const unsigned int backgroundWidth = 278; + const unsigned int backgroundHeight = 340; + + extern const char* switch_leftData; + const unsigned int switch_leftDataSize = 6273; + const unsigned int switch_leftWidth = 51; + const unsigned int switch_leftHeight = 41; + + extern const char* switch_rightData; + const unsigned int switch_rightDataSize = 6273; + const unsigned int switch_rightWidth = 51; + const unsigned int switch_rightHeight = 41; +} + +#endif // BINARY_DISTRHOARTWORKCLONECHANNEL_HPP + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoPluginCloneChannel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoPluginCloneChannel.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,208 @@ +/* + * DISTRHO CloneChannel - Copyright (C) 2023 Przemysław R. Pietraszczyk + * Based on DPF'ied SoulForce. + * Copyright (C) 2006 Niall Moody + * Copyright (C) 2015-2022 Filipe Coelho + * + * 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. + */ +#include +#include "DistrhoPluginCloneChannel.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +DistrhoPluginCloneChannel::DistrhoPluginCloneChannel() + : Plugin(kParameterCount, kProgramCount, 0) +{ + // set initial values + loadProgram(0); +} + +// ----------------------------------------------------------------------- +// Init + +void DistrhoPluginCloneChannel::initAudioPort(bool input, uint32_t index, AudioPort& port) +{ + port.groupId = kPortGroupStereo; + + Plugin::initAudioPort(input, index, port); +} + +void DistrhoPluginCloneChannel::initParameter(uint32_t index, Parameter& parameter) +{ + parameter.hints = kParameterIsAutomatable; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 1.0f; + + switch (index) + { + case kParameterSource: + parameter.hints |= kParameterIsBoolean; + parameter.name = "left/right"; + parameter.symbol = "left/right"; + parameter.ranges.def = 0.0f; + break; + case kParameterSource2: + parameter.hints |= kParameterIsBoolean; + parameter.name = "clone/move"; + parameter.symbol = "clone/move"; + parameter.ranges.def = 0.0f; + break; + } +} + +void DistrhoPluginCloneChannel::initProgramName(uint32_t index, String& programName) +{ + switch(index) + { + case kProgramDefault: + programName = "Default"; + break; + case kProgramStayDown: + programName = "Stay Down"; + break; + case kProgramLookingForTheWorld: + programName = "Looking for the World"; + break; + case kProgramGuerillaLove: + programName = "Guerilla Love"; + break; + case kProgramTumbleToThePower: + programName = "Tumble to the Power"; + break; + case kProgramDoYourselfFavour: + programName = "Do Yourself a Favour"; + break; + case kProgramPastIsPast: + programName = "Past is Past"; + break; + case kProgramYouAndOnlyYou: + programName = "You and Only You"; + break; + case kProgramCloneChannel: + programName = "Clone Channel"; + break; + } +} + +// ----------------------------------------------------------------------- +// Internal data + +float DistrhoPluginCloneChannel::getParameterValue(uint32_t index) const +{ + return parameters[index]; +} + +void DistrhoPluginCloneChannel::setParameterValue(uint32_t index, float value) +{ + asm("nop"); +} + +void DistrhoPluginCloneChannel::loadProgram(uint32_t index) +{ + switch(index) + { + case kProgramDefault: + parameters[kParameterSource] = 0.0f; + parameters[kParameterSource2] = 0.0f; + break; + case kProgramStayDown: + parameters[kParameterSource] = 0.0f; + parameters[kParameterSource2] = 0.0f; + break; + case kProgramLookingForTheWorld: + parameters[kParameterSource] = 0.0f; + parameters[kParameterSource2] = 0.0f; + break; + case kProgramGuerillaLove: + parameters[kParameterSource] = 0.0f; + parameters[kParameterSource2] = 0.0f; + break; + case kProgramTumbleToThePower: + parameters[kParameterSource] = 0.0f; + parameters[kParameterSource2] = 0.0f; + break; + case kProgramDoYourselfFavour: + parameters[kParameterSource] = 1.0f; + parameters[kParameterSource2] = 1.0f; + break; + case kProgramPastIsPast: + parameters[kParameterSource] = 1.0f; + parameters[kParameterSource2] = 1.0f; + break; + case kProgramYouAndOnlyYou: + parameters[kParameterSource] = 0.0f; + parameters[kParameterSource2] = 0.0f; + break; + case kProgramCloneChannel: + parameters[kParameterSource] = 1.0f; + parameters[kParameterSource2] = 1.0f; + break; + } +} + +// ----------------------------------------------------------------------- +// Process + +void DistrhoPluginCloneChannel::run(const float** inputs, float** outputs, uint32_t frames) +{ + + // Calculate audio. + for (uint32_t i=0; i 0.5f) { + outputs[0][i] = inputs[0][i]; + outputs[1][i] = inputs[0][i]; + } + } + // move + else if (parameters[kParameterSource2] > 0.5f) { + // na lewy + if (parameters[kParameterSource] < 0.5f) { + outputs[0][i] = inputs[1][i]; + outputs[1][i] = 0.0f; + } + // na prawy + if (parameters[kParameterSource] > 0.5f) { + outputs[0][i] = 0.0f; + outputs[1][i] = inputs[0][i]; + } + } + } +} + +// ----------------------------------------------------------------------- + +Plugin* createPlugin() +{ + return new DistrhoPluginCloneChannel(); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoPluginCloneChannel.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoPluginCloneChannel.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,141 @@ +/* + * DISTRHO CloneChannel - Copyright (C) 2023 Przemysław R. Pietraszczyk + * Based on DPF'ied SoulForce. + * Copyright (C) 2006 Niall Moody + * Copyright (C) 2015-2022 Filipe Coelho + * + * 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. + */ + +#ifndef DISTRHO_PLUGIN_CLONE_CHANNEL_HPP_INCLUDED +#define DISTRHO_PLUGIN_CLONE_CHANNEL_HPP_INCLUDED + +#include "DistrhoPlugin.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +class DistrhoPluginCloneChannel : public Plugin +{ +public: + enum Parameters { + kParameterSource, // przepisanie lewy prawy kanal + kParameterSource2, // klonowanie czy przesunięcie + kParameterCount + }; + + enum Programs { + kProgramDefault, + kProgramStayDown, + kProgramLookingForTheWorld, + kProgramGuerillaLove, + kProgramTumbleToThePower, + kProgramDoYourselfFavour, + kProgramPastIsPast, + kProgramYouAndOnlyYou, + kProgramCloneChannel, + kProgramCount + }; + + DistrhoPluginCloneChannel(); + +protected: + // ------------------------------------------------------------------- + // Information + + const char* getLabel() const noexcept override + { + return "CloneChannel"; + } + + const char* getDescription() const override + { + return "A fairly standard waveshaping distortion plugin, made more interesting through the use of feedback to control the shaping.\n\ +Can get pretty loud and obnoxious."; + } + + const char* getMaker() const noexcept override + { + return "ndc Plugs"; + } + + const char* getHomePage() const override + { + return "https://prymula.ct8.pl"; + } + + const char* getLicense() const noexcept override + { + return "MIT"; + } + + uint32_t getVersion() const noexcept override + { + return d_version(0, 1, 0); + } + + int64_t getUniqueId() const noexcept override + { + return d_cconst('C', 'l', 'C', 'h'); + + } + + // ------------------------------------------------------------------- + // Init + + void initAudioPort(bool input, uint32_t index, AudioPort& port) override; + void initParameter(uint32_t index, Parameter& parameter) override; + void initProgramName(uint32_t index, String& programName) override; + + // ------------------------------------------------------------------- + // Internal data + + float getParameterValue(uint32_t index) const override; + void setParameterValue(uint32_t index, float value) override; + void loadProgram(uint32_t index) override; + + // ------------------------------------------------------------------- + // Process + + void run(const float** inputs, float** outputs, uint32_t frames) override; + + // ------------------------------------------------------------------- + +private: + /// Array of our plugin's parameters. + float parameters[kParameterCount]; + + /// Waveshaper coefficient. + //float coeff; + /// Current wave value for the feedback. + //float wave; + /// Envelope value for the feedback. + // float env; + /// Footswitch envelope. + //float footEnv; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPluginCloneChannel) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_PLUGIN_CLONE_CHANNEL_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoPluginInfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoPluginInfo.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,44 @@ +/* + * DISTRHO CloneChannel - Copyright (C) 2023 Przemysław R. Pietraszczyk + * Based on DPF'ied SoulForce. + * Copyright (C) 2006 Niall Moody + * Copyright (C) 2015-2022 Filipe Coelho + * + * 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. + */ + +#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED +#define DISTRHO_PLUGIN_INFO_H_INCLUDED + +#define DISTRHO_PLUGIN_BRAND "DISTRHO" +#define DISTRHO_PLUGIN_NAME "Clone Channel" +#define DISTRHO_PLUGIN_URI "https://prymula.ct8.pl" +#define DISTRHO_PLUGIN_CLAP_ID "niallmoody.ndcplugs.clonechannel" + +#define DISTRHO_PLUGIN_HAS_UI 1 +#define DISTRHO_PLUGIN_IS_RT_SAFE 1 +#define DISTRHO_PLUGIN_NUM_INPUTS 2 +#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 +#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 + +#define DISTRHO_PLUGIN_CLAP_FEATURES "audio-effect", "stereo" +#define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:WaveshaperPlugin" +#define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Stereo" + +#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoUICloneChannel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoUICloneChannel.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,143 @@ +/* + * DISTRHO CloneChannel - Copyright (C) 2023 Przemysław R. Pietraszczyk + * Based on DPF'ied SoulForce. + * Copyright (C) 2006 Niall Moody + * Copyright (C) 2015-2021 Filipe Coelho + * + * 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. + */ + +#include "DistrhoUICloneChannel.hpp" +#include "DistrhoPluginCloneChannel.hpp" + +START_NAMESPACE_DISTRHO + +namespace Art = DistrhoArtworkCloneChannel; + +// ----------------------------------------------------------------------- +DistrhoUICloneChannel::DistrhoUICloneChannel() + : UI(Art::backgroundWidth, Art::backgroundHeight, true), + fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, kImageFormatBGR) +{ + // switches + fSwitchSource = new ImageSwitch(this, + Image(Art::switch_leftData, Art::switch_leftWidth, Art::switch_leftHeight, kImageFormatBGR), + Image(Art::switch_rightData, Art::switch_rightWidth, Art::switch_rightHeight, kImageFormatBGR)); + fSwitchSource->setId(DistrhoPluginCloneChannel::kParameterSource); + fSwitchSource->setAbsolutePos(116, 191); + fSwitchSource->setCallback(this); + + fSwitchSource2 = new ImageSwitch(this, + Image(Art::switch_leftData, Art::switch_leftWidth, Art::switch_leftHeight, kImageFormatBGR), + Image(Art::switch_rightData, Art::switch_rightWidth, Art::switch_rightHeight, kImageFormatBGR)); + fSwitchSource2->setId(DistrhoPluginCloneChannel::kParameterSource2); + fSwitchSource2->setAbsolutePos(116, 251); + fSwitchSource2->setCallback(this); + + // set initial values + programLoaded(0); +} + +// ----------------------------------------------------------------------- +// DSP Callbacks + +void DistrhoUICloneChannel::parameterChanged(uint32_t index, float value) +{ + switch (index) + { + case DistrhoPluginCloneChannel::kParameterSource: + fSwitchSource->setDown(value > 0.5f); + break; + case DistrhoPluginCloneChannel::kParameterSource2: + fSwitchSource2->setDown(value > 0.5f); + break; + } +} + +void DistrhoUICloneChannel::programLoaded(uint32_t index) +{ + switch(index) + { + case DistrhoPluginCloneChannel::kProgramDefault: + fSwitchSource->setDown(false); + fSwitchSource2->setDown(false); + break; + case DistrhoPluginCloneChannel::kProgramStayDown: + fSwitchSource->setDown(false); + fSwitchSource2->setDown(false); + break; + case DistrhoPluginCloneChannel::kProgramLookingForTheWorld: + fSwitchSource->setDown(false); + fSwitchSource2->setDown(false); + break; + case DistrhoPluginCloneChannel::kProgramGuerillaLove: + fSwitchSource->setDown(false); + fSwitchSource2->setDown(false); + break; + case DistrhoPluginCloneChannel::kProgramTumbleToThePower: + fSwitchSource->setDown(false); + fSwitchSource2->setDown(false); + break; + case DistrhoPluginCloneChannel::kProgramDoYourselfFavour: + fSwitchSource->setDown(true); + fSwitchSource2->setDown(true); + break; + case DistrhoPluginCloneChannel::kProgramPastIsPast: + fSwitchSource->setDown(true); + fSwitchSource2->setDown(true); + break; + case DistrhoPluginCloneChannel::kProgramYouAndOnlyYou: + fSwitchSource->setDown(false); + fSwitchSource2->setDown(false); + break; + case DistrhoPluginCloneChannel::kProgramCloneChannel: + fSwitchSource->setDown(true); + fSwitchSource2->setDown(true); + break; + } +} + +// ----------------------------------------------------------------------- +// Widget Callbacks +void DistrhoUICloneChannel::imageSwitchClicked(ImageSwitch* imageSwitch, bool down) +{ + const uint buttonId(imageSwitch->getId()); + + editParameter(buttonId, true); + setParameterValue(buttonId, down ? 1.0f : 0.0f); + editParameter(buttonId, false); +} + +void DistrhoUICloneChannel::onDisplay() +{ + const GraphicsContext& context(getGraphicsContext()); + + fImgBackground.draw(context); +} + +// ----------------------------------------------------------------------- + +UI* createUI() +{ + return new DistrhoUICloneChannel(); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoUICloneChannel.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/DistrhoUICloneChannel.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,69 @@ +/* + * DISTRHO CloneChannel - Copyright (C) 2023 Przemysław R. Pietaszczyk + * Based on DPF'ied SoulForce. + * Copyright (C) 2006 Niall Moody + * Copyright (C) 2015 Filipe Coelho + * + * 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. + */ + +#ifndef DISTRHO_UI_CLONE_CHANNEL_HPP_INCLUDED +#define DISTRHO_UI_CLONE_CHANNEL_HPP_INCLUDED + +#include "DistrhoUI.hpp" +#include "ImageWidgets.hpp" + +#include "DistrhoArtworkCloneChannel.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +class DistrhoUICloneChannel : public UI, + public ImageSwitch::Callback +{ +public: + DistrhoUICloneChannel(); + +protected: + // ------------------------------------------------------------------- + // DSP Callbacks + + void parameterChanged(uint32_t index, float value) override; + void programLoaded(uint32_t index) override; + + // ------------------------------------------------------------------- + // Widget Callbacks + + void imageSwitchClicked(ImageSwitch* imageSwitch, bool down) override; + + void onDisplay() override; + +private: + Image fImgBackground, fImgLedOff, fImgLedOn; + ScopedPointer fSwitchSource, fSwitchSource2; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUICloneChannel) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_UI_SOUL_FORCE_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/LICENSE Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,21 @@ +Copyright (C) 2004-2006 Niall Moody +Copyright (C) 2015-2021 Filipe Coelho +Copyright (C) 2023 Przemysław R. Pietraszczyk + +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 -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/CloneChannel/Makefile Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,47 @@ +#!/usr/bin/make -f +# Makefile for DISTRHO Plugins # +# ---------------------------- # +# Created by falkTX +# + +# -------------------------------------------------------------- +# Project name, used for binaries + +NAME = CloneChannel + +# -------------------------------------------------------------- +# Files to build + +FILES_DSP = \ + DistrhoPluginCloneChannel.cpp + +FILES_UI = \ + DistrhoArtworkCloneChannel.cpp \ + DistrhoUICloneChannel.cpp + +# -------------------------------------------------------------- +# Do some magic + +UI_TYPE = generic +FILE_BROWSER_DISABLED = true +include ../../dpf/Makefile.plugins.mk + +# -------------------------------------------------------------- +# Enable all possible plugin types + +#TARGETS += clap +TARGETS += jack +TARGETS += ladspa +TARGETS += lv2_sep +#TARGETS += vst2 +#TARGETS += vst3 + +ifeq ($(HAVE_CAIRO_OR_OPENGL),true) +ifeq ($(HAVE_LIBLO),true) +TARGETS += dssi +endif +endif + +all: $(TARGETS) + +# -------------------------------------------------------------- diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/artwork/background.png Binary file DPF-Prymula-audioplugins/plugins/CloneChannel/artwork/background.png has changed diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/artwork/switch_left.png Binary file DPF-Prymula-audioplugins/plugins/CloneChannel/artwork/switch_left.png has changed diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/artwork/switch_right.png Binary file DPF-Prymula-audioplugins/plugins/CloneChannel/artwork/switch_right.png has changed diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/CloneChannel/raw/background.xcf Binary file DPF-Prymula-audioplugins/plugins/CloneChannel/raw/background.xcf has changed diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/common/DistrhoPluginMaxGen.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/common/DistrhoPluginMaxGen.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,89 @@ +/* + * DPF Max Gen + * Copyright (C) 2015 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginMaxGen.hpp" + +#include "gen_exported.cpp" + +namespace gen = gen_exported; + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +DistrhoPluginMaxGen::DistrhoPluginMaxGen() + : Plugin(gen::num_params(), 0, 0), // 0 programs, 0 states + fGenState((CommonState*)gen::create(getSampleRate(), getBufferSize())) +{ + gen::reset(fGenState); +} + +DistrhoPluginMaxGen::~DistrhoPluginMaxGen() +{ + gen::destroy(fGenState); +} + +// ----------------------------------------------------------------------- +// Init + +void DistrhoPluginMaxGen::initParameter(uint32_t index, Parameter& parameter) +{ + ParamInfo& info(fGenState->params[index]); + + parameter.hints = kParameterIsAutomatable; + parameter.name = info.name; + parameter.symbol = info.name; + parameter.unit = info.units; + parameter.ranges.def = info.defaultvalue; + parameter.ranges.min = info.outputmin; + parameter.ranges.max = info.outputmax; +} + +// ----------------------------------------------------------------------- +// Internal data + +float DistrhoPluginMaxGen::getParameterValue(uint32_t index) const +{ + t_param value = 0.0f; + gen::getparameter(fGenState, index, &value); + return value; +} + +void DistrhoPluginMaxGen::setParameterValue(uint32_t index, float value) +{ + gen::setparameter(fGenState, index, value, nullptr); +} + +// ----------------------------------------------------------------------- +// Process + +void DistrhoPluginMaxGen::run(const float** inputs, float** outputs, uint32_t frames) +{ + gen::perform(fGenState, (float**)inputs, gen::gen_kernel_numins, outputs, gen::gen_kernel_numouts, frames); +} + +// ----------------------------------------------------------------------- + +Plugin* createPlugin() +{ + return new DistrhoPluginMaxGen(); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#include "gen_dsp/genlib.cpp" diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/common/DistrhoPluginMaxGen.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/common/DistrhoPluginMaxGen.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,101 @@ +/* + * DPF Max Gen + * Copyright (C) 2015-2022 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_MAX_GEN_HPP_INCLUDED +#define DISTRHO_PLUGIN_MAX_GEN_HPP_INCLUDED + +#include "DistrhoPlugin.hpp" +#include "genlib.h" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +class DistrhoPluginMaxGen : public Plugin +{ +public: + DistrhoPluginMaxGen(); + ~DistrhoPluginMaxGen() override; + +protected: + // ------------------------------------------------------------------- + // Information + + const char* getLabel() const noexcept override + { + return DISTRHO_PLUGIN_NAME; + } + + const char* getDescription() const noexcept override + { + return DISTRHO_PLUGIN_DESCRIPTION; + } + + int64_t getUniqueId() const noexcept override + { + return DISTRHO_PLUGIN_VERSION; + } + + const char* getMaker() const noexcept override + { + return "DISTRHO"; + } + + const char* getHomePage() const noexcept override + { + return "https://github.com/DISTRHO/DPF-Max-Gen"; + } + + const char* getLicense() const noexcept override + { + return "ISC"; + } + + uint32_t getVersion() const noexcept override + { + return d_version(0, 1, 0); + } + + // ------------------------------------------------------------------- + // Init + + void initAudioPort(bool input, uint32_t index, AudioPort& port) override; + void initParameter(uint32_t index, Parameter& parameter) override; + + // ------------------------------------------------------------------- + // Internal data + + float getParameterValue(uint32_t index) const override; + void setParameterValue(uint32_t index, float value) override; + + // ------------------------------------------------------------------- + // Process + + void run(const float** inputs, float** outputs, uint32_t frames) override; + + // ------------------------------------------------------------------- + +private: + CommonState* fGenState; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPluginMaxGen) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_PLUGIN_MAX_GEN_HPP_INCLUDED diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib.cpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,363 @@ +/******************************************************************************************************************* +Copyright (c) 2012 Cycling '74 + +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. +*******************************************************************************************************************/ + + +#include "genlib.h" +#include "genlib_exportfunctions.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" + +#include + +#if DISTRHO_OS_MAC +# include +#else +# include +# if DISTRHO_OS_WINDOWS +# define malloc_size _msize +# else +# define malloc_size malloc_usable_size +# endif +#endif + +// DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit +#define DATA_MAXIMUM_ELEMENTS (33554432) + +//////////// export_genlib.cpp //////////// +// export version + +void my_memset(void *p, int c, long size); +void my_memcpy(void *dst, const void *src, long size); + +t_ptr sysmem_newptr(t_ptr_size size) +{ + return (t_ptr)malloc(size); +} + +t_ptr sysmem_newptrclear(t_ptr_size size) +{ + t_ptr p = (t_ptr)malloc(size); + + if (p) + my_memset(p, 0, size); + + return p; +} + +t_ptr sysmem_resizeptr(void *ptr, t_ptr_size newsize) +{ + return (t_ptr)realloc(ptr, newsize); +} + +t_ptr sysmem_resizeptrclear(void *ptr, t_ptr_size newsize) +{ + t_ptr_size oldsize = malloc_size(ptr); + t_ptr p = (t_ptr)realloc(ptr, newsize); + + if (p) { + if (newsize > oldsize) + my_memset((char *)p + oldsize, 0, newsize - oldsize); + } + return p; +} + +t_ptr_size sysmem_ptrsize(void *ptr) +{ + return malloc_size(ptr); +} + +void sysmem_freeptr(void *ptr) +{ + free(ptr); +} + +void sysmem_copyptr(const void *src, void *dst, t_ptr_size bytes) +{ + my_memcpy(dst, src, bytes); +} + +void my_memset(void *p, int c, long size) +{ + char *p2 = (char *)p; + int i; + + for (i = 0; i < size; i++, p2++) + *p2 = c; +} + +void my_memcpy(void *dst, const void *src, long size) +{ + char *s2 = (char *)src; + char *d2 = (char *)dst; + int i; + + for (i = 0; i < size; i++, s2++, d2++) + *d2 = *s2; +} + +void set_zero64(t_sample *memory, long size) +{ + long i; + + for (i = 0; i < size; i++, memory++) { + *memory = 0.; + } +} + +void genlib_report_error(const char *s) +{ + fprintf(stderr, "%s\n", s); +} + +void genlib_report_message(const char *s) +{ + fprintf(stdout, "%s\n", s); +} + +unsigned long systime_ticks(void) +{ + return 0; // Gen code can deal with this +} + +void * genlib_obtain_reference_from_string(const char * name) { + return 0; // to be implemented +} + +// the rest is stuff to isolate gensym, attrs, atoms, buffers etc. +t_genlib_buffer * genlib_obtain_buffer_from_reference(void *ref) +{ + return 0; // to be implemented +} + +t_genlib_err genlib_buffer_edit_begin(t_genlib_buffer *b) +{ + return 0; // to be implemented +} + +t_genlib_err genlib_buffer_edit_end(t_genlib_buffer *b, long valid) +{ + return 0; // to be implemented +} + +t_genlib_err genlib_buffer_getinfo(t_genlib_buffer *b, t_genlib_buffer_info *info) +{ + return 0; // to be implemented +} + +char *genlib_reference_getname(void *ref) +{ + return 0; // to be implemented +} + +void genlib_buffer_dirty(t_genlib_buffer *b) +{ + // to be implemented +} + +t_genlib_err genlib_buffer_perform_begin(t_genlib_buffer *b) +{ + return 0; // to be implemented +} + +void genlib_buffer_perform_end(t_genlib_buffer *b) +{ + // to be implemented +} + +t_sample gen_msp_pow(t_sample value, t_sample power) +{ + return powf(value, power); +} + +void genlib_data_setbuffer(t_genlib_data *b, void *ref) { + genlib_report_error("not supported for export targets\n"); +} + +typedef struct { + t_genlib_data_info info; + t_sample cursor; // used by Delay + //t_symbol * name; +} t_dsp_gen_data; + +t_genlib_data * genlib_obtain_data_from_reference(void *ref) +{ + t_dsp_gen_data * self = (t_dsp_gen_data *)malloc(sizeof(t_dsp_gen_data)); + self->info.dim = 0; + self->info.channels = 0; + self->info.data = 0; + self->cursor = 0; + return (t_genlib_data *)self; +} + +t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info) { + t_dsp_gen_data * self = (t_dsp_gen_data *)b; + info->dim = self->info.dim; + info->channels = self->info.channels; + info->data = self->info.data; + return GENLIB_ERR_NONE; +} + +void genlib_data_release(t_genlib_data *b) { + t_dsp_gen_data * self = (t_dsp_gen_data *)b; + + if (self->info.data) { + genlib_sysmem_freeptr(self->info.data); + self->info.data = 0; + } + genlib_sysmem_freeptr(self); +} + +long genlib_data_getcursor(t_genlib_data *b) { + t_dsp_gen_data * self = (t_dsp_gen_data *)b; + return self->cursor; +} + +void genlib_data_setcursor(t_genlib_data *b, long cursor) { + t_dsp_gen_data * self = (t_dsp_gen_data *)b; + self->cursor = cursor; +} + +void genlib_data_resize(t_genlib_data *b, long s, long c) { + t_dsp_gen_data * self = (t_dsp_gen_data *)b; + + size_t sz, oldsz, copysz; + t_sample * old = 0; + t_sample * replaced = 0; + int i, j, copydim, copychannels, olddim, oldchannels; + + //printf("data resize %d %d\n", s, c); + + // cache old for copying: + old = self->info.data; + olddim = self->info.dim; + oldchannels = self->info.channels; + + // limit [data] size: + if (s * c > DATA_MAXIMUM_ELEMENTS) { + s = DATA_MAXIMUM_ELEMENTS/c; + genlib_report_message("warning: constraining [data] to < 256MB"); + } + // bytes required: + sz = sizeof(t_sample) * s * c; + oldsz = sizeof(t_sample) * olddim * oldchannels; + + if (old && sz == oldsz) { + // no need to re-allocate, just resize + // careful, audio thread may still be using it: + if (s > olddim) { + self->info.channels = c; + self->info.dim = s; + } else { + self->info.dim = s; + self->info.channels = c; + } + + set_zero64(self->info.data, s * c); + return; + + } else { + + // allocate new: + replaced = (t_sample *)sysmem_newptr(sz); + + // check allocation: + if (replaced == 0) { + genlib_report_error("allocating [data]: out of memory"); + // try to reallocate with a default/minimal size instead: + if (s > 512 || c > 1) { + genlib_data_resize((t_genlib_data *)self, 512, 1); + } else { + // if this fails, then Max is kaput anyway... + genlib_data_resize((t_genlib_data *)self, 4, 1); + } + return; + } + + // fill with zeroes: + set_zero64(replaced, s * c); + + // copy in old data: + if (old) { + // frames to copy: + // clamped: + copydim = olddim > s ? s : olddim; + // use memcpy if channels haven't changed: + if (c == oldchannels) { + copysz = sizeof(t_sample) * copydim * c; + //post("reset resize (same channels) %p %p, %d", self->info.data, old, copysz); + memcpy(replaced, old, copysz); + } else { + // memcpy won't work if channels have changed, + // because data is interleaved. + // clamp channels copied: + copychannels = oldchannels > c ? c : oldchannels; + //post("reset resize (different channels) %p %p, %d %d", self->info.data, old, copydim, copychannels); + for (i = 0; iinfo.data = replaced; + self->info.dim = s; + self->info.channels = c; + } else { + // need to be careful; the audio thread may still be using it + // since dsp_gen_data is preserved through edits + // the order of resizing has to be carefully done + // to prevent indexing out of bounds + // (or maybe I'm being too paranoid here...) + if (oldsz > sz) { + // shrink size first + if (s > olddim) { + self->info.channels = c; + self->info.dim = s; + } else { + self->info.dim = s; + self->info.channels = c; + } + self->info.data = replaced; + } else { + // shrink size after + self->info.data = replaced; + if (s > olddim) { + self->info.channels = c; + self->info.dim = s; + } else { + self->info.dim = s; + self->info.channels = c; + } + } + + // done with old: + sysmem_freeptr(old); + + } + + } +} + +void genlib_reset_complete(void *data) {} + + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,95 @@ +/******************************************************************************************************************* +Copyright (c) 2012 Cycling '74 + +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. +*******************************************************************************************************************/ + + +#ifndef GENLIB_H +#define GENLIB_H 1 + +#include "genlib_common.h" + +//////////// genlib.h //////////// +// genlib.h -- max (gen~) version + +#include "DistrhoUtils.hpp" + +#define inf (__DBL_MAX__) +#define GEN_UINT_MAX (4294967295) +#define TWO_TO_32 (4294967296.0) + +#define C74_CONST const + +// max_types.h: +typedef uintptr_t t_ptr_uint; +typedef intptr_t t_ptr_int; +typedef float t_atom_float; +typedef t_ptr_uint t_getbytes_size; + +typedef uint32_t t_uint32; +typedef t_ptr_int t_atom_long; // the type that is an A_LONG in an atom + +typedef t_ptr_int t_int; ///< an integer @ingroup misc +typedef t_ptr_uint t_ptr_size; ///< unsigned pointer-sized value for counting (like size_t) @ingroup misc +typedef t_ptr_int t_atom_long; ///< the type that is an A_LONG in a #t_atom @ingroup misc +typedef t_atom_long t_max_err; ///< an integer value suitable to be returned as an error code @ingroup misc + +extern "C" { + + // string reference handling: + void * genlib_obtain_reference_from_string(const char * name); + char *genlib_reference_getname(void *ref); + + // buffer handling: + t_genlib_buffer *genlib_obtain_buffer_from_reference(void *ref); + t_genlib_err genlib_buffer_edit_begin(t_genlib_buffer *b); + t_genlib_err genlib_buffer_edit_end(t_genlib_buffer *b, long valid); + t_genlib_err genlib_buffer_getinfo(t_genlib_buffer *b, t_genlib_buffer_info *info); + void genlib_buffer_dirty(t_genlib_buffer *b); + t_genlib_err genlib_buffer_perform_begin(t_genlib_buffer *b); + void genlib_buffer_perform_end(t_genlib_buffer *b); + + // data handling: + t_genlib_data *genlib_obtain_data_from_reference(void *ref); + t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info); + void genlib_data_resize(t_genlib_data *b, long dim, long channels); + void genlib_data_setbuffer(t_genlib_data *b, void *ref); + void genlib_data_release(t_genlib_data *b); + void genlib_data_setcursor(t_genlib_data *b, long cursor); + long genlib_data_getcursor(t_genlib_data *b); + + // other notification: + void genlib_reset_complete(void *data); + + // get/set state of parameters + size_t genlib_getstatesize(CommonState *cself, getparameter_method getmethod); + short genlib_getstate(CommonState *cself, char *state, getparameter_method getmethod); + short genlib_setstate(CommonState *cself, const char *state, setparameter_method setmethod); + +}; // extern "C" + +#define genlib_sysmem_newptr(s) sysmem_newptr(s) +#define genlib_sysmem_newptrclear(s) sysmem_newptrclear(s) +#define genlib_sysmem_resizeptr(p, s) sysmem_resizeptr(p, s) +#define genlib_sysmem_resizeptrclear(p, s) sysmem_resizeptrclear(p, s) +#define genlib_sysmem_ptrsize(p) sysmem_ptrsize(p) +#define genlib_sysmem_freeptr(p) sysmem_freeptr(p) +#define genlib_sysmem_copyptr(s, d, b) sysmem_copyptr(s, d, b) +#define genlib_set_zero64(d, n) set_zero64(d, n) +#define genlib_ticks systime_ticks + +#endif // GENLIB_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib_common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib_common.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,106 @@ +/******************************************************************************************************************* +Copyright (c) 2012 Cycling '74 + +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. +*******************************************************************************************************************/ + + +#ifndef GENLIB_COMMON_H +#define GENLIB_COMMON_H 1 + +//////////// genlib_common.h //////////// +// common data structure header file -- this is the stuff required by the +// common code and accessed by the export and max code + +#define DSP_GEN_MAX_SIGNALS 16 + +typedef float t_sample; +typedef float t_param; +typedef char *t_ptr; + +typedef long t_genlib_err; +typedef enum { + GENLIB_ERR_NONE = 0, ///< No error + GENLIB_ERR_GENERIC = -1, ///< Generic error + GENLIB_ERR_INVALID_PTR = -2, ///< Invalid Pointer + GENLIB_ERR_DUPLICATE = -3, ///< Duplicate + GENLIB_ERR_OUT_OF_MEM = -4, ///< Out of memory + + GENLIB_ERR_LOOP_OVERFLOW = 100, // too many iterations of loops in perform() + GENLIB_ERR_NULL_BUFFER = 101 // missing signal data in perform() + +} e_genlib_errorcodes; + +typedef enum { + GENLIB_PARAMTYPE_FLOAT = 0, + GENLIB_PARAMTYPE_SYM = 1 +} e_genlib_paramtypes; + +struct ParamInfo +{ + t_param defaultvalue; + void * defaultref; + char hasinputminmax; + char hasminmax; + t_param inputmin, inputmax; + t_param outputmin, outputmax; + const char *name; + const char *units; + int paramtype; // 0 -> float64, 1 -> symbol (table name) + t_param exp; // future, for scaling +}; + +struct CommonState +{ + t_sample sr; + int vs; + int numins; + int numouts; + const char **inputnames; + const char **outputnames; + int numparams; + ParamInfo *params; + + void * parammap; // implementation-dependent + void * api; // implementation-dependent +}; + +// opaque interface to float32 buffer: +typedef struct _genlib_buffer t_genlib_buffer; +typedef struct { + char b_name[256]; ///< name of the buffer + float *b_samples; ///< stored with interleaved channels if multi-channel + long b_frames; ///< number of sample frames (each one is sizeof(float) * b_nchans bytes) + long b_nchans; ///< number of channels + long b_size; ///< size of buffer in floats + float b_sr; ///< sampling rate of the buffer + long b_modtime; ///< last modified time ("dirty" method) + long b_rfu[57]; ///< reserved for future use +} t_genlib_buffer_info; + +// opaque interface to float64 buffer: +typedef struct _genlib_data t_genlib_data; +typedef struct { + int dim, channels; + t_sample * data; +} t_genlib_data_info; + +typedef void (*setparameter_method) (CommonState *, long, t_param, void *); +typedef void (*getparameter_method) (CommonState *, long, t_param *); + +#endif // GENLIB_COMMON_H + + diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib_exportfunctions.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib_exportfunctions.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,38 @@ +/******************************************************************************************************************* +Copyright (c) 2012 Cycling '74 + +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. +*******************************************************************************************************************/ + +#ifndef GENLIB_EXPORT_FUNCTIONS_H +#define GENLIB_EXPORT_FUNCTIONS_H 1 + +typedef char *t_ptr; + +t_ptr sysmem_newptr(t_ptr_size size); +t_ptr sysmem_newptrclear(t_ptr_size size); +t_ptr sysmem_resizeptr(void *ptr, t_ptr_size newsize); +t_ptr sysmem_resizeptrclear(void *ptr, t_ptr_size newsize); +t_ptr_size sysmem_ptrsize(void *ptr); +void sysmem_freeptr(void *ptr); +void sysmem_copyptr(const void *src, void *dst, t_ptr_size bytes); +unsigned long systime_ticks(void); + +void genlib_report_error(const char *s); +void genlib_report_message(const char *s); +void set_zero64(t_sample *mem, long size); + +#endif // GENLIB_EXPORT_FUNCTIONS_H diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib_ops.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib_ops.h Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,1371 @@ +/******************************************************************************************************************* +Copyright (c) 2012 Cycling '74 + +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. +*******************************************************************************************************************/ + +#ifndef GENLIB_OPS_H +#define GENLIB_OPS_H 1 + +#include "genlib_common.h" // common to common code and any host code +#include "genlib.h" // this file is different for different "hosts" + +#include + +//////////// genlib_ops.h //////////// + +// system constants +#define GENLIB_DBL_EPSILON (__DBL_EPSILON__) + +#define GENLIB_PI (3.14159265358979323846264338327950288f) +#define GENLIB_PI_OVER_2 (1.57079632679489661923132169163975144f) +#define GENLIB_PI_OVER_4 (0.785398163397448309615660845819875721f) +#define GENLIB_1_OVER_LOG_2 (1.442695040888963f) + +#define GENLIB_NO_DENORM_TEST 1 + +// assumes v is a 64-bit double: +#define GENLIB_IS_NAN_DOUBLE(v) (((((uint32_t *)&(v))[1])&0x7fe00000)==0x7fe00000) +#define GENLIB_FIX_NAN_DOUBLE(v) ((v)=GENLIB_IS_NAN_DOUBLE(v)?0.:(v)) + +#ifdef GENLIB_NO_DENORM_TEST + #define GENLIB_IS_DENORM_DOUBLE(v) (v) + #define GENLIB_FIX_DENORM_DOUBLE(v) (v) +#else + #define GENLIB_IS_DENORM_DOUBLE(v) ((((((uint32_t *)&(v))[1])&0x7fe00000)==0)&&((v)!=0.)) + #define GENLIB_FIX_DENORM_DOUBLE(v) ((v)=GENLIB_IS_DENORM_DOUBLE(v)?0.f:(v)) +#endif + +#define GENLIB_QUANT(f1,f2) (floor((f1)*(f2)+0.5)/(f2)) + +inline double genlib_isnan(double v) { return GENLIB_IS_NAN_DOUBLE(v); } +inline double fixnan(double v) { return GENLIB_FIX_NAN_DOUBLE(v); } +inline double fixdenorm(double v) { return GENLIB_FIX_DENORM_DOUBLE(v); } +inline double isdenorm(double v) { return GENLIB_IS_DENORM_DOUBLE(v); } + +inline double safemod(double f, double m) { + if (m > GENLIB_DBL_EPSILON || m < -GENLIB_DBL_EPSILON) { + if (m<0) + m = -m; // modulus needs to be absolute value + if (f>=m) { + if (f>=(m*2.)) { + double d = f / m; + d = d - (long) d; + f = d * m; + } + else { + f -= m; + } + } + else if (f<=(-m)) { + if (f<=(-m*2.)) { + double d = f / m; + d = d - (long) d; + f = d * m; + } + else { + f += m; + } + } + } else { + f = 0.0; //don't divide by zero + } + return f; +} + + +inline double safediv(double num, double denom) { + return denom == 0. ? 0. : num/denom; +} + +// fixnan for case of negative base and non-integer exponent: +inline double safepow(double base, double exponent) { + return fixnan(pow(base, exponent)); +} + +inline double absdiff(double a, double b) { return fabs(a-b); } + +inline double exp2(double v) { return pow(2., v); } + +inline double trunc(double v) { + double epsilon = (v<0.0) * -2 * 1E-9 + 1E-9; + // copy to long so it gets truncated (probably cheaper than floor()) + long val = v + epsilon; + return val; +} + +inline t_sample sign(t_sample v) { + return v > t_sample(0) ? t_sample(1) : v < t_sample(0) ? t_sample(-1) : t_sample(0); +} + +inline long is_poweroftwo(long x) { + return (x & (x - 1)) == 0; +} + +inline uint64_t next_power_of_two(uint64_t v) { + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + v++; + return v; +} + +inline t_sample fold(t_sample v, t_sample lo1, t_sample hi1){ + t_sample lo; + t_sample hi; + if(lo1 == hi1){ return lo1; } + if (lo1 > hi1) { + hi = lo1; lo = hi1; + } else { + lo = lo1; hi = hi1; + } + const t_sample range = hi - lo; + long numWraps = 0; + if(v >= hi){ + v -= range; + if(v >= hi){ + numWraps = (long)((v - lo)/range); + v -= range * (t_sample)numWraps; + } + numWraps++; + } else if(v < lo){ + v += range; + if(v < lo){ + numWraps = (long)((v - lo)/range) - 1; + v -= range * (t_sample)numWraps; + } + numWraps--; + } + if(numWraps & 1) v = hi + lo - v; // flip sign for odd folds + return v; +} + +inline double wrap(double v, double lo1, double hi1){ + double lo; + double hi; + if(lo1 == hi1) return lo1; + if (lo1 > hi1) { + hi = lo1; lo = hi1; + } else { + lo = lo1; hi = hi1; + } + const double range = hi - lo; + if (v >= lo && v < hi) return v; + if (range <= 0.000000001) return lo; // no point... + const long numWraps = long((v-lo)/range) - (v < lo); + return v - range * double(numWraps); +} + +// this version gives far better performance when wrapping is relatively rare +// and typically double of wraps is very low (>1%) +// but catastrophic if wraps is high (1000%+) +inline t_sample genlib_wrapfew(t_sample v, t_sample lo, t_sample hi){ + const t_sample range = hi - lo; + while (v >= hi) v -= range; + while (v < lo) v += range; + return v; +} + +inline t_sample phasewrap(t_sample val) { + const t_sample twopi = GENLIB_PI*2.; + const t_sample oneovertwopi = 1./twopi; + if (val>= twopi || val <= twopi) { + t_sample d = val * oneovertwopi; //multiply faster + d = d - (long)d; + val = d * twopi; + } + if (val > GENLIB_PI) val -= twopi; + if (val < -GENLIB_PI) val += twopi; + return val; +} + +/// 8th order Taylor series approximation to a cosine. +/// r must be in [-pi, pi]. +inline t_sample genlib_cosT8(t_sample r) { + const t_sample t84 = 56.; + const t_sample t83 = 1680.; + const t_sample t82 = 20160.; + const t_sample t81 = 2.4801587302e-05; + const t_sample t73 = 42.; + const t_sample t72 = 840.; + const t_sample t71 = 1.9841269841e-04; + if(r < GENLIB_PI_OVER_4 && r > -GENLIB_PI_OVER_4){ + t_sample rr = r*r; + return 1. - rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr))); + } + else if(r > 0.){ + r -= GENLIB_PI_OVER_2; + t_sample rr = r*r; + return -r * (1. - t71 * rr * (t72 - rr * (t73 - rr))); + } + else{ + r += GENLIB_PI_OVER_2; + t_sample rr = r*r; + return r * (1. - t71 * rr * (t72 - rr * (t73 - rr))); + } +} + +//inline double genlib_sin_fast(const double r){ +// const double y = (4./GENLIB_PI) * r + (-4./(GENLIB_PI*GENLIB_PI)) * r * fabs(r); +// return 0.225 * (y * fabs(y) - y) + y; // Q * y + P * y * abs(y) +//} +// +//inline t_sample genlib_sinP7(t_sample n){ +// t_sample nn = n*n; +// return n * (t_sample(3.138982) + nn * (t_sample(-5.133625) + nn * (t_sample(2.428288) - nn * t_sample(0.433645)))); +//} +// +//inline t_sample genlib_sinP9(t_sample n){ +// t_sample nn = n*n; +// return n * (GENLIB_PI + nn * (t_sample(-5.1662729) + nn * (t_sample(2.5422065) + nn * (t_sample(-0.5811243) + nn * t_sample(0.0636716))))); +//} +// +//inline t_sample genlib_sinT7(t_sample r){ +// const t_sample t84 = 56.; +// const t_sample t83 = 1680.; +// const t_sample t82 = 20160.; +// const t_sample t81 = 2.4801587302e-05; +// const t_sample t73 = 42.; +// const t_sample t72 = 840.; +// const t_sample t71 = 1.9841269841e-04; +// if(r < GENLIB_PI_OVER_4 && r > -GENLIB_PI_OVER_4){ +// t_sample rr = r*r; +// return r * (1. - t71 * rr * (t72 - rr * (t73 - rr))); +// } +// else if(r > 0.){ +// r -= GENLIB_PI_OVER_2; +// t_sample rr = r*r; +// return t_sample(1.) - rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr))); +// } +// else{ +// r += GENLIB_PI_OVER_2; +// t_sample rr = r*r; +// return t_sample(-1.) + rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr))); +// } +//} + +// use these if r is not known to be in [-pi, pi]: +inline t_sample genlib_cosT8_safe(t_sample r) { return genlib_cosT8(phasewrap(r)); } +//inline double genlib_sin_fast_safe(double r) { return genlib_sin_fast(phasewrap(r)); } +//inline t_sample genlib_sinP7_safe(t_sample r) { return genlib_sinP7(phasewrap(r)); } +//inline t_sample genlib_sinP9_safe(t_sample r) { return genlib_sinP9(phasewrap(r)); } +//inline t_sample genlib_sinT7_safe(t_sample r) { return genlib_sinT7(phasewrap(r)); } + + + +/*=====================================================================* + * Copyright (C) 2011 Paul Mineiro * + * 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 Paul Mineiro nor the names * + * of other 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 OWNER * + * 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. * + * * + * Contact: Paul Mineiro * + *=====================================================================*/ + +inline float genlib_fastersin (float x) { + static const float fouroverpi = 1.2732395447351627f; + static const float fouroverpisq = 0.40528473456935109f; + static const float q = 0.77633023248007499f; + union { float f; uint32_t i; } p = { 0.22308510060189463f }; + union { float f; uint32_t i; } vx = { x }; + uint32_t sign = vx.i & 0x80000000; + vx.i &= 0x7FFFFFFF; + float qpprox = fouroverpi * x - fouroverpisq * x * vx.f; + p.i |= sign; + return qpprox * (q + p.f * qpprox); +} + +inline float genlib_fastercos (float x) { + static const float twooverpi = 0.63661977236758134f; + static const float p = 0.54641335845679634f; + union { float f; uint32_t i; } vx = { x }; + vx.i &= 0x7FFFFFFF; + float qpprox = 1.0f - twooverpi * vx.f; + return qpprox + p * qpprox * (1.0f - qpprox * qpprox); +} + +inline float genlib_fastersinfull (float x) { + static const float twopi = 6.2831853071795865f; + static const float invtwopi = 0.15915494309189534f; + int k = x * invtwopi; + float half = (x < 0) ? -0.5f : 0.5f; + return genlib_fastersin ((half + k) * twopi - x); +} + +inline float genlib_fastercosfull (float x) { + static const float halfpi = 1.5707963267948966f; + return genlib_fastersinfull (x + halfpi); +} + +inline float genlib_fastertanfull (float x) { + static const float twopi = 6.2831853071795865f; + static const float invtwopi = 0.15915494309189534f; + int k = x * invtwopi; + float half = (x < 0) ? -0.5f : 0.5f; + float xnew = x - (half + k) * twopi; + return genlib_fastersin (xnew) / genlib_fastercos (xnew); +} + + +#define cast_uint32_t static_cast +inline float genlib_fasterpow2 (float p) { + float clipp = (p < -126) ? -126.0f : p; + union { uint32_t i; float f; } v = { cast_uint32_t ( (1 << 23) * (clipp + 126.94269504f) ) }; + return v.f; +} + +inline float genlib_fasterexp (float p) { + return genlib_fasterpow2 (1.442695040f * p); +} + +inline float genlib_fasterlog2 (float x) { + union { float f; uint32_t i; } vx = { x }; + float y = vx.i; + y *= 1.1920928955078125e-7f; + return y - 126.94269504f; +} + +inline float genlib_fasterpow (float x, float p) { + return genlib_fasterpow2(p * genlib_fasterlog2 (x)); +} + +//////////////////////////////////////////////////////////////// + +inline double fastertanfull(double x) { + return (double)genlib_fastertanfull((float)x); +} + +inline double fastersinfull(double x) { + return (double)genlib_fastersinfull((float)x); +} + +inline double fastercosfull(double x) { + return (double)genlib_fastercosfull((float)x); +} + +inline double fasterexp(double x) { + return (double)genlib_fasterexp((float)x); +} + +inline double fasterpow(double x, double p) { + return (double)genlib_fasterpow((float)x, (float)p); +} +/****************************************************************/ + + + +inline double minimum(double x, double y) { return (y +inline T smoothstep(double e0, double e1, T x) { + T t = clamp( safediv(x-T(e0),T(e1-e0)), 0., 1. ); + return t*t*(T(3) - T(2)*t); +} + +inline t_sample mix(t_sample x, t_sample y, t_sample a) { + return x+a*(y-x); +} + +inline double scale(double in, double inlow, double inhigh, double outlow, double outhigh, double power) +{ + double value; + double inscale = safediv(1., inhigh - inlow); + double outdiff = outhigh - outlow; + + value = (in - inlow) * inscale; + if (value > 0.0) + value = pow(value, power); + else if (value < 0.0) + value = -pow(-value, power); + value = (value * outdiff) + outlow; + + return value; +} + +inline t_sample linear_interp(t_sample a, t_sample x, t_sample y) { + return x+a*(y-x); +} + +inline t_sample cosine_interp(t_sample a, t_sample x, t_sample y) { + const t_sample a2 = (t_sample(1.)-genlib_cosT8_safe(a*t_sample(GENLIB_PI)))/t_sample(2.); + return(x*(t_sample(1.)-a2)+y*a2); +} + +inline t_sample cubic_interp(t_sample a, t_sample w, t_sample x, t_sample y, t_sample z) { + const t_sample a2 = a*a; + const t_sample f0 = z - y - w + x; + const t_sample f1 = w - x - f0; + const t_sample f2 = y - w; + const t_sample f3 = x; + return(f0*a*a2 + f1*a2 + f2*a + f3); +} + +// Breeuwsma catmull-rom spline interpolation +inline t_sample spline_interp(t_sample a, t_sample w, t_sample x, t_sample y, t_sample z) { + const t_sample a2 = a*a; + const t_sample f0 = t_sample(-0.5)*w + t_sample(1.5)*x - t_sample(1.5)*y + t_sample(0.5)*z; + const t_sample f1 = w - t_sample(2.5)*x + t_sample(2)*y - t_sample(0.5)*z; + const t_sample f2 = t_sample(-0.5)*w + t_sample(0.5)*y; + return(f0*a*a2 + f1*a2 + f2*a + x); +} + +template +inline T1 neqp(T1 x, T2 y) { + return ((((x) != T1(y))) ? (x) : T1(0)); +} + +template +inline T1 gtp(T1 x, T2 y) { return ((((x) > T1(y))) ? (x) : T1(0)); } +template +inline T1 gtep(T1 x, T2 y) { return ((((x) >= T1(y))) ? (x) : T1(0)); } +template +inline T1 ltp(T1 x, T2 y) { return ((((x) < T1(y))) ? (x) : T1(0)); } +template +inline T1 ltep(T1 x, T2 y) { return ((((x) <= T1(y))) ? (x) : T1(0)); } + +inline double fract(double x) { double unused; return modf(x, &unused); } + +// log2(x) = log(x)/log(2) +template +inline T log2(T x) { + return log(x)*GENLIB_1_OVER_LOG_2; +} + +inline double atodb(double in) { + return (in <=0.) ? -999. : (20. * log10(in)); +} + +inline double dbtoa(double in) { + return pow(10., in * 0.05); +} + +inline double ftom(double in, double tuning=440.) { + return 69. + 17.31234050465299 * log(safediv(in, tuning)); +} + +inline double mtof(double in, double tuning=440.) { + return tuning * exp(.057762265 * (in - 69.0)); +} + +inline t_sample mstosamps(t_sample ms, t_sample samplerate=44100.) { + return samplerate * ms * t_sample(0.001); +} + +inline t_sample sampstoms(t_sample s, t_sample samplerate=44100.) { + return t_sample(1000.) * s / samplerate; +} + +inline double triangle(double phase, double p1) { + phase = wrap(phase, 0., 1.); + p1 = clamp(p1, 0., 1.); + if (phase < p1) + return (p1) ? phase/p1 : 0.; + else + return (p1==1.) ? phase : 1. - ((phase - p1) / (1. - p1)); +} + +struct Delta { + t_sample history; + Delta() { reset(); } + inline void reset(t_sample init=0) { history=init; } + + inline t_sample operator()(t_sample in1) { + t_sample ret = in1 - history; + history = in1; + return ret; + } +}; +struct Change { + t_sample history; + Change() { reset(); } + inline void reset(t_sample init=0) { history=init; } + + inline t_sample operator()(t_sample in1) { + t_sample ret = in1 - history; + history = in1; + return sign(ret); + } +}; + +struct Rate { + t_sample phase, diff, mult, invmult, prev; + int wantlock, quant; + + Rate() { reset(); } + + inline void reset() { + phase = diff = prev = 0; + mult = invmult = 1; + wantlock = 1; + quant = 1; + } + + inline t_sample perform_lock(t_sample in1, t_sample in2) { + // did multiplier change? + if (in2 != mult && !genlib_isnan(in2)) { + mult = in2; + invmult = safediv(1., mult); + wantlock = 1; + } + t_sample diff = in1 - prev; + + if (diff < t_sample(-0.5)) { + diff += t_sample(1); + } else if (diff > t_sample(0.5)) { + diff -= t_sample(1); + } + + if (wantlock) { + // recalculate phase + phase = (in1 - GENLIB_QUANT(in1, quant)) * invmult + + GENLIB_QUANT(in1, quant * mult); + diff = 0; + wantlock = 0; + } else { + // diff is always between -0.5 and 0.5 + phase += diff * invmult; + } + + if (phase > t_sample(1.) || phase < t_sample(-0.)) { + phase = phase - (long)(phase); + } + + prev = in1; + + return phase; + } + + inline t_sample perform_cycle(t_sample in1, t_sample in2) { + // did multiplier change? + if (in2 != mult && !genlib_isnan(in2)) { + mult = in2; + invmult = safediv(1., mult); + wantlock = 1; + } + t_sample diff = in1 - prev; + + if (diff < t_sample(-0.5)) { + if (wantlock) { + wantlock = 0; + phase = in1 * invmult; + diff = t_sample(0); + } else { + diff += t_sample(1); + } + } else if (diff > t_sample(0.5)) { + if (wantlock) { + wantlock = 0; + phase = in1 * invmult; + diff = t_sample(0); + } else { + diff -= t_sample(1); + } + } + + // diff is always between -0.5 and 0.5 + phase += diff * invmult; + + if (phase > t_sample(1.) || phase < t_sample(-0.)) { + phase = phase - (long)(phase); + } + + prev = in1; + + return phase; + } + + inline t_sample perform_off(double in1, double in2) { + // did multiplier change? + if (in2 != mult && !genlib_isnan(in2)) { + mult = in2; + invmult = safediv(1., mult); + wantlock = 1; + } + double diff = in1 - prev; + + if (diff < t_sample(-0.5)) { + diff += t_sample(1); + } else if (diff > t_sample(0.5)) { + diff -= t_sample(1); + } + + phase += diff * invmult; + + if (phase > t_sample(1.) || phase < t_sample(-0.)) { + phase = phase - (long)(phase); + } + + prev = in1; + + return phase; + } +}; + +struct DCBlock { + t_sample x1, y1; + DCBlock() { reset(); } + inline void reset() { x1=0; y1=0; } + + inline double operator()(t_sample in1) { + t_sample y = in1 - x1 + y1*t_sample(0.9997); + x1 = in1; + y1 = y; + return y; + } +}; + +struct Noise { + unsigned long last; + static long uniqueTickCount(void) { + static long lasttime = 0; + long time = genlib_ticks(); + return (time <= lasttime) ? (++lasttime) : (lasttime = time); + } + + Noise() { reset(); } + Noise(double seed) { reset(seed); } + void reset() { last = uniqueTickCount() * uniqueTickCount(); } + void reset(double seed) { last = seed; } + + inline t_sample operator()() { + last = 1664525L * last + 1013904223L; + unsigned long itemp = 0x3f800000 | (0x007fffff & last); + unsigned long* itempptr = &itemp; + return ((*(float *)itempptr) * 2.f) - 3.f; + } +}; + +struct Phasor { + t_sample phase; + Phasor() { reset(); } + void reset(t_sample v=0.) { phase=v; } + inline double operator()(t_sample freq, t_sample invsamplerate) { + const t_sample pincr = freq * invsamplerate; + //phase = genlib_wrapfew(phase + pincr, 0., 1.); // faster for low frequencies, but explodes with high frequencies + phase = wrap(phase + pincr, 0., 1.); + return phase; + } +}; + +struct PlusEquals { + t_sample count; + PlusEquals() { reset(); } + void reset(t_sample v=0.) { count=v; } + + // reset post-application mode: + inline t_sample post(t_sample incr, t_sample reset, t_sample min, t_sample max) { + count = reset ? min : wrap(count+incr, min, max); + return count; + } + inline t_sample post(t_sample incr=1., t_sample reset=0., t_sample min=0.) { + count = reset ? min : count+incr; + return count; + } + + // reset pre-application mode: + inline t_sample pre(t_sample incr, t_sample reset, t_sample min, t_sample max) { + count = reset ? min+incr : wrap(count+incr, min, max); + return count; + } + inline t_sample pre(t_sample incr=1., t_sample reset=0., t_sample min=0.) { + count = reset ? min+incr : count+incr; + return count; + } +}; + +struct MulEquals { + t_sample count; + MulEquals() { reset(); } + void reset(t_sample v=0.) { count=v; } + + // reset post-application mode: + inline t_sample post(t_sample incr, t_sample reset, t_sample min, t_sample max) { + count = reset ? min : wrap(fixdenorm(count*incr), min, max); + return count; + } + inline t_sample post(t_sample incr=1., t_sample reset=0., t_sample min=0.) { + count = reset ? min : fixdenorm(count*incr); + return count; + } + + // reset pre-application mode: + inline t_sample pre(t_sample incr, t_sample reset, t_sample min, t_sample max) { + count = reset ? min*incr : wrap(fixdenorm(count*incr), min, max); + return count; + } + inline t_sample pre(t_sample incr=1., t_sample reset=0., t_sample min=0.) { + count = reset ? min*incr : fixdenorm(count*incr); + return count; + } +}; + +struct Sah { + t_sample prev, output; + Sah() { reset(); } + void reset(t_sample o=0.) { + output = prev = o; + } + + inline t_sample operator()(t_sample in, t_sample trig, t_sample thresh) { + if (prev <= thresh && trig > thresh) { + output = in; + } + prev = trig; + return output; + } +}; + +struct Train { + t_sample phase, state; + Train() { reset(); } + void reset(t_sample p=0) { phase = p; state = 0.; } + + inline t_sample operator()(t_sample pulseinterval, t_sample width, t_sample pulsephase) { + if (width <= t_sample(0.)) { + state = t_sample(0.); // no pulse! + } else if (width >= 1.) { + state = t_sample(1.); // constant pulse! + } else { + const t_sample interval = maximum(pulseinterval, t_sample(1.)); // >= 1. + const t_sample p1 = clamp(pulsephase, t_sample(0.), t_sample(1.)); // [0..1] + const t_sample p2 = p1+width; // (p1..p1+1) + const t_sample pincr = t_sample(1.)/interval; // (0..1] + phase += pincr; // +ve + if (state) { // on: + if (phase > p2) { + state = t_sample(0.); // turn off + phase -= (int)(1.+phase-p2); // wrap phase back down + } + } else { // off: + if (phase > p1) { + state = t_sample(1.); // turn on. + } + } + } + return state; + } +}; + +struct Delay { + t_sample * memory; + long size, wrap, maxdelay; + long reader, writer; + + t_genlib_data * dataRef; + + Delay() : memory(0) { + size = wrap = maxdelay = 0; + reader = writer = 0; + dataRef = 0; + } + ~Delay() { + if (dataRef != 0) { + // store write position for persistence: + genlib_data_setcursor(dataRef, writer); + // decrement reference count: + genlib_data_release(dataRef); + } + } + + inline void reset(const char * name, long d) { + // if needed, acquire the Data's global reference: + if (dataRef == 0) { + + void * ref = genlib_obtain_reference_from_string(name); + dataRef = genlib_obtain_data_from_reference(ref); + if (dataRef == 0) { + genlib_report_error("failed to acquire data"); + return; + } + + // scale maxdelay to next highest power of 2: + maxdelay = d; + size = maxdelay < 2 ? 2 : maxdelay; + size = next_power_of_two(size); + + // first reset should resize the memory: + genlib_data_resize(dataRef, size, 1); + + t_genlib_data_info info; + if (genlib_data_getinfo(dataRef, &info) == GENLIB_ERR_NONE) { + if (info.dim != size) { + // at this point, could resolve by reducing to + // maxdelay = size = next_power_of_two(info.dim+1)/2; + // but really, if this happens, it means more than one + // object is referring to the same t_gen_dsp_data. + // which is probably bad news. + genlib_report_error("delay memory size error"); + memory = 0; + return; + } + memory = info.data; + writer = genlib_data_getcursor(dataRef); + } else { + genlib_report_error("failed to acquire data info"); + } + + } else { + // subsequent reset should zero the memory & heads: + set_zero64(memory, size); + writer = 0; + } + + reader = writer; + wrap = size-1; + } + + // called at bufferloop end, updates read pointer time + inline void step() { + reader++; + if (reader >= size) reader = 0; + } + + inline void write(t_sample x) { + writer = reader; // update write ptr + memory[writer] = x; + } + + inline t_sample read_step(t_sample d) { + // extra half for nice rounding: + // min 1 sample delay for read before write (r != w) + const t_sample r = t_sample(size + reader) - clamp(d-t_sample(0.5), (reader != writer), maxdelay); + long r1 = long(r); + return memory[r1 & wrap]; + } + + inline t_sample read_linear(t_sample d) { + // min 1 sample delay for read before write (r != w) + t_sample c = clamp(d, (reader != writer), maxdelay); + const t_sample r = t_sample(size + reader) - c; + long r1 = long(r); + long r2 = r1+1; + t_sample a = r - (t_sample)r1; + t_sample x = memory[r1 & wrap]; + t_sample y = memory[r2 & wrap]; + return linear_interp(a, x, y); + } + + inline t_sample read_cosine(t_sample d) { + // min 1 sample delay for read before write (r != w) + const t_sample r = t_sample(size + reader) - clamp(d, (reader != writer), maxdelay); + long r1 = long(r); + long r2 = r1+1; + t_sample a = r - (t_sample)r1; + t_sample x = memory[r1 & wrap]; + t_sample y = memory[r2 & wrap]; + return cosine_interp(a, x, y); + } + + // cubic requires extra sample of compensation: + inline t_sample read_cubic(t_sample d) { + // min 1 sample delay for read before write (r != w) + // plus extra 1 sample compensation for 4-point interpolation + const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.)+t_sample(reader != writer), maxdelay); + long r1 = long(r); + long r2 = r1+1; + long r3 = r1+2; + long r4 = r1+3; + t_sample a = r - (t_sample)r1; + t_sample w = memory[r1 & wrap]; + t_sample x = memory[r2 & wrap]; + t_sample y = memory[r3 & wrap]; + t_sample z = memory[r4 & wrap]; + return cubic_interp(a, w, x, y, z); + } + + // spline requires extra sample of compensation: + inline t_sample read_spline(t_sample d) { + // min 1 sample delay for read before write (r != w) + // plus extra 1 sample compensation for 4-point interpolation + const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.)+t_sample(reader != writer), maxdelay); + long r1 = long(r); + long r2 = r1+1; + long r3 = r1+2; + long r4 = r1+3; + t_sample a = r - (t_sample)r1; + t_sample w = memory[r1 & wrap]; + t_sample x = memory[r2 & wrap]; + t_sample y = memory[r3 & wrap]; + t_sample z = memory[r4 & wrap]; + return spline_interp(a, w, x, y, z); + } +}; + +template +struct DataInterface { + long dim, channels; + T * mData; + void * mDataReference; // this was t_symbol *mName + int modified; + + DataInterface() : dim(0), channels(1), mData(0), modified(0) { mDataReference = 0; } + + // raw reading/writing/overdubbing (internal use only, no bounds checking) + inline t_sample read(long index, long channel=0) const { + return mData[channel+index*channels]; + } + inline void write(T value, long index, long channel=0) { + mData[channel+index*channels] = value; + modified = 1; + } + // NO LONGER USED: + inline void overdub(T value, long index, long channel=0) { + mData[channel+index*channels] += value; + modified = 1; + } + + // averaging overdub (used by splat) + inline void blend(T value, long index, long channel, t_sample alpha) { + long offset = channel+index*channels; + const T old = mData[offset]; + mData[offset] = old + alpha * (value - old); + modified = 1; + } + + // NO LONGER USED: + inline void read_ok(long index, long channel=0, bool ok=1) const { + return ok ? mData[channel+index*channels] : T(0); + } + inline void write_ok(T value, long index, long channel=0, bool ok=1) { + if (ok) mData[channel+index*channels] = value; + } + inline void overdub_ok(T value, long index, long channel=0, bool ok=1) { + if (ok) mData[channel+index*channels] += value; + } + + // Bounds strategies: + inline long index_clamp(long index) const { return clamp(index, 0, dim-1); } + inline long index_wrap(long index) const { return wrap(index, 0, dim); } + inline long index_fold(long index) const { return fold(index, 0, dim); } + inline bool index_oob(long index) const { return (index < 0 || index >= dim); } + inline bool index_inbounds(long index) const { return (index >=0 && index < dim); } + + // channel bounds: + inline long channel_clamp(long c) const { return clamp(c, 0, channels-1); } + inline long channel_wrap(long c) const { return wrap(c, 0, channels); } + inline long channel_fold(long c) const { return fold(c, 0, channels); } + inline bool channel_oob(long c) const { return (c < 0 || c >= channels); } + inline bool channel_inbounds(long c) const { return !channel_oob(c); } + + // Indexing strategies: + // [0..1] -> [0..(dim-1)] + inline t_sample phase2index(t_sample phase) const { return phase * t_sample(dim-1); } + // [0..1] -> [min..max] + inline t_sample subphase2index(t_sample phase, long min, long max) const { + min = index_clamp(min); + max = index_clamp(max); + return t_sample(min) + phase * t_sample(max-min); + } + // [-1..1] -> [0..(dim-1)] + inline t_sample signal2index(t_sample signal) const { return phase2index((signal+t_sample(1.)) * t_sample(0.5)); } + + inline T peek(t_sample index, long channel=0) const { + const long i = (long)index; + if (index_oob(i) || channel_oob(channel)) { + return 0.; + } else { + return read(i, channel); + } + } + + inline T index(double index, long channel=0) const { + channel = channel_clamp(channel); + // no-interp: + long i = (long)index; + // bound: + i = index_clamp(i); + return read(i, channel); + } + + inline T cell(double index, long channel=0) const { + channel = channel_clamp(channel); + // no-interp: + long i = (long)index; + // bound: + i = index_wrap(i); + return read(i, channel); + } + + inline T cycle(t_sample phase, long channel=0) const { + channel = channel_clamp(channel); + t_sample index = phase2index(phase); + // interp: + long i1 = (long)index; + long i2 = i1+1; + const t_sample alpha = index - (t_sample)i1; + // bound: + i1 = index_wrap(i1); + i2 = index_wrap(i2); + // interp: + T v1 = read(i1, channel); + T v2 = read(i2, channel); + return mix(v1, v2, alpha); + } + + inline T lookup(t_sample signal, long channel=0) const { + channel = channel_clamp(channel); + t_sample index = signal2index(signal); + // interp: + long i1 = (long)index; + long i2 = i1+1; + t_sample alpha = index - (t_sample)i1; + // bound: + i1 = index_clamp(i1); + i2 = index_clamp(i2); + // interp: + T v1 = read(i1, channel); + T v2 = read(i2, channel); + return mix(v1, v2, alpha); + } + // NO LONGER USED: + inline void poke(t_sample value, t_sample index, long channel=0) { + const long i = (long)index; + if (!(index_oob(i) || channel_oob(channel))) { + write(fixdenorm(value), i, channel); + } + } + // NO LONGER USED: + inline void splat_adding(t_sample value, t_sample phase, long channel=0) { + const t_sample valuef = fixdenorm(value); + channel = channel_clamp(channel); + t_sample index = phase2index(phase); + // interp: + long i1 = (long)index; + long i2 = i1+1; + const t_sample alpha = index - (double)i1; + // bound: + i1 = index_wrap(i1); + i2 = index_wrap(i2); + // interp: + overdub(valuef*(1.-alpha), i1, channel); + overdub(valuef*alpha, i2, channel); + } + // NO LONGER USED: + inline void splat(t_sample value, t_sample phase, long channel=0) { + const t_sample valuef = fixdenorm(value); + channel = channel_clamp(channel); + t_sample index = phase2index(phase); + // interp: + long i1 = (long)index; + long i2 = i1+1; + const t_sample alpha = index - (t_sample)i1; + // bound: + i1 = index_wrap(i1); + i2 = index_wrap(i2); + // interp: + const T v1 = read(i1, channel); + const T v2 = read(i2, channel); + write(v1 + (1.-alpha)*(valuef-v1), i1, channel); + write(v2 + (alpha)*(valuef-v2), i2, channel); + } +}; + +// DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit +#define DATA_MAXIMUM_ELEMENTS (33554432) + +struct Data : public DataInterface { + t_genlib_data * dataRef; // a pointer to some external source of the data + + Data() : DataInterface() { + dataRef = 0; + } + ~Data() { + //genlib_report_message("releasing data handle %d", dataRef); + if (dataRef != 0) { + genlib_data_release(dataRef); + } + } + void reset(const char * name, long s, long c) { + // if needed, acquire the Data's global reference: + if (dataRef == 0) { + void * ref = genlib_obtain_reference_from_string(name); + dataRef = genlib_obtain_data_from_reference(ref); + if (dataRef == 0) { + genlib_report_error("failed to acquire data"); + return; + } + } + genlib_data_resize(dataRef, s, c); + getinfo(); + } + bool setbuffer(void * bufferRef) { + //genlib_report_message("set buffer %p", bufferRef); + if (dataRef == 0) { + // error: no data, or obtain? + return false; + } + genlib_data_setbuffer(dataRef, bufferRef); + getinfo(); + return true; + } + + void getinfo() { + t_genlib_data_info info; + if (genlib_data_getinfo(dataRef, &info) == GENLIB_ERR_NONE) { + mData = info.data; + dim = info.dim; + channels = info.channels; + } else { + genlib_report_error("failed to acquire data info"); + } + } +}; + +// Used by SineData +struct DataLocal : public DataInterface { + DataLocal() : DataInterface() {} + ~DataLocal() { + if (mData) sysmem_freeptr(mData); + mData = 0; + } + + void reset(long s, long c) { + mData=0; + resize(s, c); + } + + void resize(long s, long c) { + if (s * c > DATA_MAXIMUM_ELEMENTS) { + s = DATA_MAXIMUM_ELEMENTS/c; + genlib_report_message("warning: resizing data to < 256MB"); + } + if (mData) { + sysmem_resizeptr(mData, sizeof(t_sample) * s * c); + } else { + mData = (t_sample *)sysmem_newptr(sizeof(t_sample) * s * c); + } + if (!mData) { + genlib_report_error("out of memory"); + resize(512, 1); + return; + } else { + dim = s; + channels = c; + } + set_zero64(mData, dim * channels); + } + + // copy from a buffer~ + // resizing is safe only during initialization! + bool setbuffer(void *dataReference) { + mDataReference = dataReference; // replaced mName + bool result = false; + t_genlib_buffer * b; + t_genlib_buffer_info info; + if (mDataReference != 0) { + b = (t_genlib_buffer *)genlib_obtain_buffer_from_reference(mDataReference); + if (b) { + if (genlib_buffer_edit_begin(b)==GENLIB_ERR_NONE) { + if (genlib_buffer_getinfo(b, &info)==GENLIB_ERR_NONE) { + float * samples = info.b_samples; + long frames = info.b_frames; + long nchans = info.b_nchans; + //long size = info.b_size; + //long modtime = info.b_modtime; // cache & compare? + + // resizing is safe only during initialization! + if (mData == 0) resize(frames, nchans); + + long frames_safe = frames < dim ? frames : dim; + long channels_safe = nchans < channels ? nchans : channels; + // copy: + for (int f=0; f { + t_genlib_buffer * mBuf; + t_genlib_buffer_info mInfo; + float mDummy; // safe access in case buffer is not valid + + Buffer() : DataInterface() {} + + void reset(const char * name) { + dim = 1; + channels = 1; + mData = &mDummy; + mDummy = 0.f; + mBuf = 0; + + // call into genlib: + mDataReference = genlib_obtain_reference_from_string(name); + } + + void setbuffer(void * ref) { + mDataReference = ref; + } + + void begin() { + t_genlib_buffer * b = genlib_obtain_buffer_from_reference(mDataReference); + mBuf = 0; + if (b) { + if (genlib_buffer_perform_begin(b) == GENLIB_ERR_NONE) { + mBuf = b; + } else { + //genlib_report_message ("not a buffer~ %s", mName->s_name); + } + } else { + //genlib_report_message("no object %s\n", mName->s_name); + } + + if (mBuf && genlib_buffer_getinfo(mBuf, &mInfo)==GENLIB_ERR_NONE) { + // grab data: + mBuf = b; + mData = mInfo.b_samples; + dim = mInfo.b_frames; + channels = mInfo.b_nchans; + } else { + //genlib_report_message("couldn't get info"); + mBuf = 0; + mData = &mDummy; + dim = 1; + channels = 1; + } + } + + void end() { + if (mBuf) { + genlib_buffer_perform_end(mBuf); + if (modified) { + genlib_buffer_dirty(mBuf); + } + modified = 0; + } + mBuf = 0; + } +}; + +struct SineData : public DataLocal { + SineData() : DataLocal() { + const int costable_size = 1 << 14; // 14 bit index (noise floor at around -156 dB) + mData=0; + resize(costable_size, 1); + for (int i=0; i +inline int dim(const T& data) { return data.dim; } + +template +inline int channels(const T& data) { return data.channels; } + +// used by cycle when no buffer/data is specified: +struct SineCycle { + + uint32_t phasei, pincr; + double f2i; + + void reset(t_sample samplerate, t_sample init = 0) { + phasei = init * t_sample(4294967296.0); + pincr = 0; + f2i = t_sample(4294967296.0) / samplerate; + } + + inline void freq(t_sample f) { + pincr = f * f2i; + } + + inline void phase(t_sample f) { + phasei = f * t_sample(4294967296.0); + } + + inline t_sample phase() const { + return phasei * t_sample(0.232830643653869629e-9); + } + + template + inline t_sample operator()(const DataInterface& buf) { + T * data = buf.mData; + // divide uint32_t range down to buffer size (32-bit to 14-bit) + uint32_t idx = phasei >> 18; + // compute fractional portion and divide by 18-bit range + const t_sample frac = t_sample(phasei & 262143) * t_sample(3.81471181759574e-6); + // index safely in 14-bit range: + const t_sample y0 = data[idx]; + const t_sample y1 = data[(idx+1) & 16383]; + const t_sample y = linear_interp(frac, y0, y1); + phasei += pincr; + return y; + } +}; + +#endif diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/utils/README-Linux.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/utils/README-Linux.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,13 @@ +############################# +## README for DPF Plugins ## + +This folder contains audio plugins downloaded from https://github.com/DISTRHO/DPF-Plugins/releases + +The plugins are separated by their type - ladspa plugins are in the ladspa folder, etc. +Check your host documentation to know where to place these files. +Note that most hosts support LADSPA or VST but not CLAP, DSSI or LV2. + + +If your host is not listing these plugins, make sure the binaries you downloaded match your host architecture. +32bit plugins go into 32bit hosts, same for 64bit. +Some hosts are able to load plugins with different architecture, but that's the exception rather than the rule. diff -r cf2cb71d31dd -r 84e66ea83026 DPF-Prymula-audioplugins/utils/README-Windows.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/utils/README-Windows.txt Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,13 @@ +############################# +## README for DPF Plugins ## + +This folder contains audio plugins downloaded from https://github.com/DISTRHO/DPF-Plugins/releases + +The included *.lv2 folders are LV2 bundles and the *.dll files are VSTs. +Check your host documentation to know where to place these files. +Note that most hosts support VST but not LV2. + + +If your host is not listing these plugins, make sure the binaries you downloaded match your host architecture. +32bit plugins go into 32bit hosts, same for 64bit. +Some hosts are able to load plugins with different architecture, but that's the exception rather than the rule.